这几天稍微研究了下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()方法清除异常。否则会有下面两种情况,如果自定义错误关闭,会显示错误黄页(即详细异常信息页面),如果没关闭则会跳转到自定义错误定义的页面:
效果图如下:
小结:这种方法有非常好的兼容性,可以在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接口,就要提到上面所介绍的HandleError特性,可以从源码中看到HandleErrorAttribute就是实现了IExceptionFilter接口和FilterAttribute特性:
但是HandleErrorAttribute作为默认提供的异常处理特性,有很多限制和不灵活的地方,比如不处理404,需要开启自定义错误,只能使用视图界面等。因此我们可以通过继承IExceptionFilter这个异常过滤接口,扩展和编写我们自己所需的处理流程。
继承IExceptionFilter接口,需要实现void OnException(ExceptionContext filterContext)方法,通过方法中的ExceptionContext类参数,我们可以极为灵活的编写各种异常处理流程,比如:
- 可以通过Exception属性获取异常对象和相关信息,保存错误日志或者判断异常类型来操作。
- 可以通过HttpContext属性来获取HTTP上下文类,从而操作HTTP状态码、跳转到相关URL页面、或者通过IsCustomErrorEnabled属性判断是否需要依赖自定义错误功能等等操作。
小结:除非考虑项目中要兼容web form的问题,在MVC中我是十分喜欢用这种方式进行自定义异常处理。
关于此接口更多详情和注意事项可以查阅这篇文章:ASP.NET MVC实现IExceptionFilter接口编写自定义异常处理过滤器
结尾:对于本文所提及到全局异常处理思路,都是在MVC中比较常用到的,如有遗漏和错误,网友可以在下方评论留言,感谢留言的朋友,有交流就有进步^^。本文只提供一个思路和总结,具体的演示代码和详细步骤在文中都有提供链接。
原创文章,作者:ItWorker,如若转载,请注明出处:https://blog.ytso.com/98718.html