1. <strong id="7actg"></strong>
    2. <table id="7actg"></table>

    3. <address id="7actg"></address>
      <address id="7actg"></address>
      1. <object id="7actg"><tt id="7actg"></tt></object>

        ASP.NET Core 實(shí)現(xiàn) MVC filter “就近原則”

        共 3513字,需瀏覽 8分鐘

         ·

        2022-03-16 15:19

        ASP.NET Core 實(shí)現(xiàn) MVC filter “就近原則”

        Intro

        在我們的日常開發(fā)中,我們可能會用到 MVC 里的 Filter 來實(shí)現(xiàn)一些切面邏輯,有一些 filter 可能只希望執(zhí)行一次,對于這樣的 filter 我們需要怎么做呢,下面就是一個示例

        Sample

        Filter 示例,這里我們以 AuthorizationFilter 為例,ActionFilter 也是一樣的

        public?class?TestAuthFilter?:?AuthorizationFilterAttribute
        {
        ????public?string?Role?{?get;?set;?}

        ????public?override?void?OnAuthorization(AuthorizationFilterContext?context)
        ????{
        ????????Console.WriteLine($"{nameof(TestAuthFilter)}({Role})?is?executing");
        ????}
        }

        AuthorizationFilterAttribute 是自己為 AuthorizationFilter 定義的一個類似于 ActionFilterAttribute 的東西,稍微簡化一些用作 Attribute 的 filter 定義,實(shí)現(xiàn)代碼如下:

        public?abstract?class?AuthorizationFilterAttribute?:?Attribute,?IAuthorizationFilter,?IAsyncAuthorizationFilter
        {
        ????public?virtual?void?OnAuthorization(AuthorizationFilterContext?context)
        ????{
        ????}

        ????public?virtual?Task?OnAuthorizationAsync(AuthorizationFilterContext?context)
        ????{
        ????????Guard.NotNull(context);
        ????????OnAuthorization(context);
        ????????return?Task.CompletedTask;
        ????}
        }

        再來看在 controller 代碼中的使用示例:

        [TestAuthFilter(Role?=?"Admin")]
        [Route("api/authTest")]
        public?class?AuthTestController?:?ControllerBase
        {
        ????[TestAuthFilter(Role?=?"User")]
        ????[HttpGet]
        ????public?IActionResult?Index()
        ????{
        ????????return?Ok();
        ????}
        }

        這個示例中,我們在 controller 和 action 上都加了 Filter,那么實(shí)際執(zhí)行的時候會怎么樣呢?

        可以訪問一下這個接口來測試一下,控制臺輸出結(jié)果如下:

        TestAuthFilter(Admin)?is?executing?
        TestAuthFilter(User)?is?executing?

        可以看到這個 filter 執(zhí)行了兩次,先執(zhí)行了 controller 定義的,然后執(zhí)行了 action 上定義的

        但是其實(shí)我期望的是如果 action ?上有定義的話只執(zhí)行 action 上的 filter,離方法最近的 filter 才生效,其他的被覆蓋掉,不生效,我稱它為 filter 的 “就近原則”,怎么實(shí)現(xiàn)呢?實(shí)現(xiàn)起來其實(shí)也非常的簡單,改造我們的 filter 在執(zhí)行 filter 的邏輯之前可以加一個判斷,修改后的 filter 如下:

        public?class?TestAuthFilter?:?AuthorizationFilterAttribute
        {
        ????public?string?Role?{?get;?set;?}

        ????public?override?void?OnAuthorization(AuthorizationFilterContext?context)
        ????{
        +???????if?(!context.IsEffectivePolicy(this))?return;
        ????????Console.WriteLine($"{nameof(TestAuthFilter)}({Role})?is?executing");
        ????}
        }

        然后我們再次訪問我們的接口,輸出結(jié)果如下:

        TestAuthFilter(User)?is?executing?

        可以看到 controller 上定義已經(jīng)沒有執(zhí)行了,只執(zhí)行 action 上定義的 filter 了。

        IsEffectivePolicyFilterContext 中的一個方法,是所有 filter 的上下文都會繼承的一個基類,無論是 AuthorizationFilter 還是 ActionFilter、ResourceFilter、ResultFilter、ExceptionFilter 都是可以像上面這樣用的,那它又是怎么實(shí)現(xiàn)的呢?

        What's inside

        我們可以反編譯或者直接去 Github 上看源代碼:https://github.com/dotnet/aspnetcore/blob/main/src/Mvc/Mvc.Abstractions/src/Filters/FilterContext.cs

        public?virtual?IList?Filters?{?get;?}

        public?bool?IsEffectivePolicy(TMetadata?policy)?where?TMetadata?:?IFilterMetadata
        {
        ????if?(policy?==?null)
        ????{
        ????????throw?new?ArgumentNullException(nameof(policy));
        ????}

        ????var?effective?=?FindEffectivePolicy();
        ????return?ReferenceEquals(policy,?effective);
        }

        public?TMetadata?FindEffectivePolicy()?where?TMetadata?:?IFilterMetadata
        {
        ????//?The?most?specific?policy?is?the?one?closest?to?the?action?(nearest?the?end?of?the?list).
        ????for?(var?i?=?Filters.Count?-?1;?i?>=?0;?i--)
        ????{
        ????????var?filter?=?Filters[i];
        ????????if?(filter?is?TMetadata?match)
        ????????{
        ????????????return?match;
        ????????}
        ????}

        ????return?default;
        }

        Filters 是當(dāng)前請求對應(yīng)的 action 所涉及到的所有 filter 的集合,離 action 最近的 filter 也就是從 filter 集合中倒序找,倒數(shù)第一個就是最近的,就是優(yōu)先級最高的,在 filter 中就可以判斷如果當(dāng)前 filter 對象是否是最近的一個從而判斷是否要執(zhí)行 filter 中的邏輯

        References

        • https://github.com/WeihanLi/WeihanLi.Web.Extensions/blob/dev/samples/WeihanLi.Web.Extensions.Samples/AuthTestController.cs
        • https://github.com/WeihanLi/WeihanLi.Web.Extensions/blob/dev/samples/WeihanLi.Web.Extensions.Samples/Filters/TestAuthFilter.cs
        • https://github.com/dotnet/aspnetcore/blob/v6.0.0/src/Mvc/Mvc.Abstractions/src/Filters/FilterContext.cs


        瀏覽 26
        點(diǎn)贊
        評論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報(bào)
        評論
        圖片
        表情
        推薦
        點(diǎn)贊
        評論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報(bào)
        1. <strong id="7actg"></strong>
        2. <table id="7actg"></table>

        3. <address id="7actg"></address>
          <address id="7actg"></address>
          1. <object id="7actg"><tt id="7actg"></tt></object>
            国产av大全 | 老司机精品免费视频 | 亚洲第一在线 | 中国黄视频 | 操逼视频日本 | 国产免费一区二区视频观看免费 | 午夜丰满少妇高清毛片1000部 | 国产又黄| 操嫩逼视频 | 日韩欧美无 |