.NET  

How to Use MediatR in .NET for Clean Architecture Implementation

Introduction

In modern .NET development, building scalable, maintainable, and clean applications is a top priority. One of the most popular ways to achieve this is by following Clean Architecture principles. But as your application grows, managing communication between different layers can become messy.

This is where MediatR in .NET comes into play.

MediatR helps you implement the Mediator Design Pattern, which allows different parts of your application to communicate without directly depending on each other. This results in cleaner code, better separation of concerns, and easier testing.

In this article, we will understand how to use MediatR in .NET for clean architecture implementation in simple words, step by step, with practical examples.

What is MediatR in .NET?

MediatR is a lightweight library that helps you implement the Mediator pattern in .NET applications.

Simple Explanation

Instead of one class directly calling another class, MediatR acts like a middleman (mediator).

  • You send a request

  • MediatR forwards it to the correct handler

  • The handler processes it and returns a response

This removes tight coupling between components.

Why MediatR is Important for Clean Architecture

In Clean Architecture:

  • Each layer should be independent

  • Business logic should not depend on infrastructure

MediatR helps achieve this by:

  • Decoupling controllers from business logic

  • Moving logic into handlers

  • Making code more modular and testable

What is Clean Architecture in .NET?

Clean Architecture is a design approach where your application is divided into layers, each with a clear responsibility.

Common Layers

  • Presentation Layer → Controllers (API/UI)

  • Application Layer → Business logic (MediatR handlers)

  • Domain Layer → Core entities and rules

  • Infrastructure Layer → Database, external services

Key Idea

Dependencies should always point inward, not outward.

This keeps your core logic safe and independent.

Installing MediatR in .NET Project

To use MediatR, you first need to install it.

Using NuGet Package Manager

dotnet add package MediatR
dotnet add package MediatR.Extensions.Microsoft.DependencyInjection

Register MediatR in Program.cs

builder.Services.AddMediatR(typeof(Program));

Explanation

This tells .NET to scan your project and register all MediatR handlers automatically.

Core Concepts of MediatR

To understand how MediatR works, you need to know three main components.

1. Request (Command or Query)

A request represents an action.

  • Command → Changes data

  • Query → Reads data

public record GetUserQuery(int Id) : IRequest<string>;

2. Handler

A handler processes the request.

public class GetUserHandler : IRequestHandler<GetUserQuery, string>
{
    public Task<string> Handle(GetUserQuery request, CancellationToken cancellationToken)
    {
        return Task.FromResult($"User Id: {request.Id}");
    }
}

3. Mediator (IMediator)

This is the main interface used to send requests.

private readonly IMediator _mediator;

public UserController(IMediator mediator)
{
    _mediator = mediator;
}

How MediatR Works Step-by-Step

  1. A request is created

  2. The request is sent using IMediator

  3. MediatR finds the correct handler

  4. The handler executes logic

  5. Response is returned

This flow keeps everything clean and organized.

Using MediatR in Clean Architecture

Let’s understand with a real-world example.

Step 1: Create Query

public record GetProductQuery(int Id) : IRequest<string>;

Step 2: Create Handler

public class GetProductHandler : IRequestHandler<GetProductQuery, string>
{
    public Task<string> Handle(GetProductQuery request, CancellationToken cancellationToken)
    {
        return Task.FromResult($"Product Id: {request.Id}");
    }
}

Step 3: Use in Controller

[ApiController]
[Route("api/products")]
public class ProductController : ControllerBase
{
    private readonly IMediator _mediator;

    public ProductController(IMediator mediator)
    {
        _mediator = mediator;
    }

    [HttpGet("{id}")]
    public async Task<IActionResult> Get(int id)
    {
        var result = await _mediator.Send(new GetProductQuery(id));
        return Ok(result);
    }
}

Explanation

The controller does not know anything about business logic. It simply sends a request using MediatR.

This makes your API clean and easy to manage.

Benefits of Using MediatR in .NET

1. Loose Coupling

Components do not depend on each other directly.

2. Clean Code Structure

Each feature is separated into its own request and handler.

3. Easy Testing

You can test handlers independently without controllers.

4. Better Maintainability

Code becomes easier to update and scale.

5. Supports CQRS Pattern

You can easily separate read and write operations.

MediatR with CQRS (Command Query Responsibility Segregation)

MediatR works perfectly with CQRS.

Command Example

public record CreateOrderCommand(string ProductName) : IRequest<bool>;

Query Example

public record GetOrderQuery(int Id) : IRequest<string>;

Why This Matters

  • Better performance

  • Clear separation of logic

  • Scalable architecture

Best Practices for Using MediatR in .NET

  • Keep handlers small and focused

  • Use one handler per request

  • Avoid putting too much logic in controllers

  • Organize code by feature (feature folders)

  • Use pipeline behaviors for logging and validation

Common Mistakes to Avoid

  • Overusing MediatR for simple logic

  • Creating very large handlers

  • Mixing business logic in controllers

  • Not following proper folder structure

When to Use MediatR

Use MediatR when:

  • You are building enterprise applications

  • You want clean architecture in .NET

  • Your project is growing and becoming complex

Avoid it in very small projects where it may add unnecessary complexity.

Summary

Using MediatR in .NET for clean architecture implementation helps you build applications that are clean, scalable, and easy to maintain. It acts as a mediator between different layers, reducing dependencies and improving code structure. By using requests and handlers, you can separate business logic from controllers, making your application more organized and testable. When combined with Clean Architecture and CQRS, MediatR becomes a powerful tool for modern .NET development.