在開發大項目的時候總會有相關的AOP面向切面編程的組件,而MVC(特指:Asp.Net MVC,如下皆同)項目中不想讓MVC開發人員去關心和寫相似身份驗證,日誌,異常,行爲截取等這部分重複的代碼,那咱們能夠經過AOP截取實現,而在MVC項目中咱們就能夠直接使用它提供的Filter的特性幫咱們解決,不用本身實現複雜的AOP了。html
在Asp.net Mvc中當你有如下及相似如下需求時你可使用Filter功能編程
Asp.Net MVC提供瞭如下幾種默認的Filter:瀏覽器
Filter Type緩存 |
實現接口ide |
執行時間字體 |
Default Implementationui |
Authorization filterspa |
IAuthorizationFilter.net |
在全部Filter和Action執行以前執行日誌 |
AuthorizeAttribute |
Action filter |
IActionFilter |
分別在Action執行以前和以後執行。 |
ActionFilterAttribute |
Result filter |
IResultFilter |
分別在Action Result執行以後和以前 |
ResultFilterAttribute |
Exception filter |
IExceptionFilter |
只有在filter, 或者 action method, 或者 action result 拋出一個異常時候執行
|
HandleErrorAttribute |
你們注意一點,Asp.Net MVC提供的ActionFilterAttribute默認實現了IActionFilter和IResultFilter。而ActionFilterAttribute是一個Abstract的類型,因此不能直接使用,由於它不能實例化,因此咱們想使用它必須繼承一下它而後才能使用。
Filter繼承於ActionFilterAttribute抽象類,並能夠覆寫 void OnActionExecuting(ActionExecutingContext) 和 void OnActionExecuted(ActionExecutedContext) 以及 void OnResultExecuting(ResultExecutingContext)和 void OnResultExecuted(ResultExecutedContext)。
它們的執行前後順序以下:
OnActionExecuting是Action執行前的操做
OnActionExecuted則是Action執行後的操做
OnResultExecuting是解析ActionResult前執行
OnResultExecuted是解析ActionResult後執行
接下來咱們只要對以上的方法進行重寫就能夠在相應的步驟作一些操做了。
光說不練假把式,下面我給你們一個示例,來看看它們的執行順序
首先添加一個普通的類,這個類要繼承ActionFilterAttribute,,直接上代碼了
public class TestFilterAttribute:ActionFilterAttribute { public string Message { get; set; } public override void OnActionExecuting(ActionExecutingContext filterContext) { base.OnActionExecuting(filterContext); filterContext.HttpContext.Response.Write("Action執行以前"+Message+"<br />"); } public override void OnActionExecuted(ActionExecutedContext filterContext) { base.OnActionExecuted(filterContext); filterContext.HttpContext.Response.Write("Action執行以後"+Message+"<br />"); } public override void OnResultExecuting(ResultExecutingContext filterContext) { base.OnResultExecuting(filterContext); filterContext.HttpContext.Response.Write("返回Result以前"+Message+"<br />"); } public override void OnResultExecuted(ResultExecutedContext filterContext) { base.OnResultExecuted(filterContext); filterContext.HttpContext.Response.Write("返回Result以後"+Message+"<br />"); } }
寫完這個代碼後,咱們回到Action上,打上上面的標記以下所示:
[TestFilter(Message="Action")] public ActionResult Index() { HttpContext.Response.Write("Action正在執行···<br />"); return Content("正在返回Result···<br />"); }
而後經過瀏覽器訪問上面的Action即可以看到下面的執行順序
這要想用到這個過濾機制的地方的時候,只要在Action上面添加標記即可以實現效果。
若是咱們將此標籤打到Controller上的話,TestFilterAttributeFilter將做用到Controller下的全部的Action。例如以下代碼所示:
[TestFilter(Message="Controller")] public class TestFilterController : Controller { // // GET: /TestFilter/ [TestFilter(Message="Action")] public ActionResult Index() { HttpContext.Response.Write("Action正在執行···<br />"); return Content("正在返回Result···<br />"); } }
若是單純的按照上面的代碼來作就有個問題了咱們再執行顯示的頁面會有什麼狀況呢?Controller上的Filter會執行嗎?那標籤的做用會執行兩次嗎?下面是最後的執行結果以下圖所示:
結果說明:默認狀況下Action上打了TestFilterAttribute 標籤後,雖然在Controller上也打上了此標籤,但它只有Action上的標籤起做用了。
補充:若是Action沒有打上TestFilterAttribute標籤,那麼Controller上的標籤便會被執行。
Index 執行時,Filter的方法只執行了一次,而某些狀況下咱們也想讓Controller上的FilterAttribute也執行一次TestFilterAttribute,那咱們怎麼才能讓Controller上的[TestFilter(Message = "controller")]也起做用呢?
答案是:咱們只需在TestFilterAttribute類的定義上打上標記[AttributeUsage(AttributeTargets.All, AllowMultiple = true)]便可【下面類的最上面紅色字體部分】,也就是讓其成爲能夠屢次執行的Action。代碼以下:
[AttributeUsage(AttributeTargets.All,AllowMultiple = true)] public class TestFilterAttribute:ActionFilterAttribute { public string Message { get; set; } public override void OnActionExecuting(ActionExecutingContext filterContext) { base.OnActionExecuting(filterContext); filterContext.HttpContext.Response.Write("Action執行以前"+Message+"<br />"); } public override void OnActionExecuted(ActionExecutedContext filterContext) { base.OnActionExecuted(filterContext); filterContext.HttpContext.Response.Write("Action執行以後"+Message+"<br />"); } public override void OnResultExecuting(ResultExecutingContext filterContext) { base.OnResultExecuting(filterContext); filterContext.HttpContext.Response.Write("返回Result以前"+Message+"<br />"); } public override void OnResultExecuted(ResultExecutedContext filterContext) { base.OnResultExecuted(filterContext); filterContext.HttpContext.Response.Write("返回Result以後"+Message+"<br />"); } }
瀏覽效果以下圖:
咱們看到的結果是Controller上的ActionFilter先於Action上打的標記執行。一樣Result執行executeResult方法以前也是先執行Controller上的Filter標記中的OnResultexecuteing方法。
最後的執行順序是:Controller上的OnActionExecuting→Action上的OnActionExecuting→Action執行→Action上的OnActionExecuted→Controller上的OnActionExecuted
到此Action就執行完畢了,咱們看到是一個入棧出棧的順序。後面是Action返回ActionResult後執行了ExecuteResult方法,但在執行以前要執行Filter。具體順序爲:
接上面→Controller的OnResultExecuting方法→Action上的OnResultExecuting→Action返回ActionResult後執行了ExecuteResult方法→Action上的OnResultExecuted執行→Controller上的OnResultExecuted執行→結束。
又接着一個問題也來了,咱們想有些公共的方法須要每一個Action都執行如下,而在全部的Controller打標記是很痛苦的。幸虧Asp。Net MVC3帶來了一個美好的東西,全局Filter。而怎麼註冊全局Filter呢?答案就在Global.asax中。讓咱們看如下代碼,我是如何將上面咱們定義的TestFilterAttribute 註冊到全局Filter中。上代碼:
public static void RegisterGlobalFilters(GlobalFilterCollection filters) { filters.Add(new HandleErrorAttribute()); //註冊全局過濾器 filters.Add(new TestFilterAttribute() { Message="全局"}); }
效果以下圖:
咱們看到的結果是全局的Action首先執行,而後纔是Controller下的Filter執行,最後纔是Action上的標籤執行。固然這是在TestFilterAttribute類的定義上打上標記[AttributeUsage(AttributeTargets.All, AllowMultiple = true)]的前提下。否則 若是Action打上了標籤跟Controller的相同則它只會執行Action上的Filter。
轉自http://www.cnblogs.com/boruipower/archive/2012/11/18/2775924.html