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