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