由於工作需要,最近在學習ASP.NET MVC3,感覺Filter在以后的應用中不能說必不可少,只能說感覺會讓我們在寫程序的時候對於一些經常要處理的並且統一處理的事情上能達到事半功倍的效果,因此在這里記錄一下學習到的內容。有不對的地方,還需要各位指出。
在ASP.NET MVC3中,給我個人感覺最大的特點就是運用的attribute(我個人理解為標記)是比較多的,而且attribute能讓我們更容易的去調用我們自定義邏輯處理的標記或者是調用系統自帶的一些標記,讓我們的代碼更簡潔。在本節中,我們還是主要看下Filter給我們程序帶來的好處。
在ASP.NET MVC 框架中,為我們提供了四種類型的Filter類型包括:IAuthorizationFilter、IActionFilter、IResultFilter、IExceptionFilter,執行順序如下:
- IAuthorizationFilter 最先執行的,在這些Filter中,我們可以說它的執行優先級是最高的,用於身份驗證並對控制器中的action進行授等進行邏輯處理
- IActionFilter 在IAuthorizationFilter之后執行,包含兩個方法,在controller中的action執行之前、執行之后進行邏輯處理
- IResultFilter 同樣包含兩個方法,在IActionFilter之后執行,在返回View之前和返回View之后執行邏輯處理
- IException 主要用於對異常信息進行處理
通過上述信息我們可以看到各個Filter之間運行的順序。在我們要對程序運行時候的這四個階段進行特殊處理的時候,我們可以自己寫一個Filter類去實現其中的邏輯處理代碼,實現相應的接口就可以進行特殊處理。ASP.NET MVC框架為我們提供了一個抽象類,名為:ActionFilterAttribute,這個抽象類只實現了IActionFilter和IResultFilter這兩個接口中的方法,分別是:IActionFilter(OnActionExcuting、OnActionExcuted)、IResultFilter(OnResultExcuting、OnResultExcuted)。如果需要對驗證或者異常進行特殊處理的話,還是需要實現IAuthorizationFilter或IException。
下面寫一個實現自定義Filter的非常簡單的例子,來更好的記住Filter的執行順序,代碼如下:
Filter:
public class OwnActionFilter : ActionFilterAttribute { /// <summary> /// 在action method之前執行 /// </summary> /// <param name="filterContext"></param> public override void OnActionExecuting(ActionExecutingContext filterContext) { filterContext.HttpContext.Response.Write("方法名稱:OnActionExecuting<br/>"); //輸出請求的控制器與action名稱 String controllerName = filterContext.RouteData.Values["controller"].ToString(); String actionName = filterContext.RouteData.Values["action"].ToString(); String message = String.Format("控制器:{0}<br/>action:{1}<br/>", controllerName, actionName); filterContext.HttpContext.Response.Write(message); filterContext.HttpContext.Response.Write("------------------華麗的分割線------------------<br>"); } /// <summary> /// 在action method之后執行 /// </summary> /// <param name="filterContext"></param> public override void OnActionExecuted(ActionExecutedContext filterContext) { filterContext.HttpContext.Response.Write("方法名稱:OnActionExecuted<br/>"); //輸出請求的控制器與action名稱 String controllerName = filterContext.RouteData.Values["controller"].ToString(); String actionName = filterContext.RouteData.Values["action"].ToString(); String message = String.Format("控制器:{0}<br/>action:{1}<br/>", controllerName, actionName); filterContext.HttpContext.Response.Write(message); filterContext.HttpContext.Response.Write("------------------華麗的分割線------------------<br/>"); } /// <summary> /// 在返回view之前執行 /// </summary> /// <param name="filterContext"></param> public override void OnResultExecuting(ResultExecutingContext filterContext) { filterContext.HttpContext.Response.Write("方法名稱:OnResultExecuting<br/>"); //輸出請求的控制器與action名稱 String controllerName = filterContext.RouteData.Values["controller"].ToString(); String actionName = filterContext.RouteData.Values["action"].ToString(); String message = String.Format("控制器:{0}<br/>action:{1}<br/>", controllerName, actionName); filterContext.HttpContext.Response.Write(message); filterContext.HttpContext.Response.Write("------------------華麗的分割線------------------<br/>"); } /// <summary> /// 在返回View之后執行 /// </summary> /// <param name="filterContext"></param> public override void OnResultExecuted(ResultExecutedContext filterContext) { filterContext.HttpContext.Response.Write("方法名稱:OnResultExecuted<br/>"); //輸出請求的控制器與action名稱 String controllerName = filterContext.RouteData.Values["controller"].ToString(); String actionName = filterContext.RouteData.Values["action"].ToString(); String message = String.Format("控制器:{0}<br/>action:{1}<br/>", controllerName, actionName); filterContext.HttpContext.Response.Write(message); filterContext.HttpContext.Response.Write("------------------華麗的分割線------------------<br/>"); } }
上面為自定義Filter,便於大家看到信息,我直接輸出到瀏覽器,其中包括方法名、控制器名稱與action名稱。在這里大家應該可以看到在ResultExcutedContex、ActionExecutingContext這兩個類型,他們都集成自ControllerContext,因此,它們一樣可以拿到HttpMethod、Session等一系列我們在ASPX中經常用到的一些信息。下面為Controller的代碼:
Controller:
public class FilterController : Controller { // // GET: /Filter/ [OwnActionFilter] public ActionResult Index() { ViewBag.DateTime = "Index View"; return View(); } }
大家可以看到,在Index方法前,我加入了OwnActionFilter的attribute(標記),那么當Index方法執行的時候,就會執行我們自己定義的Filter類中的方法。那么看一下我們自定義Filter的執行順序吧,效果如下圖:
為了便於看到執行的順序,我把Index View進行了加粗:)通過上圖,我們可以看到IActionFilter、IResultFilter執行的順序。那么,前面已經說了,IAuthorizationFilter是在IActionFilter、IResultFilter之前運行的,那么我們把IAuthorizationFilter接口實現(為了節約篇幅,一並加入IException接口並給予實現)代碼如下:
Filter:
public class OwnActionFilter : ActionFilterAttribute,IAuthorizationFilter,IExceptionFilter { /// <summary> /// 最先執行 /// </summary> /// <param name="filterContext"></param> public void OnAuthorization(AuthorizationContext filterContext) { filterContext.HttpContext.Response.Write("方法名稱:OnAuthorization<br/>"); //輸出請求的控制器與action名稱 String controllerName = filterContext.RouteData.Values["controller"].ToString(); String actionName = filterContext.RouteData.Values["action"].ToString(); String message = String.Format("控制器:{0}<br/>action:{1}<br/>", controllerName, actionName); filterContext.HttpContext.Response.Write(message); filterContext.HttpContext.Response.Write("------------------華麗的分割線------------------<br/>"); } /// <summary> /// 在action method之前執行 /// </summary> /// <param name="filterContext"></param> public override void OnActionExecuting(ActionExecutingContext filterContext) { filterContext.HttpContext.Response.Write("方法名稱:OnActionExecuting<br/>"); //輸出請求的控制器與action名稱 String controllerName = filterContext.RouteData.Values["controller"].ToString(); String actionName = filterContext.RouteData.Values["action"].ToString(); String message = String.Format("控制器:{0}<br/>action:{1}<br/>", controllerName, actionName); filterContext.HttpContext.Response.Write(message); filterContext.HttpContext.Response.Write("------------------華麗的分割線------------------<br>"); } /// <summary> /// 在action method之后執行 /// </summary> /// <param name="filterContext"></param> public override void OnActionExecuted(ActionExecutedContext filterContext) { filterContext.HttpContext.Response.Write("方法名稱:OnActionExecuted<br/>"); //輸出請求的控制器與action名稱 String controllerName = filterContext.RouteData.Values["controller"].ToString(); String actionName = filterContext.RouteData.Values["action"].ToString(); String message = String.Format("控制器:{0}<br/>action:{1}<br/>", controllerName, actionName); filterContext.HttpContext.Response.Write(message); filterContext.HttpContext.Response.Write("------------------華麗的分割線------------------<br/>"); } /// <summary> /// 在返回view之前執行 /// </summary> /// <param name="filterContext"></param> public override void OnResultExecuting(ResultExecutingContext filterContext) { filterContext.HttpContext.Response.Write("方法名稱:OnResultExecuting<br/>"); //輸出請求的控制器與action名稱 String controllerName = filterContext.RouteData.Values["controller"].ToString(); String actionName = filterContext.RouteData.Values["action"].ToString(); String message = String.Format("控制器:{0}<br/>action:{1}<br/>", controllerName, actionName); filterContext.HttpContext.Response.Write(message); filterContext.HttpContext.Response.Write("------------------華麗的分割線------------------<br/>"); } /// <summary> /// 在返回View之后執行 /// </summary> /// <param name="filterContext"></param> public override void OnResultExecuted(ResultExecutedContext filterContext) { filterContext.HttpContext.Response.Write("方法名稱:OnResultExecuted<br/>"); //輸出請求的控制器與action名稱 String controllerName = filterContext.RouteData.Values["controller"].ToString(); String actionName = filterContext.RouteData.Values["action"].ToString(); String message = String.Format("控制器:{0}<br/>action:{1}<br/>", controllerName, actionName); filterContext.HttpContext.Response.Write(message); filterContext.HttpContext.Response.Write("------------------華麗的分割線------------------<br/>"); } /// <summary> /// 當出現異常時才執行 /// </summary> /// <param name="filterContext"></param> public void OnException(ExceptionContext filterContext) { filterContext.HttpContext.Response.Write("方法名稱:OnException<br/>"); //輸出請求的控制器與action名稱 String controllerName = filterContext.RouteData.Values["controller"].ToString(); String actionName = filterContext.RouteData.Values["action"].ToString(); String message = String.Format("控制器:{0}<br/>action:{1}", controllerName, actionName); filterContext.HttpContext.Response.Write(message); filterContext.HttpContext.Response.Write("------------------華麗的分割線------------------<br/>"); } }
執行之后,效果如下圖:
通過上圖我們可以看到,OnAuthorization方法,是在所有方法(IActionFilter、IResultFilter)之前進行執行的,那么唯一沒有執行的是IException接口的OnException方法。這個方法是當我們的應用程序中出現錯誤的時候才執行的。以便我們統一對錯誤進行處理。
以上為我對ASP.NET MVC3中的Filter的理解,共享給大家,如果有什么不對的地方,也希望大家留言提出,也希望大家能留言一起討論。