为API请求禁用StatusCodePages中间件

时间:2018-09-09 20:00:13

标签: c# asp.net-core

我正在使用asp.net core 2.1,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;
}

似乎提出了API中间件禁用处理程序的假设,但实际上并没有。有没有一种更清洁的方法来仅对MVC请求启用中间件而无需调用app.UseWhen和检查路径字符串,还是最好的方法?

app.UseWhen(
    context => !context.Request.Path.Value.StartsWith("/api", StringComparison.OrdinalIgnoreCase),
    builder => builder.UseStatusCodePagesWithReExecute("/.../{0}"));

2 个答案:

答案 0 :(得分:1)

这在某种程度上取决于解释,但我要说的是,注释只是在暗示可以禁用该功能,但默认情况下实际上并没有任何作用。

我认为没有什么比这更清洁的了-您有道理,但另一种选择是使用可禁用该功能的自定义中间件。可能是这样的:

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();
    // ...
}

答案 1 :(得分:0)

对我来说,正确的答案是在Startup.cs中使用普通的UseStatusCodePagesWithReExecute,但会改变错误控制器中的处理方式。这使我可以返回纯文本内容以解决API错误,但可以为用户保留友好的视图。

Startup.cs

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

错误控制器:

[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;
}