Fox.ResultKit.MediatR 1.2.0

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

ResultKit.MediatR

MediatR integration for ResultKit - Railway Oriented Programming pipeline behaviors for CQRS commands and queries.

📋 Overview

ResultKit.MediatR provides seamless integration between MediatR and ResultKit, enabling automatic exception handling and result-based error handling in your CQRS command/query handlers.

✨ Features

  • Automatic Exception Handling - Exceptions in handlers are automatically converted to Result.Failure
  • Type-safe Pipeline Behavior - Works with both Result and Result<T> responses
  • Zero Configuration - Single extension method to enable
  • Fluent Integration - Seamlessly integrates with existing MediatR setup

🚀 Installation

This is a private NuGet package. Configure your NuGet source first:

dotnet nuget add source https://your-private-feed-url --name PrivateFeed

Then install both packages:

dotnet add package ResultKit
dotnet add package ResultKit.MediatR

📖 Usage

1. Register MediatR + ResultKit Pipeline

using ResultKit.MediatR;

var builder = WebApplication.CreateBuilder(args);

// Register MediatR
builder.Services.AddMediatR(cfg => 
    cfg.RegisterServicesFromAssemblyContaining<Program>());

// Add ResultKit pipeline behavior
builder.Services.AddResultKitMediatR();

2. Write Handlers that Return Result

using MediatR;
using ResultKit;

// Command
public record CreateUserCommand(string Email, string Password) : IRequest<Result<Guid>>;

// Handler
public class CreateUserCommandHandler : IRequestHandler<CreateUserCommand, Result<Guid>>
{
    private readonly IUserRepository _repository;

    public CreateUserCommandHandler(IUserRepository repository)
    {
        _repository = repository;
    }

    public async Task<Result<Guid>> Handle(CreateUserCommand request, CancellationToken cancellationToken)
    {
        // Validation with error codes
        if (string.IsNullOrWhiteSpace(request.Email))
            return Result<Guid>.Failure(ResultError.Create("VALIDATION_EMAIL_REQUIRED", "Email is required"));

        if (!request.Email.Contains("@"))
            return Result<Guid>.Failure(ResultError.Create("VALIDATION_EMAIL_FORMAT", "Invalid email format"));

        // Business logic (exceptions auto-handled by pipeline)
        var user = new User(request.Email, request.Password);
        await _repository.AddAsync(user, cancellationToken);

        return Result<Guid>.Success(user.Id);
    }
}

3. Use in Controllers

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

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

    [HttpPost]
    public async Task<IActionResult> CreateUser([FromBody] CreateUserRequest request)
    {
        var command = new CreateUserCommand(request.Email, request.Password);
        var result = await _mediator.Send(command);

        return result.Match<IActionResult>(
            onSuccess: userId => Ok(new { userId }),
            onFailure: error => ResultError.Parse(error) switch
            {
                ("VALIDATION_EMAIL_REQUIRED", var msg) => BadRequest(new { error = msg }),
                ("VALIDATION_EMAIL_FORMAT", var msg) => BadRequest(new { error = msg }),
                _ => BadRequest(new { error })
            }
        );
    }
}

🎯 How It Works

Without ResultKit.MediatR

public async Task<Result<User>> Handle(GetUserQuery request, CancellationToken ct)
{
    try
    {
        var user = await _repository.FindByIdAsync(request.Id, ct);
        return user != null 
            ? Result<User>.Success(user)
            : Result<User>.Failure("User not found");
    }
    catch (Exception ex)
    {
        return Result<User>.Failure($"Database error: {ex.Message}");
    }
}

With ResultKit.MediatR (Cleaner!)

public async Task<Result<User>> Handle(GetUserQuery request, CancellationToken ct)
{
    // Exceptions automatically caught and converted to Result.Failure
    var user = await _repository.FindByIdAsync(request.Id, ct);
    
    return user != null 
        ? Result<User>.Success(user)
        : Result<User>.Failure(ResultError.Create("USER_NOT_FOUND", "User not found"));
}

The pipeline behavior automatically catches exceptions and converts them to Result.Failure(ex.Message).

📚 Advanced Usage

Validation with ErrorsResult

Collect multiple validation errors before processing (better UX than fail-fast):

public async Task<Result<Guid>> Handle(CreateUserCommand request, CancellationToken ct)
{
    // Phase 1: Collect ALL validation errors
    var validation = ErrorsResult.Collect(
        ValidateEmail(request.Email),
        ValidatePassword(request.Password),
        ValidateAge(request.Age)
    );

    if (validation.IsFailure)
    {
        return validation.ToResult<Guid>(); // Returns all errors combined
    }

    // Phase 2: Business logic with fail-fast
    if (await _repository.EmailExistsAsync(request.Email, ct))
    {
        return Result<Guid>.Failure(ResultError.Create("USER_EMAIL_EXISTS", "Email already exists"));
    }

    var user = new User(request.Email, request.Password);
    await _repository.AddAsync(user, ct);
    
    return Result<Guid>.Success(user.Id);
}

private static Result ValidateEmail(string email)
{
    if (string.IsNullOrWhiteSpace(email))
        return Result.Failure(ResultError.Create("VALIDATION_EMAIL_REQUIRED", "Email is required"));
    
    if (!email.Contains("@"))
        return Result.Failure(ResultError.Create("VALIDATION_EMAIL_FORMAT", "Invalid email format"));
    
    return Result.Success();
}

Response on validation failure:

{
  "errors": [
    "VALIDATION_EMAIL_REQUIRED: Email is required",
    "VALIDATION_PASSWORD_TOO_SHORT: Password must be at least 8 characters"
  ]
}

Custom Error Handling

If you need custom exception handling, you can still catch specific exceptions:

public async Task<Result<User>> Handle(GetUserQuery request, CancellationToken ct)
{
    try
    {
        var user = await _repository.FindByIdAsync(request.Id, ct);
        return Result<User>.Success(user);
    }
    catch (UserNotFoundException ex)
    {
        return Result<User>.Failure($"User {request.Id} not found");
    }
    // Other exceptions still handled by pipeline
}

Combining with ResultKit Extensions

public async Task<Result<UserDto>> Handle(GetUserQuery request, CancellationToken ct)
{
    return await _repository.FindByIdAsync(request.Id, ct)
        .ToResult($"User {request.Id} not found")
        .MapAsync(user => new UserDto(user.Name, user.Email))
        .TapAsync(dto => _logger.LogInformation("Retrieved user: {Name}", dto.Name));
}

🏗️ API Reference

ServiceCollectionExtensions

Method Description
AddResultKitMediatR(this IServiceCollection) Registers the ResultKit pipeline behavior

ResultPipelineBehavior<TRequest, TResponse>

Automatically registered pipeline behavior that:

  • Catches unhandled exceptions in handlers
  • Converts them to Result.Failure(exception.Message)
  • Only applies to handlers returning Result or Result<T>

🔧 Requirements

  • .NET 8.0 or higher
  • MediatR 12.0 or higher
  • ResultKit 1.0 or higher

📝 License

Copyright (c) 2026 Károly Akácz. All rights reserved.

This is proprietary software for internal use only.

👤 Author

Károly Akácz

  • ResultKit - Core result handling library
  • MediatR - Simple mediator implementation in .NET

Note: This is a private NuGet package. Ensure you have proper access credentials configured.

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 is compatible.  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.2.0 82 2/10/2026
1.1.0 82 2/9/2026
1.0.0 83 2/8/2026

Version 1.2.0: Updated to Fox.ResultKit 1.2.0 with ErrorsResult support. See CHANGELOG.md for details.