mvc原始碼解讀(12)-mvc四大過濾器之ActionFilter
上一篇中我們隨便聊了聊MVC的授權過濾器AuthorizeFilter
,其實真正關於.net平臺下的認證體系之複雜遠遠超出了我們的想像,對許可權的控制我們只能找到相對安全的做法,並不能從絕對上杜絕不安全的驗證,特別是對於.net下授權許可權的控制。有機會我們可以回過頭來深入的探討有關.net平臺下的許可權控制體系。這一篇我們繼續根據mvc3的原始碼來學習mvc的ActionFilter
方法過濾器。
和AuthorizeFilter
原理一樣,所有要用在Action
方法上的方法過濾器特性都必須繼承抽象類ActionFilterAttribute
,該類是實現了不僅實現了介面FilterAttribute
,還是實現了介面IActionFilter
, IResultFilter
,介面IActionFilter
的成員如下:
public interface IActionFilter
{
void OnActionExecuting(ActionExecutingContext filterContext);
void OnActionExecuted(ActionExecutedContext filterContext);
}
OnActionExecuting
在特性標註的方法執行之前執行的方法,同理OnActionExecuted
是在特性標註的方法後執行的方法。介面IResultFilter
我們等到下章來介紹。OnActionExecuting
和OnActionExecuted
接收ActionExecutingContext
類例項作為引數,ActionExecutingContext
類的成員如下:
public virtual ActionDescriptor ActionDescriptor {get; set;}
public virtual IDictionary<string, object> ActionParameters {get; set; }
public ActionResult Result {get;set;}
看到這些成員我們該笑了,ActionDescriptor
屬性我們前面已經介紹過了,通過這個屬性我們可以獲取執行的ActionName
和ControllerDescriptor
,進而得到Controller
的一切資訊。ActionParameters
獲取Action
方法執行的引數。ActionExecutingContext
類繼承自類ControllerContext
,該類有以下幾個重要的成員如下:
public virtual ControllerBase Controller
{
get;
set;
}
public virtual HttpContextBase HttpContext
{
get
{
if (_httpContext == null)
{
_httpContext = (_requestContext != null) ? _requestContext.HttpContext : new EmptyHttpContext();
}
return _httpContext;
}
set
{
_httpContext = value;
}
}
public virtual RouteData RouteData
{
get
{
if (_routeData == null)
{
_routeData = (_requestContext != null) ? _requestContext.RouteData : new RouteData();
}
return _routeData;
}
set
{
_routeData = value;
}
}
public RequestContext RequestContext
{
get
{
if (_requestContext == null)
{
HttpContextBase httpContext = HttpContext ?? new EmptyHttpContext();
RouteData routeData = RouteData ?? new RouteData();
_requestContext = new RequestContext(httpContext, routeData);
}
return _requestContext;
}
set
{
_requestContext = value;
}
}
這裡面我們需要注意的是HttpContext
和RequestContext
這兩個屬性。一個是封住了有關HTTP
請求的資訊,一個是封裝了HttpContext
和RouteData
的請求上下文。看了那麼多的微軟定義的成員,我們來一個demo來演示ActionFilter
的流程。
1:新建一個mvc3
的應用程式,並建立一個控制器:
public class MyActionFilterController : Controller
{
[MyTestActionFiter]
public ActionResult Index()
{
return View();
}
public ActionResult TestIndex()
{
return View();
}
}
兩個Action
對應的檢視如下:
@{Layout = null; }
<!DOCTYPE html>
<html> <head><title>Index</title></head><body><div><p>這裡是測試的第一個頁面--Index</p>
</div> </body> </html>
@{Layout = null; }
<!DOCTYPE html>
<html> <head><title>TestIndex</title></head><body><div><p>這裡是測試的第二個頁面--TestIndex</p>
</div> /body></html>
緊接著我們建立一個自定義的方法過濾器MyTestActionFiter
,該類繼承自ActionFilterAttribute
,具體如下:
public class MyTestActionFiter : ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
//在動作請求之前執行的方法。
filterContext.Result = new RedirectResult("/MyActionFilter/TestIndex");
base.OnActionExecuting(filterContext);
}
}
開啟F12,我們請求的是如下所示:
相應標頭的資訊如下:
我們可以知道我們請求Index
方法的時候,由於我們在OnActionExecuting
方法中將請求重定向(HTTP狀態碼:302)到了TestIndex
方法,由此可以證明OnActionExecuting
是在Action
方法之前執行。我們再來看一個demo
。我們將MyTestActionFilter
的方法改進一下:
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
//在動作請求之前執行的方法。
//filterContext.Result = new RedirectResult("/MyActionFilter/TestIndex");
filterContext.HttpContext.Response.Write("這是方法執行前的操作<br/>");
base.OnActionExecuting(filterContext);
}
public override void OnActionExecuted(ActionExecutedContext filterContext)
{
filterContext.HttpContext.Response.Write("這是方法執行之後的操作");
base.OnActionExecuted(filterContext);
}
同時將MyActionFilter
控制器改成如下:
public class MyActionFilterController : Controller
{
[MyTestActionFiter]
public void Index()
{
Response.Write("這裡是測試的第一個頁面--Index<br/>");
}
}
按F5執行,執行結果如下:
看到這裡,大家應該對ActionFiter
的執行順序應該有個大概的瞭解了吧:OnActionExecuting>Action>OnActionExecuted
。但是有一點需要注意:ActionFiter
都是在ViewResult
執行之前執行,這也是為什麼我在MyActionFilter
中是直接輸出內容,而不是返回ViewResult
的原因,關於這一點,我們下一章結合ResultFilter
做一個詳細的解說。
相關文章
- mvc原始碼解讀(11)-mvc四大過濾器之AuthorizationFilterMVC原始碼過濾器Filter
- mvc原始碼解讀(13)-MVC四大過濾器之ResultFilterMVC原始碼過濾器Filter
- mvc原始碼解讀(14)-mvc四大過濾器之ExceptionFilterMVC原始碼過濾器ExceptionFilter
- ASP.Net MVC過濾器ASP.NETMVC過濾器
- zanphp原始碼解讀 – MVC說起PHP原始碼MVC
- spring-MVC原始碼解讀(一)SpringMVC原始碼
- Vue原始碼閱讀--過濾器Vue原始碼過濾器
- 【ASP.NET Core】MVC過濾器:執行流程ASP.NETMVC過濾器
- 【ASP.NET Core】MVC過濾器:常見用法ASP.NETMVC過濾器
- MVC使用異常過濾器處理異常MVC過濾器
- Spring MVC 啟動過程原始碼分析SpringMVC原始碼
- MVC配置原理-原始碼MVC原始碼
- 說一說MVC的Authentication過濾(四)MVC
- .Net MVC中定義全域性過濾器及在Action中排除全域性過濾器MVC過濾器
- 精盡Spring MVC原始碼分析 - HandlerMapping 元件(二)之 HandlerInterceptor 攔截器SpringMVC原始碼APP元件
- 瀑布式DEBUG Spring MVC原始碼SpringMVC原始碼
- 分析MVC5原始碼,並實現一個ASP.MVCMVC原始碼
- 跟我一起學.NetCore之MVC過濾器,這篇看完走路可以仰著頭走NetCoreMVC過濾器
- Servlet過濾器原始碼分析Servlet過濾器原始碼
- asp.net mvc中的使用者登入驗證過濾器ASP.NETMVC過濾器
- 精盡Spring MVC原始碼分析 - HandlerMapping 元件(一)之 AbstractHandlerMappingSpringMVC原始碼APP元件
- 精盡Spring MVC原始碼分析 - HandlerAdapter 元件(一)之 HandlerAdapterSpringMVC原始碼APT元件
- 精盡Spring MVC原始碼分析 - HandlerAdapter 元件(五)之 HttpMessageConverterSpringMVC原始碼APT元件HTTP
- 精盡Spring MVC原始碼分析 - HandlerAdapter 元件(四)之 HandlerMethodReturnValueHandlerSpringMVC原始碼APT元件
- 精盡Spring MVC原始碼分析 - HandlerAdapter 元件(二)之 ServletInvocableHandlerMethodSpringMVC原始碼APT元件Servlet
- 精盡Spring MVC原始碼分析 - HandlerAdapter 元件(三)之 HandlerMethodArgumentResolverSpringMVC原始碼APT元件
- 精盡Spring MVC原始碼分析 - HandlerMapping 元件(三)之 AbstractHandlerMethodMappingSpringMVC原始碼APP元件
- 精盡Spring MVC原始碼分析 - HandlerMapping 元件(四)之 AbstractUrlHandlerMappingSpringMVC原始碼APP元件
- Spring Security系列之核心過濾器原始碼分析(四)Spring過濾器原始碼
- Python之MVCPythonMVC
- DRF之過濾類原始碼分析原始碼
- Spring MVC原始碼(一) ----- 啟動過程與元件初始化SpringMVC原始碼元件
- Vue 原始碼解讀(12)—— patchVue原始碼
- 精盡Spring MVC原始碼分析 - ViewResolver 元件SpringMVC原始碼View元件
- 精盡Spring MVC原始碼分析 - RequestToViewNameTranslator 元件SpringMVC原始碼View元件
- 精盡Spring MVC原始碼分析 - LocaleResolver 元件SpringMVC原始碼元件
- 精盡Spring MVC原始碼分析 - HandlerExceptionResolver 元件SpringMVC原始碼Exception元件
- 精盡Spring MVC原始碼分析 - MultipartResolver 元件SpringMVC原始碼元件