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

來源:互聯網
上載者:User
文章目錄
  • 前言
  • 第一節:知識儲備
  • 第二節:Filter實戰
  • 下面我們說幾個系統的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

實現介面

執行時間

Default Implementation

Authorization filter

IAuthorizationFilter

在所有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 三、AcceptVerbs

規定頁面的訪問形式,如

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

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

四、ActionName

規定Action的名稱。

應用情境:如果不想用方法名做為Action名,或Action名為關鍵字的話,如

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

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

六、OutputCache

為Action添加緩衝

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

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

        [ValidateInput(false)]
public ActionResult Example()
{
return View();
}
八、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

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.