自定义异常过滤特性
在ASP.NET MVC中,默认的异常处理机制有时候无法满足项目的业务需求,我们可以通过实现
ASP.NET MVC默认提供了 PS: 自定义异常过滤器的关键代码这里先新建一个ASP.NET MVC项目,接着新建一个类库,以后所有自定义特性和过滤器的类都放在这个类库下,这里我将类库命名为CustomAttributeClassLibrary。 接下来在类库中添加要编写自定义异常处理的类,这里我命名为CustomExceptionAttribute。 CustomExceptionAttribute类代码如下: using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Web; using System.Web.Mvc; namespace CustomAttributeClassLibrary { public class CustomExceptionAttribute : FilterAttribute,IExceptionFilter { public void OnException(ExceptionContext filterContext) { Exception exception = filterContext.Exception; if (filterContext.ExceptionHandled == true) { return; } HttpException httpException = new HttpException(null,exception); //filterContext.Exception.Message可获取错误信息 /* * 1、根据对应的HTTP错误码跳转到错误页面 * 2、先对Action方法里引发的HTTP 404/400错误进行捕捉和处理 * 3、其他错误默认为HTTP 500服务器错误 */ if (httpException != null && (httpException.GetHttpCode() == 400 || httpException.GetHttpCode() == 404)) { filterContext.HttpContext.Response.StatusCode = 404; filterContext.HttpContext.Response.WriteFile("~/HttpError/404.html"); } else { filterContext.HttpContext.Response.StatusCode = 500; filterContext.HttpContext.Response.WriteFile("~/HttpError/500.html"); } /*--------------------------------------------------------- * 这里可进行相关自定义业务处理,比如日志记录等 ---------------------------------------------------------*/ //设置异常已经处理,否则会被其他异常过滤器覆盖 filterContext.ExceptionHandled = true; //在派生类中重写时,获取或设置一个值,该值指定是否禁用IIS自定义错误。 filterContext.HttpContext.Response.TrySkipIisCustomErrors = true; } } }
上面代码中主要实现了一个 ExceptionContext类文档的截图说明: 至于 下图演示可以看到没有继承 但是不影响全局操作过滤器的注册和使用: 记得使用NUGET将ASP.NET MVC 5 安装到新类库中, 到这里就完成了整个自定义异常处理过滤器的功能。 在项目中使用自定义异常过滤器有两种使用方式,一种是通过全局过滤器类 我们先将自定义特性类库引用到默认的MVC项目中: 全局注册的使用只需要在 public class FilterConfig { public static void RegisterGlobalFilters(GlobalFilterCollection filters) { filters.Add(new HandleErrorAttribute(),1); filters.Add(new CustomExceptionAttribute(),2); } }
PS:关于 这里要注意筛选器的运行顺序设置,引用文档资料:
所以Order=2的优先级反而比较高,注册好后整个MVC项目所有的异常都会被我们的CustomExceptionAttribute类捕捉和处理。 单独的作为特性使用有一个前提,就是筛选器需要继承 [CustomException] public ActionResult Index() { return View(); }
这里贴几段引发异常的操作方法代码,把下面代码放到演示项目中默认的Home控制器中: /// <summary> /// 抛出HTTP 500 /// </summary> /// <returns></returns> public ActionResult ThrowHttp500() { throw new HttpException(500,"服务器错误"); } /// <summary> /// 抛出HTTP 404 /// </summary> /// <returns></returns> public ActionResult ThrowHttp404() { throw new HttpException(404,"页面未找到"); } /// <summary> /// 抛出未引用对象异常 /// </summary> /// <returns></returns> public ActionResult ThrowNullReferenceException() { throw new NullReferenceException(); } /// <summary> /// 引发输入字符串的格式不正确异常 /// </summary> /// <returns></returns> public ActionResult ThrowFormatException() { string str = ""; int count = Convert.ToInt32(str); return View("Index"); }
网站生成运行后输入路径测试,结果如下图: 使用IExceptionFilter的一些注意事项这里总结使用 一、并不依赖自定义异常错误,所以web.config配置文件中的 但是如果你想要使用customErrors来进行控制,那么也很简单,在我们自定义的过滤器中,只需要使用 二、只能处理Action操作方法里抛出的异常,超出此范围的异常是无法被捕捉到的。这点非常重要,这是ASP.NET MVC中筛选器自身的特性。无论你是在Controller上声明筛选器,或者通过全局注册,最终都只能应用到某个具体的Action方法。这里所谓的全局注册,其实就是指所有的Action都应用了该筛选器。同样的,如果筛选器在控制器上声明,其实也是表示该控制器下所有的操作方法都要应用此筛选器。筛选器本身只针对ACtion方法!在Controller上声明和全局注册只是设定了其应用范围! 这里引用《ASP.NET MVC高级编程》的说明:
注意: PS:筛选器=过滤器!不同的翻译别称。 主要无法处理的范围和情况有:
如果遇到上面的情况又想捕获到异常,也是有两个解决办法的,一个是使用Global.asax的Application_Error事件处理这部分筛选器无法捕捉的异常。另外一个是直接设置IIS上的.NET错误即可,其实就是设置自定义异常错误,设置web.config配置文件中的 三、IIS级的错误并不会被捕捉到,因为此类错误还未进入ASP.NET 的处理流程,这个问题上面第二点就有提到。比如下图中输入某个物理路径不存在的页面,这里直接就显示IIS默认的错误页,需要在服务器上进行相关设置: 四、在我们的筛选器CustomExceptionAttribute代码中,可以看到使用了一个 if (filterContext.ExceptionHandled == true)
这个属性十分重要,是为了防止使用多个异常过滤器导致操作发生冲突。在使用多个异常过滤器的情况下此属性作用十分明显! 如果为true,则表示已有其他filter处理过此异常,就不需要再次进行处理了,以免覆盖其他filter所解决的Exception。 如果为false,就要对该Exception进行相应的处理,处理之后将 默认情况下如果 五、操作相关的页面跳转,如果网站要考虑搜索引擎优化方法,一定不要使用下面的两种方法进行跳转: //filterContext.HttpContext.Response.Redirect("~/HttpError/500.html"); //filterContext.HttpContext.Server.Transfer("~/HttpError/500.html");
因为这两种方法你设置了StatusCode是无效的。 此外要注意路由在传统的ASP.NET 跳转方法中存在不兼容问题,如果想要使用MVC的路由和视图进行跳转,可以参考下面的代码: /*-------------------------------------------------------------------------- * 下面的范例是使用MVC控制器和视图进行跳转,具体可查阅HandleErrorAttribute源码 --------------------------------------------------------------------------*/ string controllerName = (string)filterContext.RouteData.Values["controller"]; string actionName = (string)filterContext.RouteData.Values["action"]; HandleErrorInfo model = new HandleErrorInfo(filterContext.Exception,controllerName,actionName); filterContext.Result = new ViewResult { ViewName = "视图名称",MasterName = "母板名称",ViewData = new ViewDataDictionary<HandleErrorInfo>(model),TempData = filterContext.Controller.TempData }; filterContext.ExceptionHandled = true; filterContext.HttpContext.Response.Clear(); filterContext.HttpContext.Response.StatusCode = 500;
上面的代码在视图结果中还传入了错误信息实体,如果只想要简单的跳转到某个视图或控制器,其实只要设置 filterContext.Result = new ViewResult() { ViewName="视图名称"}; filterContext.ExceptionHandled = true; filterContext.HttpContext.Response.Clear(); filterContext.HttpContext.Response.StatusCode = 500;
出处:https://shiyousan.com/post/635833789557065314 版权声明:本文采用知识共享许可协议:署名-相同方式共享 4.0 国际(CC BY-SA 4.0)。欢迎转载本文,转载请声明出处或保留此段声明。 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
- asp.net – 是否可以有条件地包含CSS?
- ASP.NET自定义用户控件动态添加
- 扩展UltraGrid控件实现对所有数据行的全选功能[Source Code
- asp.net – 在SignalR 2.0中使用现有的IoC容器
- asp.net-mvc – 基于MVC中应用程序的语言选择对必需字段验证
- asp.net-mvc – 如何在MVC 4 API中打印JSON脚本
- asp.net – VS 2012发布:找不到有效的AspnetMergePath
- asp.net-mvc – 如何从URL获取ID作为参数
- ASP.NET中读取XML文件信息的4种方法与示例代码
- .net – 带有数据绑定控件的“无效的回发或回调参数”