NetNinja.Mediator
1.12.11
dotnet add package NetNinja.Mediator --version 1.12.11
NuGet\Install-Package NetNinja.Mediator -Version 1.12.11
<PackageReference Include="NetNinja.Mediator" Version="1.12.11" />
<PackageVersion Include="NetNinja.Mediator" Version="1.12.11" />
<PackageReference Include="NetNinja.Mediator" />
paket add NetNinja.Mediator --version 1.12.11
#r "nuget: NetNinja.Mediator, 1.12.11"
#:package NetNinja.Mediator@1.12.11
#addin nuget:?package=NetNinja.Mediator&version=1.12.11
#tool nuget:?package=NetNinja.Mediator&version=1.12.11
NetNinja.Mediator
Great test coverage!
A simple and efficient tool to implement the Mediator pattern in .NET 8 applications. This package provides a lightweight implementation of the Mediator pattern that enables decoupling between components by sending requests and commands through a centralized mediator service.
π Features
- β Simple Mediator pattern implementation
- β .NET 8 support
- β Automatic dependency injection
- β Automatic handler registration from assemblies
- β Clean and easy-to-use interface
- β Compatible with Microsoft.Extensions.DependencyInjection
- β Async/await support with Task-based handlers
- β CancellationToken support for better cancellation handling
π¦ Installation
Install the package from NuGet Package Manager:
dotnet add package NetNinja.Mediator
Or via Package Manager Console:
Install-Package NetNinja.Mediator
π οΈ Setup
1. Register the Mediator in Program.cs
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.Identity.Web;
using NetNinja.Mediator;
namespace Your.Api
{
public class Program
{
public static void Main(string[] args)
{
var builder = WebApplication.CreateBuilder(args);
/*Dependency Injection*/
builder.Services.AddApplicationServices();
/*Injecting mediator*/
builder.Services.AddNetNinjaMediator(
typeof(UserQueryHandler).Assembly,
typeof(UserCommandHandler).Assembly
);
app.UseHttpsRedirection();
app.UseAuthentication();
app.UseAuthorization();
app.UseCorsHere();
app.MapControllers();
app.Run();
}
}
}
Versions >= 1.0.11 you can enable behaviors, also posibility to select the handlers registration type
namespace NetNinja.Mediator.Enums;
public enum RegistrationType
{
Scoped = 0,
Transient = 1,
Singleton = 2,
None = 3
}
by default None will register handlers as Transient
/* versions >= 1.0.12 you can enable behaviors */
builder.Services.AddNetNinjaMediator(
autoRegisterValidators: true,
autoRegisterValidationBehavior: false,
autoRegisterPipelineBehaviors: false,
autoRegisterHandlers: true,
registrationType: RegistrationType.None,
typeof(CreateUserHandler).Assembly
);
But is always recommended register by your self, behaviors will be executed in the orders you register
/* for example register your validator behavior */
services.AddTransient(typeof(NetNinja.Mediator.Abstractions.IPipelineBehavior<,>), typeof(ValidationBehavior<,>));
π Basic Usage
1. Create a Request (Query or Command)
using NetNinja.Mediator.Abstractions;
// Query Request
public class GetUserByIdQuery : IRequest<UserDto>
{
public int UserId { get; set; }
public GetUserByIdQuery(int userId)
{
UserId = userId;
}
}
// Command Request
public class CreateUserCommand : IRequest<int>
{
public string Name { get; set; }
public string Email { get; set; }
public CreateUserCommand(string name, string email)
{
Name = name;
Email = email;
}
}
2. Create Request Handlers
using NetNinja.Mediator.Abstractions;
using System.Threading;
using System.Threading.Tasks;
// Query Handler
public class GetUserByIdQueryHandler : IRequestHandler<GetUserByIdQuery, UserDto>
{
private readonly IUserRepository _userRepository;
public GetUserByIdQueryHandler(IUserRepository userRepository)
{
_userRepository = userRepository;
}
public async Task<UserDto> Handle(GetUserByIdQuery request, CancellationToken cancellationToken)
{
var user = await _userRepository.GetByIdAsync(request.UserId, cancellationToken);
return new UserDto
{
Id = user.Id,
Name = user.Name,
Email = user.Email
};
}
}
// Command Handler
public class CreateUserCommandHandler : IRequestHandler<CreateUserCommand, int>
{
private readonly IUserRepository _userRepository;
public CreateUserCommandHandler(IUserRepository userRepository)
{
_userRepository = userRepository;
}
public async Task<int> Handle(CreateUserCommand request, CancellationToken cancellationToken)
{
var user = new User
{
Name = request.Name,
Email = request.Email
};
return await _userRepository.CreateAsync(user, cancellationToken);
}
}
3. Use the Mediator in your Controllers
using Microsoft.AspNetCore.Mvc;
using NetNinja.Mediator.Abstractions;
using System.Threading;
using System.Threading.Tasks;
[ApiController]
[Route("api/[controller]")]
public class UsersController : ControllerBase
{
private readonly IMediator _mediator;
public UsersController(IMediator mediator)
{
_mediator = mediator;
}
[HttpGet("{id}")]
public async Task<ActionResult<UserDto>> GetUser(int id, CancellationToken cancellationToken)
{
var query = new GetUserByIdQuery(id);
var result = await _mediator.Send(query, cancellationToken);
return Ok(result);
}
[HttpPost]
public async Task<ActionResult<int>> CreateUser([FromBody] CreateUserRequest request, CancellationToken cancellationToken)
{
var command = new CreateUserCommand(request.Name, request.Email);
var userId = await _mediator.Send(command, cancellationToken);
return CreatedAtAction(nameof(GetUser), new { id = userId }, userId);
}
}
ποΈ Architecture
The NetNinja.Mediator package implements a simple Mediator pattern with the following components:
Main Interfaces
IMediator: Main interface for the mediator service with asyncSend<TResponse>methodIRequest<TResponse>: Base interface for all requestsIRequestHandler<TRequest, TResponse>: Interface for async handlers that process requests with CancellationToken support
Workflow
- Create an instance of
IRequest<TResponse> - Send it to
IMediatorusing the asyncSend<TResponse>()method with optionalCancellationToken - The mediator automatically finds the appropriate
IRequestHandler - The handler processes the request asynchronously and returns the response
Controller β IMediator β IRequestHandler β Repository/Service β Response
ποΏ½ Async/Await Support & CancellationToken
NetNinja.Mediator fully supports asynchronous operations and provides built-in cancellation support:
Key Benefits
- Performance: Non-blocking I/O operations for better scalability
- Cancellation: Proper cancellation support throughout the pipeline
- Exception Handling: Proper async exception propagation
- Resource Management: Better resource utilization in async contexts
CancellationToken Best Practices
// In Controllers - ASP.NET Core automatically provides CancellationToken
[HttpGet("{id}")]
public async Task<ActionResult<UserDto>> GetUser(int id, CancellationToken cancellationToken)
{
var query = new GetUserByIdQuery(id);
var result = await _mediator.Send(query, cancellationToken);
return Ok(result);
}
// In Services - Pass through or provide default
public async Task<UserDto> GetUserAsync(int id, CancellationToken cancellationToken = default)
{
var query = new GetUserByIdQuery(id);
return await _mediator.Send(query, cancellationToken);
}
// In Handlers - Always pass CancellationToken to async operations
public async Task<UserDto> Handle(GetUserByIdQuery request, CancellationToken cancellationToken)
{
// Pass cancellationToken to all async operations
var user = await _userRepository.GetByIdAsync(request.UserId, cancellationToken);
var permissions = await _permissionService.GetUserPermissionsAsync(user.Id, cancellationToken);
return new UserDto
{
Id = user.Id,
Name = user.Name,
Email = user.Email,
Permissions = permissions
};
}
π§ Advanced Configuration
Register Handlers from Multiple Assemblies
builder.Services.AddNetNinjaMediator(
typeof(UserQueryHandler).Assembly, // Queries
typeof(UserCommandHandler).Assembly, // Commands
typeof(ProductQueryHandler).Assembly, // More queries
typeof(OrderCommandHandler).Assembly // More commands
);
Use in Services (not just Controllers)
using System.Threading;
using System.Threading.Tasks;
public class UserService
{
private readonly IMediator _mediator;
public UserService(IMediator mediator)
{
_mediator = mediator;
}
public async Task<UserDto> GetUserAsync(int id, CancellationToken cancellationToken = default)
{
var query = new GetUserByIdQuery(id);
return await _mediator.Send(query, cancellationToken);
}
public async Task<int> CreateUserAsync(string name, string email, CancellationToken cancellationToken = default)
{
var command = new CreateUserCommand(name, email);
return await _mediator.Send(command, cancellationToken);
}
}
π Recommended Project Structure
YourProject/
βββ Controllers/
β βββ UsersController.cs
βββ Application/
β βββ Commands/
β β βββ CreateUserCommand.cs
β β βββ UpdateUserCommand.cs
β βββ Queries/
β β βββ GetUserByIdQuery.cs
β β βββ GetUsersQuery.cs
β βββ Handlers/
β β βββ CommandHandlers/
β β β βββ CreateUserCommandHandler.cs
β β β βββ UpdateUserCommandHandler.cs
β β βββ QueryHandlers/
β β βββ GetUserByIdQueryHandler.cs
β β βββ GetUsersQueryHandler.cs
β βββ Models/
β βββ DTOs/
β β βββ UserDto.cs
β β βββ CreateUserRequest.cs
β βββ Responses/
β βββ ApiResponse.cs
βββ Domain/
β βββ Entities/
β β βββ User.cs
β βββ Interfaces/
β βββ IUserRepository.cs
βββ Infrastructure/
βββ Repositories/
βββ UserRepository.cs
Alternative Structure (Separating Models)
YourProject/
βββ Controllers/
β βββ UsersController.cs
βββ Models/
β βββ Commands/
β β βββ CreateUserCommand.cs
β β βββ UpdateUserCommand.cs
β βββ Queries/
β β βββ GetUserByIdQuery.cs
β β βββ GetUsersQuery.cs
β βββ DTOs/
β βββ UserDto.cs
βββ Application/
β βββ Handlers/
β β βββ CommandHandlers/
β β β βββ CreateUserCommandHandler.cs
β β β βββ UpdateUserCommandHandler.cs
β β βββ QueryHandlers/
β β βββ GetUserByIdQueryHandler.cs
β β βββ GetUsersQueryHandler.cs
β βββ Services/
β βββ UserService.cs
βββ Domain/
β βββ Entities/
β βββ User.cs
βββ Infrastructure/
βββ Repositories/
βββ UserRepository.cs
β‘ Mediator Pattern Benefits
- Decoupling: Controllers don't depend directly on business services
- Reusability: Handlers can be reused from different entry points
- Testability: Easy to mock and unit test
- Organization: Cleaner code organized by responsibilities
- CQRS Ready: Perfect for implementing Command Query Responsibility Segregation
π Useful Links
π₯ Contributing
Contributions are welcome! Please:
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
π License
This project is licensed under the MIT License. See the LICENSE file for details.
β¨ Author
Christian GarcΓa MartΓn
β If this package helps you in your projects, don't forget to give it a star on GitHub!
| Product | Versions 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 is compatible. 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. |
-
net10.0
- FluentValidation (>= 11.11.0)
- Microsoft.AspNetCore.Http (>= 2.3.0)
- Microsoft.Extensions.DependencyInjection (>= 10.0.0)
-
net8.0
- FluentValidation (>= 11.11.0)
- Microsoft.AspNetCore.Http (>= 2.3.0)
- Microsoft.Extensions.DependencyInjection (>= 10.0.0)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 1.12.11 | 106 | 1/30/2026 |
| 1.11.11 | 1,309 | 1/12/2026 |
| 1.0.13 | 104 | 1/12/2026 |
| 1.0.12 | 442 | 12/9/2025 |
| 1.0.10 | 256 | 11/24/2025 |
| 1.0.8 | 199 | 10/22/2025 |
| 1.0.7 | 148 | 10/21/2025 |
| 1.0.6 | 133 | 10/21/2025 |
| 1.0.5 | 139 | 10/21/2025 |
| 1.0.4 | 140 | 10/20/2025 |
| 1.0.3 | 139 | 10/20/2025 |
| 1.0.2 | 134 | 10/20/2025 |
| 1.0.1 | 137 | 10/20/2025 |