Roadmap › ASP.NET Core Web API & REST › Module: Building Robust APIs
Lessons in this course (15)

6. Global error handling with ProblemDetails

Intermediate★ Must knowLesson 6 of 15
csharp
builder.Services.AddProblemDetails();
builder.Services.AddExceptionHandler<GlobalExceptionHandler>();

public class GlobalExceptionHandler(ILogger<GlobalExceptionHandler> log, IProblemDetailsService pd) : IExceptionHandler
{
    public async ValueTask<bool> TryHandleAsync(HttpContext ctx, Exception ex, CancellationToken ct)
    {
        var (status, title) = ex switch
        {
            NotFoundException => (404, "Not found"),
            ValidationException => (400, "Validation failed"),
            ConflictException => (409, "Conflict"),
            _ => (500, "Unexpected error")
        };
        if (status == 500) log.LogError(ex, "Unhandled exception");
        ctx.Response.StatusCode = status;
        return await pd.TryWriteAsync(new() { HttpContext = ctx, ProblemDetails = { Status = status, Title = title }, Exception = ex });
    }
}
app.UseExceptionHandler();
app.UseStatusCodePages();

ProblemDetails (RFC 9457, formerly 7807) is the standard JSON error shape: type, title, status, detail, instance, plus extensions such as traceId and errors.