MStack.ErrorHandling
1.0.2
dotnet add package MStack.ErrorHandling --version 1.0.2
NuGet\Install-Package MStack.ErrorHandling -Version 1.0.2
<PackageReference Include="MStack.ErrorHandling" Version="1.0.2" />
<PackageVersion Include="MStack.ErrorHandling" Version="1.0.2" />
<PackageReference Include="MStack.ErrorHandling" />
paket add MStack.ErrorHandling --version 1.0.2
#r "nuget: MStack.ErrorHandling, 1.0.2"
#:package MStack.ErrorHandling@1.0.2
#addin nuget:?package=MStack.ErrorHandling&version=1.0.2
#tool nuget:?package=MStack.ErrorHandling&version=1.0.2
MStack.ErrorHandling
Result pattern + RFC 9457 ProblemDetails for ASP.NET Core. One package: typed results, categorised errors, and a middleware that turns failures into well-formed HTTP responses.
Why
| Problem | What this package gives you |
|---|---|
Returning Result<T> everywhere |
Result, Result<T>, Map, Bind, Match, Tap. |
| Reusing the same Error shape across the codebase | Error(Code, Message, Category) with factory methods per category. |
| Mapping failures to HTTP status codes by hand | ResultEndpointExtensions.ToHttpResult(httpContext) does it for you. |
| Standardising exception responses | app.UseMStackErrorHandling() returns RFC 9457 ProblemDetails for any uncaught exception. |
Install
dotnet add package MStack.ErrorHandling
Quick start
1. Register
using MStack.ErrorHandling;
builder.Services.AddMStackErrorHandling(opts =>
{
opts.IncludeExceptionDetails = builder.Environment.IsDevelopment();
});
var app = builder.Build();
app.UseMStackErrorHandling(); // first in the pipeline
2. Return Result from your handlers
public sealed class GetUserHandler(IUserRepository users)
{
public async Task<Result<UserDto>> HandleAsync(Guid id, CancellationToken ct)
{
var user = await users.GetByIdAsync(id, ct);
return user is null
? Error.NotFound("User", id)
: new UserDto(user.Id, user.Email);
}
}
3. Map to HTTP from Minimal APIs
app.MapGet("/users/{id:guid}", async (Guid id, GetUserHandler handler, HttpContext ctx, CancellationToken ct) =>
(await handler.HandleAsync(id, ct)).ToHttpResult(ctx));
That gives you 200 OK on success, or a fully-formed application/problem+json response on failure.
API surface
public sealed record Error(string Code, string Message, ErrorCategory Category)
{
public static Error Validation(string code, string message);
public static Error NotFound(string entity, object id);
public static Error Conflict(string entity, string message);
public static Error Forbidden(string message = "Access is forbidden.");
public static Error Unauthorized(string message = "Authentication is required.");
public static Error BusinessRule(string code, string message);
public static Error Unexpected(string message = "An unexpected error occurred.");
public static readonly Error None;
}
public class Result {
public bool IsSuccess { get; }
public bool IsFailure { get; }
public Error Error { get; }
public IReadOnlyList<Error> Errors { get; }
public ErrorCategory Category { get; }
public static Result Success();
public static Result Failure(Error error);
public static Result Failure(IEnumerable<Error> errors);
public static Result<T> Success<T>(T value);
public static Result<T> Failure<T>(Error error);
public static Result<T> Failure<T>(IEnumerable<Error> errors);
public static implicit operator Result(Error error);
}
public sealed class Result<T> : Result {
public T Value { get; }
public static implicit operator Result<T>(T value);
public static implicit operator Result<T>(Error error);
}
// Functional helpers
public static class ResultExtensions {
public static Result<TOut> Map<TIn, TOut>(this Result<TIn>, Func<TIn, TOut>);
public static Result<TOut> Bind<TIn, TOut>(this Result<TIn>, Func<TIn, Result<TOut>>);
public static TOut Match<TIn, TOut>(this Result<TIn>, Func<TIn, TOut>, Func<IReadOnlyList<Error>, TOut>);
public static TOut Match<TOut>(this Result, Func<TOut>, Func<IReadOnlyList<Error>, TOut>);
public static Result<T> Tap<T>(this Result<T>, Action<T>);
public static Result<T> TapError<T>(this Result<T>, Action<IReadOnlyList<Error>>);
}
// Minimal API
public static class ResultEndpointExtensions {
public static IResult ToHttpResult<T>(this Result<T>, HttpContext);
public static IResult ToHttpResult<T>(this Result<T>, HttpContext, Func<T, IResult>);
public static IResult ToHttpResult(this Result, HttpContext);
}
// Pipeline
public static class ServiceCollectionExtensions {
public static IServiceCollection AddMStackErrorHandling(this IServiceCollection);
public static IServiceCollection AddMStackErrorHandling(this IServiceCollection, Action<ErrorHandlingOptions>);
public static IApplicationBuilder UseMStackErrorHandling(this IApplicationBuilder);
}
ErrorCategory → HTTP status
ErrorCategory |
HTTP | Notes |
|---|---|---|
Validation |
400 | Becomes ValidationProblemDetails |
NotFound |
404 | |
Conflict |
409 | |
Forbidden |
403 | |
Unauthorized |
401 | |
BusinessRule |
422 | Becomes ValidationProblemDetails |
Unexpected |
500 | |
None |
500 | Fallback — should never reach HTTP |
License
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | 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
- No dependencies.
NuGet packages (1)
Showing the top 1 NuGet packages that depend on MStack.ErrorHandling:
| Package | Downloads |
|---|---|
|
MStack.ValueObjects
Value Object base classes for DDD plus a curated set of ready-to-use value objects (Email, Slug, Money, Cpf, Cnpj, Cep, PhoneNumberBr...). Construction returns Result<T> from MStack.ErrorHandling so failures compose naturally with the rest of your application. |
GitHub repositories
This package is not used by any popular GitHub repositories.