什么是過濾器?
MVC中的每一個請求,都會分配給相應的控制器(Controller)和對應的行為方法(Action)去處理,那么如果我們想要在Action處理的前后加上一些額外的處理邏輯怎么辦呢?這時候就用到了過濾器(Filters)。
在ASP.NET MVC的請求處理過程中有19個管道事件,這些事件分布在請求處理的各個節(jié)點中,比如BeginRequest(開始處理請求時觸發(fā))、AuthenticateRequest(對請求進行身份驗證時觸發(fā))、AuthorizeRequest(對請求進程授權(quán)時觸發(fā))…等等等等。而過濾器的主要作用就是將我們的附加邏輯注入到這些請求處理管道中。
在實際業(yè)務中,在Action方法前后添加額外附加邏輯的情況有很多,過濾器就是用來完成此功能。通過過濾器可以將與業(yè)務邏輯無關(guān)但經(jīng)常需要執(zhí)行的代碼分離開,使我們的代碼邏輯性更加清晰,代碼更加簡潔。
過濾器的類型與作用
MVC給我們提供了四種過濾器,基本滿足了我們實際業(yè)務中常用的需求,包括以下:
類型名稱 | 實現(xiàn)的接口 | 默認的實現(xiàn)類 | 作用 |
---|---|---|---|
授權(quán)過濾器 | IAuthorizationFilter | AuthorizeAttribute | 用于限制進入控制器或控制器的某個行為方法 |
動作過濾器 | IActionFilter | ActionFilterAttribute | 用于進入動作方法之前或之后的處理 |
結(jié)果過濾器 | IResultFilter | ActionFilterAttribute | 用于動作方法返回結(jié)果之前或之后的處理 |
異常處理過濾器 | IExceptionFilter | HandleErrorAttribute | 用于處理某個動作方法或某個控制器里面拋出的異常 |
這四種類型的接口是MVC對過濾器的一個接口規(guī)范,同時MVC默認通過AuthorizeAttribute(授權(quán))、HandleErrorAttribute(異常處理)、ActionFilterAttribute(動作和結(jié)果)三個類實現(xiàn)了這四個接口。
需要注意的是ActionFilterAttribute類既實現(xiàn)了IActionFilter接口,也實現(xiàn)了IResultFilter接口。這是個抽象類,要求必須提供一個實現(xiàn),AuthorizeAttribute和HandleErrorAttribute類則包含了一些有用的特性,可以不必創(chuàng)建派生類進行使用。所以我們一般都會通過繼承ActionFilterAttribute類,實現(xiàn)自定義的過濾器。
除以上接口之外,我們還要用到FilterAttribute類,這個類將我們的過濾器包裝成了特性,使我們的過濾器可以方便的在Action方法上方使用。
定義過濾器
過濾器有以下幾個特點:
- 可用于動作方法(Action)
- 可用于控制器(Controller)
- 可多個Filter可同時使用
- 不同級別可以混搭
- 可運用于基類的過濾器,會影響該基類的所有派生類
下面我們逐一介紹下基本過濾器的使用方法。
授權(quán)過濾器
所有實現(xiàn)了IAuthorizationFilter接口的都可以稱之為授權(quán)過濾器。它的接口定義如下:
namespace System.Web.Mvc
{
//
// 摘要:
// 定義授權(quán)篩選器所需的方法。
public interface IAuthorizationFilter
{
//
// 摘要:
// 在需要授權(quán)時調(diào)用。
//
// 參數(shù):
// filterContext:
// 篩選器上下文。
void OnAuthorization(AuthorizationContext filterContext);
}
}
授權(quán)過濾器是最先運行的過濾器,它運行在其它過濾器和Action方法之前??蛻舳苏埱笤谡{(diào)用Action之前,MVC框架會檢測Action上是否有授權(quán)過濾器,如果有會調(diào)用OnAuthorization方法,如果此方法批準了請求,才會調(diào)用相應的Action。流程如圖:
MVC默認使用AuthorizeAttribute實現(xiàn)了IAuthorizationFilter接口,所以我們可以在Action方法上直接添加Authorize特性標簽來驗證授權(quán):
打開Index頁面,會顯示無權(quán)限:
由于使用的是MVC自帶的授權(quán)驗證方法,未能符合它的驗證機制,所以無權(quán)限查看。通常我們需要添加一個新的派生自AuthorizeAttribute類的授權(quán)過濾器來完成我們自己業(yè)務邏輯。
下面我們自定義一個授權(quán)過濾器。我們在MVC項目中添加一個Filters文件夾,我們所有自定義的過濾器都放可以到這個文件夾下,便于管理。
在Filters下創(chuàng)建一個類,類名為MyAuthorizeAttribute。需要注意,過濾器要以Attribute結(jié)尾,這是MVC的約定。代碼如下:
public class MyAuthorizeAttribute : AuthorizeAttribute
{
//重寫授權(quán)檢查方法,返回值為true,允許訪問,false,禁止訪問。
protected override bool AuthorizeCore(HttpContextBase httpContext)
{
//請求參數(shù)user為空,禁止訪問
if (string.IsNullOrEmpty(HttpContext.Current.Request.QueryString["user"]))
{
return false;
}
return true;
}
}
可以看到,我們只要重寫AuthorizeCore方法就可以根據(jù)我們的業(yè)務需求判斷是否有權(quán)限訪問,返回值為true允許訪問,返回值為false禁止訪問。
回到HomeController,我們給About方法加上我們自定義的特性:
我們看看效果:
可以看到,當About頁面沒有user參數(shù)時,會提示無權(quán)限,有user參數(shù)則可以訪問通過。
在實際業(yè)務中我們可以使用授權(quán)過濾器來管理用戶登錄狀態(tài)的授權(quán)驗證。當然,我的這個例子只是基礎的用法,實際業(yè)務比這復雜的多,那么就需要我們自己去思考設計授權(quán)過濾器方法了。
動作過濾器
動作過濾器需要實現(xiàn)IActionFilter接口,接口定義如下:
//
// 摘要:
// 定義操作篩選器中使用的方法。
public interface IActionFilter
{
//
// 摘要:
// 在執(zhí)行操作方法后調(diào)用。
//
// 參數(shù):
// filterContext:
// 篩選器上下文。
void OnActionExecuted(ActionExecutedContext filterContext);
//
// 摘要:
// 在執(zhí)行操作方法之前調(diào)用。
//
// 參數(shù):
// filterContext:
// 篩選器上下文。
void OnActionExecuting(ActionExecutingContext filterContext);
}
我們看到該接口里有兩個方法OnActionExecuting和OnActionExecuted,前者在動作方法執(zhí)行前調(diào)用,后者在動作方法執(zhí)行后調(diào)用。
OnActionExecuting方法是在Action方法執(zhí)行前調(diào)用的,那么我們可以利用這個方法來檢測請求,并且可以在這里修改請求,取消請求等等操作。
客戶端的請求信息是一個ActionExecutingContext對象,它繼承自ControllerContext類,屬性如下:
名稱 | 類型 | 說明 |
---|---|---|
ActionDescriptor | ActionDescriptor | 獲取或設置操作描述符。 |
ActionParameters | IDictionary | 獲取或設置操作方法參數(shù)。 |
Result | ActionResult | 獲取或設置由操作方法返回的結(jié)果。 |
我們添加一個自定義的Action過濾器。由于ActionFilterAttribute類實現(xiàn)了IActionFilter接口,所以我們直接繼承ActionFilterAttribute類即可,并且重寫OnActionExecuting和OnActionExecuted方法。如下:
public class MyActionAttribute : ActionFilterAttribute
{
///
/// Action調(diào)用之前運行
///
///
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
if (string.Equals(filterContext.HttpContext.Request.HttpMethod, "get", StringComparison.CurrentCultureIgnoreCase))
{
filterContext.Result = new HttpNotFoundResult("只允許POST請求!");
}
}
///
/// Action調(diào)用之后運行
///
///
public override void OnActionExecuted(ActionExecutedContext filterContext)
{
}
}
我們給Index方法添加上MyAction特性標簽:
打開Index頁,顯示如下:
可以看到,頁面返回了404錯誤,提示信息為我們設置的Message。
-
Controller
+關(guān)注
關(guān)注
0文章
397瀏覽量
57105 -
Asp.net
+關(guān)注
關(guān)注
0文章
36瀏覽量
13864 -
過濾器
+關(guān)注
關(guān)注
1文章
430瀏覽量
19630 -
MVC
+關(guān)注
關(guān)注
0文章
73瀏覽量
13877
發(fā)布評論請先 登錄
相關(guān)推薦
評論