【问题标题】:ASP.NET MVC 4 404 error-handling not firingASP.NET MVC 4 404 错误处理未触发
【发布时间】:2014-08-08 12:33:10
【问题描述】:

首先,我不会轻易发布此消息。我刚刚花了将近创纪录的半天时间试图解决这个问题。

我正在笔记本电脑上使用 Visual Studio 2012 开发一个 ASP.NET MVC 网站。我通过使用this approach将此代码添加到我的GLOBAL.ASAX文件中实现了错误处理:

protected void Application_Error(object sender, EventArgs e)
    {
        Exception exception = Server.GetLastError();
        Server.ClearError();

        RouteData routeData = new RouteData();
        routeData.Values.Add("controller", "Error");
        routeData.Values.Add("action", "Index");
        routeData.Values.Add("exception", exception);

        if (exception.GetType() == typeof(HttpException))
        {
            routeData.Values.Add("statusCode", ((HttpException)exception).GetHttpCode());
        }
        else
        {
            routeData.Values.Add("statusCode", 500);
        }

        IController controller = new ErrorController();
        controller.Execute(new RequestContext(new HttpContextWrapper(Context), routeData));
        Response.End();
    }

我有一个视图会在 Razor 标记中产生错误:

@{
            // trigger an error
            int i =1/0; 
        }

当我浏览到这个视图时,它触发了一个错误,将我带到控制器错误,操作索引,这里的代码显示了一个适当的视图:

public ActionResult Index(int statusCode, Exception exception){
Response.StatusCode = statusCode;
return View(); }

到目前为止,一切都很好。我的问题是 - 我怎样才能以同样的方式处理 404?因此,如果我转到一个不存在的页面,我会得到:

我尝试过的事情:

  • CustomErrors 的每一种可能安排 - web.config 中的开/关
  • 调试 global.asax 以检查它是否在应用程序启动时运行
  • 还有很多其他的事情,我敢肯定,我现在已经忘记了!

Visual Studio 使用的 Web 服务器是 IIS 8 Express,如果有帮助的话。

【问题讨论】:

  • PS 这很可能是其他问题的重复,但在我看来,所提出的解决方案都没有。
  • 如果您使用自定义错误,您是否删除了 filters.Add(new HandleErrorAttribute());来自 FilterConfig 类(如果你有的话)?这可能会导致自定义错误。

标签: asp.net-mvc asp.net-mvc-4


【解决方案1】:

有很多方法可以做到这一点。

最简单的方法

下载并安装此 nuget - NotFoundMvc 并阅读此 blog post

或者在 SO 上查看这个美丽的 answer,最初取自 Real world error hadnling in ASP.NET MVC RC2。但是由于源站点的当前状态处于可怕的设计状态,我将在下面重新发布代码。

目标:

要捕获服务器上发生的每个错误,请包括 HttpExeptions,例如 404(找不到页面)。

为某些错误选择特定视图(错误模板)的能力,如果未指定通用视图/行为,也未指定特定视图。

场景 1: 匿名用户输入了错误的网址。 行动: 显示一条用户友好的消息,例如:“哎呀,页面丢失……返回主页” 将错误记录到服务器上的 .log 文件中。 向管理员发送电子邮件。

情景 2: 与场景 1 相同,但有一个区别:用户是匿名用户,但他的 IP 来自我们公司的办公室。 行动: 显示详细的错误。

让我们看一些代码:

protected void Application_Error(object sender, EventArgs e) {

Exception exception = Server.GetLastError();

// Log the exception.
ILogger logger = Container.Resolve < ILogger > ();
logger.Error(exception);

Response.Clear();


HttpException httpException = exception as HttpException;
RouteData routeData = new RouteData();
routeData.Values.Add("controller", "Error");

if (httpException == null) {
    routeData.Values.Add("action", "Index");
} else //It's an Http Exception, Let's handle it.
{

    switch (httpException.GetHttpCode()) {
        case 404:
            // Page not found.
            routeData.Values.Add("action", "HttpError404");
            break;
        case 500:
            // Server error.
            routeData.Values.Add("action", "HttpError500");
            break;
            // Here you can handle Views to other error codes.
            // I choose a General error template  
        default:
            routeData.Values.Add("action", "General");
            break;
    }
}

// Pass exception details to the target error View.
routeData.Values.Add("error", exception);

// Clear the error on server.
Server.ClearError();

// Call target Controller and pass the routeData.
IController errorController = new ErrorController();
errorController.Execute(new RequestContext(new HttpContextWrapper(Context), routeData));

}

将此方法添加到 Global.asax:

创建了一个名为 ErrorController 的新控制器:

您可以为其他接收类型指定更多行为,我为错误提供了一个视图:404、500。

public ActionResult HttpError404(string error) {
    ViewData["Title"] = "Sorry, an error occurred while processing your request. (404)";
    ViewData["Description"] = error;
    return View("Index");
}

public ActionResult HttpError500(string error) {
    ViewData["Title"] = "Sorry, an error occurred while processing your request. (500)";
    ViewData["Description"] = error;
    return View("Index");
}


public ActionResult General(string error) {
    ViewData["Title"] = "Sorry, an error occurred while processing your request.";
    ViewData["Description"] = error;
    return View("Index");
}

【讨论】:

    【解决方案2】:

    您需要在 MVC 的路由引擎中捕捉到这一点。添加这样的路线:

    routes.MapRoute(
        name: "NotFound",
        url: "{*url}",
        defaults: new { controller = "Error", action = "Http404" }
    );
    

    然后在您的ErrorController 中添加此操作:

    public ActionResult Http404()
    {
        Response.StatusCode = (int)HttpStatusCode.NotFound;
        return View();
    }
    

    【讨论】:

    • 这就是我所拥有的,但后来我遇到了静态文件的问题。当我感觉不那么笨拙时(我发现 MVC 路由对我来说就是这样),我会发布另一个相关问题并链接到它,希望它对其他人也有用。到目前为止,谢谢。
    【解决方案3】:

    Yasser 的链接让我找到了一个似乎可行的答案。在 web.config 文件 部分,添加:

       <httpErrors errorMode="Custom" existingResponse="Replace">
    <remove statusCode="404" />
    <error statusCode="404" responseMode="ExecuteURL" path="/Error/PageNotFound" />
     </httpErrors>
    

    然后您可以为此路径创建一个路由器和控制器,这一切似乎都有效。真的这么简单吗?

    【讨论】:

    • 只是想我会跟进几天。如果您也从 web.config 文件中删除了 CustomErrors 部分,上述方法也可以正常工作。请注意,此解决方案对我们来说效果很好,但它不会让您为丢失的页面返回 404 代码。这个解决方案给我带来的问题比我之前使用的解决方案要少得多,即拥有一个包罗万象的路由器。在某个阶段,当我有更多时间时,我可能会详细介绍这一点,以突出我在痛苦的旅程中遇到的许多陷阱!
    猜你喜欢
    • 2012-10-04
    • 2010-10-17
    • 2010-10-17
    • 1970-01-01
    • 1970-01-01
    • 2013-12-08
    • 2010-09-16
    • 2018-02-27
    • 2010-09-11
    相关资源
    最近更新 更多