Design ASP.NET Core MVC Application Using Onion Architecture


This article introduces that how to design ASP.NET Core MVC application using Onion Architecture. It is mostly used architecture to develop a web application. The Onion architecture provides a solution for coupling and separation of concerns. It is a layered architecture. Application design has two types of coupling – tight coupling and loose coupling.

Tight Coupling: An object is dependent to another object. If we change in one object then it requires changes to a number of other objects.

Loose Coupling: An object can use another object but both are independent. It reduces inter-dependencies among modules of the application.


Advantages of Onion Architecture

There are a number of advantages of the Onion Architecture, as listed below.

  1. It provides a better maintainability. It is a layered architecture,code depends on the layer.
  2. It is a loosely coupled architecture so one layer doesn’t tightly bound with other layers. We can perform a unit test for each method in the application.
  3. The application UI always interacts with business logic layer via the interface. We create interface instance. A concrete class object assigns to this instance at runtime
  4. Application domain entities are core and center part of the application. These are POCO classes and database tables in the application. This layer is accessed by both service and UI layers.
  5. The external layer depends on internal layers so changes should be in the external layer but the extension should be in the internal layer.

Why Onion Architecture

We develop a web application using the 3- tier and n-tier architecture either. These have two fundamental issues which are a separation of concern and tight coupling.

We develop a modern web application using Model-View-Controller architectural pattern. It is mostly used architectural pattern in the web application. Model(Data/Business Logic), View(UI) and Controller (Data Access/Business Logic) perform separate operations. MVC solves the separation of concern problem. But the controller is still used to database operation logic so it is tightly coupled with data access layer.

The Onion Architecture addresses both the separation of concern and tight coupling problem. It is to keep the business logic and data access logic separately. The model or domain entity is in the center of the application. All coupling are towards to center.


Onion Architecture Design Layers

It is a layered architecture. It relies on Dependency Inversion Principle. ASP.NET Core MVC provides inbuilt Inversion of Control. It has four layers which are:

  1. Domain Entities Layer
  2. Service Layer
  3. Repository Layer
  4. UI Layer

Onion Architecture in ASP.NET Core MVC

Figure 1: Onion Architecture Layers

Layers are towards to center. The external layer depends on internal layer. The Data/Entities always part of the center. Other layers have behavior on entities.

  1. Domain Entities Layer: It is a central part of the application. It holds domain objects. We develop an application with Entity Framework then it holds database entities.
  2. Repository Layer: It is an abstraction between domain entities and business logic layer. It is data access approach. We create a generic repository class. It holds method to performs common operations each entity.
  3. Service Layer: It holds business logic. It is used to communicate between UI and Repository layer. It holds interface with their implementation.
  4. UI Layer: It is the most external layer. It could be Web Application or Web API. It has the implementation of the Dependency Inversion Principle so that application builds a loosely coupled.

Design Application Using Onion Architecture

It has four layers so create four projects. Three projects are the class library type project while one is the web application. Let’s create four projects one by one.

Domain Entities Layer

It is a class library type project named OAA.Data. Application develops using entity framework core so it holds POCO classes. We install two NuGet packages into this project. These are used to implement the Entity Framework Core Code First approach. These are:

  • Microsoft.EntityFrameworkCore
  • Microsoft.EntityFrameworkCore.SqlServer

We create three entities. These are BaseEntity, Author, and Book. The BaseEntity class has common properties which used by other entities that’s why it be inherited by each entity. The Author and Book entities have one to many relationships.

We create first entity named BaseEntity as per following code snippet.

Now, we create a class for Author entity which inherits from the BaseEntity class as per following code snippet.

We define the configuration for Author entity in the AuthorMap class. It is used to create a database. The following code snippet for same.

Now, we create a Book entity as per following code snippet.

We define the configuration for Book entity in the BookMap class. It is used to create a database. The following code snippet for same.

The OAA.Data project also contains DbContext. We create a context class ApplicationContext(ApplicationContext.cs) which inherits DbContext class as per following code snippet.

