我們在ASP.NET Core MVC項目中有如下HomeController:
using Microsoft.AspNetCore.Mvc; namespace AspNetCoreActionFilter.Controllers { public class HomeController : Controller { /// <summary> /// 顯示一個網頁供測試 /// </summary> public IActionResult Index() { return View(); } /// <summary> /// 返回一個Json對象到客戶端瀏覽器 /// </summary> /// <returns>Json對象</returns> public IActionResult GetJson() { return Json(new { Message = "This is a GetJson message!" }); } } }
其代碼非常簡單,HomeController只有兩個Action:
- Index這個Action,輸出一個簡單的網頁供測試
- GetJson這個Action,輸出一個Json對象到客戶端瀏覽器
現在我們在瀏覽器上輸入Url地址"Home/GetJson"來訪問HomeController的GetJson這個Action,結果如下:
通過IE瀏覽器的開發者工具,我們看到,瀏覽器成功接收到了HomeController的GetJson這個Action返回的Json對象,其message屬性值為我們在GetJson這個Action中返回的"This is a GetJson message!"。
然后我們定義一個IActionFilter攔截器叫MyActionFilterAttribute,利用IActionFilter的OnActionExecuted方法,我們可以在HomeController的GetJson這個Action方法執行后,替換GetJson方法返回的Json對象:
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.Filters; using System; namespace AspNetCoreActionFilter.Filters { /// <summary> /// 定義一個IActionFilter攔截器叫MyActionFilterAttribute /// </summary> public class MyActionFilterAttribute : Attribute, IActionFilter { /// <summary> /// IActionFilter.OnActionExecuted在Controller的Action方法執行完后執行 /// </summary> public void OnActionExecuted(ActionExecutedContext context) { //等Controller的Action方法執行完后,通過更改ActionExecutedContext類的Result屬性,來替換Action方法返回的Json對象 context.Result = new JsonResult(new { Message = "This is a MyActionFilter message!" }); } /// <summary> /// IActionFilter.OnActionExecuting在Controller的Action方法執行前,但是Action方法的參數模型綁定完成后執行 /// </summary> public void OnActionExecuting(ActionExecutingContext context) { //Do something... //context.Result = new EmptyResult();//在IActionFilter.OnActionExecuting方法中,context的Result屬性只要被賦值了不為null,就不會執行Controller的Action了,也不會執行該IActionFilter攔截器的OnActionExecuted方法,同時在該IActionFilter攔截器之后注冊的其它Filter攔截器也都不會被執行了 } } }
但問題是當ASP.NET Core MVC執行IActionFilter的OnActionExecuted方法時,HomeController的GetJson這個Action方法返回的Json對象,是否已經被輸出到Http Response中發送給客戶端瀏覽器了呢?
我們將上面定義的IActionFilter攔截器MyActionFilterAttribute注冊到HomeController的GetJson方法上:
using AspNetCoreActionFilter.Filters; using Microsoft.AspNetCore.Mvc; namespace AspNetCoreActionFilter.Controllers { public class HomeController : Controller { /// <summary> /// 顯示一個網頁供測試 /// </summary> public IActionResult Index() { return View(); } /// <summary> /// 返回一個Json對象到客戶端瀏覽器 /// </summary> /// <returns>Json對象</returns> [MyActionFilter] public IActionResult GetJson() { return Json(new { Message = "This is a GetJson message!" }); } } }
然后再在瀏覽器中輸入Url地址"Home/GetJson"來訪問HomeController的GetJson這個Action,這次結果如下:
我們可以看到這次瀏覽器收到的Json對象是MyActionFilterAttribute攔截器中OnActionExecuted方法替換的Json對象,其message屬性值為"This is a MyActionFilter message!",而HomeController的GetJson這個Action返回的Json對象根本就沒有被瀏覽器收到,說明HomeController的GetJson這個Action返回的Json對象完全沒有被輸出到Http Response中發送給客戶端瀏覽器。所以這很好地說明了ASP.NET Core MVC中IActionFilter攔截器的OnActionExecuted方法,會在Controller的Action返回的對象被輸出到Http Response之前執行。
我們還可以在ASP.NET Core MVC中的.cshtml視圖文件中寫幾個C#代碼打上斷點,在IActionFilter攔截器的OnActionExecuted方法中也打上斷點,在Visual Studio調試中我們會發現,IActionFilter攔截器的OnActionExecuted方法的斷點先被執行,然后才執行.cshtml視圖文件中的斷點,這也很清晰地證明了上面黑色粗體字的觀點。當然如果你在Controller的Action方法中,直接使用Response.Body的Stream流輸出數據到客戶端瀏覽器,IActionFilter攔截器的OnActionExecuted方法執行時數據肯定已經發送給客戶端瀏覽器了。