A simple template for Onion Architecture with .NET 5



Just wanted to share a simple approach for Onion Architecture that has saved me a lot of time engaging productivity for everyone on my team.


My simple template for Onion Architecture with .NET 5

Clean architectures are awesome, I don’t have any doubt about that. Highly scalable, fully testable, easy to evolve, easy to adapt to new requirements, etc etc etc.

But unfortunately, I must say that they are not for everyone. If you start adding Input Ports, Use Cases, Output Ports, Presenters, and also adding a DDD approach together with CQRS and Event Sourcing you are adding a kind of steep learning curve for newcomers or people without deep knowledge about good practices, clean code, and related stuff.

And that’s completely fine when you work in a team you need to work as a team, understanding everyone’s point of view and trying to grow all together.

So, how did I try to solve this? How did I promote the usage of good practices in terms of architecture especially when building microservices or serverless functions without overwhelming with a ton of new concepts?

I created this template: It’s just a simple Onion Architecture with CQRS and Event Sourcing. You can use it as you want, you can create a GitHub repository using the template from there or just doing a fork/clone and creating the template from the dotnet CLI.

Just to understand it better I created this diagram which tries to explain everything that can happen in the code:


This is the structure tree of the repository:

C:..gitignore
│   Dotnet.Onion.Template.sln
│   README.md
│
├───docs
│       ARCHITECTURE.md
│       CQRS-ES.md
│       DDD.md
│       HEXAGONAL.md
│       SOLID.md
│
├───images
│       dotnet-onion-ddd-cqrs-es.jpg
│
├───src
│   ├───Dotnet.Onion.Template.API
│   │   │   .dockerignore
│   │   │   Dockerfile
│   │   │   Dotnet.Onion.Template.API.csproj
│   │   │   Program.cs
│   │   │   Startup.cs
│   │   │
│   │   ├───Bindings
│   │   ├───Config
│   │   │       appsettings-dev.json
│   │   │       appsettings-int.json
│   │   │       appsettings-prod.json
│   │   │       appsettings-stag.json
│   │   │
│   │   ├───Controllers
│   │   │       TasksController.cs
│   │   │
│   │   ├───Extensions
│   │   │   └───Middleware
│   │   │           ErrorDetails.cs
│   │   │           ExceptionMiddleware.cs
│   │   │
│   │   └───Properties
│   │           launchSettings.json
│   │
│   ├───Dotnet.Onion.Template.Application
│   │   │   Dotnet.Onion.Template.Application.csproj
│   │   │
│   │   ├───Handlers
│   │   │       TaskCommandHandler.cs
│   │   │       TaskEventHandler.cs
│   │   │
│   │   ├───Mappers
│   │   │       TaskViewModelMapper.cs
│   │   │
│   │   ├───Services
│   │   │       ITaskService.cs
│   │   │       TaskService.cs
│   │   │
│   │   └───ViewModels
│   │           TaskViewModel.cs
│   │
│   ├───Dotnet.Onion.Template.Domain
│   │   │   Dotnet.Onion.Template.Domain.csproj
│   │   │   IAggregateRoot.cs
│   │   │   IRepository.cs
│   │   │
│   │   └───Tasks
│   │       │   ITaskFactory.cs
│   │       │   ITaskRepository.cs
│   │       │   Task.cs
│   │       │
│   │       ├───Commands
│   │       │       CreateNewTaskCommand.cs
│   │       │       DeleteTaskCommand.cs
│   │       │       TaskCommand.cs
│   │       │
│   │       ├───Events
│   │       │       TaskCreatedEvent.cs
│   │       │       TaskDeletedEvent.cs
│   │       │       TaskEvent.cs
│   │       │
│   │       └───ValueObjects
│   │               Description.cs
│   │               Summary.cs
│   │               TaskId.cs
│   │
│   └───Dotnet