轉自:http://www.studyofnet.com/news/257.html
APS.NET MVC中的每一個請求,都會分配給相應的控制器和對應的行為方法去處理,而在這些處理的前前后后如果想再加一些額外的邏輯處理。這時候就用到了過濾器。
在Asp.netMvc中當你有以下及類似以下需求時你可以使用Filter功能
- 判斷登錄與否或用戶權限
- 決策輸出緩存
- 防盜鏈
- 防蜘蛛
- 本地化與國際化設置
- 實現動態Action
MVC支持的過濾器類型有四種,分別是:Authorization(授權),Action(行為),Result(結果)和Exception(異常)。
如下表
過濾器類型 |
接口 |
描述 |
Authorization |
IAuthorizationFilter |
此類型(或過濾器)用於限制進入控制器或控制器的某個行為方法 |
Exception |
IExceptionFilter |
用於指定一個行為,這個被指定的行為處理某個行為方法或某個控制器里面拋出的異常 |
Action |
IActionFilter |
用於進入行為之前或之后的處理 |
Result |
IResultFilter |
用於返回結果的之前或之后的處理 |
但是默認實現它們的過濾器只有三種,分別是Authorize(授權),ActionFilter,HandleError(錯誤處理);各種信息如下表所示
過濾器 |
類名 |
實現接口 |
描述 |
ActionFilter |
AuthorizeAttribute |
IAuthorizationFilter |
此類型(或過濾器)用於限制進入控制器或控制器的某個行為方法 |
HandleError |
HandleErrorAttribute |
IExceptionFilter |
用於指定一個行為,這個被指定的行為處理某個行為方法或某個控制器里面拋出的異常 |
自定義 |
ActionFilterAttribute |
IActionFilter和IResultFilter |
用於進入行為之前或之后的處理或返回結果的之前或之后的處理 |
一、應用於Action的Filter
創建 Action filter 必須實現 IActionFilter 接口,該接口定義了兩個方法
方法名 | 調用時機 | 可進行的操作 |
OnActionExecuting | Action方法執行之前 | 可以給 filterContext.Result 賦值,以阻止 Action 的執行 可以通過 filterContext.ActionParameters 查看或修改 Action 的參數 |
OnActionExecuted | Action方法執行之后 | 可以通過 filterContext.Exception 獲取 Action 執行時拋出的異常,並能把它標記為“已處理”:filterContext.ExceptionHandled = true。 可以查看通過filterContext.Result查看 Action 的執行結果,但是不能修改。 |
Action過濾器是通過繼承ActionFilterAttribute類來實現的一個Attribute類。ActionFilterAttribute 是一個抽象類,提供了兩個virtual的方法給我們重寫,OnActionExecuting和OnActionExecuted。
ASP.NET MVC 框架會在調用Action方法之前調用你Action過濾器中的OnActionExecuting方法,在之后調用Action過濾器中的OnActionExecuted方法。當然在創建Action過濾器的時候你不需兩個方法都實現。
下面的示例是在調用Action方法之前和之后的日志跟蹤:


public class LoggingFilterAttribute : ActionFilterAttribute

{
public override void OnActionExecuting(FilterExecutingContext
filterContext)
{
filterContext.HttpContext.Trace.Write("Starting: " +
filterContext.ActionMethod.Name);
}
public override void OnActionExecuted(FilterExecutedContext
filterContext)
{
if (filterContext.Exception != null)
{
filterContext.HttpContext.Trace.Write("Exception thrown");
}
}
} 
部分參數說明
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一樣照常執行。
使用方法
你可以將過濾器應用到任何一個你喜歡的Action方法上。下面的示例演示一個控制器中包含的用Action過濾器Attribute標記的Action方法。


public class HomeController : Controller

{
[LoggingFilter]
public void Index()
{
RenderView("Index");
}
[LoggingFilter]
public void About()
{
RenderView("About");
}
[LoggingFilter]
public void ClickMe()
{
HttpContext.Trace.Write("Button was clicked.");
InvokeAction("Index");
}
} 
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)]

public void Index()

{
RenderView("Index");
}
Filter的執行順序為:Filter3 => Filter1 => Filter2.
二、Controller的Filter
ASP.NET MVC 控制器(Controller)類定義的OnActionExecuting 和 OnActionExcuted 方法你可以重寫。當你重寫一個或者這兩個方法的時候,你實際上定義了一個將會應用到該控制器類中所有的Action方法的Action過濾器。嚴格來說,這個方法沒有構成一個Action過濾器,但不管怎樣,她們提供的功能是相似的。
將Filter應用在Controller上有2種方式
1.直接將Filter應用在Controller上,如:
[TestFilter]
public class EiceController : Controller
{
}
2.重寫Controller內的
OnActionExecuting/OnActionExecuted/OnResultExecuting/OnResultExecuted的四個方法。
在下面的示例中,控制器級別的OnActionExecuting和OnActionExecuted方法應用到控制器中所有的Action方法中:


public class HomeController : Controller

{
public void Index()
{
RenderView("Index");
}
public void About()
{
RenderView("About");
}
public void ClickMe()
{
HttpContext.Trace.Write("Button was clicked.");
InvokeAction("Index");
}
protected override void OnActionExecuting(FilterExecutingContext
filterContext)
{
filterContext.HttpContext.Trace.Write("Starting: " +
filterContext.ActionMethod.Name);
}
protected override void OnActionExecuted(FilterExecutedContext
filterContext)
{
if (filterContext.Exception != null)
{
filterContext.HttpContext.Trace.Write("Exception thrown");
}
}
} 
三、幾個系統常用的Filter過濾器
1、AcceptVerbs
規定頁面的訪問形式,如
[AcceptVerbs(HttpVerbs.Post)] public ActionResult Example(){ return View(); }
頁面只能以Post形式訪問,即表單提交。
2、ActionName
規定Action的名稱。
應用場景:如果不想用方法名做為Action名,或Action名為關鍵字的話,如
[ActionName("class")] public ActionResult Example(){ return View(); }
3、NonAction
當前方法僅是普通方法不解析為Action
4、OutputCache
為Action添加緩存
[OutputCache(Duration = 60, VaryByParam = "*")] public ActionResult Example() { return View(); }
5、ValidateInput
該Action可以接受Html等危險代碼(ASP.NET MVC在aspx中設置<%@ Page 的屬性無法完成等同任務。)
[ValidateInput(false)] public ActionResult Example() { return View(); }
6、ValidateAntiForgeryTokenAttribute
用於驗證服務器篡改。
[ValidateAntiForgeryToken] public ActionResult Example() { return View(); }