ASP.NET MVC 入門9、Action Filter 與 內建的Filter實現(介紹)

來源:互聯網
上載者:User

本系列文章基於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:

    HomeController
    [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

    ---------------------------------------------------------------------

    更多內容,請關注http://blog.51mvc.com/ 和 http://bbs.51mvc.com/

  • 相關文章

    聯繫我們

    該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

    如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

    A Free Trial That Lets You Build Big!

    Start building with 50+ products and up to 12 months usage for Elastic Compute Service

    • Sales Support

      1 on 1 presale consultation

    • After-Sales Support

      24/7 Technical Support 6 Free Tickets per Quarter Faster Response

    • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.