9

我正在使用全局操作过滤器来处理和记录所有异常。

    public static void RegisterGlobalFilters(GlobalFilterCollection filters)
    {
        filters.Add(new ElmahHandleErrorAttribute());
        filters.Add(new HandleErrorAttribute());
    }

这就是全局操作过滤器ElmahHandleErrorAttribute的定义方式——它覆盖了OnException方法。

public class ElmahHandleErrorAttribute : System.Web.Mvc.HandleErrorAttribute
{
    public override void OnException(ExceptionContext context)
    {
       //Is the exception handled already? context.ExceptionHandled seems to be true here
        if (!context.IsChildAction && (context.HttpContext.IsCustomErrorEnabled))
        {
            //Do other stuff stuff
            //Log to Elmah               
        }
    }
   ...
 }

我不明白为什么方法执行context.ExceptionHandled时的值为真。OnException如何处理此异常?

-编辑-customErrorsWeb.Config. 我有一个ErrorController班级,以及名为Generaland的动作Http404

<customErrors mode ="On" defaultRedirect="Error/General">
      <error statusCode="404" redirect="Error/Http404"/>
  </customErrors>

我不明白的是,控制器动作General没有执行(断点永远不会命中),但是当方法开始执行时,它的值ExceptionContext.ExceptionHandled设置为true 。OnExceptionElmahHandleErrorAttribute

4

1 回答 1

24

当发生异常时,全局过滤器的执行顺序是相反的。这意味着HandleErrorAttribute先运行。

可以查看HandleErrorAttribute 这里的代码,简而言之就是:

  1. 仅在ExceptionHandled为 false 时执行,并且启用了自定义错误。
  2. 设置重定向到错误视图,默认情况下称为Error.
  3. 设置ExceptionHandled为真。

因为它是第一个过滤器,ExceptionHandled所以它在执行时为假,导致它将视图设置为错误并设置ExceptionHandled为真。因此,当您自己的过滤器执行时,这就是为什么ExceptionHandled已经设置为 true。请注意,如果自定义错误被禁用,那么ExceptionHandled仍然是错误的,因为HandleErrorAttribute它不会完成它的工作。在这种情况下,ELMAH 无论如何都会记录错误,因为它没有被处理(黄色死屏),所以你班级的测试是为了防止重复记录错误。

现在,关于你的另一个问题,关于General为什么不执行操作,defaultRedirect只有在过滤器没有自己设置一些显式重定向时才使用它,所以当 ActionMethod 内部发生异常并且你HandleErrorAttribute注册了全局过滤器时,它实际上被忽略了. 但是,如果您输入了一个不存在的 URL,即不会在 ActionMethod 中发生的错误,它将被调用。此外,如果您注释掉HandleErrorAttribute在 Global.asax.cs 中注册的行,那么您将始终General执行控制器操作。

于 2012-05-18T10:21:19.090 回答