We defined all entities for the application. There are two operations remaining to order to create a database from entities. These operations are “Database Connectivity using EF” and “Database Initialize using EF Migration”. We can know about these operations with help of another article that is Repository Pattern In ASP.NET Core MVC And Entity Framework Core.

Repository Layer

We create a generic repository interface named IRepository. It uses to develop a loosely coupled application. It holds method signatures for CRUD operation which perform on both entities. The following code snippet for it under OAA.Repo project.

Now, we implement preceding interface on a class named Repository. The Repository class holds the definition of all methods along with a parameterized constructor. The following code snippet is for the Repository class under OAA.Repo project.

This repository is used to perform CRUD operations on both entities.

Service Layer

It is a business logic layer. The project named OAA.Service holds interfaces and classes. These classes have business logic of the application.

We create an interface named IAuthorService. It holds all methods signature which accesses by UI for the Author entity. The following code snippet is for the same.

Now, we implement preceding interface on the AuthorService class. It holds business logic for the Author entity. The following code snippet is for the same.

We create one more interface named IBookService. It holds method signature to perform CRUD operation on the Book entity. The following code snippet is for the same.

Now, we implement preceding interface on the BookService class. It holds business logic for Book entity. The following code snippet is for the same.

It is service layer which is created to develop a loosely coupled application.

UI Layer

It is an external layer which communicates with end users of the application. We create an ASP.NET Core MVC application named OAA.Web for UI.

The concept of dependency injection is central to the ASP.NET Core MVC application. We register repository, context, and service into the dependency injection. Thus, we register these in the ConfigureServices method in the Startup class. The following code snippet is updated of the ConfigureServices method.

Now, we create a controller named AuthorController under the Controllers folder of the application. It has action methods for each user interface to perform the CRUD operations on Author and Book entity accordingly. We create an IAuthorService and IBookService interfaces instance then inject these in the controller’s constructor to get an object of implemented classes. The following is a code snippet for the AuthorController.

Now, let’s develop the user interface to performs the CRUD operations on the Author and Book entities. We create views for adding and editing an author and listing.

Author Listing

We create a view model named AuthorListingViewModel that binds to UI for the author listing. The following code snippet for same.

Now, let’s create an index view. It shows the listing of all authors in the application. The following code snippet is for it under the Author folder of views.

It shows forms in a bootstrap model popup. We create a js file named author-index.js which holds a method. This method removes the content of model when model hides. The following code snippet is for this js file.

Now, let’s run the application. It makes a GET request for index action method and as a response all the authors listed in the UI as in Figure 2.

Onion Architecture

Figure 2: Author Listing

Add Author

Now, we perform the add operation on the author. We create a view model named AuthorBookViewModel. The following code snippet is for same.

Let’s create a partial view named _AddAuthor. It is called by GET request for the AddAuthor action. The following code snippet is under the Author folder of views.

Now, let’s run the application. There is author listing which has ‘Add Author’ button. Clicks on this button and makes a GET request for AddAuthor action method and as a response, the add author form shows in the UI as in Figure 3.

Figure 3: Add Author

Edit Author

We update author details only. So, we create a view model named AuthorViewModel for it. The following code snippet is for same.

Let’s create a partial view named _EditAuthor. It is called by GET request for the EditAuthor action. The following code snippet is under the Author folder of views.

Author listing has edit button against each author. Clicks on the Edit button, it makes a GET request for the EditAuthor() action method, then the edit author screen is shown in Figure 4.

Onion Architecture Edit

Figure 4: Edit Author

Add Book

Now, we perform the add operation on a book. Author listing has an option to add a book against each author. We create a view model named BookViewModel as per following code snippet.

Let’s create a partial view named _AddBook. It is called by GET request for the AddBook action. The following code snippet is under the Author folder of views.

Author listing has Book button against each author. Clicks on the Book button, it makes a GET request for the AddBook() action method, then the add book screen shows as in Figure 5.

Onion Architecture MVC

Figure 5: Add Book


Conclusion

This article demonstrated a practical approach that how to design ASP.NET Core MVC Application with Entity Framework Core using Onion Architecture. The complete source code is available at GitHub, click here to download.