在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 (var writer = 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拦截器执行!