Understanding Onion Architecture in ASP NET Core MVC T Digital Thoughts

Because it depends on the layers below it in the hierarchy, it can only call the methods that are exposed by the lower layers. Using dependency inversion throughout the project, depending on abstractions and not the implementations, allows us to switch out the implementation at runtime transparently. We are depending on abstractions at compile-time, which gives us strict contracts to work with, and we are being provided with the implementation at runtime. I hope you’ll find my experience useful for your projects.

Onion Architecture is comprised of multiple concentric layers interfacing with each other towards the core that represents the domain. It is based on the inversion of control principle. The architecture does not focus on underlying technology or frameworks but the actual domain models. Now create a .NET Core class library project inside the infrastructure folder. Computer Engineer Jeffrey Palermo created Onion Architecture for creating app which are highly maintainable and loosely coupled. This architecture somewhat resembles the layers which can be seen on cutting an onion vegetable.

What is onion architecture

Like with many online examples, your example is missing real life examples. It would been even better when you implement validation rules, authentication/authorization, etc. Fun Fact – Microsoft themselves recommend this kind of architecture for complex solutions. Few of the solutions developed and maintained by Microsoft MVPs like eShopOnWeb and eShopOnContainers also follow a similar .

Onion architecture

Bounded context — each microservice is built around some business function and uses bounded context as a design pattern. In fact, while there are numerous definitions of microservices, there is no single clear and unified definition. Broadly speaking, microservices are web services that create a type of service-oriented architecture. Dependency Injection is a necessary evil with this architecture. It causes us to rely heavily on something quite external that binds the entire application together and allows it to function at run-time.

What is onion architecture

The Entities Domain layer is a core and central part of the architecture. So first, we create “OA.Data” project to implement this layer. This project holds POCO class and fluent API configuration for this POCO classes.

Hence, when you separate these requests, you can use different technologies for handler implementation . The practice has shown that 90 percent of requests concern get operations; as a rule, they are small and quick. 10 percent of requests concern put operations; these operations are usually complicated due to a range of transactions and validations. The main issues we faced were related to maintaining the low connectivity of microservices.

Domain Model

The architecture is intended to address the challenges faced with traditional architectures and the common problems likecouplingandseparation of concerns. The two types of requests can/do share a common model and data store. This is an application level pattern to clarify intent. All these architectures are basically saying you should split up your code into separate areas of concern, and all the normal rules about dependencies and coupling always apply, redardless.

What is onion architecture

This eBook will be built in public, meaning I will be sharing my eBook writing journey on a daily basis via my Twitter Handle! To do this, right-click the WebApi Project and go to properties. In the Build Tab enable the XML Documentation file and give an appropriate file name and location. I have added the XML file to the root of the API Project. Similarly, create another .NET Standard Library Project in the Core Folder.

What are Some Problems with Onion Architecture?

We have now set our expectations for anyone wishing to charge a user for a transaction within our Application Services layer. However, we are not doing anything useful at the moment with the transaction so from this and following the layers of Onion Architecture we need to define our Domain Services layer. The key difference is that the Data Access, the presentation and the cross-cutting layer along with anything I/O related is at the top of the diagram and not at the bottom.

Inside the v1 Folder, add a new empty API Controller named ProductController. Since this is a very basic controller that calls the mediator object, I will not go in deep. However, I have previously written a detailed article on CQRS implementation in ASP.NET Core 3.1 API. You could go through that article which covers the same scenario.

I’m sorry, this light is really bad on the video. We could create an initialization script, connect to the Docker container while it is running the database server, and execute the script. But this is a lot of manual work, and it is error-prone. Docker Compose to group our Web https://globalcloudteam.com/ application container with a container running the PostgreSQL database image. That way, we won’t need to have PostgreSQL installed on our system. The purpose of the Presentation layer is to represent the entry point to our system so that consumers can interact with the data.

ASP.NET Core Hero Boilerplate – Quick Start Guide

They usually prefer the fast implementation approach over the long lasting and you often have to do a lot of effort to convince them. This also comes in line onion architecture with the preferences expressed by Martin Fowler. Service Interface Layer– common operations like Add, Save, Delete should go in here within interfaces.

The diagram to the left depicts the Onion Architecture. To pass the data from UI to a controller to edit a user, use same view model named UserViewModel. The UserController has an action method named EditUser, which returns the view to edit a user. We can notice that Controller takes both IUserService and IUserProfileService as a constructor parameters.

Data held by the domain objects has to be translated from layer to layer. All business logic and behavior should be encoded on the domain layer. Domain Layer– At the very core is the Domain layer which holds all of your domain objects. Please restrict yourself by keeping just the properties or definitions inside your domain objects and not any piece of code which talks to database or has any other business functions.

  • Business Logic is probably the most important part of this entire setup.
  • Few of the solutions developed and maintained by Microsoft MVPs like eShopOnWeb and eShopOnContainers also follow a similar .
  • It is clear that coupling is necessary in order for an application to be able to do anything meaningful but this architecture pattern creates unnecessary coupling.
  • In a microservice architecture, modularisation may or may not make sense depending upon the complexity and use-case.
  • As the concept of dependency injection is central to the ASP.NET Core application, we register context, repository, and service to the dependency injection during the application start up.
  • We could create an initialization script, connect to the Docker container while it is running the database server, and execute the script.
  • The OA.Data project holds three entities, one is the BaseEntity class that has common properties that will be inherited by each entity.

As with all software problems, we need to evaluate whether or not we need this additional abstraction as it is more suited for larger applications with many engineers working on them. As engineers we need to apply critical thinking to determine whether or not it will overall benefit the task at hand. Furthermore, the added complexity of defining contracts / interfaces and religiously enforcing them requires a strong understanding of the pattern. If executed well, the benefits will supercharge productivity and greatly increase the flexibility of the applications being developed. This architecture is unashamedly biased toward object-oriented programming, and it puts objects before all others.


Transitive dependencies are still dependencies. No matter how anyone else tries to formulate it. The UI cannot function if the business logic is not available.

Healthchecks in ASP.NET Core – Detailed Guide

The code snippet, mentioned below is for the UserProfile entity. Now, we create an User entity, which is inherited from BaseEntity class. The code snippet, mentioned below is for the User entity. The internal layers never depend on the external layer. The code that may have changed should be part of an external layer.

To implement the Onion architecture, we develop an ASP.NET Core application. This application performs CRUD operations on entities. The application holds four projects as per figure 2. Each project represents a layer in onion architecture. It could be the web application, Web API, or Unit Test project.

Frameworks, Clients and Drivers

Layers do not necessarily need to be in different projects, especially in small applications. The answer is, as always, “it depends”, but I would argue the extra abstraction layer is definitely worth the effort for projects of sufficient size and scope. Adding a layer of abstraction for ORM or cloud provider are the best example of faux abstraction, the one that add no good but unnecessarily complicates the codebase. There are special cases when you need but again in most cases it makes no sense. Database migration should be handled by your CI/CD pipeline.


Lazy class to ensure the lazy initialization of our services. This means that our service instances are only going to be created when we access them for the first time, and not before that. The Domain layer does not have any direct dependencies on the outside layers.

I will stay in the enterprise system space and all discussion will reside in that context. This gets even more interesting when there are multiple processes making up a single software system. The UserController has an action method named DeleteUser, which returns view to delete a user. The GET request for the EditUser action method returns _EditUser partial view, where code snippet follows under the User folder of views. The GET request for the AddUser action method returns _AddUser partial view; the code snippet follows under the User folder of views. We developed entity and context which are required to create a database but we will come back to this after creating the two more projects.

Join The Discussion

Compare listings