Centeva.RequestBehaviors.Mediator 1.0.0

Prefix Reserved
dotnet add package Centeva.RequestBehaviors.Mediator --version 1.0.0
                    
NuGet\Install-Package Centeva.RequestBehaviors.Mediator -Version 1.0.0
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Centeva.RequestBehaviors.Mediator" Version="1.0.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Centeva.RequestBehaviors.Mediator" Version="1.0.0" />
                    
Directory.Packages.props
<PackageReference Include="Centeva.RequestBehaviors.Mediator" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add Centeva.RequestBehaviors.Mediator --version 1.0.0
                    
#r "nuget: Centeva.RequestBehaviors.Mediator, 1.0.0"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package Centeva.RequestBehaviors.Mediator@1.0.0
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=Centeva.RequestBehaviors.Mediator&version=1.0.0
                    
Install as a Cake Addin
#tool nuget:?package=Centeva.RequestBehaviors.Mediator&version=1.0.0
                    
Install as a Cake Tool

Centeva Request Behaviors

Centeva.RequestBehaviors is a set of .NET libraries that provide commonly used request pipeline behaviors for "Mediator"-style applications, supporting the MediatR and Mediator.SourceGenerator libraries. These behaviors can be used to implement cross-cutting concerns such as validation and authorization in a clean and reusable way that is not tied to any specific presentation layer (e.g., ASP.Net Core).

Table of Contents

Built With

Getting Started

Add a reference to Centeva.RequestBehaviors.MediatR or Centeva.RequestBehaviors.Mediator in your project, depending on which mediator library you have chosen.

If you are using multiple projects to separate Core/Domain, Application, and Web API layers (i.e., "Clean" or "Ports and Adapters" architecture) then reference from the project containing your request handlers.

If you are migrating from the older Centeva.RequestValidation and Centeva.RequestAuthorization libraries, see the migration guide for instructions on updating your code.

Validation

NOTE: If you're also using the authorization behavior, you likely want to register validation first, then add the Authorization behavior. This ensures that validation happens first in your pipeline.

Using with MediatR

Register the validators and add the MediatR pipeline behavior in your DI container:

builder.Services.AddMediatRRequestValidation(typeof(SampleValidator).Assembly);

Using with Mediator.SourceGenerator

builder.Services.AddMediatorRequestValidation(typeof(SampleValidator).Assembly);

Validating a Request

To validate a request, add a validator class to your project that inherits from AbstractValidator<TRequest>, where TRequest is the type of request you want to validate. For example:

public class SampleValidator : AbstractValidator<SampleRequest>
{
    public SampleValidator()
    {
        RuleFor(x => x.Name).NotEmpty();
    }
}

If validation fails, a ValidationException will be thrown. Your application is responsible for handling those exceptions, possibly by mapping to a custom HTTP response or a ProblemDetails object.

Validating with Result Types

If your request handler returns a Result or Result<T> type (from the Ardalis.Result library), then validation failures will be returned as an invalid Result containing the validation errors instead of a thrown exception. This allows you to handle validation errors in a more functional style, without relying on exceptions for control flow.

var result = await _mediator.Send(new SampleRequest());

if (!result.IsInvalid)
{
    // Do something here with result.ValidationErrors
}

// Respond normally here

Authorization

Using with MediatR

Register the MediatR pipeline behavior, authorizers, and handlers in your DI container:

builder.Services.AddMediatR(cfg =>
{
    cfg.RegisterServicesFromAssembly(Assembly.GetExecutingAssembly());
});
builder.Services.AddMediatRAuthorization(typeof(DeleteItemAuthorizer).Assembly);

OR if you have multiple assemblies with authorizers/handlers:

...
builder.Services.AddMediatRAuthorization(typeof(DeleteItemAuthorizer).Assembly, typeof(OtherAuthorizer).Assembly);
...

You can alternately register your authorizers separately:

