ASP.NET Core error handling: ProblemDetails (RFC 9457) with a global IExceptionHandler

ASP.NET Core Interview Q&A November 13, 2026 csharp

With ProblemDetails (RFC 9457) and a central IExceptionHandler.

csharp
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
// ======================================================================
// Q: How do you handle errors consistently in an API?
//
// With ProblemDetails (RFC 9457) and a central IExceptionHandler. Stack traces
// never reach the client.
// ======================================================================

builder.Services.AddProblemDetails();
builder.Services.AddExceptionHandler<GlobalExceptionHandler>();

public class GlobalExceptionHandler(ILogger<GlobalExceptionHandler> log) : IExceptionHandler
{
    public async ValueTask<bool> TryHandleAsync(HttpContext ctx, Exception ex, CancellationToken ct)
    {
        var (status, title) = ex switch
        {
            ValidationException => (400, "Validation failed"),
            NotFoundException   => (404, "Not found"),
            _                   => (500, "Unexpected error")
        };
        if (status == 500) log.LogError(ex, "Unhandled exception");

        ctx.Response.StatusCode = status;
        await ctx.Response.WriteAsJsonAsync(new ProblemDetails
        {
            Status = status, Title = title,
            Extensions = { ["traceId"] = ctx.TraceIdentifier }
        }, ct);
        return true;
    }
}