什么是ASP.NET Core Middleware?
ASP.NET Core中間件組件是被組裝到應用程序管道中以處理HTTP請求和響應的軟件組件(從技術上來說,組件只是C#類)。
ASP.NET Core應用程序中的每個中間件組件都執行以下任務。
- 選擇是否將 HTTP 請求傳遞給管道中的下一個組件。這可以通過在中間件中調用下一個 next() 方法實現。
- 可以在管道中的下一個組件之前和之后執行工作。
在ASP.NET Core中,已經有很多內置的中間件組件可供使用,您可以直接使用它們。 如果需要,還可以在ASP.NET Core應用程序中創建自己的中間件組件。
您需要牢記的最重要的一點是,在ASP.NET Core中,給定的中間件組件應僅具有特定目的,即單一職責。
在ASP.NET Core應用程序中使用中間件組件的一些示例如下:
- 用於驗證用戶身份的中間件
- 中間件可用於記錄請求和響應
- 用於處理錯誤的中間件
- 用於處理靜態文件,例如圖像,Javascript或CSS文件的中間件
- 用於在訪問特定資源時授權用戶的中間件
中間件組件是我們通常用於在ASP.NET Core應用程序中建立請求處理管道的組件。
如果您使用過.NET Framework的早期版本,那么您可能知道,我們使用HTTP處理程序和HTTP模塊來設置請求處理管道。 正是此管道將確定如何處理HTTP請求和響應。
如何在ASP.NET Core應用程序中配置中間件組件?
在ASP.NET Core應用程序中,我們需要在Startup.cs文件中存在的Startup類的Configure()方法內配置中間件組件。
這是在應用程序啟動時將要運行的類。 當我們使用空模板創建ASP.NET Core應用程序時,默認情況下,將使用Configure()方法創建Startup類,如下圖所示。
因此,每當要在任何類型的.net核心應用程序中配置任何中間件組件時,都需要通過在IApplicationBuilder對象上調用Use方法在Startup類的Configure() 方法中對其進行配置。
如上圖所示,configuration() 方法使用三個中間件組件設置了請求處理管道,如下所示。
- **UseDeveloperExceptionPage() **
- **UseRouting() **
- UseEndpoints()
在了解以上三個內置的中間件組件之前。 首先讓我們了解什么是中間件組件,以及這些中間件組件如何在ASP.NET Core應用程序中正常工作。
了解ASP.NET Core中的中間件組件
在ASP.NET Core應用程序中,中間件組件可以訪問傳入的HTTP請求和傳出的HTTP響應。 因此,ASP.NET Core中的中間件組件可以:
- 通過生成HTTP響應來處理傳入的HTTP請求。
- 處理傳入的HTTP請求,對其進行修改,然后將其傳遞給下一個中間件組件
- 處理傳出的HTTP響應,進行修改,然后將其傳遞給下一個中間件組件或ASP.NET Core Web服務器。
為了更好地理解,請查看下圖,該圖顯示了中間件組件如何在ASP.NET Core應用程序的請求處理管道中使用。
如上圖所示,我們有一個日志記錄中間件組件。 該組件僅記錄請求時間,然后將請求傳遞到下一個中間件組件,即請求管道中的靜態文件中間件組件,以進行進一步處理。
ASP.NET Core中的中間件組件也可以通過生成HTTP響應來處理HTTP請求。 ASP.NET Core中間件組件也可能決定不調用請求管道中的下一個中間件組件。 這個概念稱為短路請求管道。
例如,我們有一個靜態文件中間件組件。 並且,如果傳入的HTTP請求來自某些靜態文件,例如圖像,CSS文件,JavaScript等,則此Static Files Middleware組件可以處理請求,然后通過不調用管道中的下一個組件來縮短請求管道 即MVC中間件組件。
正如上面討論的,ASP.NET Core中間件組件可以訪問管道中的HTTP請求和響應。 因此,中間件組件也可以處理傳出響應。 例如,在我們的案例中,日志記錄中間件組件可能會記錄響應發送回客戶端的時間。
ASP.NET Core應用程序中中間件組件的執行順序是什么?
了解中間件組件的執行順序非常重要。 ASP.NET Core中間件組件的執行順序與添加到管道中的順序相同。 因此,在將中間件組件添加到請求處理管道時,我們需要小心。
根據應用程序的業務需求,您可以添加任意數量的中間件組件。
例如,如果您要開發具有某些靜態HTML頁面和圖像的靜態Web應用程序,則在請求處理管道中可能僅需要“ StaticFiles”中間件組件。
但是,如果您正在開發安全的動態數據驅動的Web應用程序,則可能需要幾個中間件組件,例如日志記錄中間件,身份驗證中間件,授權中間件,MVC中間件等。
什么是ASP.NET Core中的請求委托?
在ASP.NET Core中,請求委托用於構建請求管道,即請求委托用於處理每個傳入的HTTP請求。 在ASP.NET Core中,可以使用“運行”,“映射”和“使用”擴展方法配置請求委托。
您可以使用嵌入式匿名方法(稱為嵌入式中間件)指定請求委托,也可以使用可重用的類指定請求委托。
這些可重用的類和嵌入式匿名方法稱為中間件或中間件組件。 請求處理管道中的每個中間件組件負責調用管道中的下一個組件,或者通過不調用下一個中間件組件來使管道短路。
Use and Run方法的用途是什么?
在ASP.NET Core中,可以使用“Use”和“Run”擴展方法將內聯中間件組件注冊到請求處理管道中。
“Run”擴展方法使我們可以添加終止中間件(不會在請求處理管道中調用下一個中間件組件的中間件)。
另一方面,“Use”擴展方法使我們可以添加中間件組件,該中間件組件可以在請求處理管道中調用下一個中間件組件。
如果您觀察Configure方法,那么您將看到它獲得了IApplicationBuilder接口的一個實例,並將該實例與諸如Use and Run之類的擴展方法一起使用,它將配置中間件組件。
如您所見,在Configure方法中,使用IApplicationBuilder實例即app在請求處理管道中注冊了三個中間件組件。 他們如下:
- UseDeveloperExceptionPage()
- UseRouting()
- UseEndpoints()
UseDeveloperExceptionPage
如您所見,在Configure方法中,UseDeveloperExceptionPage() 中間件組件已注冊到管道中,並且僅在將托管環境設置為“Development”時,該中間件組件才會出現。
當應用程序中發生未處理的異常時,該中間件組件將執行,並且由於它處於開發模式,因此它將向您顯示代碼的錯誤信息。 您也可以考慮將其替換為其它內容。
UseRouting
該中間件組件用於將端點路由中間件添加到請求處理管道,即它將URL(或傳入的HTTP請求)映射到特定資源。
UseEndpoints
在此中間件中,將使用Map擴展方法來做出路由決策。 以下是UseEndpoints中間件組件的默認實現。 在MapGet擴展方法中,我們指定了URL模式,例如“ /”。 這僅表示域名。
因此,只有域名的任何請求都將由該中間件處理。
除了MapGet,您還可以使用Map方法,如下所示。
MapGet和Map方法有什么區別?
MapGet方法將處理GET HTTP請求,而Map方法將處理所有類型的HTTP請求,例如GET,POST,PUT和DELETE等。
如何使用Run() 擴展方法配置中間件組件?
首先我們需要了解如何使用“Run”擴展方法創建和配置自定義中間件組件。 首先,注釋一下Configure方法中存在的所有代碼。
注釋現有代碼后,將以下代碼復制並粘貼到Configure方法中。 以下代碼只是向應用程序的請求管道中添加了一個新的中間件組件,並僅打印了一條消息"My Name is Zhangsan"。
運行后,輸出:
我們正在IApplicationBuilder實例(應用程序)上調用Run() 擴展方法,以將中間件組件注冊到請求處理管道中。 以下是Run方法的定義:
從Run() 方法的定義中可以看到,該方法被實現為IApplicationBuilder接口的擴展方法。 這就是為什么我們能夠使用IApplicationBuilder實例即app調用Run() 方法的原因。
您還可以從上圖看到Run() 方法采用RequestDelegate類型的輸入參數。 以下是RequestDelegate的定義。
從上圖可以看到,RequestDelegate是一個采用HttpContext對象類型的輸入參數的委托。
正如我們上面討論的那樣,ASP.NET Core應用程序中的中間件組件可以訪問HTTP請求和響應,這是因為上面的HttpContext對象。
在示例中,我們使用lambda表達式將請求委托內聯作為匿名方法傳遞給內聯,此外,我們還將HTTPContext對象作為輸入參數傳遞給請求委托。 下圖顯示了以上內容:
向該應用程序再添加一個中間件。
運行該應用程序,則將獲得以下輸出:
My Name is Zhangsan
輸出來自第一個中間件組件。 原因是,當我們使用Run() 擴展方法注冊中間件組件時,該組件成為終端組件,這意味着它不會在請求處理管道中調用下一個中間件組件。
使用Use擴展方法配置中間件組件
現在想到的問題是如何在請求處理管道中調用下一個組件,答案是使用Use擴展方法注冊中間件組件,如下所示。
現在運行該應用程序,您將看到來自兩個中間件組件的預期輸出:
My Name is ZhangsanMy Name is LiSi
了解Use擴展方法
Use擴展方法將在行中定義的中間件委托添加到應用程序的請求管道中。 以下是Use擴展方法的定義:
此方法也實現為IApplicationBuilder接口上的擴展方法。 這就是為什么我們能夠使用IApplicationBuilder實例調用此方法的原因。 從上面的定義可以看出,該方法采用兩個輸入參數。 第一個參數是HttpContext上下文對象,通過它可以訪問HTTP請求和響應。 第二個參數是Func類型,即它是一個通用委托,可以處理請求或調用請求管道中的下一個中間件組件。
注意:如果要將請求從一個中間件發送到下一個中間件,則需要調用下一個方法。