aspnetcore
aspnetcore copied to clipboard
Mapping Exception x StatusCode in ExceptionHandlerMiddleware
Background and Motivation
In .NET 7 the ExceptionHandlerMiddleware
was updated to generate a Problem Details
when the IProblemDetailsService
is registered.
While this change allows a consistent ProblemDetails
for the application the default handler for ExceptionHandlerMiddleware
always sets the response status code to 500
and changing to produce a different Status Code requires a custom implementation (as mentioned here #43831).
Proposed API
The community ProblemDetails
middleware (https://github.com/khellang/Middleware) has a capability to map an Exception to Status Code when producing the payload. Since the ExceptionHandlerMiddleware
is the built-in feature to handle exception, my suggestion is to add a similar feature to allow mapping exception type
X status code
every time an exception is handled.
namespace Microsoft.AspNetCore.Builder;
public class ExceptionHandlerOptions
{
+ public void Map<TException>(int statusCode) where TException : Exception {}
+ public bool TryGetMap(Exception exception, out int statusCode) {}
}
Usage Examples
Configuring the ExceptionHandlerOptions
var builder = WebApplication.CreateBuilder(args);
// Add services to the container.
builder.Services.AddExceptionHandler(o =>
{
o.Map<InvalidOperationException>(400);
});
var app = builder.Build();
app.UseExceptionHandler();
app.MapGet("/", () =>
{
throw new InvalidOperationException();
});
app.Run();
Setting ExceptionHandlerOptions
directly to the middleware
var app = WebApplication.Create(args);
var options = new ExceptionHandlerOptions();
options.Map<InvalidOperationException>(400);
app.UseExceptionHandler(options);
app.MapGet("/", () =>
{
throw new InvalidOperationException();
});
app.Run();
Alternative Designs
Alternative names
public void AddMap<TException>(int statusCode) where TException : Exception {}
public void MapStatusCode<TException>(int statusCode) where TException : Exception {}
public void MapToStatusCode<TException>(int statusCode) where TException : Exception {}
Using a property instead
namespace Microsoft.AspNetCore.Builder;
public class ExceptionHandlerOptions
{
+ public IDictionary<Type, int> StatusCodeMapping { get; } = new Dictionary<Type, int>();
}
The disadvantage of this design is the Dictionary
potentially accepts any type, not necessarily an Exception
type.
cc @khellang