在ASP.NET Core MVC中子類Controller攔截器要先於父類Controller攔截器執行
我們知道在ASP.NET Core MVC中Controller上的Filter攔截器是有執行順序的,那麽如果我們在有繼承關系的兩個Controller類上,聲明同一種類型的Filter攔截器,那麽是父Controller類的Filter攔截器先執行呢,還是子Controller類的Filter攔截器先執行呢?
首先我們新建一個ASP.NET Core MVC項目。
然後我們新建四個IActionFilter攔截器:MyActionOneAttribute、MyActionTwoAttribute、MyActionThreeAttribute和MyActionFourAttribute
MyActionOneAttribute攔截器將會全局聲明在ASP.NET Core MVC項目的所有Controller上:
/// <summary> /// MyActionOneAttribute攔截器將會全局聲明在ASP.NET Core MVC項目的所有Controller上 /// </summary> public class MyActionOneAttribute : Attribute, IActionFilter { public void OnActionExecuted(ActionExecutedContext context) {using (var writer = new StreamWriter(context.HttpContext.Response.Body)) { writer.Write("<div>MyAction 1 OnActionExecuted</div></body></html>"); } } public void OnActionExecuting(ActionExecutingContext context) { using (varwriter = new StreamWriter(context.HttpContext.Response.Body)) { context.HttpContext.Response.ContentType = "text/html"; context.HttpContext.Response.StatusCode = 200; writer.Write("<html><head></head><body><div>MyAction 1 OnActionExecuting</div>"); } } }
MyActionTwoAttribute攔截器將會聲明在父Controller類BaseController上:
/// <summary> /// MyActionTwoAttribute攔截器將會聲明在父Controller類BaseController上 /// </summary> public class MyActionTwoAttribute : Attribute, IActionFilter { public void OnActionExecuted(ActionExecutedContext context) { using (var writer = new StreamWriter(context.HttpContext.Response.Body)) { writer.Write("<div>MyAction 2 OnActionExecuted</div>"); } } public void OnActionExecuting(ActionExecutingContext context) { using (var writer = new StreamWriter(context.HttpContext.Response.Body)) { writer.Write("<div>MyAction 2 OnActionExecuting</div>"); } } }
MyActionThreeAttribute攔截器將會聲明在子Controller類HomeController上:
/// <summary> /// MyActionThreeAttribute攔截器將會聲明在子Controller類HomeController上 /// </summary> public class MyActionThreeAttribute : Attribute, IActionFilter { public void OnActionExecuted(ActionExecutedContext context) { using (var writer = new StreamWriter(context.HttpContext.Response.Body)) { writer.Write("<div>MyAction 3 OnActionExecuted</div>"); } } public void OnActionExecuting(ActionExecutingContext context) { using (var writer = new StreamWriter(context.HttpContext.Response.Body)) { writer.Write("<div>MyAction 3 OnActionExecuting</div>"); } } }
MyActionFourAttribute攔截器將會聲明在子Controller類HomeController的Index方法上:
/// <summary> /// MyActionFourAttribute攔截器將會聲明在子Controller類HomeController的Index方法上 /// </summary> public class MyActionFourAttribute : Attribute, IActionFilter { public void OnActionExecuted(ActionExecutedContext context) { using (var writer = new StreamWriter(context.HttpContext.Response.Body)) { writer.Write("<div>MyAction 4 OnActionExecuted</div>"); } } public void OnActionExecuting(ActionExecutingContext context) { using (var writer = new StreamWriter(context.HttpContext.Response.Body)) { writer.Write("<div>MyAction 4 OnActionExecuting</div>"); } } }
然後我們在ASP.NET Core MVC項目中Startup類的ConfigureServices方法中,全局聲明MyActionOneAttribute攔截器到項目的所有Controller上:
public void ConfigureServices(IServiceCollection services) { services.AddMvc(options => { options.Filters.Add(typeof(MyActionOneAttribute)); }); }
然後我們定義父Controller類BaseController,它繼承於Microsoft.AspNetCore.Mvc.Controller,並聲明了MyActionTwoAttribute攔截器:
[MyActionTwo] public class BaseController : Controller { }
然後我們定義子Controller類HomeController,它繼承於BaseController,並在類上聲明了MyActionThreeAttribute攔截器,Action方法Index上聲明了MyActionFourAttribute攔截器:
[MyActionThree] public class HomeController : BaseController { [MyActionFour] public IActionResult Index() { using (var writer = new StreamWriter(HttpContext.Response.Body)) { writer.Write("<div>Index</div>"); } return new EmptyResult(); } }
並且我們在HomeController的Action方法Index中,輸出了一個字符串"<div>Index</div>"。
所以現在我們相當於是在子Controller類HomeController的Index方法上,同時聲明了MyActionOneAttribute、MyActionTwoAttribute、MyActionThreeAttribute和MyActionFourAttribute四個攔截器,那麽這四個攔截器的執行順序是什麽樣的呢?
現在我們運行ASP.NET Core MVC項目,在Web瀏覽器中輸出結果如下:
從上圖結果中,我們可以看出:
- 最先執行的是全局聲明的MyActionOneAttribute攔截器
- 然後執行的是聲明在子Controller類HomeController上的MyActionThreeAttribute攔截器
- 接著執行的是聲明在父Controller類BaseController上的MyActionTwoAttribute攔截器
- 最後執行的是聲明在子Controller類HomeController的Index方法上的MyActionFourAttribute攔截器
所以這個結果證明了聲明在子Controller類上的Filter攔截器,要先與聲明在父Controller類上的Filter攔截器執行!
在ASP.NET Core MVC中子類Controller攔截器要先於父類Controller攔截器執行