Flowsy.Mediation 13.0.1

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

Flowsy Mediation

This package provides a simple but useful implementation of the mediator pattern for .NET applications. As of version 13, this packagke no longer depends on MediatR and provides its own implementation of the mediator pattern, which is designed to be lightweight and easy to use. For request validation, it still can use FluentValidation if you configure it to do so.

Concepts

The mediator pattern allows us to centralize communication between different parts of an application through a single mediator object in charge of dispatching requests and notifications to the appropriate components containing the logic to handle them.

A common application flow would be:

  1. User requests some action to be executed.
  2. The application validates the request and returns some error information to the user in case of invalid input.
  3. The application executes the requested operation.
  4. The application returns to the user the result of the operation or some error information if something went wrong during the process.
  5. After the request has been fulfilled, the application may notify other parts of the system to trigger another related operation.

In fact, the mediator pattern is a powerful way to implement the CQRS (Command Query Responsibility Segregation) pattern, which separates the read and write operations of an application.

  • Query: A request for reading data with no alteration of the application's current state.
  • Command: A request for creating, updating or removing data, thus altering the application's current state.

Requests

In the context of the mediation pattern, a request is an object that represents an operation to be performed and it contains all the necessary information to execute that operation. Some requests can execute wihout returning any result, while others can return a response.

  • IRequest: Represents a request without a response.
  • IRequest<TResponse>: Represents a request that returns a response of type TResponse.

Request Handlers

A request handler is a component containing the logic to execute a request. It is responsible for processing the request and returning a response if applicable.

  • IRequestHandler<TRequest>: Represents a handler for a request of type TRequest without a response.
  • IRequestHandler<TRequest, TResponse>: Represents a handler for a request of type TRequest that returns a response of type TResponse.

Notifications

Notifications contain information about relevant events that have occurred in the application and are published by the mediation system wihtout expecting a response.

  • INotification: Represents a notification that can be published to subscribers.

Notifications Handlers

A notification handler is a component that processes notifications published by the mediation system. This concept is a powerful way to trigger side effects or notify other parts of the system about changes without requiring a response.

  • INotificationHandler<TNotification>: Represents a handler for a notification of type TNotification.

Middleware

Middleware components can be used to intercept and process requests and notifications before they reach the associated handler. For instance, you can use a middleware to count the number of attempts to execute a given request, or to record audit trails for the request execution.

  • IRequestMiddleware<TRequest>: Represents a middleware that can intercept and process requests of type TRequest before they reach the handler.
  • IRequestMiddleware<TRequest, TResponse>: Represents a middleware that can intercept and process requests of type TRequest with a response of type TResponse before they reach the handler.
  • INotificationMiddleware<TNotification>: Represents a middleware that can intercept and process notifications of type TNotification before they reach the handler.
Built-in Middleware

This package provides some built-in middleware components to facilitate common tasks:

Logging
  • RequestLoggingMiddleware<TRequest>: Logs information about a request of type TRequest.
  • RequestLoggingMiddleware<TRequest, TResponse>: Logs information about a request of type TRequest and its response of type TResponse.
  • NotificationLoggingMiddleware<TNotification>: Logs information about a notification of type TNotification.
Validation
  • RequestValidationMiddleware<TRequest>: Validates requests of type TRequest.
  • RequestValidationMiddleware<TRequest, TResponse>: Validates requests of type TRequest with a response of type TResponse.

Usage

1. Define Some Queries

// Queries/CustomersByRegion/CustomersByRegionQuery.cs
// using ...
using Flowsy.Mediation;
// using ...

// You can use classes or records to define your queries.
public record CustomersByRegionQuery(string CountryId, string? StateId) : IRequest<IEnumerable<CustomerDto>>;

2. Define Some Query Validators

// Queries/CustomersByRegion/CustomersByRegionQueryValidator.cs
// using ...
using Flowsy.Mediation;
using FluentValidation;
// using ...

public class CustomersByRegionQueryValidator : AbstractValidator<CustomersByRegionQuery>
{
    public CustomersByRegionQueryValidator()
    {
        RuleFor(query => query.CountryId)
            .NotEmpty()
            .WithMessage("Country identifier is required.");
    }
}

3. Define Some Query Handlers

// Queries/CustomersByRegion/CustomersByRegionQueryHandler.cs
// using ...
using Flowsy.Mediation;
// using ...

public class CustomersByRegionQueryHandler : IRequestHandler<CustomerByIdQuery, IEnumerable<CustomerDto>>
{
    private readonly ICustomerRepository _customerRepository;
    
    public CustomersByRegionQueryHandler(ICustomerRepository customerRepository)
    {
        _customerRepository = customerRepository;
    }

    protected override async Task<IEnumerable<CustomerDto>> HandleAsync(CustomersByRegionQuery request, CancellationToken cancellationToken)
    {
        var customers = await _customerRepository.GetCusomtersByRegionAsync(request.CountryId, request.StateId, cancellationToken);
        
        return customers;
    }
}

4. Define Some Commands

// Commands/CreateCustomer/CreateCustomerCommand.cs
// using ...
using Flowsy.Mediation;
// using ...

// You can use classes or records to define your commands.
public record CreateCustomerCommand(string FirstName, string LastName, string Email) : IRequest<CreateCustomerCommandResult>;

5. Define Some Command Validators

// Commands/CreateCustomer/CreateCustomerCommandValidator.cs
// using ...
using Flowsy.Mediation;
using FluentValidation;
// using ...

