UseCasePipeline 1.0.9
dotnet add package UseCasePipeline --version 1.0.9
NuGet\Install-Package UseCasePipeline -Version 1.0.9
<PackageReference Include="UseCasePipeline" Version="1.0.9" />
<PackageVersion Include="UseCasePipeline" Version="1.0.9" />
<PackageReference Include="UseCasePipeline" />
paket add UseCasePipeline --version 1.0.9
#r "nuget: UseCasePipeline, 1.0.9"
#:package UseCasePipeline@1.0.9
#addin nuget:?package=UseCasePipeline&version=1.0.9
#tool nuget:?package=UseCasePipeline&version=1.0.9
UseCasePipeline
A lightweight UseCase pipeline library for .NET 8+. Implement clean, structured use cases with built-in support for request validation, entity validation, rule enforcement, authorisation, custom pipes, and a mediator — all wired up automatically via DI.
Installation
dotnet add package UseCasePipeline
Getting Started
1. Register the pipeline
In Program.cs, call AddUseCasePipeline() with no arguments. It automatically scans every assembly in your app that references this library:
using UseCasePipeline.Extensions;
using UseCasePipeline.Middleware;
builder.Services.AddUseCasePipeline();
var app = builder.Build();
// Optional: maps pipeline exceptions to HTTP responses automatically
app.UseUseCasePipelineExceptionHandler();
2. Define a request and response
using UseCasePipeline.Infrastructure;
public class CreateOrderRequest : IUseCaseRequest<CreateOrderResponse>
{
public Guid CustomerId { get; set; }
public List<Guid> ProductIds { get; set; } = [];
}
public class CreateOrderResponse : IUseCaseResponse
{
public Guid OrderId { get; set; }
}
3. Implement the handler
using UseCasePipeline.Infrastructure;
public class CreateOrderHandler : IUseCaseHandler<CreateOrderRequest, CreateOrderResponse>
{
public async Task<CreateOrderResponse> Handle(CreateOrderRequest request, CancellationToken cancellationToken)
{
// core use case logic
return new CreateOrderResponse { OrderId = Guid.NewGuid() };
}
}
4. Add optional pipeline stages
All stages are optional. Register as many as you need per use case.
Request Validator — validates the incoming request data:
public class CreateOrderRequestValidator : IUseCaseRequestValidator<CreateOrderRequest>
{
public Task Validate(CreateOrderRequest request, CancellationToken cancellationToken)
{
if (request.ProductIds.Count == 0)
throw new UseCaseValidationException("At least one product is required.");
return Task.CompletedTask;
}
}
Entity Validator — checks required entities exist before the handler runs:
public class CreateOrderEntityValidator : IUseCaseEntityValidator<CreateOrderRequest>
{
public async Task Validate(CreateOrderRequest request, CancellationToken cancellationToken)
{
var customer = await _repo.FindCustomerAsync(request.CustomerId);
if (customer is null)
throw new UseCaseEntityNotFoundException(nameof(Customer), request.CustomerId);
}
}
Authoriser — enforces permissions:
public class CreateOrderAuthoriser : IUseCaseAuthoriser<CreateOrderRequest>
{
public Task Authorise(CreateOrderRequest request, CancellationToken cancellationToken)
{
if (!_currentUser.CanCreateOrders)
throw new UseCaseAuthorisationException();
return Task.CompletedTask;
}
}
Rule Enforcer — enforces business rules after validation and before the handler runs:
public class CreateOrderRuleEnforcer : IUseCaseRuleEnforcer<CreateOrderRequest>
{
public Task Enforce(CreateOrderRequest request, CancellationToken cancellationToken)
{
if (!_orderingRules.CustomerCanPlaceOrder(request.CustomerId))
throw new UseCaseRuleViolationException("Customer cannot place orders at this time.");
return Task.CompletedTask;
}
}
Custom Pipe - runs custom use-case pipeline logic after the built-in authorisation, validation, entity validation, and rule enforcement stages, but before the handler:
public class CreateOrderAuditPipe : IUseCaseCustomPipe<CreateOrderRequest>
{
public Task InvokeAsync(CreateOrderRequest request, CancellationToken cancellationToken)
{
// custom pipeline logic, such as auditing, enrichment, or instrumentation
return Task.CompletedTask;
}
}
5. Send a request
Inject UseCaseMediator and call Send. The response type is inferred automatically:
public class OrdersController(UseCaseMediator mediator) : ControllerBase
{
[HttpPost]
public async Task<IActionResult> Create(CreateOrderRequest request, CancellationToken cancellationToken)
{
var response = await mediator.Send(request, cancellationToken);
return Ok(response);
}
}
Pipeline Execution Order
For every Send call the pipeline runs stages in this order:
Authoriser(s) -> Request Validator(s) -> Entity Validator(s) -> Rule Enforcer(s) -> Custom Pipe(s) -> Handler
All stages are optional. Multiple implementations of the same stage are all executed sequentially in registration order.
Exception Middleware
UseUseCasePipelineExceptionHandler() catches pipeline exceptions and maps them to HTTP responses:
| Exception | Status Code |
|---|---|
UseCaseValidationException |
400 Bad Request |
UseCaseEntityNotFoundException |
404 Not Found |
UseCaseAuthorisationException |
403 Forbidden |
UseCaseRuleViolationException |
400 Bad Request |
| Any other exception | Propagates unhandled |
Command-style Use Cases (no response)
For use cases that produce no result, implement IUseCaseRequest and IUseCaseHandler<TRequest> directly:
public class DeleteOrderRequest : IUseCaseRequest
{
public Guid OrderId { get; set; }
}
public class DeleteOrderHandler : IUseCaseHandler<DeleteOrderRequest>
{
public async Task Handle(DeleteOrderRequest request, CancellationToken cancellationToken)
{
// delete logic
}
}
// Send with no return value
await mediator.Send(new DeleteOrderRequest { OrderId = id });
License
MIT
| 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 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. |
-
net8.0
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.