dotnet / aspnetcore

ASP.NET Core is a cross-platform .NET framework for building modern cloud-based web applications on Windows, Mac, or Linux.
https://asp.net
MIT License
35.4k stars 10k forks source link

Problem details middleware ignores response status code when handling an exception. #58130

Open kjkrum opened 4 weeks ago

kjkrum commented 4 weeks ago

Is there an existing issue for this?

Describe the bug

I tried to use problem details middleware and exception handler middleware in this manner:

builder.Services.AddExceptionHandler<MyExceptionHandler>();
builder.Services.AddProblemDetails(options =>
{
    options.CustomizeProblemDetails = context =>
    {
        if (context.Exception is MyUserFacingException)
        {
            context.ProblemDetails.Details = context.Exception.Message;
        }   
    };
});

app.UseStatusCodePages();
app.UseExceptionHandler();

If the exception handler returns true then ProblemDetailsContext.Exception is null. I think this makes sense since the handler returning true means the exception does not propagate. The problem details middleware initializes ProblemDetailsContext.ProblemDetails to whatever status code was set by the exception handling middleware.

If the exception handler returns false, then the exception is available in ProblemDetailsContext.Exception, which is good. But now the problem details middleware always initializes ProblemDetailsContext.ProblemDetails as a 500, ignoring the status code set by the exception handler middleware. And there's no way to leverage the existing defaults to re-initialize it (https://github.com/dotnet/aspnetcore/issues/47978). The actual HTTP response code is the one set by the exception handler, not the 500 shown in the problem details.

Searching the code base for uses of ProblemDetailsDefaults.Apply, the only place it's called with a null status code that would result in it defaulting to 500 is here:

https://github.com/dotnet/aspnetcore/blob/6b9bba1472da66a9f02ae3cd0f564ad6e2bb5fff/src/Http/Http.Results/src/ProblemHttpResult.cs#L24

Expected Behavior

The problem details middleware should always initialize ProblemDetailsContext.ProblemDetails using HttpContext.Response.StatusCode.

Steps To Reproduce

No response

Exceptions (if any)

No response

.NET Version

8.0.400

Anything else?

No response

kjkrum commented 3 weeks ago

My workaround is for the exception handler to always return true and pass user-facing information to problem details via HttpContext.Items.