How to use MediatR Notifications

Feb 10 2025

 
 

Many thanks to the sponsors who make it possible for this newsletter to be free for readers.

 

• Level up your projects with FREE Clean Architecture template created by Milan Jovanovic, trusted by over 10,000 developers. Packed with features like CQRS, JWT authentication, Domain Events, and Docker support, it’s everything you need to start strong. Download Now

 
 

Background

 
 

 

It is often used in CQRS (Command Query Responsibility Segregation) architectures but is not limited to such applications. Essentially, you create simple C# classes for your commands and queries, and then create handler classes that handle those commands and queries. You can then use MediatR to dispatch these requests to their respective handlers.

 

MediatR also brings implementations of other patterns.
With MediatR, it is possible to implement a notification system.

 

Let's see how to implement MediatR Notifications feature in ASP.NET Core using C#.

 
 

Scenario

 
 

A practical real-world scenario for using MediatR notifications in .NET 9 is a User Registration System, where multiple services need to react to a new user registration event without tightly coupling them.

 

You are building a user management system where:

 

When a new user registers, the system needs to:
1. Send a welcome email.
2. Log the new registration for auditing.
3. Notify an analytics service.

 
 

Step-by-Step Implementation in .NET 9

 
 

1. Define the Notification Event

 

When a user registers, we trigger an event using INotification:

using MediatR;

public class UserRegisteredNotification : INotification
{
    public string UserId { get; }
    public string Email { get; }

    public UserRegisteredNotification(string userId, string email)
    {
        UserId = userId;
        Email = email;
    }
}
2. Create Handlers for Different Actions

 

Each service subscribes to this event independently.

 

Handler 1: Sending Welcome Email

public class SendWelcomeEmailHandler : INotificationHandler<UserRegisteredNotification>
{
    private readonly ILogger<SendWelcomeEmailHandler> _logger;

    public SendWelcomeEmailHandler(ILogger<SendWelcomeEmailHandler> logger)
    {
        _logger = logger;
    }

    public Task Handle(UserRegisteredNotification notification, CancellationToken cancellationToken)
    {
        _logger.LogInformation($"Sending welcome email to {notification.Email}");
        // Simulate sending email logic
        return Task.CompletedTask;
    }
}

 

Handler 2: Logging the Event

public class LogUserRegistrationHandler : INotificationHandler<UserRegisteredNotification>
{
    private readonly ILogger<LogUserRegistrationHandler> _logger;

    public LogUserRegistrationHandler(ILogger<LogUserRegistrationHandler> logger)
    {
        _logger = logger;
    }

    public Task Handle(UserRegisteredNotification notification, CancellationToken cancellationToken)
    {
        _logger.LogInformation($"User registered: {notification.UserId}, Email: {notification.Email}");
        return Task.CompletedTask;
    }
}

 

Handler 3: Notify Analytics Service

public class AnalyticsServiceHandler : INotificationHandler<UserRegisteredNotification>
{
    private readonly ILogger<AnalyticsServiceHandler> _logger;

    public AnalyticsServiceHandler(ILogger<AnalyticsServiceHandler> logger)
    {
        _logger = logger;
    }

    public Task Handle(UserRegisteredNotification notification, CancellationToken cancellationToken)
    {
        _logger.LogInformation($"Analytics: Tracking new user registration for {notification.UserId}");
        return Task.CompletedTask;
    }
}

 

3. Program.cs - Publish the Notification + Configure MediatR

 

When a user registers, we publish the notification:

var builder = WebApplication.CreateBuilder(args);

// Register MediatR
builder.Services.AddMediatR(Assembly.GetExecutingAssembly());

var app = builder.Build();

// Minimal API Endpoint for User Registration
app.MapPost("/register", async (UserRegistrationRequest request, IMediator mediator) =>
{
    var userId = Guid.NewGuid().ToString();

    // Simulating user registration (e.g., saving to database)
    await mediator.Publish(new UserRegisteredNotification(userId, request.Email));

    return Results.Ok(new { Message = "User registered successfully!", UserId = userId });
});

app.Run();

// DTO for user registration
public record UserRegistrationRequest(string Email);

 

Excellent!

 

We have implemented Notification System with MediatR.

 
 

Wrapping up

 
 

Why is MediatR useful here?

 

Decoupled Components → Email, Logging, and Analytics Services are independent.
Scalability → New handlers (e.g., SMS notifications) can be added easily.
Testability → Each handler can be tested in isolation.

 

This approach ensures that each service only cares about its job without affecting others. By using MediatR notifications, you build a flexible, scalable, and maintainable architecture for handling events in .NET applications.
That's all from me today.
P.S. Follow me on YouTube.

There are 3 ways I can help you:

My Design Patterns Ebooks

1. Design Patterns that Deliver

This isn’t just another design patterns book. Dive into real-world examples and practical solutions to real problems in real applications.Check out it here.


1. Design Patterns Simplified

Go-to resource for understanding the core concepts of design patterns without the overwhelming complexity. In this concise and affordable ebook, I've distilled the essence of design patterns into an easy-to-digest format. It is a Beginner level. Check out it here.


Join TheCodeMan.net Newsletter

Every Monday morning, I share 1 actionable tip on C#, .NET & Arcitecture topic, that you can use right away.


Sponsorship

Promote yourself to 15,250+ subscribers by sponsoring this newsletter.



Join 15,250+ subscribers to improve your .NET Knowledge.

Powered by EmailOctopus

Subscribe to
TheCodeMan.net

Subscribe to the TheCodeMan.net and be among the 15,250+ subscribers gaining practical tips and resources to enhance your .NET expertise.

Powered by EmailOctopus