1. 程式人生 > >ASP.NET MVC : Action過濾器(Filtering)

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的方法給我們重寫,OnActionExecutingOnActionExecuted

ASP.NET MVC 框架會在呼叫Action方法之前呼叫你Action過濾器中的OnActionExecuting方法,在之後呼叫Action過濾器中的OnActionExecuted方法。當然在建立Action過濾器的時候你不需兩個方法都實現。

下面的示例是在呼叫Action方法之前和之後的日誌跟蹤:

LoggingFilterAttribute

Action 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 Filter


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 過濾器