ASP.NET Core 2.2 十八.各种Filter的内部处理机制及执行顺序
ASP.NET core 的Filter是系统中经常用到的,本文详细分享一下各种Filter定义、执行的内部机制以及执行顺序。(ASP.NET Core 系列目录)
一、 概述
ASP.NET Core MVC 中有好几种常用的筛选器,例如Authorization filters 、Resource filters、Action filters 、Exception filters 、Result filters,他们运行在请求处理管道中的特定阶段,例如Authorization filters当前请求的用户是否已授权。 如果请求未获授权,则中止执行后面的请求处理。其他几种filters也类似,只是执行阶段不同。如下图:
图一
Filter从定义到执行,本文通过四个阶段说明,如下图:
图二
1.定义:以为例,可以通过继承ActionFilterAttribute并override它的OnActionExecuting和OnActionExecuted方法实现。
2.注册:主要有三种方式:在Startup的AddMvc、Controller、Action中注册。
3.获取:上一章有介绍,在确定了处理请求的Endpoint后,下一步就是创建创建invoker,它有个关键的属性就是filters,它由FilterFactory的GetAllFilters方法获取到。
4.执行:invoker的执行阶段,会进入InvokeFilterPipelineAsync,在这里,各种Filter按照图一的方式逐一被执行。
二、Filter的定义
Filter有好几种,但由于本文主要是分享Filter的运行机制,所以只以ActionFilter一种来举例,现在定义一个Test1Filter如下:
public class Test1Filter : ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext context)
{
base.OnActionExecuting(context);
//do.....
} public override void OnActionExecuted(ActionExecutedContext context)
{
base.OnActionExecuted(context);
//do......
}
}
很简单,可以很方便的通过继承系统提供的ActionFilterAttribute并override 它的相应方法即可。
三、Filter的注册
Filter定义好之后就是将其插入到处理管道中,可以在Startup的AddMvc、Controller、Action中注册。
1.全局:在Startup的AddMvc中注册
services.AddMvc(
options => { options.Filters.Add(new Test6Filter()); options.Filters.Add(new Test4Filter()); }
).SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
2.只对指定的Controller生效
[Test5Filter]
[Test3Filter]
public class FlyLoloController : Controller
3.只对指定的Action生效
[Test2Filter]
[Test1Filter]
public JsonResult Index()
在实际业务中,我们可以根据具体的需求来确定Filter的作用范围。
四、Filter的获取
Filter的获取是在FilterFactory的GetAllFilters方法中,
public static FilterFactoryResult GetAllFilters(IFilterProvider[] filterProviders, ActionContext actionContext)
{
//省略……
var orderedFilters = actionDescriptor.FilterDescriptors.OrderBy(filter => filter,FilterDescriptorOrderComparer.Comparer).ToList();
//省略....
return new FilterFactoryResult(staticFilterItems, filters);
}
保留了关键的一句话,那就是根据actionDescriptor来获取到它对应的所有Filter(无论是针对全局、Controller还是Action),然后对这些Filter进行排序,这里用到了排序方法FilterDescriptorOrderComparer,它用来定义Filter的执行顺序,详细内容见后文。
五、Filter的执行
Filter的执行在invoker的执行阶段,会进入InvokeFilterPipelineAsync,在这里,各种Filter按照图一的方式逐一被执行。具体内容上一章已经进行了详细的描述。它是通过两个while循环实现了如图一的顺序逐一执行。
while (!isCompleted)
{
await Next(ref next, ref scope, ref state, ref isCompleted);
}
具体不再赘述。
六、Filter的执行顺序
Filter的执行顺序由三部分决定:
1.对于不同种的Filter,按照图一的顺序执行,例如Authorization filters会最先被执行。
2.对于同种的Filter,执行顺序由其Order和Scope来决定。
在Filter的获取一节提到了Filter的排序方法FilterDescriptorOrderComparer,它拥有对Filter定的排序。
public class FilterDescriptorOrderComparer : IComparer<FilterDescriptor>
{
public static FilterDescriptorOrderComparer Comparer { get; } = new FilterDescriptorOrderComparer(); public int Compare(FilterDescriptor x, FilterDescriptor y)
{
if (x == null)
{
throw new ArgumentNullException(nameof(x));
} if (y == null)
{
throw new ArgumentNullException(nameof(y));
} if (x.Order == y.Order)
{
return x.Scope.CompareTo(y.Scope);
}
else
{
return x.Order.CompareTo(y.Order);
}
}
}
从这个方法可以看到Filter的执行顺序,按照先Order后Scope的方式排序。对于继承默认的内置Filter的,Order默认为0,所有对于这样的Filter来说觉得他们顺序的是Scope,也就是作用域,默认情况下,全局的为10、Controller上的为20、Action上的为30.也就是说,Filter的执行顺序为
全局 -> Controller -> Action, 实际的执行顺序是这样的:
全局 OnActionExecuting Controller OnActionExecuting Action OnActionExecuting Action OnActionExecuted Controller OnActionExecuted 全局 OnActionExecuted
也是嵌套的,和中间件的处理方式类似。
当然我们可以自定义Filter的Order使其不再采用默认值0,只需在其构造函数中设置即可
public class Test1Filter : ActionFilterAttribute
{
public Test1Filter()
{
Order = ;
} //........... }
3.对于同样作用域的同种Filter来说,它们的执行顺序是按照注册先后排列的。
例如:
[Test2Filter]
[Test1Filter]
public JsonResult Index()
则先执行Test2Filter、后执行Test1Filter。
ASP.NET Core 2.2 十八.各种Filter的内部处理机制及执行顺序的更多相关文章
- ASP.NET Core 2.2 : 十六.扒一扒新的Endpoint路由方案 try.dot.net 的正确使用姿势 .Net NPOI 根据excel模板导出excel、直接生成excel .Net NPOI 上传excel文件、提交后台获取excel里的数据
ASP.NET Core 2.2 : 十六.扒一扒新的Endpoint路由方案 ASP.NET Core 从2.2版本开始,采用了一个新的名为Endpoint的路由方案,与原来的方案在使用上差别不 ...
- ExpandoObject与DynamicObject的使用 RabbitMQ与.net core(一)安装 RabbitMQ与.net core(二)Producer与Exchange ASP.NET Core 2.1 : 十五.图解路由(2.1 or earler) .NET Core中的一个接口多种实现的依赖注入与动态选择看这篇就够了
ExpandoObject与DynamicObject的使用 using ImpromptuInterface; using System; using System.Dynamic; names ...
- C#编译器优化那点事 c# 如果一个对象的值为null,那么它调用扩展方法时为甚么不报错 webAPI 控制器(Controller)太多怎么办? .NET MVC项目设置包含Areas中的页面为默认启动页 (五)Net Core使用静态文件 学习ASP.NET Core Razor 编程系列八——并发处理
C#编译器优化那点事 使用C#编写程序,给最终用户的程序,是需要使用release配置的,而release配置和debug配置,有一个关键区别,就是release的编译器优化默认是启用的.优化代码 ...
- ASP.NET Core 2.2 十九. 你扔过来个json,我怎么接
原文:ASP.NET Core 2.2 十九. 你扔过来个json,我怎么接 前文说道了Action的激活,这里有个关键的操作就是Action参数的映射与模型绑定,这里即涉及到简单的string.in ...
- ASP.NET Core 2.2 : 十六.扒一扒2.2版更新的新路由方案
原文:ASP.NET Core 2.2 : 十六.扒一扒2.2版更新的新路由方案 ASP.NET Core 从2.2版本开始,采用了一个新的名为Endpoint的路由方案,与原来的方案在使用上差别不大 ...
- 学习ASP.NET Core Blazor编程系列八——数据校验
学习ASP.NET Core Blazor编程系列一--综述 学习ASP.NET Core Blazor编程系列二--第一个Blazor应用程序(上) 学习ASP.NET Core Blazor编程系 ...
- 学习ASP.NET Core Razor 编程系列八——并发处理
学习ASP.NET Core Razor 编程系列目录 学习ASP.NET Core Razor 编程系列一 学习ASP.NET Core Razor 编程系列二——添加一个实体 学习ASP.NET ...
- ASP.NET Core 2.2 十九. Action参数的映射与模型绑定
前文说道了Action的激活,这里有个关键的操作就是Action参数的映射与模型绑定,这里即涉及到简单的string.int等类型,也包含Json等复杂类型,本文详细分享一下这一过程.(ASP.NET ...
- ASP.NET Core 2.2 : 十六.扒一扒新的Endpoint路由方案
ASP.NET Core 从2.2版本开始,采用了一个新的名为Endpoint的路由方案,与原来的方案在使用上差别不大,但从内部运行方式上来说,差别还是很大的.上一篇详细介绍了原版路由方案的运行机制, ...
随机推荐
- centos7中输入ifconfig出现ens33,没有eth0
vmware安装的centos7中没有出现eth0网卡,也没有ip,不能上网,输入ifconfig后如下图 解决办法 1.编辑网卡的配置文件 vi /etc/sysconfig/network-scr ...
- Java开源生鲜电商平台-安全设计与架构(源码可下载)
Java开源生鲜电商平台-安全设计与架构(源码可下载) 说明:Java开源生鲜电商平台是一个B2B的生鲜电商平台,由于是APP的一种模式,所以安全方面一般会思考以下几个维度: 1.数据安全. 2.传输 ...
- java中的数组二分法
数组二分法意在以较快的速度查找到某个值的下标位置. 二分法的核心思想:找到一个数组的中间位置值,判断某个数值是在这个中间值的左边还是右边,如果是左边,将中间位置之前进行二分,二分后,结束位置变为原始中 ...
- Haskell学习-函数式编程初探
原文地址:Haskell学习-函数式编程初探 为什么要学习函数式编程?为什么要学习Haskell? .net到前端,C#和JavaScript对我来说如果谈不上精通,最起码也算是到了非常熟悉的 ...
- 【重学计算机】操作系统D3章:存储管理
1. 存储管理的基本概念 逻辑地址:用户地址,从零开始编号 一维逻辑地址:(地址) 二维逻辑地址:(段号: 段内地址) 主存储器的复用方式 按分区:主存划分为多个固定/可变分区,一个程序占一个分区 按 ...
- [翻译 EF Core in Action 1.9] 掀开EF Core的引擎盖看看EF Core内部是如何工作的
Entity Framework Core in Action Entityframework Core in action是 Jon P smith 所著的关于Entityframework Cor ...
- JS 各种宽高
1.window的各种宽高 outerWidth.innerWidth.outerHeight.innerHeight outerHeight 获取浏览器窗口外部的高度(单位:像素).表示整个浏览 ...
- ajax调用WebAPI添加数据
//获取账号名 var Name = document.getElementById("Text1").value;//获取密码 var Pass = document.getEl ...
- 工程文件csproj使用编译条件指定属性
csproj工程文件中有很多xml格式的属性,比如PropertyGroup.ItemGroup,某些属性操作默认是全部的或者是当前编译条件的而已,当我们想指定某些属性只在某个编译条件下发生时就可以通 ...
- DML(数据操纵语言)
1.概念(C) 数据操纵语言 DML (Data Manipulation Langua)是SQL语言的一个分类,用于对表的内容或者说数据进行增.删.改.查等操作. 通过以下几个关键字实现: SELE ...