builder.Services.AddRequestAuthorizersFromAssembly(typeof(DeleteItemAuthorizer).Assembly);
builder.Services.AddRequestAuthorizationHandlersFromAssembly(typeof(MustBeItemOwnerHandler).Assembly);

Using with Mediator.SourceGenerator

Register the Mediator pipeline behavior, authorizers, and handlers in your DI container:

builder.Services.AddMediator(cfg =>
{
    ...
});
builder.Services.AddMediatorAuthorization(typeof(DeleteItemAuthorizer).Assembly);

OR if you have multiple assemblies with authorizers/handlers:

...
builder.Services.AddMediatorAuthorization(typeof(DeleteItemAuthorizer).Assembly, typeof(OtherAuthorizer).Assembly);
...

You can alternately register your authorizers separately:

builder.Services.AddRequestAuthorizersFromAssembly(typeof(DeleteItemAuthorizer).Assembly);
builder.Services.AddRequestAuthorizationHandlersFromAssembly(typeof(MustBeItemOwnerHandler).Assembly);

Authorization Requirements

Implement IRequestAuthorizationRequirement and IRequestAuthorizationHandler<TRequirement> to create reusable authorization rules:

public class MustBeItemOwnerRequirement : IRequestAuthorizationRequirement
{
  public int UserId { get; set; }
  public int ItemId { get; set; }
}

public class MustBeItemOwnerHandler : IRequestAuthorizationHandler<MustBeItemOwnerRequirement>
{
  public MustBeItemOwnerHandler(IItemRepository itemRepository)
  {
    _itemRepository = itemRepository;
  }

  public async Task<AuthorizationResult> Handle(
    MustBeItemOwnerRequirement requirement,
    CancellationToken cancellationToken)
  {
    var item = await _itemRepository.Get(requirement.ItemId, cancellationToken);

    if (item != null && item.OwnerId == requirement.UserId)
      return AuthorizationResult.Succeed();

    return AuthorizationResult.Fail("Must be the owner of this item");
  }
}

Each IAuthorizationHandler must return either a success or failure result based on the logic in the Handle method.

Request Authorizers

Derive from AbstractRequestAuthorizer<TRequest> and implement BuildPolicy to compose requirements for authorizing the given MediatR request:

public class DeleteItemAuthorizer : AbstractRequestAuthorizer<DeleteItemCommand>
{
  public DeleteItemAuthorizer(ICurrentUserService currentUserService)
  {
      _currentUserService = currentUserService;
  }

  public override void BuildPolicy(DeleteItemCommand request)
  {
      UseRequirement(new MustBeItemOwnerRequirement
      {
        UserId = _currentUserService.UserId,
        ItemId = request.ItemId
      });
  }
}
Authorizing with Result Types

If your request handler returns a Result or Result<T> type (from the Ardalis.Result library), then authorization failures will be returned as an "Forbidden" Result containing the failure message, if any, instead of a thrown exception. This allows you to handle authorization in a more functional style, without relying on exceptions for control flow.

var result = await _mediator.Send(new SampleRequest());

if (result.IsForbidden)
{
    // Do something here like return an HTTP 403
}

// Respond normally here

Contributing

Please use a Pull Request to suggest changes to this library. As this is a shared library, strict semantic versioning rules should be followed to avoid unexpected breaking changes.

Running Tests

From Windows, use the dotnet test command, or your Visual Studio Test Explorer.

Deployment

This library is released via GitHub Releases.

Resources

Some of the code here is based heavily on this article: Handling Authorization In Clean Architecture with ASP.NET Core and MediatR from Austin Davies.

Product Compatible and additional computed target framework versions.
.NET net8.0 is compatible.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 was computed.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 was computed.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages (1)

Showing the top 1 NuGet packages that depend on Centeva.RequestBehaviors.Mediator:

Package Downloads
Centeva.AdamsInterface

ADAMS API client library for .NET - Supports Windows Authentication, Bearer Token (OIDC), and pluggable authentication strategies for integrating with ADAMS document management systems.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
1.0.0 149 5/20/2026