When working with MediatR in .NET, we can often utilize its Pipeline Behavior. In this article, we’ll examine a common warning related to the type TRequest that can occur while working with it, see why it appears, and how we can solve it.

To download the source code for this article, you can visit our GitHub repository.

Let’s dive in.

What Is MediatR and Pipeline Behaviour?

MediatR is a popular open-source library in .NET that simplifies the implementation of the Mediator pattern.

Support Code Maze on Patreon to get rid of ads and get the best discounts on our products!
Become a patron at Patreon!

It helps us centralize handling application-level commands, queries, and events and promotes loose coupling between components. Also, we have the benefit of improved code organization, maintainability, and separation of concerns in .NET applications. In addition, we commonly use MediatR to implement the CQRS pattern in ASP.NET Core.

When it comes to MediatR’s Pipeline Behaviors, they were first introduced in the major version 3. They allow us to build a pipeline inside of MediatR. They serve as a great place to add cross-cutting concerns like validation logic or logging before executing the handler.

So let’s now see how to set it up and what warning we will encounter.

Project Setup

We will start by creating a new ASP.NET Core Web API project. We can do it using the ASP.NET Core Web API template in Visual Studio, or using the dotnet new webapi command.

Next, we need to install the MediatR NuGet package into our project. We can achieve this either through the Package Manager Window in Visual Studio or by utilizing the dotnet add package MediatR command.

Now that we have everything ready, we can implement MediatR Pipeline Behaviour to showcase the warning. We’ll create a straightforward example of a Pipeline Behavior that logs request information:

public class LoggingPipelineBehaviour<TRequest, TResponse> : IPipelineBehavior<TRequest, TResponse>
{
    private readonly ILogger<LoggingPipelineBehaviour<TRequest, TResponse>> _logger;

    public LoggingPipelineBehaviour(ILogger<LoggingPipelineBehaviour<TRequest, TResponse>> logger)
    {
        _logger = logger;
    }

    public async Task<TResponse> Handle(
        TRequest request,
        RequestHandlerDelegate<TResponse> next,
        CancellationToken cancellationToken)
    {
        _logger.LogInformation(
            "Handling {RequestType} - {RequestData}",
            typeof(TRequest).Name, request);

        var response = await next();

        _logger.LogInformation(
            "Handled {RequestType} - Response: {ResponseData}",
            typeof(TRequest).Name, response);

        return response;
    }
}

We start by creating a  LoggingPipelineBehaviour class that acts as middleware in the MediatR pipeline. Since it inherits from IPipelineBehavior<TRequest, TResponse> we need to implement its Handle() method.

Inside of the Handle() method we log request and response information, and this method will get executed each time MediatR request is processed.

Cannot Use ‘TRequest’ as a Type Parameter for the Pipeline Behavior Warning

Now, if we take a look at the LoggingPipelineBehaviour class, we can see that we get a warning:

The type 'TRequest' cannot be used as type parameter 'TRequest' in the generic type or method 
'IPipelineBehavior<TRequest, TResponse>'.
Nullability of type argument 'TRequest' doesn't match 'notnull' constraint

This warning started to occur in a major version 10 of the MediatR package. Up until the major version 12 it was treated as an error, and although in the latest version, it is a warning, it is a good practice to know why it occurs and how we can solve it. 

Resolve the TRequest Type Parameter Warning

Depending on the major version we are using, there are two ways to address this issue but both of them consist of adding a constraint on the type parameter TRequest.

The first approach we can take is to implement what MediatR authors suggest in their migration documentation to major version 10:

public class LoggingBehavior<TRequest, TResponse> : IPipelineBehavior<TRequest, TResponse> 
   where TRequest : IRequest<TResponse>

By adding where TRequest : IRequest<TResponse> constraint we ensure that only requests of types that implement the IRequest<TResponse> interface can be processed by this behavior. It helps in type safety and allows us to work with requests in a more strongly-typed manner.

The second way to resolve it is to use the notnull constraint: 

public class LoggingBehavior<TRequest, TResponse> : IPipelineBehavior<TRequest, TResponse> 
    where TRequest : notnull

This time, we use the where TRequest : notnull constraint, ensuring that when using TRequest as a type parameter, it cannot be assigned a null value.

Both these approaches will be efficient in resolving this warning. We can give little advantage to the second one, since in MediatR documentation they also state that the constraint they imposed in the first approach was too strict in some situations and didn’t add much value.

Conclusion

In this article, we saw what constraints we need to add to ensure that MediatR Pipeline Behaviour works as expected and doesn’t throw a TRequest-related warning. We learned when the warning started to happen and also learned different ways to resolve it, depending on the major version of MediatR we are using.

Liked it? Take a second to support Code Maze on Patreon and get the ad free reading experience!
Become a patron at Patreon!