ASP.NET 基于 HTTP 状态代码的 MVC 6 处理错误

ASP.NET MVC 6 handling errors based on HTTP status code

我想为每个状态代码显示不同的错误消息,例如:

如何在新的 ASP.NET MVC 6 应用程序中实现这一点?我可以使用内置的 UseErrorHandler 方法执行此操作吗?

application.UseErrorHandler("/error");

此外,我注意到即使使用上述处理程序,输入一个不存在的 URL 例如/this-page-does-not-exist,导致 IIS 出现难看的 404 Not Found 错误页面。这也可以如何处理?

在 MVC 5 中,我们必须使用 system.web customerrors 部分 ASP.NET system.webServer httpErrors 部分 web.config 文件,但很难处理一个笨重的文件,有很多非常奇怪的行为。 MVC 6 是否使这变得更简单?

How can I achieve this in the new ASP.NET MVC 6 applications? Can I do this using the built in UseErrorHandler method?

快速回答:不优雅。

Explanation/Alternative: 首先让我们先看看 UseErrorHandler 方法实际做了什么: https://github.com/aspnet/Diagnostics/blob/6dbbe831c493e6e7259de81f83a04d1654170137/src/Microsoft.AspNet.Diagnostics/ErrorHandlerExtensions.cs#L25 which adds the following middleware: https://github.com/aspnet/Diagnostics/blob/6dbbe831c493e6e7259de81f83a04d1654170137/src/Microsoft.AspNet.Diagnostics/ErrorHandlerMiddleware.cs 注意 第 29-78 行(调用方法)

只要有请求进入,就会执行 invoke 方法(由 application.UseErrorHandler("...")Startup.cs 中的位置控制)。所以 UseErrorHandler 是添加自定义中间件的一种美化方式:中间件 = 可以处理 http 请求的组件。

现在有了这个背景,如果我们想添加我们自己的区分请求的错误中间件。我们可以通过修改这些行来添加类似于默认 ErrorHandlerMiddleware 的类似中间件来做到这一点: https://github.com/aspnet/Diagnostics/blob/6dbbe831c493e6e7259de81f83a04d1654170137/src/Microsoft.AspNet.Diagnostics/ErrorHandlerMiddleware.cs#L48-L51 使用这种方法,我们可以根据状态代码控制重定向路径。

In MVC 5 we have had to use the system.web customerrors section for ASP.NET and the system.webServer httpErrors section in the web.config file but it was difficult to work with an unwieldy, with lots of very strange behaviour. Does MVC 6 make this a lot simpler?

答案: 确实如此 :)。就像上面的答案一样,解决方法在于添加中间件。通过 Startup.cs 中的 IApplicationBuilder 添加简单的中间件有一个快捷方式;在 Configure 方法的末尾,您可以添加以下内容:

app.Run(async (context) =>
{
    await context.Response.WriteAsync("Could not handle the request.");

    // Nothing else will run after this middleware.
});

这会起作用,因为这意味着您到达了 http 管道的末尾,但请求未被处理(因为它在 Startup.cs 中的 Configure 方法的末尾)。如果你想添加这个中间件(以快速方式)并选择在你之后执行中间件,方法如下:

app.Use(async (context, next) =>
{
    await context.Response.WriteAsync("Could not handle the request.");

    // This ensures that any other middelware added after you runs.
    await next();
});

希望对您有所帮助!

您可以为此使用 StatusCodePagesMiddleware。下面是一个例子:

public void Configure(IApplicationBuilder app, ILoggerFactory loggerFactory)
{
    app.UseStatusCodePagesWithReExecute("/StatusCodes/StatusCode{0}");

    app.UseMvcWithDefaultRoute();

处理状态代码请求的控制器:

public class StatusCodesController : Controller
{
    public IActionResult StatusCode404()
    {
        return View(viewName: "NotFound"); // you have a view called NotFound.cshtml
    }

    ... more actions here to handle other status codes
}

一些注意事项:

  • 检查其他扩展方法,例如 UseStatusCodePagesWithRedirects UseStatusCodePages 其他功能。
  • 我在示例中尝试将 StatusCode 作为查询字符串,但看起来像这样 中间件不处理查询字符串,但你可以看看 this 编写代码并修复此问题。