mvc原始碼解讀(13)-MVC四大過濾器之ResultFilter
上一篇講到ActionFilter
,這一篇我們來講解ResultFilter
,顧名思義,就是結果過濾器。和ActionFilter
要實現抽象類ActionFilterAttribute
裡面的四個方法一樣,我們自定義的ResultFilter
的過濾特性類也要繼承ActionFilterAttribute
才行,同時實現介面IResultFilter
裡面的方法:
public interface IResultFilter {
void OnResultExecuting(ResultExecutingContext filterContext);
void OnResultExecuted(ResultExecutedContext filterContext);
}
OnResultExecuting
是在動作結果執行之前執行,OnResultExecuted
是在動作結果之後執行,什麼是動作結果?我們可以這樣來理解,Action
就是一個動作,這個動作的結果是可能會返回一個ViewResult
渲染到瀏覽器中,在整個Action
的生命週期之內成為Action
的執行,之前執行OnActionExecuting
,之後執行OnResultExecuted
方法,那OnActionExecuted
方法和OnResultExecuting
方法在什麼時候執行呢,答案是在Action
之後,Result
之前。我們來看一個的demo
吧:
我們定義一個MyTestResultFiter
,讓他繼承自ActionFilterAttribute
類,具體實現如下:
public class MyTestResultFiter : ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
filterContext.HttpContext.Response.Write("OnActionExecuting方法:<br/>");
base.OnActionExecuted(filterContext);
}
public override void OnActionExecuted(ActionExecutedContext filterContext)
{
filterContext.HttpContext.Response.Write("OnActionExecuted方法<br/>");
base.OnActionExecuted(filterContext);
}
public override void OnResultExecuting(ResultExecutingContext filterContext)
{
filterContext.HttpContext.Response.Write("OnResultExecuting方法: <br/>");
base.OnResultExecuting(filterContext);
}
public override void OnResultExecuted(ResultExecutedContext filterContext)
{
filterContext.HttpContext.Response.Write("OnResultExecuted方法:<br/>");
base.OnResultExecuted(filterContext);
}
同時我們建立一個MVC
的專案,建立一個MyResultFilter
控制器,具體如下:
public class MyResultFilterController : Controller
{
[MyTestResultFiter]
public ActionResult Index()
{
Response.Write("這裡執行是Action方法,非ViewResult<br/>");
return View();
}
}
Index
的檢視如下:
@{Layout = null; }
<!DOCTYPE html>
<html> <head> <title>Index</title> </head>
<body><div>
<p>ViewResult:這裡是Result的首頁哦~~~~~~</p>
</div> </body>
</html>
執行結果如下:
OnActionExecuting
方法和OnResultExecuted
方法的執行順序無可爭議,問題在於Action
裡面Response.Write
的內容是先於OnActionExecuted
方法執行的,因此我們可以斷定:OnActionExecuted
方法的執行時間實在Action
的生命週期之後執行的,Action
的生命週期說白了就是大括號{}
裡面的程式碼,OnResultExecuting
方法實在動作結果之前執行,我們的示例中動作結果輸出的是Index
這個檢視,因此會看到OnResultExecuted
實在ViewResult
之後執行。上圖中示例執行順序
OnActionExecuting>Action>OnActionExecuted>OnResultExecuting>ViewResult>OnResultExecuted。
但是如果只有動作結果過濾器來過濾請求的話,標籤要在每一個動作上做上標籤,顯然是不符合軟體的設計思想的,mvc
好在為我們提供了一個全域性的過濾器,全域性過濾器我們需要在全域性檔案Global.asax
中進行註冊,我們按照剛才的例子稍加改進一下,來看具體的結果。
在Global.asax
中註冊全域性過濾器:
public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
filters.Add(new HandleErrorAttribute());
filters.Add(new MyTestResultFiter() { FilterMessage="標誌全域性過濾器"});
}
同時將MyTestResultFiter
過濾器稍作修改如下:
[AttributeUsage(AttributeTargets.All, AllowMultiple = true)]
public class MyTestResultFiter : ActionFilterAttribute
{
public string FilterMessage
{
get;
set;
}
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
filterContext.HttpContext.Response.Write("OnActionExecuting方法:" + FilterMessage + "<br/>");
base.OnActionExecuting(filterContext);
}
public override void OnActionExecuted(ActionExecutedContext filterContext)
{
filterContext.HttpContext.Response.Write("OnActionExecuted方法" + FilterMessage + "<br/>");
base.OnActionExecuted(filterContext);
}
public override void OnResultExecuting(ResultExecutingContext filterContext)
{
filterContext.HttpContext.Response.Write("OnResultExecuting方法" + FilterMessage + "<br/>");
base.OnResultExecuting(filterContext);
}
public override void OnResultExecuted(ResultExecutedContext filterContext)
{
filterContext.HttpContext.Response.Write("OnResultExecuted方法" + FilterMessage + "<br/>");
base.OnResultExecuted(filterContext);
}
}
同時注意將MyTestResultFiter
標註為AllowMultiple = true
,這樣MyTestResultFiter
就可以執行在Controller
和Action
上都起作用。否則執行執行Action
上的MyTestResultFiter
特性。執行結果如下:
但是還有一點我們需要注意的是Controller
它本身也是一個過濾器,我們來看Controller
的定義:
public abstract class Controller : ControllerBase, IActionFilter, IAuthorizationFilter, IDisposable, IExceptionFilter, IResultFilter
Controller
也實現了mvc
的四大過濾器的介面,因此我們來測試一下這個Controller
過濾器的執行順序是什麼?我們在MyResultFilter
裡面稍作修改:
[MyTestResultFiter(FilterMessage="這裡是Controller的:")]
public class MyResultFilterController : Controller
{
[MyTestResultFiter(FilterMessage = "這裡是Action的:")]
public ActionResult Index()
{
Response.Write("這裡執行是Action方法,非ViewResult<br/>");
return View();
}
}
最終執行的效果如下:
因此整個過濾器的執行順序大致如下:全域性過濾器>Controller上標記的特性過濾器>Action上標記的特性過濾器
,裡面的四種方法的執行順序大家看完之後應該明白了吧~~~
相關文章
- mvc原始碼解讀(11)-mvc四大過濾器之AuthorizationFilterMVC原始碼過濾器Filter
- mvc原始碼解讀(12)-mvc四大過濾器之ActionFilterMVC原始碼過濾器Filter
- mvc原始碼解讀(14)-mvc四大過濾器之ExceptionFilterMVC原始碼過濾器ExceptionFilter
- asp.net core MVC 過濾器之ActionFilter過濾器(二)ASP.NETMVC過濾器Filter
- ASP.Net MVC過濾器ASP.NETMVC過濾器
- zanphp原始碼解讀 – MVC說起PHP原始碼MVC
- ASP.NET MVC筆記 之 Action 過濾器ASP.NETMVC筆記過濾器
- spring-MVC原始碼解讀(一)SpringMVC原始碼
- ASP.NET MVC動作過濾器ASP.NETMVC過濾器
- Vue原始碼閱讀--過濾器Vue原始碼過濾器
- MVC使用異常過濾器處理異常MVC過濾器
- 【ASP.NET Core】MVC過濾器:執行流程ASP.NETMVC過濾器
- 【ASP.NET Core】MVC過濾器:常見用法ASP.NETMVC過濾器
- .Net MVC中定義全域性過濾器及在Action中排除全域性過濾器MVC過濾器
- MVC配置原理-原始碼MVC原始碼
- Spring MVC 啟動過程原始碼分析SpringMVC原始碼
- Servlet過濾器原始碼分析Servlet過濾器原始碼
- Spring MVC中,通過Java程式碼讀取資原始檔時,發生亂碼的解決方法SpringMVCJava
- DRF之過濾類原始碼分析原始碼
- asp.net mvc中的使用者登入驗證過濾器ASP.NETMVC過濾器
- 分析MVC5原始碼,並實現一個ASP.MVCMVC原始碼
- Spring Security系列之核心過濾器原始碼分析(四)Spring過濾器原始碼
- ASP.NET MVC 5改進了基於過濾器的身份驗證ASP.NETMVC過濾器
- 跟我一起學.NetCore之MVC過濾器,這篇看完走路可以仰著頭走NetCoreMVC過濾器
- 精盡Spring MVC原始碼分析 - HandlerMapping 元件(二)之 HandlerInterceptor 攔截器SpringMVC原始碼APP元件
- 瀑布式DEBUG Spring MVC原始碼SpringMVC原始碼
- Spring MVC原始碼解析(一)——概況SpringMVC原始碼
- Vue initAssetRegisters()建立元件、指令、過濾器原始碼Vue元件過濾器原始碼
- 13.gateway中的過濾器的介紹以及自定義過濾器Gateway過濾器
- HBase Filter 過濾器之 ValueFilter 詳解Filter過濾器
- PHP基礎之過濾器講解PHP過濾器
- 精盡Spring MVC原始碼分析 - HandlerAdapter 元件(四)之 HandlerMethodReturnValueHandlerSpringMVC原始碼APT元件
- 精盡Spring MVC原始碼分析 - HandlerAdapter 元件(二)之 ServletInvocableHandlerMethodSpringMVC原始碼APT元件Servlet
- Python之MVCPythonMVC
- 【過濾器】web中過濾器的使用與亂碼問題解決過濾器Web
- Spring MVC原始碼(一) ----- 啟動過程與元件初始化SpringMVC原始碼元件
- ASP.NET MVC 幾種 Filter 的執行過程原始碼解析ASP.NETMVCFilter原始碼
- Day70 Spring MVC的響應方式,檢視解析器以及上傳下載和編碼過濾器SpringMVC過濾器