FBC.Mediator is a lightweight, high-performance Mediator pattern implementation for .NET projects.
It provides command/query dispatching, request handler caching, and endpoint registration for ASP.NET Core.
Please feel free to provide any feedback that could help the project reach a level where it can benefit everyone.
IMediatorfor type-safe request/response and void requests- Supports
IRequestHandler<TRequest, TResponse>andIRequestHandler<TRequest> - Request handler caching for performance
- Easy integration with ASP.NET Core Minimal APIs
- Compatible with Swagger/OpenAPI
- Auto-registration of handlers and endpoints
// In Startup.cs or Program.cs
builder.Services.AddMediator(typeof(Program).Assembly);
...
var app = builder.Build();
...
app.UseMediatorEndpoints();
...You can pass multiple assemblies if your handlers or endpoints are spread across projects.
Define a request:
public sealed class CreateItem
{
public record Command(string Name) : IRequest<long>;
internal sealed class Handler(ILogger<Handler> logger) : IRequestHandler<Command, long>
{
public async Task<long> Handle(Command request, CancellationToken token = default)
{
logger.LogInformation("Creating item with Name: {ItemName}", request.Name);
// Perform your logic here
await Task.Delay(100, token); // simulated async operation
return new Random().Next(1, 1000); // example ID
}
}
}Define an endpoint:
public sealed class CreateItemEndPoint : IEndpoint
{
public void AddRoutes(IEndpointRouteBuilder app)
{
app.MapPost("/items/create", async (CreateItem.Command command, IMediator mediator, CancellationToken token) =>
{
var itemId = await mediator.Send(command, token);
return Results.Ok(itemId);
})
.WithTags("Items")
.WithName("CreateItem")
.WithSummary("Creates a new item.")
.WithDescription("Creates a new item and returns the ID of the created item.")
.Produces<long>(StatusCodes.Status200OK)
.Produces(StatusCodes.Status400BadRequest)
.Produces(StatusCodes.Status500InternalServerError);
}
}Use a void request:
public sealed class VoidTest
{
public record Command() : IRequest;
internal sealed class Handler(ILogger<Handler> logger) : IRequestHandler<Command>
{
public async Task Handle(Command request, CancellationToken token = default)
{
logger.LogInformation("Handling void command");
await Task.CompletedTask;
}
}
}Endpoint for void request:
public sealed class VoidTestEndPoint : IEndpoint
{
public void AddRoutes(IEndpointRouteBuilder app)
{
app.MapPost("/voidtest", async (VoidTest.Command command, IMediator mediator, CancellationToken token) =>
{
await mediator.Send(command, token);
return Results.Ok();
})
.WithTags("Test")
.WithName("VoidTest")
.WithSummary("Tests void command.")
.WithDescription("Sends a void command and returns OK.")
.Produces(StatusCodes.Status200OK)
.Produces(StatusCodes.Status400BadRequest)
.Produces(StatusCodes.Status500InternalServerError);
}
}var builder = WebApplication.CreateBuilder(args);
builder.Services.AddMediator(typeof(Program).Assembly);
var app = builder.Build();
app.UseMediatorEndpoints();AddMediatorautomatically registers all handlers and endpoints.UseMediatorEndpointsmaps allIEndpointimplementations to the route builder.
FBC.Mediator includes a safe schema ID selector for Swagger, ensuring nested classes or records display correctly.
- Type-safe, generic, and high-performance mediator
- Minimal API-friendly
- Handler caching for fast request dispatch
- Supports void and generic requests
- Compatible with Swagger/OpenAPI
- Use
IRequest<TResponse>for commands and queries. - Use
IRequestfor void operations. - Define endpoints using
IEndpoint. - Register the mediator using
AddMediator. - Map endpoints using
UseMediatorEndpoints.