This document provides a high-level architectural overview of the TestClone API project, a RESTful API built on .NET 10 and ASP.NET Core. The architecture follows clean architecture principles with a layered structure designed to ensure separation of concerns, maintainability, and testability.
The system implements a Layered Architecture (also known as Clean Architecture or Onion Architecture), organizing code into distinct layers with clear responsibilities and dependencies flowing inward toward the domain core.
graph TB
subgraph Presentation Layer
WebApi[WebApi<br/>Controllers, HTTP Concerns]
end
subgraph Business Logic Layer
DomainApi[DomainApi<br/>Application Services, Facade]
end
subgraph Domain Layer
DomainModel[DomainModel<br/>Entities, Value Objects]
end
WebApi -->|depends on| DomainApi
DomainApi -->|depends on| DomainModel
style WebApi fill:#e3f2fd
style DomainApi fill:#fff3e0
style DomainModel fill:#f3e5f5
Dependencies flow inward only:
- Outer layers depend on inner layers
- Inner layers have no knowledge of outer layers
- The domain layer (DomainModel) has no external dependencies
Location: src/WebApi/
Assembly: TestClone.WebApi
Purpose: HTTP endpoint management and API contracts
Responsibilities:
- Expose HTTP endpoints via controllers
- Handle request/response serialization
- Route management and HTTP verb mapping
- Input validation and model binding
- API documentation (OpenAPI/Swagger)
- Authentication and authorization (future)
Key Components:
Program.cs- Application entry point, middleware pipeline configurationTestCloneController.cs- Example controller demonstrating API patternsappsettings.json- Configuration management
Dependencies:
- ASP.NET Core framework
- OpenAPI/Swagger for documentation
- References DomainApi project
Location: src/DomainApi/
Assembly: TestClone.DomainApi
Purpose: Business logic orchestration and application services
Responsibilities:
- Implement business rules and workflows
- Orchestrate domain operations
- Provide simplified interface to business functionality
- Transaction coordination (future)
- Business-level validation
Key Components:
IFacadeinterface - Defines business operation contractsFacadeimplementation - Executes business logic- Located in
Interfaces/folder
Dependencies:
- Will reference DomainModel project (currently no dependency)
- No external framework dependencies
Location: src/DomainModel/
Assembly: TestClone.DomainModel
Purpose: Core domain entities and business rules
Responsibilities:
- Define domain entities and value objects
- Encapsulate domain-specific business rules
- Maintain domain invariants
- Provide domain behavior
Current Status:
- Empty placeholder project
- Intended for future domain entity implementation
- No dependencies on external projects or frameworks
graph LR
WebApi[WebApi<br/>Presentation]
DomainApi[DomainApi<br/>Business Logic]
DomainModel[DomainModel<br/>Domain]
WebApiTests[WebApi.UnitTests]
DomainApiTests[DomainApi.UnitTests]
WebApi --> DomainApi
DomainApi -.future.-> DomainModel
WebApiTests -.tests.-> WebApi
DomainApiTests -.tests.-> DomainApi
style WebApi fill:#4CAF50,color:#fff
style DomainApi fill:#FF9800,color:#fff
style DomainModel fill:#9C27B0,color:#fff
style WebApiTests fill:#90EE90
style DomainApiTests fill:#FFE0B2
| Project | References | Reason |
|---|---|---|
| WebApi | DomainApi | Access business logic through Facade |
| DomainApi | (none currently) | Self-contained; will reference DomainModel |
| DomainModel | (none) | Pure domain layer with no dependencies |
| WebApi.UnitTests | WebApi | Test presentation layer |
| DomainApi.UnitTests | DomainApi | Test business logic layer |
Implementation: IFacade and Facade classes in DomainApi
Purpose:
- Provide a simplified, unified interface to business operations
- Hide complexity of business logic from the presentation layer
- Enable easy mocking for controller testing
- Reduce coupling between layers
Example:
public interface IFacade
{
Task<string> TestOperation();
}
public class Facade : IFacade
{
public async Task<string> TestOperation()
{
return await Task.FromResult("Hello from the Facade!");
}
}Benefits:
- Controllers remain thin and focused on HTTP concerns
- Business logic changes don't impact controller structure
- Clear contract for testing and mocking
Configuration: Defined in Program.cs
Pattern:
- Constructor injection for all dependencies
- Interface-based contracts (program to abstractions)
- Scoped service lifetime for request-scoped operations
Registration Example:
builder.Services.AddScoped<IFacade, Facade>();Benefits:
- Loose coupling between components
- Enhanced testability through interface mocking
- Centralized service configuration
- Support for multiple implementations
Decision Rationale:
- Traditional, structured approach over Minimal APIs
- Clear separation of concerns with dedicated controller classes
- Attribute-based routing for explicit endpoint definitions
- Built-in model validation and action filters
Example:
[ApiController]
[Route("[controller]")]
public class TestCloneController(IFacade facade) : ControllerBase
{
[HttpGet]
[Route("TestOperation")]
public async Task<IActionResult> GetTestOperation()
{
var result = await facade.TestOperation();
return Ok(result);
}
}- .NET 10.0 - Latest LTS with C# 14 language features
- ASP.NET Core - Web framework for building HTTP APIs
- Nullable Reference Types - Enabled for null-safety
- OpenAPI 3.0 - API specification standard
- Swashbuckle/Swagger - Interactive API documentation
- TUnit - Modern unit testing framework
- Moq - Mocking framework for test isolation
- Microsoft.NET.Sdk.Web - Web SDK for ASP.NET Core projects
- .NET Code Analyzers - Static code analysis
- Warnings as Errors - Strict quality enforcement
Implementation: Directory.Packages.props
Rationale:
- Single source of truth for package versions
- Prevents version conflicts across projects
- Simplifies version upgrades
- Reduces maintenance overhead
Configuration: Directory.Build.props
Rationale:
- Enforce code quality standards
- Catch potential issues during compilation
- Maintain consistent codebase quality
- Prevent technical debt accumulation
Decision: Use Facade as the primary business logic interface
Rationale:
- Simplifies controller logic (thin controllers)
- Provides clear contract for business operations
- Enables independent testing of layers
- Facilitates future refactoring of business logic
- Reduces coupling between presentation and business layers
Configuration: Services registered with AddScoped<T>()
Rationale:
- Appropriate for web request-scoped operations
- New instance per HTTP request
- Enables request-specific state management
- Aligns with typical web application patterns
- Balances performance and resource management
Decision: Use traditional controller-based approach
Rationale:
- Structured, class-based organization
- Clear separation of endpoint logic
- Rich attribute-based metadata
- Better suited for complex APIs with many endpoints
- Familiar pattern for most .NET developers
- Built-in conventions (model binding, validation)
Usage: Modern C# 12+ primary constructor syntax in controllers
Example: TestCloneController(IFacade facade)
Rationale:
- Reduces boilerplate code
- Clear dependency declaration
- Leverages latest C# language features
- Improves code readability
Layers Tested:
- WebApi.UnitTests - Controller logic with mocked dependencies
- DomainApi.UnitTests - Business logic with concrete implementations
Testing Patterns:
- Constructor injection of mocked dependencies (Moq)
- Async test patterns with TUnit assertions
- Test naming convention:
ClassNameMethodNameExpectedBehavior - No arrange/act/assert comments (clean test code)
WebApi Tests:
- Mock
IFacadeto isolate controller logic - Verify correct HTTP responses and status codes
- Test routing and model binding
DomainApi Tests:
- Test concrete
Facadeimplementation - Verify business logic correctness
- No mocking needed for self-contained logic
-
Domain Model Population
- Implement domain entities in DomainModel project
- Add repository pattern for data access
- Establish rich domain models with behavior
-
Authentication & Authorization
- JWT Bearer token authentication
- Role-based or policy-based authorization
- Integration with identity providers
-
Data Persistence
- Entity Framework Core integration
- Repository and Unit of Work patterns
- Database migration strategy
-
Error Handling
- Global exception handling middleware
- Standardized error responses (RFC 9457 Problem Details)
- Structured logging with correlation IDs
-
API Versioning
- Version strategy (URL, header, or query string)
- Backward compatibility approach
- Deprecation policy
-
Integration Testing
- End-to-end API tests
- In-memory test database
- WebApplicationFactory pattern
- Caching Strategy - In-memory or distributed caching
- Async/Await Patterns - Already implemented for non-blocking operations
- Pagination & Filtering - For large data set operations
- Response Compression - Reduce payload sizes
- Contributing Guidelines - Development workflow and standards
- Copilot Instructions - Coding conventions and patterns
- README - Project overview and quick start
Document Version: 1.0
Last Updated: February 17, 2026
Maintained By: Development Team