摘要
在asp.net mvc中除了使用try...catch/finally來處理異常外,它提供了一種通過在Controller或者Action上添加特性的方式來處理異常。
HandleErrorAttribute
首先看一下該特性的定義
using System; namespace System.Web.Mvc { // 摘要: // 表示一個特性,該特性用於處理由操作方法引發的異常。 [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, Inherited = true, AllowMultiple = true)] public class HandleErrorAttribute : FilterAttribute, IExceptionFilter { // 摘要: // 初始化 System.Web.Mvc.HandleErrorAttribute 類的新實例。 public HandleErrorAttribute(); // 摘要: // 獲取或設置異常的類型。 // // 返回結果: // 異常的類型。 public Type ExceptionType { get; set; } // // 摘要: // 獲取或設置用於顯示異常信息的母版視圖。 // // 返回結果: // 母版視圖。 public string Master { get; set; } // // 摘要: // 獲取此特性的唯一標識符。 // // 返回結果: // 此特性的唯一標識符。 public override object TypeId { get; } // // 摘要: // 獲取或設置用於顯示異常信息的頁視圖。 // // 返回結果: // 頁視圖。 public string View { get; set; } // 摘要: // 在發生異常時調用。 // // 參數: // filterContext: // 操作篩選器上下文。 // // 異常: // System.ArgumentNullException: // filterContext 參數為 null。 public virtual void OnException(ExceptionContext filterContext); } }
ExceptionType:屬性,相當於try catch(Exception)中的catch捕獲的異常類型,默認所有異常類型。
View:異常展示視圖,這個視圖需要在目錄Views/Shared/下。例如:
Order:該屬性是父類FilterAttribute的一個屬性,用來獲取或者設置執行操作篩選器的順序,默認-1,-1最先執行。
一個例子
在Index中直接拋出一個異常,我們現在需要做的就是通過HandlerError特性捕獲到這個異常,並且在視圖MyError上顯示詳細信息。
步驟1:添加特性
public class UserController : Controller { // GET: User [HandleError(ExceptionType = typeof(Exception), View = "MyError")] public ActionResult Index() { throw new Exception("Sorry,threre is an error in your web server."); } }
步驟2:定義錯誤視圖,並通過@Model獲取異常對象並顯示錯誤信息。
@{ Layout = null; } <!DOCTYPE html> <html> <head> <meta name="viewport" content="width=device-width" /> <title></title> </head> <body> <div> @Model.Exception.GetType().Name<br /> @Model.Exception.Message<br /> @Model.ControllerName<br /> @Model.ActionName<br /> @Model.Exception.StackTrace<br /> </div> </body> </html>
步驟3:注冊過濾器。
在App_Start目錄添加類FilterConfig
public class FilterConfig
{
public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
filters.Add(new HandleErrorAttribute());
}
}
在Global.asax中注冊
public class MvcApplication : System.Web.HttpApplication { protected void Application_Start() { AreaRegistration.RegisterAllAreas(); FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters); RouteConfig.RegisterRoutes(RouteTable.Routes); GlobalConfiguration.Configure(WebApiConfig.Register); } }
步驟4:開啟自定義錯誤配置
<system.web> ... <customErrors mode="On"></customErrors> </system.web>
測試
以上是采用ErrorHanlder的默認實現的方式,當然我們也可以自定義異常處理過濾器,方法很簡單繼承HandleErrorAttribute類,並且重寫OnException方法即可。
/// <summary> /// 自定義異常過濾器 /// </summary> public class CustomerErrorAttribute : HandleErrorAttribute { public override void OnException(ExceptionContext filterContext) { //如果沒有處理該異常 if (!filterContext.ExceptionHandled) { if (filterContext.Exception.Message.Contains("Sorry,threre is an error in your web server.")) { filterContext.ExceptionHandled = true; filterContext.HttpContext.Response.Write("這是一個自定義異常處理過濾器"); } } } }
public class UserController : Controller { // GET: User [CustomerError(ExceptionType = typeof(Exception), View = "MyError")] public ActionResult Index() { throw new Exception("Sorry,threre is an error in your web server."); } }
public class FilterConfig { public static void RegisterGlobalFilters(GlobalFilterCollection filters) { filters.Add(new HandleErrorAttribute()); filters.Add(new CustomerErrorAttribute()); } }
測試
好了,自定義的異常處理過濾器已經起作用了。
需要注意在自定義處理異常過濾器的時候需要重寫OnException方法,該方法有一個ExceptionContext類型的參數。
// 摘要: // 提供使用 System.Web.Mvc.HandleErrorAttribute 類的上下文。 public class ExceptionContext : ControllerContext { // 摘要: // 初始化 System.Web.Mvc.ExceptionContext 類的新實例。 public ExceptionContext(); // // 摘要: // 使用指定的控制器上下文針對指定的異常初始化 System.Web.Mvc.ExceptionContext 類的新實例。 // // 參數: // controllerContext: // 控制器上下文。 // // exception: // 異常。 // // 異常: // System.ArgumentNullException: // exception 參數為 null。 public ExceptionContext(ControllerContext controllerContext, Exception exception); // 摘要: // 獲取或設置異常對象。 // // 返回結果: // 異常對象。 public virtual Exception Exception { get; set; } // // 摘要: // 獲取或設置一個值,該值指示是否已處理異常。 // // 返回結果: // 如果已處理異常,則為 true;否則為 false。 public bool ExceptionHandled { get; set; } // // 摘要: // 獲取或設置操作結果。 // // 返回結果: // 操作結果。 public ActionResult Result { get; set; } }
需要注意的是,在自定義的異常過濾器中,如果對異常已經處理了,需要將ExceptionHandled設置為true,這樣其它的過濾器可以根據該值判斷當前異常是否已經處理過了。
通過異常處理過濾器的特性,你可以更方便的來處理action或者Controller中的異常,比try--catch用起來更方便,用這種方式,也可以簡化異常處理的代碼,少一些大塊兒大塊兒的異常處理代碼。