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的路由方案,与原来的方案在使用上差别不大,但从内部运行方式上来说,差别还是很大的.上一篇详细介绍了原版路由方案的运行机制, ...
随机推荐
- USACO JAN14 奶牛冰壶运动 凸包+判定
满足条件的一定是在凸包内的,直接判断 恬不知耻的加了特判,2333 #include<cstdio> #include<iostream> #include<cstrin ...
- BZOJ_2142_礼物_扩展lucas+组合数取模+CRT
BZOJ_2142_礼物_扩展lucas+组合数取模 Description 一年一度的圣诞节快要来到了.每年的圣诞节小E都会收到许多礼物,当然他也会送出许多礼物.不同的人物在小E 心目中的重要性不同 ...
- css3波纹特效、H5实现动态波浪
css3实现动态波纹特效,由于css3里面有过渡和动画效果,现在利用css3实现动态波浪效果就很简单了,直接使用transform来实现就ok, 使得translateX 产生偏移就可以不断实现循环动 ...
- MYSQL—— year类型的使用与注意点!
mysql的日期与时间类型:分为time.date.datetime.timestamp.year,主要总结下year的用法: 1.类型支持:year 与 year(4),注意无year(2)的定义方 ...
- SQL Server事务 事务日志
事务 (SQL Server) 一.事务概念 事务是一种机制.是一种操作序列,它包含了一组数据库操作命令,这组命令要么全部执行,要么全部不执行.因此事务是一个不可分割的工作逻辑单元.在数据库系统 ...
- Discuz3.4-SSRF-从触发点到构造payload
目录 SSRF逆向分析 0x00 前言 0x01 收集情报 0x02 尝试逆向找到触发点 0x03 尝试构造payload 0x04 总结 SSRF逆向分析 0x00 前言 之前有复现过一些漏洞,但是 ...
- ES 19 - Elasticsearch的检索语法(_search API的使用)
目录 1 Search API的基本用法 1.1 查询所有数据 1.2 响应信息说明 1.3 timeout超时机制 1.4 查询多索引和多类型中的数据 2 URI Search的用法 2.1 GET ...
- 使用BeetleX的TcpBenchmark工具进行百万设备模拟测试
其实TCP测试的工具有很多,那BeetleX工具所提供的特点又是什么呢?如果你需数十万的请求或模拟上百万的设备连接,那这个工具相信可以满足你的需要!工具是基于BeetleX的基础功能扩展,支持多IP绑 ...
- APP测试要点—UI、功能测试
一.UI测试 测试用户界面(如菜单.对话框.窗口和其它可规控件)布局.风格是否满足客户要求.文字是否正确.页面是否美观.文字.图片组合是否完美.操作是否友好等. UI测试的目标是确保用户界面会通过测试 ...
- [Swift]LeetCode1033. 移动石子直到连续 | Moving Stones Until Consecutive
Three stones are on a number line at positions a, b, and c. Each turn, let's say the stones are curr ...