【问题标题】:Where is the proper place to attach for catching ALL ASP.NET MVC errors?捕获所有 ASP.NET MVC 错误的正确位置在哪里?
【发布时间】:2013-06-18 11:13:38
【问题描述】:

我正在为我们的 asp.net mvc 3 应用程序添加错误处理。基本上,我想捕捉除核熔毁之外的所有未处理错误。

我已经确定了以下几点:

  • OnException 在控制器基类中(我所有的控制器都派生自同一个基类,因此可行)
  • HandleErrorAttribute 带有处理异常的自定义视图
  • Application_ErrorGlobal.asax 中的事件
  • 在 web.config 中打开 <customErrors mode="On"> 并设置一个自定义 URL 来处理异常。

我对这些地方之间的关系有一个非常模糊的想法,希望有人能解释一下它们之间的区别是什么以及为什么会有这么多。

另外,我应该使用哪一个(或全部?)?其中一些是多余的吗?是否存在可以被一个人捕获但不能被其他人捕获的异常?如果这些都失败了(例如,最后的异常处理方法本身引发异常),会发生什么?

【问题讨论】:

    标签: asp.net-mvc exception-handling unhandled-exception


    【解决方案1】:
    • 基本控制器中的 OnException 不会捕获所有错误 (特别是如果不是所有控制器都继承自它)。

    • HandleErrorAttribute 需要您在任何地方单独应用该属性。或者使用全局过滤器应用它,但它对所有控制器都是一样的。

    • 关闭 customErrors 只会显示错误,而不是处理它。而且您不能为不同类型的错误提供不同的视图。

    我们通常做的是这样的:

    安装 ELMAH 或类似软件包以跟踪您的所有错误,即使它们是静默发生的。

    然后,在 global.asax 中:

    protected void Application_Error(object sender, EventArgs e)
    {
        //Retrieving the last server error
        var exception = Server.GetLastError();
    
        //Erases any buffered HTML output
        Response.Clear();
    
        var httpException = exception as HttpException;
    
        var routeData = new RouteData();
        routeData.Values.Add("controller", "Error"); //Adding a reference to the error controller
        if (httpException == null)
        {
            routeData.Values.Add("action", "ServerError"); //Non HTTP related error handling
        }
    
        else //It's an Http Exception, Let's handle it.
        {
            switch (httpException.GetHttpCode())
            {
                case 401:
                case 403:
                    //Forbidden page.
                    routeData.Values.Add("action", "Forbidden");
                    break;
                case 404:
                    //Page not found.
                    routeData.Values.Add("action", "NotFound");
                    break;
                case 500:
                    routeData.Values.Add("action", "ServerError");
                    break;
                default:
                    routeData.Values.Add("action", "Index");
                    break;
            }
        }
    
        //Pass exception details to the target error View.
        routeData.Values.Add("message", exception);
    
        //Clear the error on server.
        Server.ClearError();
    
        //Avoid IIS7 getting in the middle
        Response.TrySkipIisCustomErrors = true;
    
        // Call target Controller and pass the routeData.
        IController errorController = new ErrorController();
        errorController.Execute(new RequestContext(
             new HttpContextWrapper(Context), routeData));
    }        
    

    我们认为这是使我们能够最大程度地控制处理和向访问者展示什么的选项。显示的每个操作(服务器错误、未找到和禁止)都有不同的屏幕,取决于服务器是在调试还是发布,然后我们会显示堆栈跟踪信息(但我们总是用 ELMAH 捕获它,所以我们总是可以看到它在那里)

    【讨论】:

    • Elmah 很棒,但也有一些陷阱 - 它不会捕获 WCF 服务错误,以及 StackOverflowException 和 OutOfMemoryException。
    • @OndrejSvejdar - StackOverflow 和 OutOfMemory 无论如何都几乎无法恢复,所以如果它们没有被捕获也没关系。
    • 我的控制器确实都继承自同一个类,我正在寻找一个全局解决方案。那么,如果我已经可以在Application_Error 中完成所有操作,为什么还有OnExceptionHandleErrorAttribute 呢?有两个重定向位置(customErrorsHandleErrorAttribute)有什么意义?
    • 我认为是这样的:自从 ASP.NET 开始使用 WebForms 以来,customErrors 就在那里,当异常发生时,IIS 会捕获它并将您重定向到特定页面。 HandleErrorAttribute 允许您捕获错误,然后决定如何处理它:管理它、重新抛出它,或者只是将用户重定向到另一个页面(这是 customError 所做的)
    猜你喜欢
    • 2010-10-12
    • 1970-01-01
    • 2011-04-02
    • 1970-01-01
    • 2011-04-26
    • 2014-08-22
    • 2022-01-11
    • 2010-10-16
    • 1970-01-01
    相关资源
    最近更新 更多