CQRS Using MediatR In .NET 6.0

In this blog, we are going to discuss on MediatR library and its implementation. The MediatR library was built to facilitate the below two primary software architecture patterns.

  • CQRS – Command Query Responsibility Segregation.
  • Mediator Pattern.

In this article, we will be checking the implementation of CQRS Pattern using MediatR.

The source code can be downloaded from here

Command Query Responsibility Segregation

CQRS stands for Command Query Responsibility Segregation. Its main intention is to split the responsibilities of Commands(saves) and Queries(reads) into different models. 

If we consider the commonly used CRUD pattern (Create, Read, Update and Delete), usually, we will have a single interface with all these four operations. But CQRS, would split these operations into two models – one for queries (Read) and another one for commands (Create, Update and Delete)

In nutshell,

  1. It will accept incoming request.
  2. Handle that request and give back a response.

Let us now deep dive into a simple Web API with MediatR.

For this demo, I have used the below tools

  1. VS 2022 Community Edition Preview Version 17.4.0
  2. .NET 6.0
  3. Swagger/Postman
  4. MediatR Library

To begin with, create a ASP.NET Core Web API

Create a sample MediatRDemo API project and add a class library as below

CQRS using MediatR in .NET 6.0

Will create a model Student now

public class StudentModel
{
    public int Id { get; set; }
    public string Name { get; set; }
    public string School { get; set; }
}

Now, we will create a Data Repository interface

public interface IDataRepository
{
    List<StudentModel> GetStudents();
    StudentModel AddStudent(StudentModel student);
}

Let us go ahead and create the Data Repository Implementation class

namespace MediatorDemo.Library.Data
{
    public class DataRepository : IDataRepository
    {
        private static List<StudentModel> _students = new()
        {
            new StudentModel { Id=3456, Name="Prasad Raveendran", School="Mount Fort"},
            new StudentModel { Id=6543, Name="Prabha Raveendran", School="St. Pious"}
        };
        public StudentModel AddStudent(StudentModel student)
        {
            _students.Add(student);
            return student;
        }
        public List<StudentModel> GetStudents()
        {
            return _students;
        }
    }
}

So far so good. Now is the time to implement MediatR library.

Let us go ahead and install the package MediatR.

Install MediatR

CQRS using MediatR in .NET 6.0

Once the installation is complete, we will create the below folders in the MediatorDemo.Library Class Library

  • Queries
  • Handlers

Now, we will add GetStudentsListQuery class under the “Queries” folder as below. This will be the request

namespace MediatorDemo.Library.Queries
{
    public record GetStudentsListQuery():IRequest<List<StudentModel>>;  
}

Create the handler GetStudentsListHandler class under the folder “Handlers” as below. This will be the handler which will process the request and the send the response back.

namespace MediatorDemo.Library.Handlers
{
    public class GetStudentsListHandler : IRequestHandler<GetStudentsListQuery, List<StudentModel>>
    {
        public Task<List<StudentModel>> Handle(GetStudentsListQuery request, CancellationToken cancellationToken)
        {
            throw new NotImplementedException();
        }
    }
}

Now, let us bring the IDataRepository into GetStudentsListHandler as below

namespace MediatorDemo.Library.Handlers
{
    public class GetStudentsListHandler : IRequestHandler<GetStudentsListQuery, List<StudentModel>>
    {
        private readonly IDataRepository _repository;
        public GetStudentsListHandler(IDataRepository repository)
        {
            this._repository = repository;
        }
        public Task<List<StudentModel>> Handle(GetStudentsListQuery request, CancellationToken cancellationToken)
        {
            return Task.FromResult(this._repository.GetStudents());
        }
    }
}

Time to register the interfaces into container via dependency injection.

We need to install the MediatR dependency in the API project.

Install MediatR.Extensions.Microsoft.DependencyInjection

The below changes need to be added into Program.cs

builder.Services.AddScoped<IDataRepository, DataRepository>();
builder.Services.AddMediatR(typeof(DataRepository).Assembly);

Now introduce new controller StudentController.cs as below

namespace MediatorDemo.Controllers
{
    [Route("api/[Controller]")]
    [ApiController]
    public class StudentController : ControllerBase
    {
        IMediator _mediator;
        public StudentController(IMediator mediator)
        {
            _mediator = mediator;
        }
        [HttpGet]
        public async Task<List<StudentModel>> Get()
        {
            return await _mediator.Send(new GetStudentsListQuery());
        }
    }
}

Here we are injecting the IMediator interface and invoking the “Send” method to send the request as Query.

The overall project structure looks like below

CQRS using MediatR in .NET 6.0

The entire source code can be downloaded from here

Execute the API and see whether we are getting the response

Execute the endpoint api/sudent in postman

CQRS using MediatR in .NET 6.0

We have got the response.  Fantastic! The MediatR is working as expected. We have just implemented the “Query” in CRQS. In my upcoming tutorial, I will be explaining the implementation of “Command”.

Thank you for reading my article. Please leave your comments in the comment box below.

Next Recommended Reading API Gateway In .NET 6.0 Using Ocelot