Skip to main content

Solution Structure

Simple Web API

Solution 'xxENSONOxx.xxSTACKSss.API'
├── API
│  ├── xxENSONOxx.xxSTACKSxx.API
│  ├── xxENSONOxx.xxSTACKSxx.API.Models
└── Tests
   ├── xxENSONOxx.xxSTACKSxx.API.UnitTests

Web API with CQRS

Solution 'xxENSONOxx.xxSTACKSss.API'
├── API
│  ├── xxENSONOxx.xxSTACKSxx.API
│  ├── xxENSONOxx.xxSTACKSxx.API.Models
├── Application
│  ├── xxENSONOxx.xxSTACKSxx.Application.CommandHandlers
│  ├── xxENSONOxx.xxSTACKSxx.Application.Integration
│  ├── xxENSONOxx.xxSTACKSxx.Application.QueryHandlers
├── Domain
│  ├── xxENSONOxx.xxSTACKSxx.Domain
│  └── External
├── Shared
│  ├── xxENSONOxx.xxSTACKSxx.Common
│  └── xxENSONOxx.xxSTACKSxx.CQRS
└── Tests
   ├── xxENSONOxx.xxSTACKSxx.API.ComponentTests
   ├── xxENSONOxx.xxSTACKSxx.Common.UnitTests
   ├── xxENSONOxx.xxSTACKSxx.Domain.UnitTests
   └── xxENSONOxx.xxSTACKSxx.Infrastructure.IntegrationTests

Functions and Worker Services

├── Functions
│  ├── function-aeh-listener
│ │   ├── xxENSONOxx.xxSTACKSxx.Listener
│ │   └── xxENSONOxx.xxSTACKSxx.Listener.UnitTests
│  ├── function-asb-listener
│ │   ├── xxENSONOxx.xxSTACKSxx.Listener
│ │   └── xxENSONOxx.xxSTACKSxx.Listener.UnitTests
│  ├── function-cosmosdb-worker
│ │   ├── xxENSONOxx.xxSTACKSxx.Worker
│ │   └── xxENSONOxx.xxSTACKSxx.Worker.UnitTests
├── Worker
│  └── xxENSONOxx.xxSTACKSxx.BackgroundWorker

The API scope contains the components which are exposed publicly, such as the APIs and it's Models. It contains infrastructure components responsible to arrange all dependencies within the solution. If the API wasn't self-hosted, the WebHost would have been added to this scope to manage the hosting concerns of the API.


Company.Project.API

The API project containing the controllers and swagger documentation. The purpose of the API project is to expose the application via a set of REST\HTTP endpoints. The API will validate requests either by built-in validators using DataAnnotations attributes or using FluentValidation(not included in the template).

The API is a self hosted service using .NET Core kestrel and does not require any external web server. The hosting logic is handled by the Program.cs class.

The API depends on ICommandHandler and IQueryHandler abstractions and does not contain a direct reference to the command-handlers and query-handler projects to reduce coupling. The bridge between the interface abstraction and implementations will be provided by the infrastructure that maps the interfaces and implementations of many components, like the queries and commands handlers, repositories, caches and so on.

Having the constructor depending on abstractions also makes the API flexible for Contract Testing, where the interfaces can me mocked and don't require a dependency to the Application.


Company.Project.Models

The Models exposed by the API have been pulled out of the API project to make them reusable. The models have their own validation using DataAnnotations, therefore the validation id provided in the models without dependency on third party libraries like FluentValidation, which should be implemented only if needed.

  • QA have demonstrated interest in reuse of Models to avoid duplication of code in API.Models and TestModels. The separate models project will make it easier to expose the models as NuGet packages for reuse by QA Functional Tests.

  • A Client SDK can be create in the future to communicate with the API, having a reusable Model, makes it easy to write the SDK without rewriting them every time the API changes.


Company.Project.Infrastructure

The infrastructure project is a cross cutting project responsible to tie the dependencies within the API and application. In general, the API communicates to an Interface that abstracts away the need to have an implementation available at API design time. It needs to know only the Commands and Queries available for each operation. The command and query handlers are implemented in their own projects and the API does not have a direct dependency on it. The infrastructure will be responsible to bridge the commands to handlers making the API decoupled from the implementation.

The same happens for other components, CommandHandlers do not have a direct dependency in the Repository implementation, they just expect an implementation to be injected at runtime, the real implementation will be managed by the Infrastructure in real environments or managed by test fixtures using Mocks or Stubs during test contexts.

In simple terms, the Infrastructure setups the IoC container with all dependencies needed to run the application.