CQRS with MediatR

Implementing Mediator pattern using ASP.NET Core 5.0

Lakshitha Fernando
4 min readMay 30, 2021
https://elements-video-cover-images-0.imgix.net/

In my previous article, we have discussed the usability of CQRS pattern, pros and cons as well as its implementation using ASP.NET Core 5.0.

In case if you haven’t read it yet.

If you had noticed, the main issue was using CQRS was the constructor overloading. The more the controller gets complexed more the constructor gets cluttered with command and query handlers hence,difficult to maintain.

Constructor overloading
Constructor overloading

As a solution for this MediatR pattern is introduced and there will be a single entry point and MediatR is responsible for resolving the respective command and query handlers.

MediatR

MediatR is a library developed by Jimmy Bogard and that can be used to implement mediator pattern.

Mediator pattern

Is a behavioral pattern which defines an object that encapsulates how a set of objects interact.

Pros

  • Decoupled components — A class depends only on the mediator. It removes the dependency between different components/classes so the communication among classes are encapsulated within mediator.
  • Separation of concern — As the mediator implements an abstract level of implementation for command and queries, each handler has its own level of execution context.

Cons

  • Complexity — Due to the heaviness of the mediator implementation, this could easily make complex for anyone without having a proper understanding.
Mediator Request Flow

For the sake of simplicity of the entity creation, schema changes and project initialization will not be discussed here which is the same as the previous post. Let’s focus only on the MediatR implementation.

First, we will install NuGet packages for MediatR via package manager console or NuGet package manager.

Install-Package MediatR Install-Package MediatR.Extensions.Microsoft.DependencyInjection

Then register the MediatR service in Startup.cs

Register MediatR service
Register MediatR service

Next, inject the IMediatR interface to the Customer controller.

Controllers>CustomerController.cs

Inject IMediatR Interface
Inject IMediatR Interface

Let’s modify SaveCustomerRequestModel to implement IRequest interface.
RequestModels>CommandRequests>SaveCustomerRequestModel.cs

SaveCustomerRequestModel.cs

Note that all the request models should implement IRequest<T> where the T should be the type of the response model.

In MediatR void does not consider as a valid return type for C#. Instead using void it has the type of Unit.

In our implementation, Response model was left empty so that the request will be marked as void.

Now let’s see how we implement the SaveCustomerRequestModel in the SaveCustomerCommandHandler.

Handlers>CommandHandlers>SaveCustomerCommandHandler.cs

SaveCustomerCommandHandler.cs

Important to note

  • Command handler was implemented with IRequestHandler.
  • IRequestHandler has the parameters as <TRequest,TResponse>
  • TRequest — SaveCustomerRequestModel
  • TResponse — Unit (void)
  • Every Handler implementation must have a return type.
  • Separate handler interface is not required as IReqeustHandler provides its own implementation.

Controllers>CustomerController.cs

CustomerController.cs

Note that the constructor of the Customer Controller is injected only IMeadiatR and that can be used with multiple request handlers without having to overload it.

The beauty of the MediatR is, when the Send method is called, based on the type of the request, it resolves and redirect the request to the appropriate handler.

So when the above save-customer is invoked using postman.

save-customer
save-customer

Finally, we will see how to implement get-all endpoint using MediatR.

As we discussed earlier, every command/query must have a request model. But first, let’s implement our response model and this is exactly same as the previous post.

ResponseModels>QueryResponses>AllCustomerQueryResponseModel.cs

AllCustomerQueryResponseModel.cs

Then the AllCustomerQueryRequestModel

RequestModels>QueryRequests>AllCustomerQueryRequestModel.cs

AllCustomerQueryRequestModel.cs

Note that List<AllCustomerQueryResponseModel> has been set as the type of the response.

Next the implementing query handler.

Handlers>QueryHandlers>AllCustomerQueryHandler.cs

AllCustomerQueryHandler.cs

Note that how the request model and response type have been set as the parameters for IRequestHandler.

As the last step we will modify our get-all endpoint in the Customer controller.

get-all

Note that no changes is made to the constructor and the query request model is passed as a parameter.

So when the above method is executed

get-all Postman

For the implementation of customer-id end point download the source code along with all the project changes.

If you enjoyed the post leave a clap or a comment.
Happy Coding!!!!

Source code : https://github.com/lakshithacodes/CQRSwithMediatR

Reference

--

--

Lakshitha Fernando
Lakshitha Fernando

Written by Lakshitha Fernando

Technical Lead at Camms. A graduate of University of Colombo School of Computing Sri Lanka. Microsoft certified programmer | Traveller | Hiker and Bookworm