EasyRequestHandler 1.1.5
See the version list below for details.
dotnet add package EasyRequestHandler --version 1.1.5
NuGet\Install-Package EasyRequestHandler -Version 1.1.5
<PackageReference Include="EasyRequestHandler" Version="1.1.5" />
<PackageVersion Include="EasyRequestHandler" Version="1.1.5" />
<PackageReference Include="EasyRequestHandler" />
paket add EasyRequestHandler --version 1.1.5
#r "nuget: EasyRequestHandler, 1.1.5"
#:package EasyRequestHandler@1.1.5
#addin nuget:?package=EasyRequestHandler&version=1.1.5
#tool nuget:?package=EasyRequestHandler&version=1.1.5
Easy Request Handler
EasyRequestHandler is a lightweight and extensible .NET library that simplifies request and event handling using patterns like Mediator and Event Dispatcher. It integrates seamlessly with the .NET Dependency Injection (DI) system and supports asynchronous operations, making it ideal for modular applications and event-driven systems.
β¨ Features
Core Capabilities
- π― Mediator Pattern: Centralizes request handling with the
ISenderinterface, promoting loose coupling and separation of concerns - π Flexible Request Handling: Support for both input-based (
RequestHandler<TRequest, TResponse>) and no-input handlers (RequestHandler<TResponse>) - π‘ Event Dispatching: Publish events to multiple handlers with support for both sequential and parallel execution
- π Automatic Registration: Register all handlers with a single fluent API call using
IServiceCollectionextensions - πͺ Request Hooks: Execute logic before and/or after request handling with three types of hooks:
IRequestHook<TRequest, TResponse>- Pre and post executionIRequestPreHook<TRequest>- Pre-execution onlyIRequestPostHook<TRequest, TResponse>- Post-execution only
- π§ Pipeline Behaviors: Add cross-cutting concerns (logging, validation, caching, etc.) as middleware-style behaviors
- π Built-in Logging: Optional structured logging with contextual information for debugging and monitoring
- β‘ Performance Optimized: Singleton pattern for no-input requests, optimized task handling, and minimal allocations
- π Type-Safe: Fully generic, compile-time type checking for requests, responses, and events
- π§ͺ Testable: Clean abstractions make unit testing straightforward
Key Benefits
- β Minimal Boilerplate: Define handlers as simple classesβno complex setup required
- β DI-First Design: Built on Microsoft.Extensions.DependencyInjection for seamless integration
- β Async by Default: All operations use Task-based async patterns for scalability
- β Zero Breaking Changes: Backward compatible design maintains existing functionality
- β Production Ready: Comprehensive error handling, cancellation support, and security validated
π¦ Installation
Install from NuGet using the .NET CLI:
dotnet add package EasyRequestHandler
Or using Package Manager Console:
Install-Package EasyRequestHandler
π― Why Choose EasyRequestHandler?
Compared to MediatR
- Simpler API: No need for
IRequest<T>marker interfaces on your request types - Built-in Hooks: Pre/post execution hooks without additional packages
- Event Publishing: Native support for event dispatching with parallel execution
- Lightweight: Minimal dependencies and smaller footprint
Compared to Custom Solutions
- Battle-Tested: Proven patterns and comprehensive error handling
- Extensible: Easy to add behaviors, hooks, and custom logic
- Maintained: Regular updates and security fixes
- Well-Documented: Clear examples and API documentation
π Quick Start
Here's a minimal example to get started in 3 steps:
1. Define Your Request and Handler
// Your request
public class CalculateRequest
{
public int X { get; set; }
public int Y { get; set; }
}
// Your response
public class CalculateResponse
{
public int Sum { get; set; }
}
// Your handler
public class CalculateHandler : RequestHandler<CalculateRequest, CalculateResponse>
{
public override Task<CalculateResponse> HandleAsync(CalculateRequest request, CancellationToken cancellationToken = default)
{
return Task.FromResult(new CalculateResponse { Sum = request.X + request.Y });
}
}
2. Register in DI Container
// In Program.cs or Startup.cs
services.AddEasyRequestHandlers(typeof(Program))
.WithMediatorPattern() // Optional: enable ISender
.Build();
3. Use in Your Application
public class CalculatorController : ControllerBase
{
private readonly ISender _sender;
public CalculatorController(ISender sender) => _sender = sender;
[HttpGet("calculate")]
public async Task<IActionResult> Calculate(int x, int y)
{
var result = await _sender.SendAsync<CalculateRequest, CalculateResponse>(
new CalculateRequest { X = x, Y = y });
return Ok(result);
}
}
That's it! Your handler is automatically discovered, registered, and ready to use.
π Usage
π§ Request Handling
Basic Request Handlers
Handlers can be used in two ways:
- Direct Injection: Inject the handler class itself (e.g.,
MyRequestHandler) into your controller or service and callHandleAsync()directly. - Mediator Pattern: Use the
ISenderinterface to decouple request handling and improve testability and separation of concerns.
Hereβs how you could invoke a request using the ISender interface:
public class MyApiController : ControllerBase
{
private readonly ISender _sender;
public MyApiController(ISender sender)
{
_sender = sender;
}
[HttpGet("double")]
public async Task<IActionResult> GetDoubledNumber([FromQuery] int number)
{
var response = await _sender.SendAsync<MyRequest, MyResponse>(new MyRequest { Number = number });
return Ok(response.Result);
}
}
Define a request and handler:
public class MyRequest
{
public int Number { get; set; }
}
public class MyResponse
{
public int Result { get; set; }
}
public class MyRequestHandler : RequestHandler<MyRequest, MyResponse>
{
public override Task<MyResponse> HandleAsync(MyRequest request, CancellationToken cancellationToken = default)
{
return Task.FromResult(new MyResponse { Result = request.Number * 2 });
}
}
For handlers with no input request:
public class WeatherForecastHandler : RequestHandler<List<WeatherForecast>>
{
public override Task<List<WeatherForecast>> HandleAsync(CancellationToken cancellationToken = default)
{
return Task.FromResult(GetForecasts());
}
}
Mediator Pattern
Use the ISender interface to decouple request invocation:
public async Task<IActionResult> GetForecast(string city, ISender sender)
{
var forecast = await sender.SendAsync<string, WeatherForecast>(city);
return Ok(forecast);
}
Request Behaviors
Behaviors are middleware for requests:
public class LoggingBehaviour<TRequest, TResponse> : IPipelineBehaviour<TRequest, TResponse>
{
private readonly ILogger<LoggingBehaviour<TRequest, TResponse>> _logger;
public LoggingBehaviour(ILogger<LoggingBehaviour<TRequest, TResponse>> logger)
{
_logger = logger;
}
public async Task<TResponse> Handle(TRequest request, CancellationToken cancellationToken, RequestHandlerDelegate<TResponse> next)
{
_logger.LogInformation("Handling {RequestType}", typeof(TRequest).Name);
var response = await next();
_logger.LogInformation("Handled {RequestType}", typeof(TRequest).Name);
return response;
}
}
Request Hooks
The library now supports three different types of hooks to provide more flexibility in your request processing pipeline:
// Complete hook (both pre and post execution)
public class MyRequestHook : IRequestHook<MyRequest, MyResponse>
{
public Task OnExecutingAsync(MyRequest request, CancellationToken cancellationToken)
{
Console.WriteLine("Before handling request");
return Task.CompletedTask;
}
public Task OnExecutedAsync(MyRequest request, MyResponse response, CancellationToken cancellationToken)
{
Console.WriteLine("After handling request");
return Task.CompletedTask;
}
}
// Pre-execution only hook
public class MyRequestPreHook : IRequestPreHook<MyRequest>
{
public Task OnExecutingAsync(MyRequest request, CancellationToken cancellationToken)
{
Console.WriteLine("Pre-hook executing");
// You can modify request properties here
return Task.CompletedTask;
}
}
// Post-execution only hook
public class MyRequestPostHook : IRequestPostHook<MyRequest, MyResponse>
{
public Task OnExecutedAsync(MyRequest request, MyResponse response, CancellationToken cancellationToken)
{
Console.WriteLine("Post-hook executed");
// You can work with both request and response here
return Task.CompletedTask;
}
}
Registration and Configuration
services.AddEasyRequestHandlers(typeof(Program))
.WithMediatorPattern()
.WithBehaviours(typeof(LoggingBehaviour<,>), typeof(ValidationBehaviour<,>))
.WithRequestHooks()
.Build();
Minimal API example:
//Using direct handler injection.
app.MapGet("/weather-forecast", async (WeatherRequest request, WeatherForecastHandler handler) =>
{
return await handler.HandleAsync(request);
});
//Using Mediator Pattern
app.MapGet("/weather-forecast", async (WeatherRequest request, ISender sender) =>
{
return await sender.SendAsync<WeatherRequest, WeatherForecast?>(request, cancellationToken: cancellationToken);
});
π£ Event Handling
A single event can have multiple handlers. All handlers registered for an event will be invoked, and they can run either sequentially or in parallel depending on the event publisher's implementation.
Basic Event Handler
public class MyEvent
{
public string Message { get; set; }
}
public class MyEventHandler : IEventHandler<MyEvent>
{
public Task HandleAsync(MyEvent @event, CancellationToken cancellationToken)
{
Console.WriteLine(@event.Message);
return Task.CompletedTask;
}
}
Publishing Events
public class MyController
{
private readonly IEventPublisher _publisher;
public MyController(IEventPublisher publisher)
{
_publisher = publisher;
}
public async Task SendNotification(string message)
{
await _publisher.PublishAsync(new MyEvent { Message = message });
}
}
β Summary
EasyRequestHandler provides a clean, extensible way to manage requests and events in .NET, with support for modern patterns like mediator, behaviors, and hooksβall without unnecessary boilerplate.
Perfect For
- β CQRS Applications: Separate command and query handling with clear boundaries
- β Clean Architecture: Enforce separation of concerns and dependency inversion
- β Event-Driven Systems: Publish domain events and handle them asynchronously
- β Microservices: Standardize request/event handling across services
- β API Development: Build maintainable REST APIs with consistent patterns
Getting Help
- π Documentation - Full API reference and examples
- π Issues - Report bugs or request features
- π¬ Discussions - Ask questions and share ideas
Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
π License
Licensed under MIT License.
Made with β€οΈ by Juan Carlos Torres Cuervo
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net5.0 was computed. net5.0-windows was computed. net6.0 was computed. net6.0-android was computed. net6.0-ios was computed. net6.0-maccatalyst was computed. net6.0-macos was computed. net6.0-tvos was computed. net6.0-windows was computed. net7.0 was computed. net7.0-android was computed. net7.0-ios was computed. net7.0-maccatalyst was computed. net7.0-macos was computed. net7.0-tvos was computed. net7.0-windows was computed. net8.0 was computed. 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. |
| .NET Core | netcoreapp3.0 was computed. netcoreapp3.1 was computed. |
| .NET Standard | netstandard2.1 is compatible. |
| MonoAndroid | monoandroid was computed. |
| MonoMac | monomac was computed. |
| MonoTouch | monotouch was computed. |
| Tizen | tizen60 was computed. |
| Xamarin.iOS | xamarinios was computed. |
| Xamarin.Mac | xamarinmac was computed. |
| Xamarin.TVOS | xamarintvos was computed. |
| Xamarin.WatchOS | xamarinwatchos was computed. |
-
.NETStandard 2.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 | Downloads | Last Updated |
|---|---|---|
| 1.2.0 | 359 | 3/14/2026 |
| 1.1.5 | 138 | 2/16/2026 |
| 1.1.3 | 1,096 | 7/23/2025 |
| 1.1.2 | 249 | 7/16/2025 |
| 1.1.1 | 222 | 7/8/2025 |
| 1.1.0 | 220 | 7/7/2025 |
| 1.0.9 | 218 | 7/7/2025 |
| 1.0.8 | 179 | 7/5/2025 |
| 1.0.7 | 453 | 4/10/2025 |
| 1.0.6 | 238 | 4/10/2025 |
| 1.0.4 | 1,574 | 9/2/2024 |
| 1.0.3 | 200 | 8/30/2024 |
| 1.0.2 | 192 | 8/30/2024 |
| 1.0.1 | 186 | 8/30/2024 |
| 1.0.0 | 212 | 8/30/2024 |