在MVC中處理異常的總結


無論是桌面程序還是web程序,異常處理都是必須的. 一般的處理方式是, 捕獲異常,然后記錄異常的詳細信息到文本文件或者數據庫中.
在Asp.net MVC中可以使用內建的filter——HandleError來處理程序發生的異常。接下來,來看看如何在我們的MVC項目中使用。

要讓HandleErrorAttribute特性工作,需要修改我們的Web.config文件配置

</system.web>
...
<customErrors mode="On" defaultRedirect="Error.htm"/>
</system.web>

HandleErrorAttribute 特性能夠在Action, Controller, 和Global 三個級別中使用

1. 在 Action方法級別使用

在Action方法上使用,非常簡單,只需要在方法頭上加上HandleError特性,告訴MVC如果該Action方法出現異常,交由HandleError特性處理

[HandleError(ExceptionType = typeof(System.Data.DataException), View = "DatabaseError")]
public ActionResult Index(int id)
{
    var db = new MyDataContext();
    return View("Index", db.Categories.Single(x => x.Id == id));
}

上面例子中,當在運行Index方法的時候,如果發生數據庫異常,  MVC 將會顯示DatabaseError view. 所以需要在Views\Shared\下面建立一個DatabaseError.cshtml。

2. 在 Controller級別使用

同Action相似,只需要簡單的將改特性放到controller類頭上,告訴MVC如果該Controller中的Action方法出現異常,都交由HandleError特性處理

[HandleError(ExceptionType = typeof(System.Data.DataException), View = "DatabaseError")]
public class HomeController : Controller
{
/* Controller Actions with HandleError applied to them */
}

3. 在Global級別上使用

我們也可以把HandleError特性注冊到全局級別,使得它在全局范圍中起作用。全局范圍起作用的意思是,項目中的所有controller都使用HandleError處理異常。要注冊global級別, 在項目的文件夾App_Start中打開 FilterConfig.cs文件找到RegisterGlobalFilters方法

默認的, ASP.NET MVC已經把HandleError特性注冊成global. 這里你可以添加自定義的filter

public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
    filters.Add(new HandleErrorAttribute
    {
        ExceptionType = typeof(System.Data.DataException),
        View = "DatabaseError"
    });
      filters.Add(new HandleErrorAttribute()); //by default added
}

一定要注意, 全局的filter是依照它們注冊的順序執行的。所以如果有多個filter, 要在注冊其它fileter之前注冊error filter

當然,你也可以在注冊global filter的時候,指定它們的順序。下面的代碼是指定了順序的,和上面的等價。

public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
    filters.Add(new HandleErrorAttribute(),2); //by default added
    filters.Add(new HandleErrorAttribute
    {
        ExceptionType = typeof(System.Data.DataException),
        View = "DatabaseError"
    },1);
}

4. 使用MVC默認的HandleError特性的局限性

  1. 沒有辦法記錄錯誤日志

  2. 它只捕獲http 500錯誤, 但是不捕獲其它類型的Http錯誤,比如404, 401等。

  3. 如果是在Ajax請求的情況下,返回的錯誤view,對於ajax訪問沒有任何意義。如果在Ajax請求出錯的情況下,返回json對於客戶端的處理就容易和友好的多。

5. 擴展HandleErrorAttribute

我們可以通過繼承 HandleError filter來實現自己的異常處理filter.  下面的filter, 實現了在出現錯誤的時候,記錄異常日志和在Ajax請求異常的情況下,返回json對象.

 1 public class CustomHandleErrorAttribute : HandleErrorAttribute
 2 {
 3     public override void OnException(ExceptionContext filterContext)
 4     {
 5         if (filterContext.ExceptionHandled || !filterContext.HttpContext.IsCustomErrorEnabled)
 6         {
 7             return;
 8         }
 9         if (new HttpException(null, filterContext.Exception).GetHttpCode() != 500)
10         {
11             return;
12         }
13         if (!ExceptionType.IsInstanceOfType(filterContext.Exception))
14         {
15             return;
16         }
17         // if the request is AJAX return JSON else view.
18         if (filterContext.HttpContext.Request.Headers["X-Requested-With"] == "XMLHttpRequest")
19         {
20             filterContext.Result = new JsonResult
21             {
22                 JsonRequestBehavior = JsonRequestBehavior.AllowGet,
23                 Data = new
24                 {
25                     error = true,
26                     message = filterContext.Exception.Message
27                 }
28             };
29         }
30         else
31         {
32             var controllerName = (string)filterContext.RouteData.Values["controller"];
33             var actionName = (string)filterContext.RouteData.Values["action"];
34             var model = new HandleErrorInfo(filterContext.Exception, controllerName, actionName);
35             filterContext.Result = new ViewResult
36             {
37                 ViewName = View,
38                 MasterName = Master,
39                 ViewData = new ViewDataDictionary(model),
40                 TempData = filterContext.Controller.TempData
41             };
42         }
43         // log the error by using your own method
44         LogError(filterContext.Exception.Message, filterContext.Exception);
45         filterContext.ExceptionHandled = true;
46         filterContext.HttpContext.Response.Clear();
47         filterContext.HttpContext.Response.StatusCode = 500;
48         filterContext.HttpContext.Response.TrySkipIisCustomErrors = true;
49     }
50 }
View Code

以上就是在MVC開發中,自己常用到的一些小技巧,希望對大家有幫助。


免責聲明!

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



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