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 = 1;
        }

        //...........

    }

 

3.对于同样作用域的同种filter来说,它们的执行顺序是按照注册先后排列的。

例如:

        [test2filter]
        [test1filter]
        public jsonresult index()

则先执行test2filter、后执行test1filter。

 

本文链接:https://2i3i.com/aspnetcore2_18.html ,转载请注明来源地址。
暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