ASP.NET MVC 入门9、Action Filter 与 内置的Filter实现(介绍)
本系列文章基于ASP.NET MVC Preview5.
有時候你想在調用action方法之前或者action方法之后處理一些邏輯,為了支持這個,ASP.NET MVC允許你創建action過濾器。Action過濾器是自定義的Attributes,用來標記添加Action方法之前或者Action方法之后的行為到控制器類中的Action方法中。
一些可能用到Action過濾器的地方有:
- 日志,異常處理
- 身份驗證和授權 - 限制用戶的訪問
- 輸出緩存 - 保存一個Action的結果
- 網絡爬蟲的過濾
- 本地化
- 動態Action - 將一個Action注入到控制器中
ASP.NET MVC為我們提供了下面的幾個Filter接口:
- IActionFilter
- IAuthorizationFilter
- IExceptionFilter
- IResultFilter
要實現一個Filter,我們需要繼承自FilterAttribute類同時實現上面的一個或幾個接口:
public?class?MyFilter?:?FilterAttribute,?IActionFilter,?IResultFilter
{
}??
這幾個接口提供的方法如下:
上圖的方法和Filter接口對應的方法按名稱對號入座就可以。
IActionFilter接口有兩個方法:
其中OnActionExecuting在執行Action方法之前會被調用,OnActionExecuted會在Action方法執行后調用。注意他們的參數分別是ActionExecutingContext和ActionExecutedContext。
ActionExecutedContext類包含一個?Canceled的屬性,允許你取消當前的Action(怎么原來在P3中是在ActionExecutingContext的Canceled屬性在P5中沒有了呢?神奇.那么在OnActionExecuting的時候怎么取消一個Action呢?)。
FilterExcutedContext 類包含一個Exception屬性和一個ExceptionHandled屬性。如果Exception屬性為null,則沒有異常在action stack中,表明Action方法運行并沒有發生錯誤。反之則為出現異常。如果將ExceptionHandled屬性設置為true則表明在這個Filter中已經處理了異常。
IResultFilter接口也提供了兩個方法:
轉存失敗重新上傳取消
他們分別在Action返回結果(例如return View();)之前和之后執行。和IActionFilter差不多就不多說了。
IAuthorizationFilter是一個用于身份驗證的Filter。只提供了一個void OnAuthorization(AuthorizationContext filterContext)方法。
IExceptionFilter會在出現異常的時候調用,也是只 提供一個void OnException(ExceptionContext filterContext)的方法;
這些Filter可以被應用在類或者方法上,下面我們來看一下他們的執行順序。首先我們寫一個BaseController并加上兩個Filter:
[MyFilter2(Target?=?"BaseController")]
[MyFilter1(Target="BaseController")]
public?class?BaseController?:?Controller
{?
}??
應為Controller類是實現這幾個Filter接口的,所以我們在HomeController中重寫Controller基類中的所有Filter接口的方法,并在HomeController類和里面的Filter方法加上我們自定義的MyFilter:
[MyFilter2(Target?=?"HomeController")]
//[MyFilter1(Target?=?"HomeController")]//注意我在這里把MyFilter1注釋了.
[HandleError]
public?class?HomeController?:?BaseController
{
????[MyFilter2(Target?=?"HomeController.Filter")]
????[MyFilter1(Target?=?"HomeController.Filter")]
????public?ActionResult?Filter()
????{
????????return?Content("<div>這是在Action方法里面返回的內容!</div>");
????}?
????protected?override?void?OnActionExecuted(ActionExecutedContext?filterContext)
????{
????????filterContext.HttpContext.Response.Write("<div>這是在HomeController里面重寫OnActionExecuted方法添加的內容!</div>");
????}?
????protected?override?void?OnActionExecuting(ActionExecutingContext?filterContext)
????{
????????filterContext.HttpContext.Response.Write("<div>這是在HomeController里面重寫OnActionExecuting方法添加的內容!</div>");
????}?
????protected?override?void?OnAuthorization(AuthorizationContext?filterContext)
????{
????????filterContext.HttpContext.Response.Write("<div>這是在HomeController里面重寫OnAuthorization方法添加的內容!</div>");
????}?
????protected?override?void?OnException(ExceptionContext?filterContext)
????{
????????filterContext.HttpContext.Response.Write("<div>這是在HomeController里面重寫OnException方法添加的內容!</div>");
????????filterContext.ExceptionHandled?=?true;
????}?
????protected?override?void?OnResultExecuted(ResultExecutedContext?filterContext)
????{
????????filterContext.HttpContext.Response.Write("<div>這是在HomeController里面重寫OnResultExecuted方法添加的內容!</div>");
????}?
????protected?override?void?OnResultExecuting(ResultExecutingContext?filterContext)
????{
????????filterContext.HttpContext.Response.Write("<div>這是在HomeController里面重寫OnResultExecuting方法添加的內容!</div>");
????}
}?然后我們運行一下看看結果如何:
從運行結果我們可以看到,在Controller中重寫的Filter會最先執行,然后到應用在類上的Filter,然后再到應用在類方法上的Filter。
而4個接口的方法執行順序如下:IAuthorizationFilter ->?IActionFilter ->?IResultFilter ->?IExceptionFilter?.
而對于同一個Filter,例如IAuthorizationFilter在MyFilter1和MyFilter2里里面的實現,又根據他們的加載順序不同而不同。
在BaseController中應用的Filter會被子類繼承,如果子類又應用了和基類同樣的Filter,則會不執行基類的Filter。例如上面的HomeController應用了MyFilter2,所以調用HomeController的MyFilter2,而不是BaseController的MyFilter2。
這個執行順序還得大家好好研究才能了解的。
同時FilterAttribute還提供了一個Order的屬性,用于指定Filter的執行順序。
每一個Action過濾器都有一個 Order 屬性,用來決定Action過濾器在該范圍內的執行順序。Order屬性必需是0(默認值)或者更大的整數值。省略Order屬性則會給該過濾器的Order值為 -1, 表明未指明順序。任何一個在同一范圍的Action過濾器Order設為 -1 的都將按不確定的順序執行,但在此之前過濾器有一個特定的順序(請參考上圖).
當設置Order屬性的值的時候,必需指定一個唯一的值。如果兩個或者更多的Action過濾器具有相同的Order屬性值,將會拋出一個異常。
來看一個示例:
[Filter1(Order?=?2)]
[Filter2(Order?=?3)]
[Filter3(Order?=?1)]
public?void?Index()
{
????RenderView("Index");
}??
Filter的執行順序為:Filter3 => Filter1 => Filter2.
暫時就寫這么多吧,這一部分主要介紹概念。Enjoy!Post by?Q.Lee.lulu。
本文的Blog程序示例代碼:?ActionFilter.rar
總結
以上是生活随笔為你收集整理的ASP.NET MVC 入门9、Action Filter 与 内置的Filter实现(介绍)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 拿出1万元买国债,5年后的利息有多少?不
- 下一篇: [你必须知道的.NET]第三十四回,ob