我们知道在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 = ;
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拦截器执行的更多相关文章

  1. ASP.NET Core MVC中的IActionFilter.OnActionExecuting方法,可以获取Controller的Action方法参数值

    用过ASP.NET Core MVC中IActionFilter拦截器的开发人员,都知道这是一个非常强大的MVC拦截器.最近才发现IActionFilter的OnActionExecuting方法,甚 ...

  2. ASP.NET Core MVC中的IActionFilter.OnActionExecuted方法执行时,Controller中Action返回的对象是否已经输出到Http Response中

    我们在ASP.NET Core MVC项目中有如下HomeController: using Microsoft.AspNetCore.Mvc; namespace AspNetCoreActionF ...

  3. ASP.NET Core MVC 中的 [Controller] 和 [NonController]

    前言 我们知道,在 MVC 应用程序中,有一部分约定的内容.其中关于 Controller 的约定是这样的. 每个 Controller 类的名字以 Controller 结尾,并且放置在 Contr ...

  4. 006.Adding a controller to a ASP.NET Core MVC app with Visual Studio -- 【在asp.net core mvc 中添加一个控制器】

    Adding a controller to a ASP.NET Core MVC app with Visual Studio 在asp.net core mvc 中添加一个控制器 2017-2-2 ...

  5. ASP.NET MVC和ASP.NET Core MVC中获取当前URL/Controller/Action (转载)

    ASP.NET MVC 一.获取URL(ASP.NET通用): [1]获取完整url(协议名+域名+虚拟目录名+文件名+参数) string url=Request.Url.ToString(); [ ...

  6. ASP.NET Core MVC中Controller的Action,默认既支持HttpGet,又支持HttpPost

    我们知道ASP.NET Core MVC中Controller的Action上可以声明HttpGet和HttpPost特性标签,来限制可以访问Action的Http请求类型(GET.POST等). 那 ...

  7. ASP.NET Core MVC中Controller的Action如何直接使用Response.Body的Stream流输出数据

    在ASP.NET Core MVC中,我们有时候需要在Controller的Action中直接输出数据到Response.Body这个Stream流中,例如如果我们要输出一个很大的文件到客户端浏览器让 ...

  8. 008.Adding a model to an ASP.NET Core MVC app --【在 asp.net core mvc 中添加一个model (模型)】

    Adding a model to an ASP.NET Core MVC app在 asp.net core mvc 中添加一个model (模型)2017-3-30 8 分钟阅读时长 本文内容1. ...

  9. ASP.NET Core MVC中构建Web API

    在ASP.NET CORE MVC中,Web API是其中一个功能子集,可以直接使用MVC的特性及路由等功能. 在成功构建 ASP.NET CORE MVC项目之后,选中解决方案,先填加一个API的文 ...

随机推荐

  1. Jenkins 利用Build With Parameters Plugin实现Jenkins参数化构建

    利用Build With Parameters Plugin实现Jenkins参数化构建   by:授客 QQ:1033553122 测试环境 Build With Parameters Plugin ...

  2. ArrayMap 和HashMap的区别

    在以往android开发中,我们常常用key-value存储数据时,随手就会打出HashMap的代码,当数据量较小时,这种方法还不错还可以,当数据量比较多的时候,如果是PC机上,也还阔以.但是如果使用 ...

  3. [Objective-C]用Block实现链式编程

    看这篇博客时最快让你上手ReactiveCocoa之基础篇看到作者介绍链式编程那一块,发现自己的钻研精神不足.想想自己使用链式编程也有段时间了,对,就是 Masonry 库.自己一直享受点语法带来的效 ...

  4. 虚拟机-linux系统中图形界面和命令行界面切换

    linux系统中图形化界面和命令行界面之间的切换可以分为两种,临时性切换和永久性切换. 临时性切换即切换后只对本次生效,系统重启后界面还是默认界面. 永久性切换即切换后系统开机后永远处于的界面. 临时 ...

  5. [转载] erp开发-数据查询优化方法

    系统运行环境:MSSQL 2008随着公司业务快速发展,各种业务数据如火箭般的高速增长,出现一个又一个千万行数据的表,往往大表之间的关联,耗费系统大量的磁盘io,并且会影响正常的实时业务的操作,所以我 ...

  6. 解决tomcat中文传输乱码问题

    <Connector URIEncoding="utf-8" connectionTimeout="20000" encoding="utf-8 ...

  7. 洗礼灵魂,修炼python(77)--全栈项目实战篇(5)—— ATM自动存取机系统

    要求: 1.完成常识中的ATM存取款机功能 2.把ATM机故障考虑进去 3.不能直接输入账户名和卡号等等信息,模拟出插银行卡让ATM机自动读取卡信息 4.密码验证超过三次错误即锁定账户 5.操作类型有 ...

  8. SMB协议原理抓包分析

    SMB协议原理抓包分析 目录: 1.SMB概述 2.SMB原理 3.SMB配置 一.SMB概述 SMB(全称是Server Message Block)是一个协议名,可用于在计算机间共享文件.打印机. ...

  9. JavaScript -- 时光流逝(十二):DOM -- Element 对象

    JavaScript -- 知识点回顾篇(十二):DOM -- Element 对象 (1) element.accessKey: 设置或返回accesskey一个元素,使用 Alt + 指定快捷键 ...

  10. vue调试工具的安装

    开发避免不了的就是调试工具,因为vue是进行数据驱动的,单从chrome里面进行element查看,查不到什么鸟东西,必须要进行对数据动向进行关查 首先是下载这个工具,github下载地址:https ...