ASP.NET MVC : Action過濾器(Filtering)
相關文章:
有時候你想在呼叫action方法之前或者action方法之後處理一些邏輯,為了支援這個,ASP.NET MVC允許你建立action過濾器。Action過濾器是自定義的Attributes,用來標記新增Action方法之前或者Action方法之後的行為到控制器類中的Action方法中。
一些可能用到Action過濾器的地方有:
- 日誌
- 身份驗證和授權 - 限制使用者的訪問
- 輸出快取 - 儲存一個Action的結果
- 網路爬蟲的過濾
- 本地化
- 動態Action - 將一個Action注入到控制器中
實現一個Action過濾器
Action過濾器是通過繼承ActionFilterAttribute類來實現的一個Attribute類。ActionFilterAttribute 是一個抽象類,提供了兩個virtual的方法給我們重寫,OnActionExecuting和OnActionExecuted。
ASP.NET MVC 框架會在呼叫Action方法之前呼叫你Action過濾器中的OnActionExecuting方法,在之後呼叫Action過濾器中的OnActionExecuted方法。當然在建立Action過濾器的時候你不需兩個方法都實現。
下面的示例是在呼叫Action方法之前和之後的日誌跟蹤:
LoggingFilterAttributeAction Filter Context
OnActionExecuting方法有一個型別為FilterExecutingContext的引數,而OnActionExecuted方法有一個相應的型別為FilterExcutedContext的引數。兩個Context類都是繼承自FilterContext類,而FilterContext類繼承自ControllerContext類幷包含一個ActionMethod屬性。你可以使用ActionMethod屬性來堅定這個Action過濾器是應用到哪個Action方法上的。
FilterExecutingContext類包含一個 Cancel 的屬性,允許你取消當前的Action。
FilterExcutedContext 類包含一個Exception屬性和一個ExceptionHandled屬性。如果Exception屬性為null,則沒有異常在action stack中,表明Action方法執行並沒有發生錯誤。如果Exception屬性不為null,則過濾器知道該怎麼處理,過濾器處理完異常後會發出已經處理完的訊號,然後將ExceptionHandled屬性設為true。就算ExceptionHandled屬性為true,堆疊中新增到其他Action方法的OnActionExcetued方法將會照常被呼叫,這種場景就如就算一個異常被處理了,日誌記錄filter一樣照常執行。
用過濾器特性(Attribute)來標記一個Action方法
你可以將過濾器應用到任何一個你喜歡的Action方法上。下面的示例演示一個控制器中包含的用Action過濾器Attribute標記的Action方法。
publicclass HomeController : Controller{
[LoggingFilter]
publicvoid Index()
{
RenderView("Index");
}
[LoggingFilter]
publicvoid About()
{
RenderView("About");
}
[LoggingFilter]
publicvoid ClickMe()
{
HttpContext.Trace.Write("Button was clicked.");
InvokeAction("Index");
}
}
實現一個控制器範圍的Action過濾器
ASP.NET MVC 控制器(Controller)類定義的OnActionExecuting 和 OnActionExcuted 方法你可以重寫。當你重寫一個或者這兩個方法的時候,你實際上定義了一個將會應用到該控制器類中所有的Action方法的Action過濾器。嚴格來說,這個方法沒有構成一個Action過濾器,但不管怎樣,她們提供的功能是相似的。
在下面的示例中,控制器級別的OnActionExecuting和OnActionExecuted方法應用到控制器中所有的Action方法中:
Action過濾器的作用範圍
除了用Action過濾器標記一個Action方法外,你也可以用來標記一個完成的控制器類。如果這樣的話,這個Action過濾器將會應用到該控制器的所有Action方法上。
另外,如果你的控制器類繼承自別的控制器類,而基控制器類可能有它自己的Action過濾器Attributes。如果你在子類中重寫了基控制器類的Action方法,則子類的該Action方法也會有它自己的從基類繼承而來的Action過濾器Attributes。
Action過濾器的執行順序
每一個Action過濾器都有一個 Order 屬性,用來決定Action過濾器在該範圍內的執行順序。Order屬性必需是0(預設值)或者更大的整數值。省略Order屬性則會給該過濾器的Order值為 -1, 表明為指明順序。任何一個在同一範圍的Action過濾器Order設為 -1 的都將按不確定的順序執行,單在此之前過濾器有一個特定的順序(注:下面會說到).
當設定Order屬性的值的時候,必需指定一個唯一的值。如果兩個或者更多的Action過濾器具有相同的Order屬性值,將會丟擲一個異常。
來看一個示例:
[Filter1(Order =2)][Filter2(Order =3)]
[Filter3(Order =1)]
publicvoid Index()
{
RenderView("Index");
}
Filter的執行順序為:Filter3 => Filter1 => Filter2.
在同一範圍,Action過濾器按下面的順序執行:
- OnActionExecuting virtual method of the controller.
- OnActionExecuting method of any filters that are applied to the current controller, in this order:
-
Base class
-
Any derived class
-
- OnActionExecuting method of filters that are applied to the action method, in this order:
-
Base class
-
Derived class
-
- Action method
- OnActionExecuted method of filters that are applied to the action method, in this order:
-
Derived class
-
Base class
-
- OnActionExecuted method of filters that are applied to the current controller, in this order:
-
Derived class
-
Base class
-
- OnActionExecuted virtual method of the controller.
可以看到OnActionExecuted 和 OnActionExecuting 的執行順序是反過來的。
Action過濾器執行順序的示例
下面的示例演示了一個包含兩個Action過濾器的MVC程式。DebugFilter 過濾器寫trace資訊,而ThrowExceptionFilter 過濾器引起一個異常。這個程式也包含一個基控制器和一個子控制器和一個檢視。
DebugFilter 過濾器