NetNinja.Mediator 1.12.11

dotnet add package NetNinja.Mediator --version 1.12.11
                    
NuGet\Install-Package NetNinja.Mediator -Version 1.12.11
                    
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="NetNinja.Mediator" Version="1.12.11" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="NetNinja.Mediator" Version="1.12.11" />
                    
Directory.Packages.props
<PackageReference Include="NetNinja.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 NetNinja.Mediator --version 1.12.11
                    
#r "nuget: NetNinja.Mediator, 1.12.11"
                    
#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 NetNinja.Mediator@1.12.11
                    
#: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=NetNinja.Mediator&version=1.12.11
                    
Install as a Cake Addin
#tool nuget:?package=NetNinja.Mediator&version=1.12.11
                    
Install as a Cake Tool

NetNinja.Mediator

Great test coverage!

  • alt text

NuGet Downloads

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 async Send<TResponse> method
  • IRequest<TResponse>: Base interface for all requests
  • IRequestHandler<TRequest, TResponse>: Interface for async handlers that process requests with CancellationToken support

Workflow

  1. Create an instance of IRequest<TResponse>
  2. Send it to IMediator using the async Send<TResponse>() method with optional CancellationToken
  3. The mediator automatically finds the appropriate IRequestHandler
  4. 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);
    }
}
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

πŸ‘₯ Contributing

Contributions are welcome! Please:

  1. Fork the repository
  2. Create a feature branch (git checkout -b feature/amazing-feature)
  3. Commit your changes (git commit -m 'Add amazing feature')
  4. Push to the branch (git push origin feature/amazing-feature)
  5. 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 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. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

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