如何将服务器错误的 http 状态代码捕获到 ASP.NET MVC 中的通用自定义错误视图中

How do I catch the http status code of server errors into a generic custom error view in ASP.NET MVC

我正在尝试在 ASP.NET MVC 4 中实现一个通用的自定义错误页面。 我基本上设置了一个错误布局,它定义了一个用于输出响应的 http 状态代码的部分。

我希望我的错误结束的视图继承了这样的布局,并简单地添加了一条来自其模型的消息,该消息已实例化并在调用控制器中的 View() 时传递(名为 "Error") 我设置处理自定义错误,在web.config.

<customErrors defaultRedirect="/Error" mode="On"> 
</customErrors>

自定义错误控制器:

public class ErrorController : Controller
{
    public ActionResult Index()
    {
        return View(new CustomErrorViewModel(Response.Status));
    }
}

自定义错误视图:

@{
    Layout = "~/Views/Shared/_CustomErrorLayout.cshtml";
}

@using System.Web.Configuration;
@using System.Configuration;
@using MVC_Tests.Models;
@model CustomErrorViewModel

@section HttpCode { @Response.StatusCode }

@Model.Status

布局为:

<!DOCTYPE html>
<html>
<head>
    <meta name="viewport" content="width=device-width" />
    <title></title>
    <link href="~/Content/CustomError.css" rel="stylesheet" />
</head>
<body>
    <div id="divError">
        <h1>
            <span>Error &nbsp;</span>
            @RenderSection("HttpCode")
        </h1>
        <div id="divErrorMessage">
            <p>@RenderBody()</p>
        </div>
    </div>
</body>
</html>

我试图处理的错误是我添加到主页索引操作中的一个简单的除以零。请注意,我想要一个 单一视图 来处理不同的服务器 http 状态错误代码(500 系列)。 我知道对每个不同的 http 状态代码使用不同的视图是可行的,我希望通过一个视图来处理多个代码。

自定义错误处理正在运行,我在所需的视图中结束 - 但是 - 如上所述,我希望输出错误的 http 状态代码。 相反,我总是显示 200 (OK),根据我的理解和调试,这是因为:

1.首先,在被零除时出错,引发异常。

2. 由于我的 web.config 指令以自定义方式处理错误(因为在 web.config,我在同一个 controller/view ("/Error") 中处理每个 http 状态错误代码。这里的关键是重定向是一个 new 请求。

3. 第 2 步的重定向将我发送到错误控制器,然后将我发送到它的视图,该视图已呈现。

4.渲染视图时,在布局定义部分插入http状态码,添加我的自定义消息,http状态码部分输出如下我说:200(好)。为什么,如果强制抛出 500 服务器端错误?因为,如果我没记错的话,视图是在不同的请求管道(重定向管道)中呈现的,并且在重定向中 - 没有发生错误 - 我最终得到 200(OK)状态响应。

我仔细阅读了 Dino Esposito this post 关于 asp.net mvc 中错误处理的内容,但我不想向所有应用程序的控制器(我可以创建一个具有此类过滤器的新基本控制器,并让所有其他控制器继承它,但这也需要更改所有控制器 类)。他提到的最后一种方法(处理 global.asax 的 Application_Error 事件)我不确定是否能达到这个目的——我必须在处理程序中发出重定向 "Response.Redirect" 语句,这比灵活性要差能够在 web.config 中设置自定义页面(我仍然可以重定向到 web.config 中定义的路由,但我想知道这对于看起来如此简单的东西来说是不是太麻烦了)。

将任何服务器错误的响应的 http 状态代码捕获到我的自定义错误视图中的最佳方法是什么?

如果您使用的是 IIS7+,我会像这样禁用 "customerrors":

 <customErrors mode="Off" />

并像这样使用 httpErrors:

<system.webServer>
 <httpErrors errorMode="DetailedLocalOnly" existingResponse="Replace" defaultPath="/error">
     <remove statusCode="404" />
     <error statusCode="404" path="/error/notfound" responseMode="ExecuteURL" />
 </httpErrors>
....

这允许您在您的控制器中使用以下内容来获得显示 404 状态代码的非 url 更改错误页面:

public class ErrorController : Controller
{
public ActionResult notfound()
    {
        Response.TrySkipIisCustomErrors = true;
        Response.StatusCode = (int)HttpStatusCode.NotFound;
        return View("OneErrorViewToRuleThemAll");
    }
}

ps。 "errorMode" 需要更改为 "Custom" 才能在本地查看....取决于您的本地设置(即,如果您使用的是 IISExpress),在上传到实时服务器之前,您可能看不到正确的错误.

pps。您可以使用单一视图 "OneErrorViewToRuleThemAll" 来处理您决定以这种方式处理的任何状态代码的屏幕输出。每个 ErrorController 操作都会在此视图上结束。

描述了我正在寻找的解决方案(在处于放弃的边缘之后)here

步骤总结:

  1. 将您的 web.config 设置为针对您要处理的每个错误重定向到控制器操作。
  2. 将Response对象的TryToSkipCustomErrors属性设置为true,在1.
  3. 中定义的每个动作中
  4. 注释掉该行 filters.Add(new HandleErrorAttribute()); 来自您的 filterConfig.cs 文件。

使用这种方法,我终于成功地重定向到错误 500 的自定义页面。 IIS 似乎对 500 有某种默认跳过,因为设置了错误 404 的自定义页面不需要步骤 2 和 3。

所以,最后,对于我想要呈现自定义页面的每个 http 状态代码,我创建了一个控制器操作,相应地设置了描述的属性,然后针对所有操作重定向到相同的视图 - 我在这里显示@Response.Status,使其成为我的通用解决方案。