ASP.NET MVC 過濾器(三)
ASP.NET MVC 過濾器(三)
前言
本篇解說行為過濾器的執行過程,過濾器實現、使用方式有AOP的意思。能夠通過學習瞭解過濾器在框架中的執行過程從而獲得一些AOP方面的知識(在順序執行的過程中,這樣的程式設計模式就是橫向的插入點),言歸正傳,我們還是以學習過濾器為主。對於IAuthorizationFilter授權認證過濾器的使用篇幅。我知道怎麼用可是寫不出來,裡面包括知識點非常多。功底尚淺寫了一半又給刪掉了。寧願不發也不能坑人,在後面的學習中假使我能夠掌握了,一定會及時的寫出來跟大家分享。這個資料夾也空在這也算是給自己的一個提醒吧。
ASP.NET MVC過濾器
- 過濾器在系統框架中的總體物件模型
- IAuthorizationFilter授權認證過濾器的執行過程
- 使用IAuthorizationFilter過濾器
- IActionFilter行為過濾器的執行過程
- 自己定義實現IActionFilter行為過濾器
- 異常過濾器的使用
IActionFilter行為過濾器的執行過程
我們直接進入主題。這裡的執行過程還是接著過濾器(一)中的部分,我們看下執行過程的示意圖:
圖1
如圖1所看到的,就是整個的一個執行過程,圖太大拆開來看。這樣比較仔細一點(這裡捎帶一句,後面很多部分的內容都都包括在這個示意圖裡。比方說Model元資料、Model繫結和Model驗證)。
圖2
首先是呼叫了ControllerActionInvoker型別的GetParameterValues()方法,GetParameterValues()方法的引數是控制器上下文引數物件【ControllerContext型別】和控制器方法描寫敘述物件【ActionDescriptor型別】。然後在此方法中會依據ActionDescriptor型別的引數來呼叫GetParameters()方法獲取到控制器方法引數的描寫敘述物件【ParameterDescriptor型別】的集合,這裡對ParameterDescriptor型別不做過多的解說,僅僅需瞭解它是包括了控制器方法引數的一些資訊,比方說引數名稱、引數型別等等。
圖3
從圖2中所看到的的那樣,獲取到了ParameterDescriptor型別的集合後,便會遍歷此集合而且呼叫圖3中所看到的的ControllerActionInvoker型別的GetParameterValue()方法【這裡注意一下跟上面的圖2所看到的的方法是不同的】,呼叫GetParameterValue()方法的目的是生成一個鍵值隊型別的物件【紅色箭頭所指】,鍵值隊中的鍵表示引數名稱,值則為引數的值,而生成的過程是:首先MVC框架會呼叫使用者自己定義的模型繫結器(假設有自己定義的)【實現了IModelBinder介面的型別】,而且呼叫自己定義模型繫結器的方法以此來獲取控制器方法引數的引數值,假設沒有發現自己定義的模型繫結器,則會呼叫預設的Model繫結器進行引數繫結。假設沒有匹配的型別返回一個預設值【ParameterDescriptor.DefaultValue】。(關於Model繫結器內容興許系列會有解說)
圖4
有了引數值資訊的鍵值隊過後,接著呼叫ControllerActionInvoker型別的InvokeActionMethodWithFilters()方法,在此方法會生成兩種引數型別以便由ControllerActionInvoker型別的InvokeActionMethodFilter()方法呼叫,以下我們先解說這兩種引數型別:
- ActionExecutingContext
- Func<ActionExecutedContext>
第一個引數
1 public class ActionExecutingContext : ControllerContext 2 { 3 public ActionExecutingContext(); 4 public ActionExecutingContext(ControllerContext controllerContext, ActionDescriptor actionDescriptor, IDictionary<string, object> actionParameters); 5 6 public virtual ActionDescriptor ActionDescriptor { get; set; } 7 public virtual IDictionary<string, object> ActionParameters { get; set; } 8 public ActionResult Result { get; set; } 9 }
在上面型別的定義中,我們瞭解到ActionExecutingContext型別繼承至ControllerContext型別,而且包括著一些資訊的引用。這便是能夠在控制器方法執行之前執行自己的一些自己定義操作。
第二個引數
1 public class ActionExecutedContext : ControllerContext 2 { 3 4 public ActionExecutedContext(); 5 public ActionExecutedContext(ControllerContext controllerContext, ActionDescriptor actionDescriptor, bool canceled, Exception exception); 6 7 public virtual ActionDescriptor ActionDescriptor { get; set; } 8 public virtual bool Canceled { get; set; } 9 public virtual Exception Exception { get; set; } 10 public bool ExceptionHandled { get; set; } 11 public ActionResult Result { get; set; } 12 }
ActionExecutedContext型別跟ActionExecutingContext型別的差別在於前者多了兩個屬性一個是用於儲存異常資訊的,還有一個屬性是用來設定是否處理了異常,這個會在異常過濾器篇幅中解說。
切回主題。大概知道這兩種型別的定義即可了,說到Func<ActionExecutedContext>型別的引數。在MVC框架中預設的設定了Lambda表示式。而且對返回型別中的Result屬性又設定了一個表示式呼叫的是ControllerActionInvoker型別的InvokeActionMethod()方法,這種方法後面會講到。
我們看一下表達式的定義,不然有點混亂:
1 Func<ActionExecutedContext> seed = () => 2 { 3 new ActionExecutedContext(controllerContext,actionDescriptor, false,null) 4 { 5 Result = this.InvokeActionMethod(controllerContext, actionDescriptor, parameters) 6 } 7 };
上述的這些引數都準備完成後,能夠呼叫執行最後的ControllerActionInvoker型別的InvokeActionMethodFilter()方法。而當中的IActionFilter型別的引數則有在前面篇幅中講到的FilterInfo型別中的ActionFilters屬性提供。而且是遍歷執行的,最後能夠看到在InvokeActionMethodFilter()方法的內部首先是由IActionFilter型別的引數呼叫了OnActionExecuting()方法,然後執行Func<ActionExecutedContext>型別的引數,由於上面說到的。這個託付型別的引數已經定義好了預設的執行方式。是執行ControllerActionInvoker型別的中的InvokeActionMethod()方法。在此方法執行後在執行IActionFilter型別的OnActionExecuted()方法,而且終於的結果值返回到了ActionExecutedContext型別的Result屬性中。
最後我們看一下IActionFilter型別的結構定義:
1 public interface IActionFilter 2 { 3 // 摘要: 4 // 在執行操作方法後呼叫。 5 // 6 // 引數: 7 // filterContext: 8 // 篩選器上下文。 9 void OnActionExecuted(ActionExecutedContext filterContext); 10 // 11 // 摘要: 12 // 在執行操作方法之前呼叫。 13 // 14 // 引數: 15 // filterContext: 16 // 篩選器上下文。 17 void OnActionExecuting(ActionExecutingContext filterContext); 18 }
行為過濾器大概的執行過程解說完成了,下一篇會對這樣的型別的過濾器的應用作大概解說。
作者:金源
出處:http://blog.csdn.net/jinyuan0829
本文版權歸作者和CSDN共同擁有。歡迎轉載。但未經作者允許必須保留此段宣告,且在文章頁面