FlowR.Mediator 2.0.2

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

FlowR 🌊

NuGet NuGet Downloads License: MIT CI

A free, high-performance, open-source mediator pattern library for .NET — forever.

FlowR brings the mediator/CQRS pattern to .NET with zero licensing fees, excellent performance through compiled expression trees, and more features out of the box than alternatives.


Why FlowR?

Feature FlowR MediatR
License ✅ MIT (free forever) ❌ Paid for commercial
Request/Response ✅ ✅
Void Commands ✅ ✅
Notifications ✅ ✅
Streaming ✅ ✅
Pipeline Behaviors ✅ ✅
Notification Strategies ✅ Sequential, Parallel, FireAndForget ❌
Built-in Logging Behavior ✅ ❌
Built-in Validation Behavior ✅ ❌
Built-in Retry Behavior ✅ ❌
Built-in Performance Behavior ✅ ❌
Notification Pipeline Behaviors ✅ ❌
Compiled Expression Trees (fast!) ✅ ✅

Installation

dotnet add package FlowR.Mediator

Quick Start

1. Register FlowR

// Program.cs
builder.Services.AddFlowR(typeof(Program).Assembly);

2. Define a Request

// Request (returns a response)
public record GetUserQuery(int UserId) : IRequest<UserDto>;
public record UserDto(int Id, string Name);

// Command (no response)
public record CreateUserCommand(string Name, string Email) : IRequest;

3. Create a Handler

public class GetUserQueryHandler : IRequestHandler<GetUserQuery, UserDto>
{
    private readonly IUserRepository _repo;
    public GetUserQueryHandler(IUserRepository repo) => _repo = repo;

    public async Task<UserDto> HandleAsync(GetUserQuery request, CancellationToken cancellationToken = default)
    {
        var user = await _repo.GetByIdAsync(request.UserId, cancellationToken);
        return new UserDto(user.Id, user.Name);
    }
}

4. Send It

public class UserController : ControllerBase
{
    private readonly ISender _sender;
    public UserController(ISender sender) => _sender = sender;

    [HttpGet("{id}")]
    public async Task<UserDto> GetUser(int id)
        => await _sender.SendAsync(new GetUserQuery(id));
}

Notifications

Publish events to multiple handlers:

// Define
public record UserRegisteredEvent(int UserId) : INotification;

// Multiple handlers
public class SendWelcomeEmailHandler : INotificationHandler<UserRegisteredEvent> { ... }
public class CreateDefaultProfileHandler : INotificationHandler<UserRegisteredEvent> { ... }

// Publish
await mediator.PublishAsync(new UserRegisteredEvent(userId));

// Publish in parallel
await mediator.PublishAsync(new UserRegisteredEvent(userId), NotificationPublishStrategy.Parallel);

// Fire and forget (background, non-critical)
await mediator.PublishAsync(new UserRegisteredEvent(userId), NotificationPublishStrategy.FireAndForget);

Streaming

public record GetOrdersStream(int CustomerId) : IStreamRequest<OrderDto>;

public class GetOrdersStreamHandler : IStreamRequestHandler<GetOrdersStream, OrderDto>
{
    public async IAsyncEnumerable<OrderDto> HandleAsync(GetOrdersStream request, CancellationToken cancellationToken = default)
    {
        await foreach (var order in _db.GetOrdersAsync(request.CustomerId, cancellationToken))
            yield return new OrderDto(order.Id, order.Total);
    }
}

// Use
await foreach (var order in sender.CreateStream(new GetOrdersStream(customerId)))
    Console.WriteLine(order);

Pipeline Behaviors

Add cross-cutting concerns to your request pipeline:

public class AuthorizationBehavior<TRequest, TResponse> : IPipelineBehavior<TRequest, TResponse>
    where TRequest : IRequest<TResponse>
{
    private readonly ICurrentUser _currentUser;
    public AuthorizationBehavior(ICurrentUser currentUser) => _currentUser = currentUser;

    public async Task<TResponse> HandleAsync(TRequest request, RequestHandlerDelegate<TResponse> next, CancellationToken cancellationToken = default)
    {
        if (!_currentUser.IsAuthenticated)
            throw new UnauthorizedAccessException();

        return await next();
    }
}

// Register for all requests (open generic)
services.AddTransient(typeof(IPipelineBehavior<,>), typeof(AuthorizationBehavior<,>));

Built-in Behaviors

FlowR ships with ready-to-use behaviors:

// Logging (logs request name and duration)
services.AddTransient(typeof(IPipelineBehavior<,>), typeof(LoggingBehavior<,>));

// Performance (warns on slow requests > 500ms)
services.AddTransient(typeof(IPipelineBehavior<,>), typeof(PerformanceBehavior<,>));

// Validation (integrates with any validator)
services.AddTransient(typeof(IPipelineBehavior<,>), typeof(ValidationBehavior<,>));
services.AddTransient<IFlowRValidator<CreateUserCommand>, CreateUserCommandValidator>();

// Retry (retries failed requests up to N times)
services.AddTransient(typeof(IPipelineBehavior<,>), typeof(RetryBehavior<,>));

Validation

public class CreateUserCommandValidator : IFlowRValidator<CreateUserCommand>
{
    public Task<IEnumerable<ValidationError>> ValidateAsync(CreateUserCommand request, CancellationToken cancellationToken = default)
    {
        var errors = new List<ValidationError>();
        if (string.IsNullOrWhiteSpace(request.Name))
            errors.Add(new ValidationError("Name", "Name is required."));
        if (!request.Email.Contains('@'))
            errors.Add(new ValidationError("Email", "Invalid email address."));

        return Task.FromResult<IEnumerable<ValidationError>>(errors);
    }
}

When validation fails, FlowRValidationException is thrown with all errors:

catch (FlowRValidationException ex)
{
    foreach (var error in ex.Errors)
        Console.WriteLine($"{error.PropertyName}: {error.ErrorMessage}");
}

Configuration

services.AddFlowR(options =>
{
    options.MediatorLifetime = ServiceLifetime.Scoped;   // default: Transient
    options.HandlerLifetime = ServiceLifetime.Transient; // default: Transient
    options.BehaviorLifetime = ServiceLifetime.Transient; // default: Transient
},
typeof(Program).Assembly,
typeof(OtherAssemblyMarker).Assembly);

Performance

FlowR uses compiled expression trees to build handler delegates once and cache them. After the first call, handler resolution is essentially a dictionary lookup — no reflection overhead on hot paths.


License

MIT — free for personal and commercial use, forever.


Contributing

PRs welcome! See CONTRIBUTING.md.

Star ⭐ the repo if FlowR helps you!

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

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
2.0.2 257 4/24/2026
2.0.1 114 4/24/2026
2.0.1-pr.2.4f56e93 68 4/24/2026
2.0.0 113 4/24/2026
2.0.0-alpha.8c5a067 72 4/24/2026
1.0.1 124 4/14/2026
1.0.1-alpha.a55379a 69 4/23/2026
1.0.0 122 3/19/2026