Asp.Net MVC3 簡單入門詳解過濾器Filter

前言

在開發大項目的時候總會有相關的AOP面向切面編程的組件,而MVC(特指:Asp.Net MVC,如下皆同)項目中不想讓MVC開發人員去關心和寫相似身份驗證,日誌,異常,行爲截取等這部分重複的代碼,那咱們能夠經過AOP截取實現,而在MVC項目中咱們就能夠直接使用它提供的Filter的特性幫咱們解決,不用本身實現複雜的AOP了。編程

在Asp.net Mvc中當你有如下及相似如下需求時你可使用Filter功能瀏覽器

  1. 判斷登陸與否或用戶權限
  2. 決策輸出緩存
  3. 防盜鏈
  4. 防蜘蛛
  5. 本地化與國際化設置 
  6. 實現動態Action

第一節:知識儲備

Asp.Net MVC提供瞭如下幾種默認的Filter:緩存

Filter Type服務器

實現接口ide

執行時間字體

Default Implementationui

Authorization filter.net

IAuthorizationFilter3d

在全部Filter和Action執行以前執行日誌

AuthorizeAttribute

Action filter

IActionFilter

分別在Action執行以前和以後執行。

ActionFilterAttribute

Result filter

IResultFilter

分別在Action Result執行以後和以前

ResultFilterAttribute

Exception filter

IExceptionFilter

只有在filter,

或者 action method, 或者 action result 拋出一個異常時候執行

HandleErrorAttribute

你們注意一點,Asp.Net MVC提供的ActionFilterAttribute默認實現了IActionFilter和IResultFilter。而ActionFilterAttribute是一個Abstract的類型,因此不能直接使用,由於它不能實例化,因此咱們想使用它必須繼承一下它而後才能使用。

Filter繼承於ActionFilterAttribute抽象類,並能夠覆寫 void OnActionExecuting(ActionExecutingContext) 和 voidOnActionExecuted(ActionExecutedContext) 以及 void OnResultExecuting(ResultExecutingContext)和 voidOnResultExecuted(ResultExecutedContext)。

它們的執行前後順序以下:

OnActionExecuting是Action執行前的操做

OnActionExecuted則是Action執行後的操做

OnResultExecuting是解析ActionResult前執行

OnResultExecuted是解析ActionResult後執行

接下來咱們只要對以上的方法進行重寫就能夠在相應的步驟作一些操做了。

第二節:Filter實戰

光說不練假把式,下面我給你們一個示例,來看看它們的執行順序

首先添加一個普通的類,這個類要繼承ActionFilterAttribute,,直接上代碼了

複製代碼

  public class TestFilterAttribute:ActionFilterAttribute
    {
        public string Message { get; set; }

        public override void OnActionExecuting(ActionExecutingContext filterContext)
        {
            base.OnActionExecuting(filterContext);
            filterContext.HttpContext.Response.Write("Action執行以前"+Message+"<br />");
        }

        public override void OnActionExecuted(ActionExecutedContext filterContext)
        {
            base.OnActionExecuted(filterContext);
            filterContext.HttpContext.Response.Write("Action執行以後"+Message+"<br />");
        }

        public override void OnResultExecuting(ResultExecutingContext filterContext)
        {
            base.OnResultExecuting(filterContext);
            filterContext.HttpContext.Response.Write("返回Result以前"+Message+"<br />");
        }

        public override void OnResultExecuted(ResultExecutedContext filterContext)
        {
            base.OnResultExecuted(filterContext);
            filterContext.HttpContext.Response.Write("返回Result以後"+Message+"<br />");
        }
    }

複製代碼

寫完這個代碼後,咱們回到Action上,打上上面的標記以下所示:

     [TestFilter(Message="Action")]
        public ActionResult Index()
        {
            HttpContext.Response.Write("Action正在執行···<br />");
            return Content("正在返回Result···<br />");
        }

而後經過瀏覽器訪問上面的Action即可以看到下面的執行順序

總的執行順序是:

Action執行前:OnActionExecuting方法先執行→Action執行→OnActionExecuted方法執行→OnResultExecuting方法執行→返回的ActionRsult中的executeResult方法執行→OnResultExecuted執行。最終顯示的效果就是如上圖所示。

感受很爽吧!呵呵!這要想用到這個過濾機制的地方的時候,只要在Action上面添加標記即可以實現效果。

若是咱們將此標籤打到Controller上的話,TestFilterAttributeFilter將做用到Controller下的全部的Action。例如以下代碼所示:

複製代碼

  [TestFilter(Message="Controller")]
    public class TestFilterController : Controller
    {
        //
        // GET: /TestFilter/
        [TestFilter(Message="Action")]
        public ActionResult Index()
        {
            HttpContext.Response.Write("Action正在執行···<br />");
            return Content("正在返回Result···<br />");
        }

    }

複製代碼

若是單純的按照上面的代碼來作就有個問題了咱們再執行顯示的頁面會有什麼狀況呢?Controller上的Filter會執行嗎?那標籤的做用會執行兩次嗎?下面是最後的執行結果以下圖所示:

結果說明:默認狀況下Action上打了TestFilterAttribute 標籤後,雖然在Controller上也打上了此標籤,但它只有Action上的標籤起做用了。

