ASP.NET MVC 過濾器(一)
前言
前面的篇幅中,了解到了控制器的生成的過程以及在生成的過程中的各種注入點,按照常理來說篇幅應該到了講解控制器內部的執行過程以及模型綁定、驗證這些知識了。但是呢,在MVC框架中提供了一種機制在控制器方法執行之前我們還可以通過這種機制來做一些橫向切面的操作,這種機制的實現就是過濾器了,在本篇和后續的篇幅中將會對幾種過濾器做一番講解,並且會對過濾器在框架中的一個執行過程進行粗略的講解。
ASP.NET MVC過濾器
- 過濾器在系統框架中的整體對象模型
- IAuthorizationFilter授權認證過濾器的執行過程
- 使用IAuthorizationFilter過濾器
- IActionFilter行為過濾器的執行過程
- 自定義實現IActionFilter行為過濾器
- 異常過濾器的使用
過濾器在系統框架中的整體對象模型
我們在獲得控制器工廠生成的控制器后,執行某些控制器行為之前,總是要驗證一些數據或者是請求信息什么的,這里就要用到過濾器的機制了,而在框架中過濾器是怎么運轉的,通過本小節的學習會讓你有個大概的了解。
現在我們切入主題來講解一下在MVC框架中的過濾器。
圖1
如上圖所示的這樣,在控制器執行的時候會調用ControllerActionInvoker類型的InvokeAction()方法,而在InvokeAction()方法中,框架會默認的生成控制器描述對象ControllerDescriptor和控制器行為描述對象ActionDescriptor,這兩種類型的對象都是對當前的控制器和所要請求的控制器方法信息的封裝,這個知識點我們會在后續的篇幅中講到,這里只須了解一下,忽略它們的生成過程。參照如下圖:
圖2
按照InvokeAction()方法的執行流程,到了生成FilterInfo類型的時候,我們都知道MVC框架給我們提供了四種過濾器,哪四種后面一一介紹,那么FilterInfo類型是干什么的呢?來看一下它的對象結構:
1 //封裝有關可用的操作篩選器的信息。 2 public class FilterInfo 3 { 4 public FilterInfo(); 5 public FilterInfo(IEnumerable<Filter> filters); 6 public IList<IActionFilter> ActionFilters { get; } 7 public IList<IAuthorizationFilter> AuthorizationFilters { get; } 8 public IList<IExceptionFilter> ExceptionFilters { get; } 9 public IList<IResultFilter> ResultFilters { get; } 10 }
它的內部有着四種過濾器集合類型的屬性,並且有個構造函數是接收IEnumerable<Filter>類型的,當FilterInfo類型在初始化的時候會根據構造函數傳入的類型進行解析,並且對四個屬性分別賦值,這就要涉及到另一個元數據描述對象Filter了。
我們來看一下Filter對象的結構:
1 // 表示一個元數據類,它包含對一個或多個篩選器接口的實現、篩選器順序和篩選器范圍的引用。 2 public class Filter 3 { 4 public const int DefaultOrder = -1; 5 public Filter(object instance, FilterScope scope, int? order); 6 7 public object Instance { get; protected set; } 8 public int Order { get; protected set; } 9 public FilterScope Scope { get; protected set; } 10 }
看到這里有可能有的朋友不明白這個對象,具體怎么表示?因為元數據編程模式很少見,這里我給大家舉個例子,一看就明白了:
1 [Authorize(Order=1)] 2 public class DemoController : Controller 3 { 4 …… 5 }
上面的這個列子則會在系統生成的時候生成一個Filter類型的對象,並且賦值Order等於1,而Filter類型中的Instance屬性則是對上述例子中的Authorize類型實例引用,這就是元數據描述對象,當然了講的不是太詳細,能讓大家明白就行了,Authorize類型的具體使用在下一篇中會有講到。
現在我們回歸主題,如圖2中所表示的那樣,IEnumerable<Filter>集合類型是關鍵,那么怎么生成IEnumerable<Filter>集合類型?
先是調用ControllerActionInvoker類型中的GetFilters()方法,我們看到方法的參數類型為控制器參數上下文對象和控制器行為元數據描述對象,這兩個對象就夠了,它們中包含的信息已經很多了,在ControllerActionInvoker的GetFilters()方法內部調用FilterProviderCollection類型的GetFilters(),和上面所述的類型方法簽名一樣,只不過返回類型有差異而已,而真正的根據參數執行生成Filter類型的對象是實現了IFilterProvider類型的對象,
看一下IFilterProvider類型的結構:
1 // 提供用於查找篩選器的接口。 2 public interface IFilterProvider 3 { 4 IEnumerable<Filter> GetFilters(ControllerContext controllerContext, ActionDescriptor actionDescriptor); 5 }
而這個對象是可以從外部注入進來的,在控制器(三)中提到過的,通過實現IDependencyResolver類型,而在框架中也會默認的實現一個(只是我通過反編譯工具沒看到,顯示的是錯誤信息,表示很郁悶,后文中就叫它為默認實現)。在FilterProviderCollection類型的GetFilters()中,會通過默認實現來得到當前請求的行為上的所有過濾器元數據描述對象,並且進行排序、驗證,這里就不多敘述了。然后返回IEnumerable<Filter>集合類型並且生成FilterInfo類型的對象。
IAuthorizationFilter授權認證過濾器的執行過程
圖3
先來看一下IAuthorizationFilter類型的定義:
1 public interface IAuthorizationFilter 2 { 3 // 摘要: 4 // 在需要授權時調用。 5 // 6 // 參數: 7 // filterContext: 8 // 篩選器上下文。 9 void OnAuthorization(AuthorizationContext filterContext); 10 }
看到如上的定義,再看圖3IAuthorizationFilter類型的執行過程一目了然,根據ControllerContext控制器參數上下文對象和控制器行為據描述對象actionDescriptor生成AuthorizationContext授權認證過濾器參數上下文對象,並且會遍歷FilterInfo類型中的AuthorizationFilters屬性,挨個的去執行我們定義的過濾器。
本篇的內容就講到這里,下個篇幅中會講到IAuthorizationFilter類型的使用
作者:金源
出處:http://www.cnblogs.com/jin-yuan/
本文版權歸作者和博客園共有,歡迎轉載,但未經作者同意必須保留此段聲明,且在文章頁面