我正在使用全局操作过滤器来处理和记录所有异常。
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
的值为true。
如何处理这个异常?
- 编辑 -
我在customErrors
中有一个Web.Config
部分。我有一个ErrorController
类,以及名为General
和Http404
的操作。
<customErrors mode ="On" defaultRedirect="Error/General">
<error statusCode="404" redirect="Error/Http404"/>
</customErrors>
我不明白的是,控制器操作General
未执行(断点永远不会被命中),但ExceptionContext.ExceptionHandled
的值设置为真{{1 OnException
的方法开始执行。
答案 0 :(得分:22)
发生异常时,全局过滤器的顺序将执行in reverse order。这意味着HandleErrorAttribute
首先运行。
您可以查看HandleErrorAttribute
here的代码,但简而言之,它可以:
ExceptionHandled
为false且已启用自定义错误时执行。Error
。ExceptionHandled
设置为true。 由于它是第一个过滤器,因此ExceptionHandled
在执行时为false,导致它将视图设置为Error并将ExceptionHandled
设置为true。那么,当您自己的过滤器执行时,这就是ExceptionHandled
已经设置为true的原因。请注意,如果自定义错误被禁用,则ExceptionHandled
仍然是假的,因为HandleErrorAttribute
不会完成其中的任务。在这种情况下,ELMAH无论如何都会记录错误,因为它是未处理的(黄色死亡屏幕),因此您班级中的测试是为了防止重复记录错误。
现在,关于你没有执行General
操作的另一个问题,defaultRedirect
仅在过滤器没有自己设置一些显式重定向时使用,所以当它实际上被忽略时ActionMethod中发生异常,并且您已注册了全局过滤器HandleErrorAttribute
。但是,如果您输入的URL不存在,则会调用它,即在ActionMethod中不会发生错误。此外,如果您注释掉行以在Global.asax.cs中注册HandleErrorAttribute
,那么您将始终执行General
控制器操作。