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
<PackageReference Include="Fox.ResultKit.MediatR" Version="1.2.0" />
<PackageVersion Include="Fox.ResultKit.MediatR" Version="1.2.0" />
<PackageReference Include="Fox.ResultKit.MediatR" />
paket add Fox.ResultKit.MediatR --version 1.2.0
#r "nuget: Fox.ResultKit.MediatR, 1.2.0"
#:package Fox.ResultKit.MediatR@1.2.0
#addin nuget:?package=Fox.ResultKit.MediatR&version=1.2.0
#tool nuget:?package=Fox.ResultKit.MediatR&version=1.2.0
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
ResultandResult<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
ResultorResult<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
- GitHub: @akikari
- Repository: ResultKit.MediatR
🔗 Related Packages
Note: This is a private NuGet package. Ensure you have proper access credentials configured.
| Product | Versions 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. |
-
net10.0
- Fox.ResultKit (>= 1.2.0)
- MediatR (>= 12.4.1)
-
net8.0
- Fox.ResultKit (>= 1.2.0)
- MediatR (>= 12.4.1)
-
net9.0
- Fox.ResultKit (>= 1.2.0)
- MediatR (>= 12.4.1)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
Version 1.2.0: Updated to Fox.ResultKit 1.2.0 with ErrorsResult support. See CHANGELOG.md for details.