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的路由方案,与原来的方案在使用上差别不大,但从内部运行方式上来说,差别还是很大的.上一篇详细介绍了原版路由方案的运行机制, ...
随机推荐
- BZOJ_3942_[Usaco2015 Feb]Censoring_KMP
BZOJ_3942_[Usaco2015 Feb]Censoring_KMP Description 有一个S串和一个T串,长度均小于1,000,000,设当前串为U串,然后从前往后枚举S串一个字符一 ...
- BZOJ_4002_[JLOI2015]有意义的字符串_矩阵乘法
BZOJ_4002_[JLOI2015]有意义的字符串_矩阵乘法 Description B 君有两个好朋友,他们叫宁宁和冉冉.有一天,冉冉遇到了一个有趣的题目:输入 b;d;n,求 Input 一行 ...
- BZOJ1854: [Scoi2010]游戏 二分图
很早之前写的题了,发现没有更博,想了想,更一发出来. Orz ljss 这是冬令营上的例题...之后,我推出来了一种时间复杂度没有问题,空间复杂度没有问题的方法,额(⊙o⊙)…和给出的正解不同,但是能 ...
- Description Resource Path Location Type Cannot change version of project facet Dynamic Web Module to 2.3.
报错信息:Description Resource Path Location Type Cannot change version of project facet Dynamic Web Modu ...
- 深入解读Service Mesh的数据面Envoy
在前面的一篇文章中,详细解读了Service Mesh中的技术细节,深入解读Service Mesh背后的技术细节. 但是对于数据面的关键组件Envoy没有详细解读,这篇文章补上. 一.Envoy的工 ...
- 【工具篇】Selenium 学习实践(一)环境搭建
一.环境搭建 (1)初学者最佳环境: Python 2.7 + Selenium 2+ Firefox 46 (2)喜欢尝新的环境: Python 3.6 + Selenium 3+ Firefox ...
- 你可能不知道的jvm的类加载机制
引言:在java代码中,类型的加载.连接与初始化过程都是在程序运行期间完成的. 加载:查找并加载类的二进制数据(class文件加载到内存中) 连接:a 验证:确保被加载类的正确性. b准备:为类的静态 ...
- .NET Core之微信支付之公众号、H5支付篇
前言 本篇主要记录微信支付中公众号及H5支付全过程. 准备篇 公众号或者服务号(并开通微信支付功能).商户平台中开通JSAPI支付.H5支付. 配置篇 公众号或者服务号中 -------开发----- ...
- [深度应用]·实战掌握Dlib人脸识别开发教程
[深度应用]·实战掌握Dlib人脸识别开发教程 个人网站--> http://www.yansongsong.cn/ 项目GitHub地址--> https://github.com/xi ...
- SpringCloud-分布式链路跟踪配置详解
SpringCloud-分布式链路跟踪 作者 : Stanley 罗昊 [转载请注明出处和署名,谢谢!] 注:作者使用IDEA + Gradle 注:需要有一定的java SpringBoot and ...