我们知道在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. 使用vuejs2.0和element-ui 搭建的一个后台管理界面

    说明: 这是一个用vuejs2.0和element-ui搭建的后台管理界面. 相关技术: vuejs2.0:一套构建用户界面的渐进式JavaScript框架,易用.灵活.高效. element-ui: ...

  2. nginx的rewrite ,如何在flask项目中获取重写前的url

    1. 在flask配一个重写到哪的路由,假设是/rewite/,然后到nginx的配置文件写重写规则,我这里重写全部的请求,接着测试能否重写成功 1. 添加一个路由 配置重写规则 测试成功 2.接下来 ...

  3. PHP断言(ASSERT)的用法

    简述 编写代码时,我们总是会做出一些假设,断言就是用于在代码中捕捉这些假设,可以将断言看作是异常处理的一种高级形式.程序员断言在程序中的某个特定点该的表达式值为真.如果该表达式为假,就中断操作. 可以 ...

  4. Linux下对lvm逻辑卷分区大小的调整(针对xfs和ext4不同文件系统)

    当我们在安装系统的时候,由于没有合理分配分区空间,在后续维护过程中,发现有些分区空间不够使用,而有的分区空间却有很多剩余空间.如果这些分区在装系统的时候使用了lvm(前提是这些分区要是lvm逻辑卷分区 ...

  5. ApplicationContext 配置里dataSource mysql连接数据源,设置ssl和utf-8

    ?useUnicode&useSSL=false

  6. TP中的图片水印

    $img_dir = ROOT_PATH . 'public/upload/card/' . $data['jt_id']; //创建合成图片存放位置 //自动创建文件夹 if (!file_exis ...

  7. Centos7安装搭建FTP服务器(最简便方法)

    简介: vsftpd 是“very secure FTP daemon”的缩写,安全性是它的一个最大的特点. vsftpd 是一个 UNIX 类操作系统上运行的服务器的名字,它可以运行在诸如 Linu ...

  8. 【算法】LeetCode算法题-Merge Two Sorted List

    这是悦乐书的第148次更新,第150篇原创 01 看题和准备 今天介绍的是LeetCode算法题中Easy级别的第7题(顺位题号是21).合并两个已排序的链表并将其作为新链表返回. 新链表应该通过拼接 ...

  9. puppet 横向扩展(一)

    目录 1. 概述 2. 实验环境 3. 实验步骤 3.1. 创建puppetmaster的rack环境 3.2. 配置文件设置 3.3. 补充说明 3.4. 测试配置结果 3.4.1. 默认的负载均衡 ...

  10. Docker: dockerfile常用关键字

    Dockerfile指令 Dockfile执行和shell命令一行,一行一行执行- 写Dockerfile注意点: 1.           尽量少RUN 2.           多个命令拼接在一起 ...