補充:若是Action沒有打上TestFilterAttribute標籤,那麼Controller上的標籤便會被執行。

Index 執行時,Filter的方法只執行了一次,而某些狀況下咱們也想讓Controller上的FilterAttribute也執行一次TestFilterAttribute,那咱們怎麼才能讓Controller上的[TestFilter(Message = "controller")]也起做用呢?

答案是:咱們只需在TestFilterAttribute類的定義上打上標記[AttributeUsage(AttributeTargets.All, AllowMultiple = true)]便可【下面類的最上面紅色字體部分】,也就是讓其成爲能夠屢次執行的Action代碼以下:

複製代碼

  [AttributeUsage(AttributeTargets.All,AllowMultiple = true)]
    public class TestFilterAttribute:ActionFilterAttribute
    {
        public string Message { get; set; }

        public override void OnActionExecuting(ActionExecutingContext filterContext)
        {
            base.OnActionExecuting(filterContext);
            filterContext.HttpContext.Response.Write("Action執行以前"+Message+"<br />");
        }

        public override void OnActionExecuted(ActionExecutedContext filterContext)
        {
            base.OnActionExecuted(filterContext);
            filterContext.HttpContext.Response.Write("Action執行以後"+Message+"<br />");
        }

        public override void OnResultExecuting(ResultExecutingContext filterContext)
        {
            base.OnResultExecuting(filterContext);
            filterContext.HttpContext.Response.Write("返回Result以前"+Message+"<br />");
        }

        public override void OnResultExecuted(ResultExecutedContext filterContext)
        {
            base.OnResultExecuted(filterContext);
            filterContext.HttpContext.Response.Write("返回Result以後"+Message+"<br />");
        }
    }

複製代碼

瀏覽效果以下圖:

咱們看到的結果是Controller上的ActionFilter先於Action上打的標記執行。一樣Result執行executeResult方法以前也是先執行Controller上的Filter標記中的OnResultexecuteing方法。

最後的執行順序是:Controller上的OnActionExecuting→Action上的OnActionExecuting→Action執行→Action上的OnActionExecuted→Controller上的OnActionExecuted

到此Action就執行完畢了,咱們看到是一個入棧出棧的順序。後面是Action返回ActionResult後執行了ExecuteResult方法,但在執行以前要執行Filter。具體順序爲:

接上面→Controller的OnResultExecuting方法→Action上的OnResultExecuting→Action返回ActionResult後執行了ExecuteResult方法→Action上的OnResultExecuted執行→Controller上的OnResultExecuted執行→結束。

又接着一個問題也來了,咱們想有些公共的方法須要每一個Action都執行如下,而在全部的Controller打標記是很痛苦的。幸虧Asp。Net MVC3帶來了一個美好的東西,全局Filter。而怎麼註冊全局Filter呢?答案就在Global.asax中。讓咱們看如下代碼,我是如何將上面咱們定義的TestFilterAttribute 註冊到全局Filter中。上代碼:

    public static void RegisterGlobalFilters(GlobalFilterCollection filters)
        {
            filters.Add(new HandleErrorAttribute());
            //註冊全局過濾器
            filters.Add(new TestFilterAttribute() { Message="全局"});
        }

效果以下圖:

咱們看到的結果是全局的Action首先執行,而後纔是Controller下的Filter執行,最後纔是Action上的標籤執行。固然這是在TestFilterAttribute類的定義上打上標記[AttributeUsage(AttributeTargets.All, AllowMultiple = true)]的前提下。否則 若是Action打上了標籤跟Controller的相同則它只會執行Action上的Filter。

下面咱們說幾個系統的Filter

3、AcceptVerbs

規定頁面的訪問形式,如

[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Example(){
return View();
}

頁面只能以Post形式訪問,即表單提交。

4、ActionName

規定Action的名稱。

應用場景:若是不想用方法名作爲Action名,或Action名爲關鍵字的話,如

[ActionName("class")]
public ActionResult Example(){
return View();
}

5、NonAction

當前方法僅是普通方法不解析爲Action

6、OutputCache

爲Action添加緩存

[OutputCache(Duration = 60, VaryByParam = "*")]
public ActionResult Example()
{
return View();
}

7、ValidateInput

該Action能夠接受Html等危險代碼(ASP.NET MVC在aspx中設置<%@ Page 的屬性沒法完成等同任務。)

[ValidateInput(false)]
public ActionResult Example()
{
return View();
}

8、ValidateAntiForgeryTokenAttribute

用於驗證服務器篡改。

[ValidateAntiForgeryToken]
public ActionResult Example()
{
return View();
}

總結

通過這一篇文章的介紹咱們大致瞭解了Filter的使用方法,還了解到全局Filter的用法,尤爲是當相同的Filter重複做用到同一個Action上時,若是沒有設置可屢次執行的標籤那只有Action上的Filter執行,而Controller和全局Filter都被屏蔽掉,可是設置可屢次執行,那首先執行全局Filter其次是Controller再次之就是Action上的Filter了。同時還了解了系統的Filter的用法。

做者:boruipower

出處:http://www.cnblogs.com/boruipower

相關文章
相關標籤/搜索