實現攔截器
在ASP.NET MVC中,有三種攔截器:Action攔截器、Result攔截器和Exception攔截器。其實所謂的ASP.NET MVC攔截器,也沒什麼神秘的,就是一個普通的類而已。只不過需要繼承FilterAttribute基類,Action攔截器還要實現IActionFilter介面,而Exception攔截器需要實現IExceptionFilter介面。
我們先來看實現:讓我們在Controllers目錄下建立一個Filters目錄,然後在Filters下建立兩個類,一個叫AccountFilter.cs一個叫ExceptionFilter。首先是AccountFilter.cs的代碼。
AccountFilter.cs:
AccountFilter.csusing System.Web.Mvc;namespace MvcWeb.Controllers.Filters{ public class AccountFilter : ActionFilterAttribute { //Action 執行前 (未登入通過。跳轉到 “~/Account/LoginOn” ) public override void OnActionExecuting(ActionExecutingContext filterContext) { var authenticate = StructureMap.ObjectFactory.GetInstance<Ants.Provider.IAuthenticateProvider>(); if (!authenticate.IsAuthenticated) { filterContext.Result = new RedirectResult("~/Account/LoginOn"); } base.OnActionExecuting(filterContext); } }}
這個地方我得解釋一下,你攔截器攔截了Action,在做處理時難免要用到被攔截Action相關的東西,例如在我們的例子中,就需要想被攔截Action所在Controller的ViewData中新增內容,所以,攔截器方法有一個參數表示被攔截Action的上下文是順理成章的事。
下面再看ExceptionFilter這個攔截器,它是在Action出現異常時發揮作用的。
ExceptionFilter.cs
using System.Web.Mvc;namespace MvcWeb.Controllers.Filters{ public class ExceptionFilter : FilterAttribute, IExceptionFilter { void IExceptionFilter.OnException(ExceptionContext filterContext) { filterContext.Controller.ViewData["Error"] = filterContext.Exception; filterContext.Result = new ViewResult() { ViewName = "Error", ViewData = filterContext.Controller.ViewData, }; filterContext.ExceptionHandled = true; } }}
異常攔截器需要繼承FilterAttribute,但是不要實現IActionFilter,而是要實現IExceptionFilter介面,這個介面只有一個方法:OnException,顧名思義,當然是發生異常時被調用了。我們看看我讓它做了什麼:首先將異常資訊(ExceptionContext一樣也是上下文,而其成員的Exception就是一個Exception類型的執行個體,就是被拋出的異常)記錄到ViewData相應的索引值裡,然後我們要呈現Error這個視圖。
注意!這裡已經不是Controller裡了,而是另一個類,所以當然不能調用View方法 返回ViewResult執行個體了。我們只好建立一個ViewResult執行個體,並將其視圖名設為Error,將上下文中的DataView傳過去。
最後那行filterContext.ExcepitonHandled = true;很重要,這行的意思是告訴系統,異常已經處理,不要再次處理了。應用了ExceptionFilter的Action中不用再寫try…catch語句啦,因為異常攔截器成功攔截了異常,並做了相應處理。
應用攔截器
好了,攔截器建立完了,要怎麼應用到相應的Action上呢?在ASP.NET MVC中,應用攔截器簡直是輕鬆加愉快。只要將攔截器當做Attribute寫在要應用此攔截器的Action上就行了.比如:
[Filters.AccountFilter] [Filters.ExceptionFilter] public ActionResult Test(){}