DEV Community

Cover image for .NET Clean Architecture, Yet Another!
amr swalha
amr swalha

Posted on

.NET Clean Architecture, Yet Another!

As you for sure know, there is a lot of .NET Clean Architecture projects, we try to provide a much easier one to use and one that can help developer provide much better results. So, we released .NET Clean Architecture that we worked on for years and used it in multiple projects to help other fellow software developers build better .NET applications.

Backstory

While working at some company, I saw an architecture that layered the application into 4 parts: Core for entities, Infra for general operations, Business for the implementation and the API layer to expose them all.

When looking at them, they really provided a good way to separate the different layers and make the work more reusable. But there was a big problem of boilerplate code for the basic operations.
You had to have on each class GetById and you had to write them for each one, so this was way too boring and redundant for me as a guy who had installed many extensions just to save a few clicks ;)

So, I wanted to make a better solution where you don't have this many codes to write each time and all the basic cruds are already there. So, after some time of trying and testing, I started this project as an internal tool for Advanced Software Solutions and used it in many projects. Now, reached V2.0 I want it to have more exposure and have more people feedback. Also, it was battle tested with a small company, and they liked it a lot so I want more people to take advantage of this.

V1.0

In this version, I had the four layers, Core Operation Business and the API layer. This version was a good start as it shown the ability of the architecture to minimize the need to create any GET operation unless it was very custom, due to the usage of OData. Just add your entity and map it to EF, add a service and an api controller and magic you have all the CRUDs you need created for you. If you want a custom method, you can add it freely to the API or the service.

The feedback was really good, and the usage of this method was really helpful for the developers. But we got feedback that the developers had each time to add a new entity the need to add a service and an API controller. Which became very redundant task in case the application grows bigger. Also, most of the time they just needed the basic CRUD and rarely edited the service or the controller.

V2.0+ (Current Release)

Taking advice from the first release, I looked at the architecture again and decided the following:

  1. Instead of using a service for each entity, and most of the time you don't need a custom code, the Business layer is optional for each entity. If you need more custom code or business logic, you implement an Actor using Akka and then create a partial class for the API controller to use it.
  2. The usage of .NET Source Generator to lower the amount of boilerplate code. Just add your entity and map it to EF and you are all set! The Source Generators will generate the API controller for you, and you will have all the CRUD ready with OData as well.

How to use it

First please go to .NET Clean Architecture and then download the project.

Afterward, you can run the project directly from VS 2022 or just use .NET run cli command (dotnet run) and make sure you install the latest SDK (.NET 9 at the time of writing).

After running the application you will be presented by Scalar

Project After Running

Configuration

In the appsettings.Development.json, you can specify the configuration for the application. The "CleanAppConfiguration" section contains the configuration needed for the application to function correctly. Let's take a look at the section:

"CleanAppConfiguration": {
    "InMemoryCaching": {
      "Enabled": true,
      "Provider": "InMemory",
      "Configs": {
        "Host": "localhost",
        "Port": "11211"
      }
    },
    "Auth": {
      "Authority": "CleanAPI",
      "Audience": "CleanAPI",
      "ValidAudiences": [
        "CleanAPI"
      ],
      "ValidIssuers": [
        "CleanAPI"
      ],
      "Key": "d18bf0b49d5c2679e2250246779570f7a5e79f23"
    },
    "Datastore": {
      "ConnectionString": "Data Source=.;Database=CleanDB;Integrated Security=True;Persist Security Info=False;Pooling=False;Multiple Active Result Sets=False;Connect Timeout=60;Encrypt=False;Trust Server Certificate=True;Command Timeout=0",
      "Provider": "SQLite"
    },
    "ResponseCache": {
      "Enabled": true,
      "Duration": 30,
      "VaryByHeaders": ["Authorization"]
    }
  }
Enter fullscreen mode Exit fullscreen mode
  • InMemoryCaching
    • This to configure the caching for the api and you can enable it or turn it off. You can choose the InMemory or Memcached.
  • Auth
    • To configure the authorization on the API, make sure to change the key and the relevant information.
  • Datastore
    • Where you can configure the datastore, either in memory, SQLite, SQL Server or Postgres. Note that the connection string is required for the SQL server and Postgres.

Note the ResponseCache section is under development.

Adding an Entity

To expose an entity, simply add it inside the CleanBase project inside the Entity folder. After that, make it inherit the EntityRoot class. And you are done! The source generator will generate the API controller for you and hookup the OData to it, so you are good to go!

You can see the generated code for the controller by going to CleanAPI -> Analyzers -> CleanAPIGenerator -> Expand the generator as the image below:

The source generators in action

Afterward

We hope you take advantage of this project and architecture, and we welcome your suggestions for this project as we want it to grow better and larger. We want to keep the community version under the MIT license forever.

Top comments (0)