public class CreateCustomerCommandValidator : AbstractValidator<CreateCustomerCommand>
{
    public CreateCustomerCommandValidator()
    {
        RuleFor(command => command.FirstName)
            .NotEmpty()
            .WithMessage("First name is required.");
            
        RuleFor(command => command.Email)
            .EmailAddress()
            .WithMessage("Invalid email address")
            .DependentRules(() => 
            {
                RuleFor(command => command.Email)
                    .NotEmpty()
                    .WithMessage("Email is required.")
                    .MaximumLength(320)
                    .WithMessage("Up to 320 characters.");
            });
    }
}

6. Define Some Command Results

// Commands/CreateCustomer/CreateCustomerCommandResult.cs

// You can use classes or records to define your command results.
public record CreateCustomerCommandResult(Guid CustomerId);

7. Define Some Command Handlers

// Commands/CreateCustomer/CreateCustomerCommandHandler.cs
// using ...
using Flowsy.Mediation;
// using ...

public class CreateCustomerCommandHandler : IRequestHandler<CreateCustomerCommand, CreateCustomerCommandResult>
{
    private readonly ICustomerRepository _customerRepository;
    
    public CreateCustomerCommandHandler(ICustomerRepository customerRepository)
    {
        _customerRepository = customerRepository;
    }

    protected override async Task<CreateCustomerCommandResult> HandleAsync(CreateCustomerCommand request, CancellationToken cancellationToken)
    {
        var customer = new Customer(Guid.NewGuid(), request.FirstName, request.LastName, request.Email);
    
        await _customerRepository.CreateCustomerAsync(customer, cancellationToken);
        
        return new CreateCustomerCommandResult(customer.CustomerId); 
    }
}

8. Register and Configure Services

// Program.cs
// using ...
using Flowsy.Mediation;
using FluentValidation;
// using ...

var builder = WebApplication.CreateBuilder(args);

builder.Services
    .AddMediation()
    .FromAssemblies(Assembly.GetExecutingAssembly()) // Add one or more assemblies containing your requests, notifications, validators and handlers
    // .FromAssemblies([Assembly.GetExecutingAssembly()], false) // Use this version to prevent automatic registration of FluentValidation validators
    .WithMiddleware() // Allow middleware registration
    .ForLogging(LogLevel.Debug, true, true, true) // Built-in logging middleware for requests and notifications
    .ForRequest(typeof(AuditMiddleware<>)) // Fictitious middleware for auditing requests without a response
    .ForRequest(typeof(AuditMiddleware<,>)) // Fictitious middleware for auditing requests with a response
    .ForRequest<CustomerCreationAttemptMiddleware>() // Fictitious middleware for counting attempts to create a customer
    .ForValidation() // Built-in validation middleware for requests
    .ForNotification<CustomerCreationCompletedMiddleware>(); // Fictitious middleware for handling customer creation completion notifications

//!!!!!!!!!!!
// IMPORTANT: The order of middleware registration matters, as they will be executed in the order they are registered.
//!!!!!!!!!!!

// Add other services

var app = builder.Build();

// Use services

app.Run();

9. Using the Mediator

// SomeController.cs
// using ...
using Flowsy.Mediation;
// using ...

[Route("api/[controller]")]
public class CustomersController : ControllerBase
{
    private readonly IMediator _mediator;

    public SomeController(IMediator mediator)
    {
        _mediator = mediator;
    }

    [HttpGet]
    public async Task<IActionResult> GetCustomersByRegion([FromQuery] string countryId, [FromQuery] string? stateId)
    {
        var query = new CustomersByRegionQuery(countryId, stateId);
        var customers = await _mediator.Send(query);
        
        return Ok(customers);
    }

    [HttpPost]
    public async Task<IActionResult> CreateCustomer(CreateCustomerCommand command)
    {
        var result = await _mediator.Send(command);
        
        return CreatedAtAction(nameof(GetCustomerById), new { id = result.CustomerId }, result);
    }
}
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 Flowsy.Mediation:

Package Downloads
Flowsy.Web.Api

Foundation components for Web APIs.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
13.0.1 139 6/4/2025
13.0.0 146 6/4/2025
12.0.0 147 12/4/2024
11.0.4 213 1/17/2024
11.0.3 135 1/17/2024
11.0.2 135 1/17/2024
11.0.1 142 1/16/2024
11.0.0 147 1/16/2024
10.0.0 150 1/16/2024
9.0.2 187 12/14/2023
9.0.1 132 12/14/2023
9.0.0 131 12/14/2023
8.0.1 140 12/6/2023
8.0.0 154 12/5/2023
7.3.2 258 10/5/2023
7.3.1 172 10/5/2023
7.3.0 162 10/5/2023
7.2.1 190 10/4/2023
7.2.0 165 10/4/2023
7.1.0 164 10/4/2023
7.0.0 291 8/29/2023
6.1.7 414 6/2/2023
6.1.6 222 5/24/2023
6.1.5 171 5/24/2023
6.1.4 374 3/25/2023
6.1.3 425 3/10/2023
6.1.2 324 3/10/2023
6.1.1 343 3/10/2023
6.1.0 269 3/10/2023
6.0.3 317 3/9/2023
6.0.2 338 3/9/2023
6.0.1 393 3/9/2023
6.0.0 336 3/9/2023
5.1.1 378 2/27/2023
5.1.0 359 2/24/2023
5.0.0 355 2/23/2023
4.1.0 347 2/22/2023
4.0.0 418 2/21/2023
3.4.0 343 2/21/2023
3.3.0 261 2/21/2023
3.2.0 470 2/21/2023
3.1.0 285 2/21/2023
3.0.1 1,783 11/6/2022
3.0.0 686 11/5/2022
2.0.0 789 11/3/2022
1.1.2 383 11/2/2022
1.1.1 581 11/2/2022
1.1.0 389 11/2/2022
1.0.0 395 11/2/2022