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、配置文件如下:

<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視圖頁面如下:

@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>

結果:


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM