Mediator Design Pattern with .NET CORE

Design patterns are documented and tested solutions for recurring problems. They are used to solve the problems of objection creation and integration. Developers encounters these problems on a day to day basis. So, it is a best practice to use design patterns as they are reusable solutions.

It is important to remember that you do not need to over-do design patterns. Design patterns are for projects, projects are not for design patterns. So, use it in the project if you think it is a good fit. Otherwise, It can make your project messy.

Types of Design Patterns

Gang of Four categorised design patterns into three main categories

1. Creational Design Pattern
2. Structural Design Pattern
3. Behavioural Design Pattern

In this blog, we will discuss Mediator design pattern. It is a behavioral design pattern that promotes loose coupling.

Mediator Design Pattern

It is used to reduce communication between objects. This pattern provides a mediator object and that object handles all the communication between objects. 

In the following diagram, you can see there are 3 objects(X, Y, and Z). Suppose, object X has to send data to Y and then Y has to send a message to Z. These objects need to know each other. They are tightly coupled. In the real world, there are hundreds and thousands of objects that have to call each other. It makes the on-going management of code an up-hill task.

How Mediator Pattern solves the problem?

If object X has to call object Y and Z. It doesn’t have to call directly. It will call the mediator object and it is the responsibility of the mediator object to pass the message to the destination object. The mediator helps you promote loose coupling by keeping objects from referring and interacting with each other.

Implementation of Mediator Pattern

You can install by Nuget Package Manager

Install-Package MediatR

or via .Net core CLI

dotnet add package MediatR

dotnet add package MediatR.Extensions.Microsoft.DependencyInjection

I have installed MediatR and MediatR.Extensions.Microsoft.DependencyInjection in my demo project.

mediator installation
Register MediatR with assembly

Next thing is that you have to inject the mediatR in controller.

The mediator call consists of a request and a handler. Every request has its handler. The request could be anything from a complex object to an integer value.

In the following image, you can see we are making a request to the mediator which takes CreateUserCommand as a model.

Mediator request call

Request

Requests are of two types.

1. IRequest<TRequest> – returns TRequest
2. IRequest – returns nothing

A request is a class that has a handler attached to it. You can see in the image below, I have implemented IRequest<TRequest>. CreateUserCommand request takes AppUser as a return value.

Handler

Request Handler (Responses) are of two types.

1. IRequestHandler<TRequest, TResponse> – returns TResponse
2. IRequestHandler<TRequest> – returns nothing

You can see in the image below, I have implemented IRequestHandler<TRequest, TResponse>. This handler implements the request of CreateUserCommand and returns AppUser.

Mediator handler request

Conclusion

The mediator design pattern helps us reduce coupling and promote SOLID principles. You should use it if you think it can be a good fit for your project. I have explained in this blog about the design pattern and its implementation. As a reference, you can find the complete source code in my demo app.

CQRS pattern with ASP.NET CORE

CQRS is a command and query responsibility pattern that separates read and write operations into different models. Commands (Insert/update) operations will have a separate model. Queries (read) operations will have a separate model.  By separating them, it allows models to be more focused on the tasks that they are performing. 

Traditionally, commands will have a large model as it would map the model to the whole database table with some business logic validating the model before saving it the database. Whereas, on the other hand, queries will have a simple model, returning a dataset according to UI requirements. 

Traditional vs CQRS

In traditional applications, we use the same data model for read and write operations. It is good for simple CRUD applications but if you have a large complex application which has a large model. It get’s really difficult to manage it as every other change can cause issues in testing with additional bloated code. 

When we use CQRS, we can either have one database or we have can have two databases, one for commands and others for queries. If we create two databases then we have to keep them in sync. This is the additional work you have to do.

How to implement it?

You will see two folders, one for command and another for the query. Query folder has one model class and one handler. I am using a mediator pattern here, which I will explain in my other blog post.

Query:

In the following image, you can see the handler class receives the query model and makes a query to the database to get all users from the database.

Command:

In the following image, you can see the handler class receives the command model and makes a write operation to save the user in the database.

Conclusion:

There are pros and cons to everything. Some of you may feel that implementing CQRS may add additional complexity to the project. In my opinion, It comes down to the use case of the project and how you use this pattern. I have also made a working demo app on GitHub with the CQRS pattern.