ASP.NET MVC全局异常处理和捕获的思路

这几天稍微研究了下ASP.NET MVC的全局异常处理以及捕获,相比ASP.NET Web Form,ASP.NET MVC的处理方式有所不同,以往是通过注册Global.asax文件中的Application_Error事件进行全局异常捕获,现在MVC可以使用强大的过滤器进行自定义错误的处理。本文作为学习笔记,将ASP.NET MVC中,我已知的几种全局异常捕获及处理的思路进行整理和对比分析。

使用Global.asax的Application_Error事件进行全局异常处理

此方法对于Web Form和MVC来说都是通用的,在ASP.NET中,只要网站程序抛出未捕获的异常都会触发Application_Error事件。我们在事件中通过Server.GetLastError()方法获取Exception对象(可转化成HttpException对象,以获取相关的HTTP错误代码)。

使用此方法一定要把GlobalFilter全局过滤器中的HandleErrorAttribute注册取消掉,也可以将配置文件中的customErrors节点关闭,否则HTTP 500的错误将不会被Application_Error事件捕获。

还要注意一点,如果想在事件中跳转到自己定义的错误页面,那么在响应输出之前一定要记得调用 Server.ClearError()方法清除异常。否则会有下面两种情况,如果自定义错误关闭,会显示错误黄页(即详细异常信息页面),如果没关闭则会跳转到自定义错误定义的页面:

在Application_Error事件中处理全局异常

效果图如下:

全局异常跳转到正确的错误信息页面

小结:这种方法有非常好的兼容性,可以在Web Form和MVC中通用。另外一点是SEO优化十分友好,我们可以对HTTP错误码进行控制,毕竟customErrors是使用302跳转,是十分不利于SEO的。此外要注意在MVC中Server.Transfer不支持路由!

具体的操作方法和代码看这篇文章:ASP.NET MVC中注册Global.asax的Application_Error事件处理全局异常

使用HandleErrorAttribute特性捕获全局异常

ASP.NET MVC为异常处理提供了一个HandleErrorAttribute特性,该特性主要捕获及处理由操作方法引发的异常,一般在visual studio中新建的项目都是默认全局注册,通过GlobalFilter全局过滤器注册了此特性,所以整个ASP.NET MVC网站程序中所引发的异常默认都会被HandleError捕获到!

另外需要注意的是,HandleError特性是基于customErrors(自定义错误消息处理功能),所以只有在Web.config配置文件中设置customErrors元素的mode="On"或者或"RemoteOnly",HandleError特性才能有效,具体看源码中的这段判断:

// If custom errors are disabled, we need to let the normal ASP.NET exception handler
// execute so that the user can see useful debugging information.
if (filterContext.ExceptionHandled || !filterContext.HttpContext.IsCustomErrorEnabled)
{
    return;
}

PS:本人使用的是vs2013新建的MVC 5项目

打开项目中的Global.asax文件,可以看到默认调用了FilterConfig类对HandleError特性进行全局注册:

默认全局注册了异常处理特性

FilterConfig.cs文件在App_Start下:

过滤器配置文件类

FilterConfig类代码如下:

using System.Web;
using System.Web.Mvc;

namespace asp.net_mvc_global_exception
{
    public class FilterConfig
    {
        public static void RegisterGlobalFilters(GlobalFilterCollection filters)
        {            
            filters.Add(new HandleErrorAttribute());
        }
    }
}

如果上面的代码中我们不注册HandleErrorAttribute,那么此特性就会失效,但是我们依然可以设置customErrors元素搭配Web窗体进行自定义错误的处理,就和以往Web Form的处理方式一样,也算是另一种方式吧。

小结:对于HandleError特性的使用,我一般是用在B/S架构的企业系统中,有时候还会根据需求继承此特性以扩展功能,比如需要记录错误日志。另外此特性不对404错误进行任何处理,查看HandleErrorAttribute.cs文件源码,在源码中可看出对404做了额外处理:

有关此特性具体的可以看这篇文章:ASP.NET MVC 5 学习笔记:使用HandleErrorAttribute处理异常。文章中有代码样式和范例下载

继承IExceptionFilter接口扩展自定义异常处理功能

在ASP.NET MVC高级编程中是这样描述的:

异常过滤器用来处理操作或结果执行期间可能抛出的异常。参与异常处理的操作过滤器需要实现IExceptionFilter接口。ASP.NET MVC 框架只提供了一个异常过滤器:[HandleError]

说到IExceptionFilter接口,就要提到上面所介绍的HandleError特性,可以从源码中看到HandleErrorAttribute就是实现了IExceptionFilter接口和FilterAttribute特性:

但是HandleErrorAttribute作为默认提供的异常处理特性,有很多限制和不灵活的地方,比如不处理404,需要开启自定义错误,只能使用视图界面等。因此我们可以通过继承IExceptionFilter这个异常过滤接口,扩展和编写我们自己所需的处理流程。

继承IExceptionFilter接口,需要实现void OnException(ExceptionContext filterContext)方法,通过方法中的ExceptionContext类参数,我们可以极为灵活的编写各种异常处理流程,比如:

  1. 可以通过Exception属性获取异常对象和相关信息,保存错误日志或者判断异常类型来操作。
  2. 可以通过HttpContext属性来获取HTTP上下文类,从而操作HTTP状态码、跳转到相关URL页面、或者通过IsCustomErrorEnabled属性判断是否需要依赖自定义错误功能等等操作。

ExceptionContext类属性

小结:除非考虑项目中要兼容web form的问题,在MVC中我是十分喜欢用这种方式进行自定义异常处理。

关于此接口更多详情和注意事项可以查阅这篇文章:ASP.NET MVC实现IExceptionFilter接口编写自定义异常处理过滤器


结尾:对于本文所提及到全局异常处理思路,都是在MVC中比较常用到的,如有遗漏和错误,网友可以在下方评论留言,感谢留言的朋友,有交流就有进步^^。本文只提供一个思路和总结,具体的演示代码和详细步骤在文中都有提供链接。




原创文章,作者:ItWorker,如若转载,请注明出处:https://blog.ytso.com/98718.html

(0)
上一篇 2021年8月21日
下一篇 2021年8月21日

相关推荐

发表回复

登录后才能评论