MVC教程九:异常过滤器
我们平常在程序里面为了捕获异常,会加上try-catch-finally代码,但是这样会使得程序代码看起来很庞大,在MVC中我们可以使用异常过滤器来捕获程序中的异常,如下图所示:
使用了异常过滤器以后,我们就不需要在Action方法里面写Try -Catch-Finally这样的异常处理代码了,而把这份工作交给HandleError去做,这个特性同样可以应用到Controller上面,也可以应用到Action方面上面。
注意:
使用异常过滤器的时候,customErrors配置节属性mode的值,必须为On。
演示示例:
1、Error控制器代码如下:
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Web; 5 using System.Web.Mvc; 6 using System.Data.SqlClient; 7 using System.IO; 8 9 namespace _3_异常过滤器.Controllers 10 { 11 public class ErrorController : Controller 12 { 13 // GET: Error 14 [HandleError(ExceptionType =typeof(ArithmeticException),View ="Error")] 15 public ActionResult Index(int a,int b) 16 { 17 int c = a / b; 18 ViewData["Result"] = c; 19 return View(); 20 } 21 22 /// <summary> 23 /// 测试数据库异常 24 /// </summary> 25 /// <returns></returns> 26 [HandleError(ExceptionType = typeof(SqlException), View = "Error")] 27 public ActionResult DbError() 28 { 29 // 错误的连接字符串 30 SqlConnection conn = new SqlConnection(@"Initial Catalog=StudentSystem; Integrated Security=False;User Id=sa;Password=******;Data Source=127.0.0.1"); 31 conn.Open(); 32 // 返回Index视图 33 return View("Index"); 34 } 35 36 /// <summary> 37 /// IO异常 38 /// </summary> 39 /// <returns></returns> 40 [HandleError(ExceptionType = typeof(IOException), View = "Error")] 41 public ActionResult IOError() 42 { 43 // 访问一个不存在的文件 44 System.IO.File.Open(@"D:\error.txt",System.IO.FileMode.Open); 45 // 返回Index视图 46 return View("Index"); 47 } 48 } 49 }
2、路由配置如下:
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Web; 5 using System.Web.Mvc; 6 using System.Web.Routing; 7 8 namespace _3_异常过滤器 9 { 10 public class RouteConfig 11 { 12 public static void RegisterRoutes(RouteCollection routes) 13 { 14 routes.IgnoreRoute("{resource}.axd/{*pathInfo}"); 15 16 routes.MapRoute( 17 name: "Default", 18 url: "{controller}/{action}/{id}", 19 defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional } 20 ); 21 22 // 新增路由配置 23 routes.MapRoute( 24 name: "Default2", 25 url: "{controller}/{action}/{a}/{b}", 26 defaults: new { controller = "Home", action = "Index", a=0,b=0 } 27 ); 28 } 29 } 30 }
3、配置文件如下:
1 2 3 4 5 6 7 8 9 10 | <system.web> <compilation debug= "true" targetFramework= "4.6.1" /> <httpRuntime targetFramework= "4.6.1" /> <httpModules> <add name= "ApplicationInsightsWebTracking" type= "Microsoft.ApplicationInsights.Web.ApplicationInsightsHttpModule, Microsoft.AI.Web" /> </httpModules> <!--customErrors配置节mode的属性值必须为On--> <customErrors mode= "On" > </customErrors> </system.web> |
4、运行结果
URL:http://localhost:21868/error/index/8/4
结果:
URL:http://localhost:21868/error/index/8/0
结果:
URL:http://localhost:21868/error/DbError
结果:
URL:http://localhost:21868/error/IOError
结果:
在同一个控制器或Action方法上可以通过HandleError处理多个异常,通过Order属性决定捕获的先后顺序,但最上面的异常必须是下面异常的同类级别或子类。如下图所示:
上面的程序可以修改成如下的代码:
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Web; 5 using System.Web.Mvc; 6 using System.Data.SqlClient; 7 using System.IO; 8 9 namespace _3_异常过滤器.Controllers 10 { 11 [HandleError(Order =1, ExceptionType = typeof(SqlException), View = "Error")] 12 [HandleError(Order =2, ExceptionType = typeof(IOException), View = "Error")] 13 [HandleError(Order =3)] //不指定View,默认跳转到Share下面的Error视图 14 public class ErrorController : Controller 15 { 16 public ActionResult Index(int a,int b) 17 { 18 int c = a / b; 19 ViewData["Result"] = c; 20 return View(); 21 } 22 23 /// <summary> 24 /// 测试数据库异常 25 /// </summary> 26 /// <returns></returns> 27 public ActionResult DbError() 28 { 29 // 错误的连接字符串 30 SqlConnection conn = new SqlConnection(@"Initial Catalog=StudentSystem; Integrated Security=False;User Id=sa;Password=******;Data Source=127.0.0.1"); 31 conn.Open(); 32 // 返回Index视图 33 return View("Index"); 34 } 35 36 /// <summary> 37 /// IO异常 38 /// </summary> 39 /// <returns></returns> 40 public ActionResult IOError() 41 { 42 // 访问一个不存在的文件 43 System.IO.File.Open(@"D:\error.txt",System.IO.FileMode.Open); 44 // 返回Index视图 45 return View("Index"); 46 } 47 } 48 }
在上面的示例中,捕获异常的时候只是跳转到了Error视图,如果我们想获取异常的具体信息该怎么办呢?如下图所示:
查看MVC源码,可以发现HandleError返回的是HandleErrorInfo类型的model,利用该model可以获取异常的具体信息,修改Error视图页面如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | @model HandleErrorInfo <! DOCTYPE html> < html > < head > < meta http-equiv="Content-Type" content="text/html; charset=utf-8"/> < meta name="viewport" content="width=device-width" /> < title >错误</ title > < style type="text/css"> p{ color:red; } </ style > </ head > < body > @*< hgroup > < h1 >错误。</ h1 > < h2 >处理你的请求时出错。</ h2 > </ hgroup >*@ < p > 抛错控制器:< b >@Model.ControllerName</ b > 抛错方法:< b >@Model.ActionName</ b > 抛错类型:< b >@Model.Exception.GetType()</ b > </ p > < p > 异常信息:@Model.Exception.Message </ p > < p > 堆栈信息:@Model.Exception.StackTrace </ p > </ body > </ html > |
结果:
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【译】Visual Studio 中新的强大生产力特性
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
· 字符编码:从基础到乱码解决
2017-05-08 DataGridView使用技巧十三:点击列头实现升序和降序排序