Mvc过滤器的使用【转载】
前言
在開發(fā)大項(xiàng)目的時(shí)候總會(huì)有相關(guān)的AOP面向切面編程的組件,而MVC(特指:Asp.Net?MVC,以下皆同)項(xiàng)目中不想讓MVC開發(fā)人員去關(guān)心和寫類似身份驗(yàn)證,日志,異常,行為截取等這部分重復(fù)的代碼,那我們可以通過AOP截取實(shí)現(xiàn),而在MVC項(xiàng)目中我們就可以直接使用它提供的Filter的特性幫我們解決,不用自己實(shí)現(xiàn)復(fù)雜的AOP了。
在Asp.net Mvc中當(dāng)你有以下及類似以下需求時(shí)你可以使用Filter功能
第一節(jié):知識(shí)儲(chǔ)備
Asp.Net?MVC提供了以下幾種默認(rèn)的Filter:
| Filter?Type | 實(shí)現(xiàn)接口 | 執(zhí)行時(shí)間 | Default?Implementation |
| Authorization?filter | IAuthorizationFilter | 在所有Filter和Action執(zhí)行之前執(zhí)行 | AuthorizeAttribute |
| Action?filter | IActionFilter | 分別在Action執(zhí)行之前和之后執(zhí)行。 | ActionFilterAttribute |
| Result?filter | IResultFilter | 分別在Action?Result執(zhí)行之后和之前 | ResultFilterAttribute |
| Exception?filter | IExceptionFilter | 只有在filter, 或者?action?method,?或者?action?result?拋出一個(gè)異常時(shí)候執(zhí)行 ? | HandleErrorAttribute |
大家注意一點(diǎn),Asp.Net MVC提供的ActionFilterAttribute默認(rèn)實(shí)現(xiàn)了IActionFilter和IResultFilter。而ActionFilterAttribute是一個(gè)Abstract的類型,所以不能直接使用,因?yàn)樗荒軐?shí)例化,所以我們想使用它必須繼承一下它然后才能使用。
Filter繼承于ActionFilterAttribute抽象類,并可以覆寫 void?OnActionExecuting(ActionExecutingContext) 和?void?OnActionExecuted(ActionExecutedContext)?以及 void?OnResultExecuting(ResultExecutingContext)和?void?OnResultExecuted(ResultExecutedContext)。
它們的執(zhí)行先后順序如下:
OnActionExecuting是Action執(zhí)行前的操作
OnActionExecuted則是Action執(zhí)行后的操作
OnResultExecuting是解析ActionResult前執(zhí)行
OnResultExecuted是解析ActionResult后執(zhí)行
接下來我們只要對(duì)以上的方法進(jìn)行重寫就可以在相應(yīng)的步驟做一些操作了。
第二節(jié):Filter實(shí)戰(zhàn)
光說不練假把式,下面我給大家一個(gè)示例,來看看它們的執(zhí)行順序
首先添加一個(gè)普通的類,這個(gè)類要繼承ActionFilterAttribute,,直接上代碼了
public class TestFilterAttribute:ActionFilterAttribute{public string Message { get; set; }public override void OnActionExecuting(ActionExecutingContext filterContext){base.OnActionExecuting(filterContext);filterContext.HttpContext.Response.Write("Action執(zhí)行之前"+Message+"<br />");}public override void OnActionExecuted(ActionExecutedContext filterContext){base.OnActionExecuted(filterContext);filterContext.HttpContext.Response.Write("Action執(zhí)行之后"+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 />");}}寫完這個(gè)代碼后,我們回到Action上,打上上面的標(biāo)記如下所示:
[TestFilter(Message="Action")]public ActionResult Index(){HttpContext.Response.Write("Action正在執(zhí)行···<br />");return Content("正在返回Result···<br />");}然后通過瀏覽器訪問上面的Action便可以看到下面的執(zhí)行順序
總的執(zhí)行順序是:
Action執(zhí)行前:OnActionExecuting方法先執(zhí)行→Action執(zhí)行→OnActionExecuted方法執(zhí)行→OnResultExecuting方法執(zhí)行→返回的ActionRsult中的executeResult方法執(zhí)行→OnResultExecuted執(zhí)行。最終顯示的效果就是如上圖所示。
感覺很爽吧!呵呵!這要想用到這個(gè)過濾機(jī)制的地方的時(shí)候,只要在Action上面添加標(biāo)記便可以實(shí)現(xiàn)效果。
如果我們將此標(biāo)簽打到Controller上的話,TestFilterAttributeFilter將作用到Controller下的所有的Action。例如如下代碼所示:
[TestFilter(Message="Controller")]public class TestFilterController : Controller{//// GET: /TestFilter/[TestFilter(Message="Action")]public ActionResult Index(){HttpContext.Response.Write("Action正在執(zhí)行···<br />");return Content("正在返回Result···<br />");}}如果單純的按照上面的代碼來做就有個(gè)問題了我們?cè)賵?zhí)行顯示的頁面會(huì)有什么情況呢?Controller上的Filter會(huì)執(zhí)行嗎?那標(biāo)簽的作用會(huì)執(zhí)行兩次嗎?下面是最后的執(zhí)行結(jié)果如下圖所示:
結(jié)果說明:默認(rèn)情況下Action上打了TestFilterAttribute 標(biāo)簽后,雖然在Controller上也打上了此標(biāo)簽,但它只有Action上的標(biāo)簽起作用了。
補(bǔ)充:如果Action沒有打上TestFilterAttribute標(biāo)簽,那么Controller上的標(biāo)簽便會(huì)被執(zhí)行。
Index?執(zhí)行時(shí),Filter的方法只執(zhí)行了一次,而某些情況下我們也想讓Controller上的FilterAttribute也執(zhí)行一次TestFilterAttribute,那我們?cè)趺床拍茏孋ontroller上的[TestFilter(Message?=?"controller")]也起作用呢?
答案是:我們只需在TestFilterAttribute類的定義上打上標(biāo)記[AttributeUsage(AttributeTargets.All,?AllowMultiple?=?true)]即可【下面類的最上面紅色字體部分】,也就是讓其成為可以多次執(zhí)行的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執(zhí)行之前"+Message+"<br />");}public override void OnActionExecuted(ActionExecutedContext filterContext){base.OnActionExecuted(filterContext);filterContext.HttpContext.Response.Write("Action執(zhí)行之后"+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 />");}}瀏覽效果如下圖:
我們看到的結(jié)果是Controller上的ActionFilter先于Action上打的標(biāo)記執(zhí)行。同樣Result執(zhí)行executeResult方法之前也是先執(zhí)行Controller上的Filter標(biāo)記中的OnResultexecuteing方法。
最后的執(zhí)行順序是:Controller上的OnActionExecuting→Action上的OnActionExecuting→Action執(zhí)行→Action上的OnActionExecuted→Controller上的OnActionExecuted?
到此Action就執(zhí)行完畢了,我們看到是一個(gè)入棧出棧的順序。后面是Action返回ActionResult后執(zhí)行了ExecuteResult方法,但在執(zhí)行之前要執(zhí)行Filter。具體順序?yàn)?#xff1a;
接上面→Controller的OnResultExecuting方法→Action上的OnResultExecuting→Action返回ActionResult后執(zhí)行了ExecuteResult方法→Action上的OnResultExecuted執(zhí)行→Controller上的OnResultExecuted執(zhí)行→結(jié)束。
?
又接著一個(gè)問題也來了,我們想有些公共的方法需要每個(gè)Action都執(zhí)行以下,而在所有的Controller打標(biāo)記是很痛苦的。幸好Asp。Net?MVC3帶來了一個(gè)美好的東西,全局Filter。而怎么注冊(cè)全局Filter呢?答案就在Global.asax中。讓我們看以下代碼,我是如何將上面我們定義的TestFilterAttribute?注冊(cè)到全局Filter中。上代碼:
public static void RegisterGlobalFilters(GlobalFilterCollection filters){filters.Add(new HandleErrorAttribute());//注冊(cè)全局過濾器filters.Add(new TestFilterAttribute() { Message="全局"});}效果如下圖:
我們看到的結(jié)果是全局的Action首先執(zhí)行,然后才是Controller下的Filter執(zhí)行,最后才是Action上的標(biāo)簽執(zhí)行。當(dāng)然這是在TestFilterAttribute類的定義上打上標(biāo)記[AttributeUsage(AttributeTargets.All,?AllowMultiple?=?true)]的前提下。不然?如果Action打上了標(biāo)簽跟Controller的相同則它只會(huì)執(zhí)行Action上的Filter。
?
下面我們說幾個(gè)系統(tǒng)的Filter
三、AcceptVerbs
規(guī)定頁面的訪問形式,如
[AcceptVerbs(HttpVerbs.Post)]public ActionResult Example(){
return View();
}
頁面只能以Post形式訪問,即表單提交。
四、ActionName
規(guī)定Action的名稱。
應(yīng)用場(chǎng)景:如果不想用方法名做為Action名,或Action名為關(guān)鍵字的話,如
[ActionName("class")]public ActionResult Example(){
return View();
}
?
五、NonAction
當(dāng)前方法僅是普通方法不解析為Action
六、OutputCache
為Action添加緩存
[OutputCache(Duration = 60, VaryByParam = "*")]public ActionResult Example()
{
return View();
}
?
七、ValidateInput
該Action可以接受Html等危險(xiǎn)代碼(ASP.NET MVC在aspx中設(shè)置<%@ Page 的屬性無法完成等同任務(wù)。)
[ValidateInput(false)]public ActionResult Example()
{
return View();
}
?
八、ValidateAntiForgeryTokenAttribute
用于驗(yàn)證服務(wù)器篡改。
[ValidateAntiForgeryToken]public ActionResult Example()
{
return View();
}
總結(jié)
經(jīng)過這一篇文章的介紹我們大體了解了Filter的使用方法,還了解到全局Filter的用法,尤其是當(dāng)相同的Filter重復(fù)作用到同一個(gè)Action上時(shí),如果沒有設(shè)置可多次執(zhí)行的標(biāo)簽?zāi)侵挥蠥ction上的Filter執(zhí)行,而Controller和全局Filter都被屏蔽掉,但是設(shè)置可多次執(zhí)行,那首先執(zhí)行全局Filter其次是Controller再次之就是Action上的Filter了。同時(shí)還了解了系統(tǒng)的Filter的用法。
轉(zhuǎn)載于:https://www.cnblogs.com/cwy173/p/3378247.html
總結(jié)
以上是生活随笔為你收集整理的Mvc过滤器的使用【转载】的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: linux系统怎么ping网络(Linu
- 下一篇: s3c2440移植MQTT