Implementing Mediator Pattern in .NET Core using MediatR

Mediator pattern is the event-driven pattern, where handlers are registered for specific event and when the event is triggered, event handlers are invoked and the underlying logic is executed. It is highly used with the Microservices architecture which is one of the most demanding architecture for large-scale enterprise applications these days. In this blog post, I will show the usage of mediator pattern and how we implement using the MediatR library in .NET Core.

What is Mediator Pattern

As per the definition mediator pattern defines an object that encapsulates the logic of how objects interact with each other. Generally, in business applications we have form  that contains some fields. For each action we call a controller to invoke the backend manager to execute particular logic. If any change is required in the underlying logic, same method needed to be modified. With mediator pattern, we can break this coupling and encapsulate the interaction between the objects by defining one or multiple handlers for each request in the system.

How to use MediatR in .NET Core

MediatR is the simple mediator pattern implementation library in .NET that provides support for request/response, commands, queries, notifications and so on.

To use MediatR we will simply add two packages namely MediatR and MediatR.Extensions.Microsoft.DependencyInjection into your ASP.NET Core project. Once these packages are added, we will simply add MediatR in our ConfigureServices method in Startup class as shown below

public void ConfigureServices(IServiceCollection services)
        {
            services.AddMediatR();
            services.AddMvc();
        }

MediatR provides two types of messages; one is of type Notification that just publishes the message executed by one or multiple handlers and the other one is the Request/Response that is only executed by one handler that returns the response of the type defined in the event.

Let’s create a notification event first that will execute multiple handlers when the event is invoked. Here is the simple LoggerNotification event that implements the INotification interface of MediatR library

public class LoggerEvent : INotification
    {
        public string _message;

        public LoggerEvent(string message)

        {
            _message = message;
        }
    }

And here are the three notification handlers used to log information into the database, filesystem and email.

Here is the sample implementation of DBNotificationHandler that implements the INotificationHandler of MediatR

public class DBNotificationHandler : INotificationHandler

    {
        public Task Handle(LoggerEvent notification, CancellationToken cancellationToken)

        {
            string message = notification._message;

            LogtoDB(message);

     return Task.FromResult(0);

        }

        private void LogtoDB(string message) => throw new NotImplementedException();

    }

Same goes with EmailNotificationHandler for email and FileNotificationHandler to log for file as shown below.

public class EmailNotificationHandler : INotificationHandler

    {

        public Task Handle(LoggerEvent notification, CancellationToken cancellationToken)
        {
            //send message in email

            string message = notification._message;

            SendEmail(message);

            return Task.FromResult(0);

        }
        private void SendEmail(string message) => throw new NotImplementedException();

    }


public class FileNotificationHandler : INotificationHandler

    {

        public Task Handle(LoggerEvent notification, CancellationToken cancellationToken)

        {

            string message = notification._message;

            WriteToFile(message);

            return Task.FromResult(0);

        }

        private void WriteToFile(string message) => throw new NotImplementedException();

    }


Finally, we can use MediatR in our MVC Controller and call publish as shown below. It will invoke all the handlers attached to the LoggerEvent and execute the underlying logic.

[Produces("application/json")]

    [Route("api/Person")]

    public class PersonController : Controller
    {
        private readonly IMediator _mediator;
        public PersonController(IMediator mediator)
        {
            this._mediator = mediator;
        }
        [HttpPost]
        public void SavePerson(Person person)
        {
            _mediator.Publish(new LoggerEvent($"Person Id={person.PersonId}, Name ={person.FirstName + person.LastName}, Email={person.Email}"));
        }
    }

In the next post, I will show a simple example of sending a Request/Response message using MediatR.

Hope this helps!