ASP.NET Core 2.2 十八.各種Filter的內部處理機制及執行順序

来源:https://www.cnblogs.com/FlyLolo/archive/2019/02/22/ASPNETCore2_18.html
-Advertisement-
Play Games

ASP.NET core 的Filter是系統中經常用到的,本文詳細分享一下各種Filter定義、執行的內部機制以及執行順序。 一、 概述 ASP.NET Core MVC 中有好幾種常用的篩選器,例如Authorization filters 、Resource filters、Action fi ...


ASP.NET core 的Filter是系統中經常用到的,本文詳細分享一下各種Filter定義、執行的內部機制以及執行順序。

一、 概述

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。

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 題意 "題目鏈接" Sol 神仙題Orz 首先不難看出如果我們從$a_i$向$i$連一條邊,我們會得到以$0$為根的樹(因為每個點一定都有一個入度,出現環說明無解),同時在進行排列的時候需要保證父親節點一定在孩子節點之前出現 接下來考慮直接貪心。對於某些權值很小的點,我們需要讓其儘早出現,同時又要滿 ...
  • 假定一個全英文的文件,讀取該文件,請統計多少個不重覆的單詞,並且在另外一個文件中寫上結果每個單詞出現的次數,以及一共有多少個不重覆的單詞分別為哪些 註意:文件中可能包含特殊符號 Step1:打開文件,可使用方法如下: 方法1:fp = open(file,'r',encoding ='utf-8') ...
  • 題意 "題目鏈接" Sol 神仙題Orz Orz zbq爆搜70。。 考慮"與"和"或"的性質 $0 \& 0 = 0, 1 \& 0 = 0$ $0 \mid 1 = 1, 1 \mid 1 = 1$ 也就是說某一個數$\& 0$之後不管之前是什麼,現在的值變為$0$ 某一個數$\mid 1$之後 ...
  • json模塊 JSON (JavaScript Object Notation):是一個輕量級的數據交換格式模塊,受javascript對象文本語法啟發,但不屬於JavaScript的子集。 常用方法: dump(obj,fp):將對象以字元串的形式寫入文件中。 load(fp):將數據從文件中讀出 ...
  • H2engine的GitHub星星不知不覺已經破百了,也沒有特意推廣過,但是慢慢的關註的人越來越多。因為事情多,好久沒有寫東西了,前一段時間有了一些想法,把h2engine又更新了一下,感覺h2engine又向前邁了一大步。本文記錄一下最近的心得體會,以及做出的相應修改。 ...
  • 對於泛型的使用我想大家都非常熟悉,但是對於類型擦除,邊界拓展等細節問題,可能不是很清楚,所以本文會重點講解一下;另外對泛型的瞭解其實可以看出,一個語言特性的產生邏輯,這對我們平時的開發也是非常有幫助的; 一、為什麼會出現泛型 首先泛型並不是Java的語言特性,是直到 JDK1.5 才支持的特性(具體 ...
  • error介面1.error就是一個介面interface2.屬於errors包,該包有一個導出方法New,返回了errorString類型3.errorString類型實現了error介面4.之所以這樣是因為可以實現每個錯誤都是不同的實例 ...
  • 介面類型1.介面類型具體描述了一系列方法的集合,實現這些方法的具體類型是這個介面類型的實例2.一個類型如果擁有一個介面需要的所有方法,那麼這個類型就實現了這個介面 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...