ExceptionContext.ExceptionHandled变为true。异常处理在哪里进行?
ExceptionContext.ExceptionHandled变为true。异常处理在哪里进行?
我正在使用一个全局操作过滤器来处理和记录所有的异常。
这是全局操作过滤器ElmahHandleErrorAttribute的定义 - 它重写了OnException方法。
我不明白为什么当OnException方法执行时,context.ExceptionHandled的值为true。
这个异常是如何被处理的?
-编辑-
我在Web.Config中有一个customErrors部分。我有一个ErrorController类,还有一个叫做General和Http404的操作。
我不明白的是,控制器操作General没有被执行(断点从未被命中),但是当ElmahHandleErrorAttribute的OnException方法开始执行时,ExceptionContext.ExceptionHandled的值被设置为true。
当发生异常时,全局过滤器的执行顺序是反向的。这意味着HandleErrorAttribute
首先运行。
HandleErrorAttribute
的代码可以在这里查看,但简而言之,它的功能包括:
- 只有当
ExceptionHandled
为false并且启用了自定义错误时,才执行。 - 设置一个重定向到错误视图,默认情况下称为
Error
。 - 将
ExceptionHandled
设置为true。
由于它是第一个过滤器,所以当它执行时,ExceptionHandled
为false,导致它将视图设置为Error并将ExceptionHandled
设置为true。所以,当您自己的过滤器执行时,ExceptionHandled
已经设置为true。请注意,如果禁用了自定义错误,则ExceptionHandled
仍将为false,因为HandleErrorAttribute
不会执行其操作。在这种情况下,ELMAH仍会记录错误,因为它是未处理的(黄屏幕错误),因此您的类中的测试是为了防止错误重复记录。
现在,关于为什么General
操作未执行的问题,只有在过滤器没有设置某些明确的重定向时,defaultRedirect
才会被使用,所以当在ActionMethod内部发生异常并且注册了全局过滤器HandleErrorAttribute
时,它实际上会被忽略。但是,如果您输入不存在的URL,即在ActionMethod之外发生的错误,则会调用它。此外,如果您在Global.asax.cs中注释掉注册HandleErrorAttribute
的行,则始终会执行General
控制器操作。
谢谢您的解释。它确实帮助了我。我希望ElmahHandleErrorAttribute
成为首个执行的过滤器。设置这个自定义过滤器的顺序能解决这个问题吗?根据这个评论(stackoverflow.com/a/9163926/1242061),我应该给我想要首先执行的过滤器一个更高的Order值。
是的,我认为您可以尝试调整Order属性(但不确定如何在全局过滤器上这样做,只在使用属性时这样做过)。只需反转在RegisterGlobalFilters中添加过滤器的顺序即可...当发生错误时,最后添加的过滤器将首先运行。不确定为什么您希望ELMAH首先运行,如果您确实希望这样做,那么您不能检查ExceptionHandled,因为在这种情况下它始终为false。
我在注册过滤器时指定了顺序。现在我的自定义过滤器ElmahHandleErrorAttribute
首先处理错误。关于您的问题不确定为什么您希望ELMAH首先运行,您认为这是个坏主意吗?我这样做是因为我想显示自定义错误页面并检查错误类型并显示特定视图。
只要ELMAH视图始终显示一个视图,那么是的,我认为这是可以的。但是,如果您让默认的HandleErrorAttribute
处理回退情况,如果它也没有设置视图,那么将会发生YSOD,并且您可能最终会在ELMAH中记录错误两次(一次在全局过滤器中,一次在异常未标记为已处理时)。如果您在ELMAH过滤器中设置视图,那么也许您应该完全摆脱HandleErrorAttribute
?
我猜我应该摆脱HandleErrorAttribute
。自定义的ElmahHandleErrorAttribute
将显示一个视图。由于我在global.asax
中定义了Application_Error()来处理404和其他未处理的异常,所以我认为不会显示YSOD。