In this article, I will briefly go through Clean Architecture implementation with HTTP-triggered Azure Function and Cosmos DB. The base code is taken from the ShawnShiSS GitHub repo. Along with CQRS, Mediator pattern, and Repository patterns, a DDD Specification pattern is also used which is really helpful to separate the filter and query rules. An Ardalis.Specification package is used in the project to implement the specification pattern. Search specification pattern and specification pattern C# in chatgpt to learn more about specification patterns.
Let’s Start
There are the same projects e.g. Application, Domain, and Infrastructure in the solution I already explained in the learning path. So there is no need to repeat the same information, let’s briefly understand the updates in each project other than the learning path. The solution is implemented to manage the user i.e. loading all users, adding or updating users, and updating user status. Clone the repository, and follow the instructions in the Readme file to build the project.
user.domain
The domain project contains the entities reflecting database collection e.g. User
and, the BaseEntity
contains single Id
field which is shared between both entities. The Specification folder contains the specifications filter classes for User
and Audit
entities e.g. get all or single users or search users by email. Rest, the project contains the Repository interfaces.
user.infrastructure
The user.infrastructure project has Repositories implementation defined in user.domain project. It also contains code to connect to CosmosDB containers User
and Audit
. Go through the Repository -> CosmosDbRepository folder class, this is a base repository with common CRUD functions and ApplySpecification
functions that take the Specification interface defined by user.domain, evaluate it, and return IQueryable
that is used to filter the data as per the condition defined in Specification class. The Specification object is passed from user.application project.
user.application
A user.application project follows the CQRS principle and implements the commands and queries to insert, update, and load the data using repositories implemented in user.infrastructure project. It uses Fluent Validation to validate the request model. View the User -> Queries folder classes, the Specification classes are in action, e.g. in GetSingleUserQuery class, UserGetSingleSpecification is instantiated by sending the input email address and passed as an argument to a common GetItemsAsync
function implemented in the base CosmosDbRepository
class. It provides the flexibility to create a Specification class per filter request and saves us from complex SQL queries.
af-userapi
A userAPI contains HTTP trigged functions using the good old MediatR package to communicate to user.application project. The Startup class contains the service registration statements for all projects e.g. CosmosDB connection in an Infrastructure project, AutoMapper, FluentValidation, and MediatR for an application project. The Azure Function can be easily replaced with the WebAPI project and deployed as Azure App Service if required.