Nabeel Codes

Blog for all things tech that I do

Trying Out the Ardalis Clean Architecture .NET 9 Template

Posted by:

|

On:

|

,

As someone who is relatively new to the whole clean architecture thing, I decided to try out the latest template by Ardalis. You can find it here: https://github.com/ardalis/CleanArchitecture

Here’s the folder structure you get if you download the whole repo as a zip and extract it.

Running the Project

In order to run the project, you can set the Clean.Architecture.Web project as the startup project and run it. For me it opened at this URL and showed the following command prompt window https://localhost:57679

Web Project

The whole thing starts off in the Web project. This is where your ‘controllers’ would reside. In this template, FAST Endpoints is used. The image below shows how the requests are created and stored as different files. The request, response, and validators are also stored as separate files.

Contributors/ContributorRecord.cs

Every folder contains a basic record. The record can be thought of as the return model used for this object. In other words, for actions such as GetList, GetByID, Update, one or more objects of this type (ContributorRecird) will be returned. For example, here is the what the list endpoint response looks like. You can define more properties as needed for specific endpoints, but they will all share the base ContributorRecord for consistency. It may or may not be the same as your domain representation of the Contributor.

Contributors/Create.cs

The create.cs class implements the FastEndpoints class called Endpoint and overrides the Configure and HandleAsync methods. Configure is used to define the required request, authentication, documentation, and a sample request. The handle method uses mediator to send a command or query and then returns the response based on the result received from the inner layer.

Use Cases Project

This project contains all the use cases. It includes the commands and queries depending on the use case. For example the create contributor use case contains a command and the get contributor use case contains a query. Both contains handlers too.

The command or query contains a record class with parameters if required.

The handler has a Handle method. The constructor gets injected with the repository of any objects that it requires. For example in the case of create contributor the handle method creates a new contributor object by instantiating the class from the Core (domain) project. And using its methods to set the required properties which ensures domain consistency. Then it passes that object to the repository which adds it to the persistence layer.

Core Project

The core project contains the domain of the project. It also contains the interfaces and implementations of any services. They are used to model complex operations and interactions that involve multiple entities or require coordination between them.

Infrastructure Project

The infrastructure project contains the persistence layer information. It includes the config files for the domain objects which map the domain object to the required database configuration.

Here is a description of the infrastructure project taken from the readme file

In Clean Architecture, Infrastructure concerns are kept separate from the core business rules (or domain model in DDD).

The only project that should have code concerned with EF, Files, Email, Web Services, Azure/AWS/GCP, etc is Infrastructure.

Infrastructure should depend on Core (and, optionally, Use Cases) where abstractions (interfaces) exist.

Infrastructure classes implement interfaces found in the Core (Use Cases) project(s).

These implementations are wired up at startup using DI. In this case using Microsoft.Extensions.DependencyInjection and extension methods defined in each project.

Here is how the email sender is created using the infrastructure project:

The email sender can be configured / registered in the web project as follows

Tests

The tests are kept separately and split into 3 projects

  1. Unit Tests
  2. Integration Tests
  3. Functional Tests

Unit Tests

Unit tests are the smallest and simplest type of test. They focus on testing individual methods or functions in isolation, without involving any external systems like databases or APIs. Dependencies like databases or external services are replaced with mock objects. This is where you would test all the core domain objects in isolation and make sure that the business rules on each object are being applied correctly.

Integration Tests

Integration tests check how different parts of the system work together. These tests ensure that components like controllers, services, and the database integrate properly. For instance, you might test whether a controller correctly processes a request, calls the appropriate service, and saves the data in the database. Integration tests can use real or in-memory versions of dependencies to verify that the interactions between the components. In this template, the tests are using an in-memory database.

Functional Tests

Functional tests test the entire system from a user’s perspective. These tests simulate real-world scenarios, such as making an API call to create a new contributor. Functional tests involve all parts of the system, including real databases and APIs, and ensure that the system behaves as it should when used by an end user. In this template Ardalis.HttpClientTestExtensions is used to use some extension methods to help ensure different HTTP status codes such as 404 not found.

Conclusion

So this was a brief look into the Ardalis Clean Architecture template using .NET 9. I’ll keep adding more this is post as I dig deeper into it. Thanks for reading 🙂

https://github.com/ardalis/CleanArchitecture