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的路由方案,与原来的方案在使用上差别不大,但从内部运行方式上来说,差别还是很大的.上一篇详细介绍了原版路由方案的运行机制, ...
随机推荐
- webpack下css/js/html引用图片的正确方式
在webpack的处理下,为了使引用的图片被打包编译(以把src的图片文件编译到dist中或者对src的文件进行base64编码),应使用如下引用方式: 1. 在html/ejs等中引用图片: 借助r ...
- i春秋----Misc
好久没有写 博客今天更新多了一些 解题思路:题目做多了,自然能够想到是凯撒解密: 查看得到答案; flag{4c850c5b3b2756e67a91bad8e046dda} 2: 解题思路:是我想太多 ...
- 【转】百度站长平台MIP引入工具使用心得
MIP引入主动推送流程 对于 MIP 站点改造好了,我们如何提交数据,并且 MIP 提交后,我们能得到哪些数据的反馈,在这里简单的写一篇文章,说一下. 改造 MIP,我们一般是添加了一个二级域名站点进 ...
- 深入解读Service Mesh的数据面Envoy
在前面的一篇文章中,详细解读了Service Mesh中的技术细节,深入解读Service Mesh背后的技术细节. 但是对于数据面的关键组件Envoy没有详细解读,这篇文章补上. 一.Envoy的工 ...
- 死磕 java集合之ConcurrentLinkedQueue源码分析
问题 (1)ConcurrentLinkedQueue是阻塞队列吗? (2)ConcurrentLinkedQueue如何保证并发安全? (3)ConcurrentLinkedQueue能用于线程池吗 ...
- 【纯技术贴】.NETStandard FreeSql v0.0.9 功能预览
年关将至,首页技术含量文章真是越来越少,理解大家盼着放假过年,哥们我何尝不是,先给大家拜个早年. 兄弟我从11月底发了神经,开启了 ORM 功能库的开发之旅,历时两个月编码和文档整理,目前预览版本更新 ...
- Java设计模式小议之1------- 迭代器模式
定义:提供一种方法访问一个容器对象中各个元素,而又不暴露该对象的内部细节. 类型:行为类模式 这里用一个具体的案例来说明一下迭代器模式的简单使用 我们都知道在商店中,经常要把商品放到书架上,并将商品的 ...
- eclipse中运行出错:无法初始化主类的解决办法
问题描述:eclipse中运行程序时,出现如下错误 解决办法: 出现此类:无法初始化主类有可能是因为eclipse中Java的版本与JDK的版本不匹配,我开始用的时候eclipse中用的是Java s ...
- vue学习记录⑤(组件通信-父与子)
今天我们看一下组件通信. 经过前面几篇文章,我们已经可以构建出完整的单个组件,并利用路由使其串联起来访问了. 但这明显还是不够的.一个页面不可能就是个单组件,一般是由多个组件合成的.正因为如此,组件之 ...
- Android之Lottie动画详解
文章大纲 一.Lottie介绍二.Lottie实战三.项目源码下载四.参考文章 一.Lottie介绍 1. 什么是Lottie Lottie是Android和iOS的移动库,用于解析Adobe ...