🔥 Pragmatic .NET Code Rules Course is on Presale - 40% off!BUY NOW

MediatR Pipeline Behavior

Sponsored

• If you have ever used Postman to debug and write tests for your REST APIs, guess what, those are the same concepts you need to know for writing tests for your gRPC requests in Postman For more info about gRPC, they created a great beginner article here .

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

Watch YouTube video here

Watch YouTube video

The Background

MediatR is a popular library in .NET used for implementing the Mediator pattern. It helps in reducing coupling between components and makes it easier to manage code by sending requests to the appropriate handlers. A Pipeline Behavior in MediatR is a concept that allows developers to implement cross-cutting concerns (like logging, validation, etc.) for MediatR requests. How to implement it? Let's take a look deeply!

Define a Pipeline Behavior Interface

This interface represents a pipeline behavior that will be applied to every request and its corresponding response. MediatR provides an interface called IPipelineBehavior<TRequest, TResponse> that you can implement.

C#
public interface IPipelineBehavior<TRequest, TResponse>{    Task<TResponse> Handle(TRequest request, CancellationToken cancellationToken, RequestHandlerDelegate<TResponse> next);}

Implement the Pipeline Behavior

You create a class that implements the IPipelineBehavior<TRequest, TResponse> interface . This class will contain the logic that you want to apply to requests. For example, a simple logging behavior:

C#
public class LoggingBehavior<TRequest, TResponse> : IPipelineBehavior<TRequest, TResponse>{    private readonly ILogger<LoggingBehavior<TRequest, TResponse>> _logger;     public LoggingBehavior(ILogger<LoggingBehavior<TRequest, TResponse>> logger)    {        _logger = logger;    }     public async Task<TResponse> Handle(TRequest request, CancellationToken cancellationToken, RequestHandlerDelegate<TResponse> next)    {        // Pre-processing        _logger.LogInformation($"Handling {typeof(TRequest).Name}");         var response = await next();         // Post-processing        _logger.LogInformation($"Handled {typeof(TResponse).Name}");         return response;    }}

The LoggingBehavior<TRequest, TResponse> in a MediatR pipeline will automatically log information both before and after each request is processed. When a request is made, it logs the type of request being handled, then passes control to the next handler in the pipeline. After the request is handled, it logs the type of response generated, providing an audit trail of the requests and responses within the application.

Register the Pipeline Behavior

In the startup configuration of your application, register your pipeline behavior so that MediatR knows to apply it to requests.

C#
services.AddTransient(typeof(IPipelineBehavior<, ), typeof(LoggingBehavior<, )));

With this setup, every time a MediatR request is made, it will go through this LoggingBehavior (or any other behavior you define) before reaching the actual request handler. This allows you to add additional processing like logging, validation, or even exception handling in a clean, reusable way.

How and when is it used?

Let's say we have a basic MediatR request defined:

C#
public class MyRequest : IRequest<MyResponse>{    // Request properties} public class MyRequestHandler : IRequestHandler<MyRequest, MyResponse>{    public async Task<MyResponse> Handle(MyRequest request, CancellationToken cancellationToken)    {        // Handle the request        return new MyResponse();    }}

When you call _mediator.Send(new MyRequest()) , MediatR will process this request through the pipeline behavior (e.g., LoggingBehavior) before it reaches MyRequestHandler. This allows you to add common logic, like logging, validation, or error handling, in a centralized way without cluttering the business logic in the handlers.

Wrapping up

The LoggingBehavior<TRequest, TResponse> in MediatR for .NET enhances application monitoring and debugging by consistently logging all request and response types. This approach promotes cleaner code through separation of concerns, adheres to best practices like the Single Responsibility Principle, and offers ease of integration and reusability across the application.

If you want to implement CQRS with or without MediatR, check out How to implement CQRS without MediatR. For a fully custom pipeline without any external dependencies, see Build Your Own MediatR: A Lightweight Handler Pipeline.

Frequently Asked Questions

What is MediatR Pipeline Behavior?

MediatR Pipeline Behavior is a feature that lets you add cross-cutting concerns (logging, validation, caching, error handling) to your request pipeline without modifying individual handlers. You implement IPipelineBehavior<TRequest, TResponse> and register it in DI. Every request that passes through MediatR will execute your behavior before and after the handler.

How do I register a Pipeline Behavior in .NET?

Register your pipeline behavior as an open generic in your DI container: services.AddTransient(typeof(IPipelineBehavior<,>), typeof(LoggingBehavior<,>)). MediatR will automatically discover and execute it for every request/response pair. You can register multiple behaviors — they execute in the order they are registered.

Can I have multiple Pipeline Behaviors?

Yes. You can chain multiple behaviors like logging, validation, and caching. Each behavior calls next() to pass execution to the next behavior or the final handler. The execution order matches the registration order in your DI container.

That's all from me today - first day of the year. See ya on the next Monday coffee. P.S. Follow me on YouTube.


Want more design patterns with real-world examples? My ebook Design Patterns that Deliver covers 5 essential patterns (Builder, Decorator, Strategy, Adapter, Mediator) with hands-on C# code you can use right away. Or try a free chapter on the Builder Pattern first.

About the Author

Stefan Djokic is a Microsoft MVP and senior .NET engineer with extensive experience designing enterprise-grade systems and teaching architectural best practices.

There are 3 ways I can help you:

1

Pragmatic .NET Code Rules Course

Stop arguing about code style. In this course you get a production-proven setup with analyzers, CI quality gates, and architecture tests — the exact system I use in real projects. Join here.

Not sure yet? Grab the free Starter Kit — a drop-in setup with the essentials from Module 01.

2

Design Patterns Ebooks

Design Patterns that Deliver — Solve real problems with 5 battle-tested patterns (Builder, Decorator, Strategy, Adapter, Mediator) using practical, real-world examples. Trusted by 650+ developers.

Just getting started? Design Patterns Simplified covers 10 essential patterns in a beginner-friendly, 30-page guide for just $9.95.

3

Join 20,000+ subscribers

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

Join 20,000+ subscribers who mass-improve their .NET skills with actionable tips on C#, Software Architecture & Best Practices.

Subscribe to
TheCodeMan.net

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