Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Disabling StatusCodePages middleware for API requests

I am using asp.net core 2.1, the source for StatusCodePagesMiddleware.cs

if (!statusCodeFeature.Enabled)
{
    // Check if the feature is still available because other middleware (such as a web API written in MVC) could
    // have disabled the feature to prevent HTML status code responses from showing up to an API client.
    return;
}

appears to present the assumption that the API middleware disables the handler, however it does not. Is there a cleaner way to enable the middleware only for MVC requests without a call to app.UseWhen and checking the path string, or is this the best approach?

app.UseWhen(
    context => !context.Request.Path.Value.StartsWith("/api", StringComparison.OrdinalIgnoreCase),
    builder => builder.UseStatusCodePagesWithReExecute("/.../{0}"));
like image 875
Ritmo2k Avatar asked May 23 '26 20:05

Ritmo2k


2 Answers

It's somewhat down to interpretation, but I'd say that comment is just suggesting that something could have disabled the feature, but not that anything actually does, by default.

I don't think there's anything obviously cleaner - what you have makes sense but another option would be to use a custom middleware that toggles the feature off. Here's what that might look like:

public void Configure(IApplicationBuilder app)
{
    // ...
    app.UseStatusCodePagesWithReExecute("/.../{0}");

    app.Use(async (ctx, next) =>
    {
        if (ctx.Request.Path.Value.StartsWith("/api", StringComparison.OrdinalIgnoreCase))
        {
            var statusCodeFeature = ctx.Features.Get<IStatusCodePagesFeature>();

            if (statusCodeFeature != null && statusCodeFeature.Enabled)
                statusCodeFeature.Enabled = false;
        }

        await next();
    });

    // ...
    app.UseMvc();
    // ...
}
like image 128
Kirk Larkin Avatar answered May 26 '26 09:05

Kirk Larkin


The right answer for me was to use plain UseStatusCodePagesWithReExecute in Startup.cs but vary the handling in the error controller. This allowed me to return plain text content for API errors but retain a friendly view for users.

Startup.cs

app.UseStatusCodePagesWithReExecute("/error/{0}");

Error controller:

[HttpGet("error/{statusCode:int}")]
public IActionResult Error(int statusCode)
{
    var statusCodeFeature = HttpContext.Features.Get<IStatusCodeReExecuteFeature>();

    var exceptionDataFeature = HttpContext.Features.Get<IExceptionHandlerPathFeature>();

    // ... Other logging and stuff

    IActionResult actionResult;

    if (statusCodeFeature == null || statusCodeFeature.OriginalPath.StartsWith("/api", StringComparison.InvariantCultureIgnoreCase))
    {
        actionResult = Content($"The request could not be processed: {statusCode.ToString(CultureInfo.InvariantCulture)}");
    }
    else
    {
        ViewBag.StatusCode = statusCode;

        actionResult = View();
    }

    return actionResult;
}
like image 26
gb2d Avatar answered May 26 '26 08:05

gb2d



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!