配置 ASP.NET Core 請求(Request)處理管道
在本節中,我們將討論使用中間件組件為 asp.net core 應用程式配置請求處理管道,
作為應用程式啟動的一部分,我們要在Configure()方法中設定請求處理管道,
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.Run(async (context) =>
{
await context.Response.WriteAsync("Hello World!");
});
}
}
目前我們的代碼中有 2 個中間件在管道中 :UseDeveloperExceptionPage()方法和Run()方法
UseDeveloperExceptionPage 中間件:顧名思義,如果存在例外并且環境是Development,此中間件會被呼叫,顯示開發例外頁面, 我們將在后面的視頻中討論這個DeveloperExceptionPage 中間件和環境變數的使用,
第二個中間件是注冊Run()方法到管道中,它只能處理將一個資訊傳入Response物件, 目前,它是一個回應每個請求的中間件,回傳 Hello world, 在這種情況下,無論您的請求路徑是什么, 所有請求都會被這個中間件所處理,我們得到的回傳值都是這個中間件呼叫Response物件,回傳的 string 型別的字串, 回傳的值是純文本而不是 html, 我們可以通過檢查頁面源代碼來確認這一點, 可以看到,我們在源代碼中沒有任何 html 標記, 只是純文本,
即使您現在創建一個為52abp.html的檔案,并且您在請求中包含該檔案的路徑,我們的應用程式也無法回傳該靜態檔案, 這是因為,目前我們的請求處理管道沒有可以提供靜態檔案的中間件,如html檔案,影像,CSS和JavaScript檔案, 在后面的課程中,我們將添加所需的中間件以便能夠提供靜態檔案,
研究下 Configure()方法中的代碼,#
app.Run(async (context) =>
{
await context.Response.WriteAsync("Hello World!");
});
代碼說明:
- 我們呼叫 Run() 方法添加中間件到請求處理管道中,
- 如果將滑鼠懸停在 Run()方法上,則可以從 智能提示中看到
Run()方法是作為IApplicationBuilder介面的擴展方法實作的,這就是我們能夠在IApplicationBuilder物件應用程式上呼叫此Run()方法的原因, - 我們傳遞給
Run()方法的引數是一個RequestDelegate,我們可以從智能提示中看到它, RequestDelegate是一個作為HttpContext物件的引數委托,- 通過這個
HttpContext物件,中間件可以訪問傳入的 http 請求和傳出的 http 回應, - 目前,我們使用
lambda將請求,它通過委托行內的方式作為匿名方法傳遞,所以很多人都說 lambda 運算式是一種特殊的委托,如果你聽不明白 lambda 運算式,委托,及行內,你可以參考學習:- 委托(delegate)
- Lambda 簡介 ,或者等我錄制 C#的基礎視頻吧,
- 使用
Run()擴展方法,我們只能將一個終端中間件添加到請求管道, 終端中間件是我們之前已經說到過,他會使管道短路,不會去呼叫下一個中間件,
研究下面的代碼#
app.Run(async (context) =>
{
await context.Response.WriteAsync("從第一個中間件中列印Hello World");
});
app.Run(async (context) =>
{
await context.Response.WriteAsync("從第二個中間件中列印Hello World");
});
- 我們使用
Run()方法注冊了 2 個中間件, - 運行此專案時,我們只看到第一個中間件的回應,有回傳值,
- 我們沒有看到第二個中間件的回應,
- 這是因為,使用
Run()方法注冊的中間件無法呼叫管道中的下一個中間件, - 因此,我們使用
Run()方法注冊的中間件是終端中間件
如果您希望中間件能夠呼叫管道中的下一個中間件,則使用Use()方法注冊中間件,如下所示,
app.Use(async (context, next) =>
{
await context.Response.WriteAsync("從第一個中間件中列印Hello World");
await next();
});
app.Run(async (context) =>
{
await context.Response.WriteAsync("從第二個中間件中列印Hello World");
});
注意,Use()方法有 2 個引數,第一個引數是HttpContext背景關系物件,第二個引數是Func型別,即它是代表管道中下一個中間件的通用委托,
我們再看看以下代碼#
public void Configure(IApplicationBuilder app, IHostingEnvironment env,
ILogger<Startup> logger)
{
app.Use(async (context, next) =>
{
logger.LogInformation("MW1:傳入請求");
await next();
logger.LogInformation("MW1:傳出回應");
});
app.Use(async (context, next) =>
{
logger.LogInformation("MW2: 傳入請求");
await next();
logger.LogInformation("MW2: 傳出回應");
});
app.Run(async (context) =>
{
await context.Response.WriteAsync("MW3: 處理請求并生成回應");
logger.LogInformation("MW3: 處理請求并生成回應");
});
}
ILogger < Startup >被注入到Configure()方法中Main()方法呼叫的CreateDefaultBuilder()配置日志記錄- 您可以通過查看在 GitHub 的源代碼驗證這一點 :https://github.com/aspnet/MetaPackages/blob/release/2.2/src/Microsoft.AspNetCore/WebHost.cs
- 檢查方法
ConfigureLogging(),* 您會發現,ILogger 配置了Console,Debug和EventSource三種. - 我們使用
依賴注入的方式將ILogger記錄到系統中, - 如果使用.NET Core CLI 運行專案,則可以在“控制臺”視窗中查看記錄的資訊
- 如果直接從
Visual Studio運行專案,則可以在輸出視窗中查看記錄的資訊,從輸出視窗的下拉串列中選擇 ASP.NET Core Web Server, - 您將看到,資訊按以下順序記錄
- MW1:傳入請求
- MW2:傳入請求
- MW3:處理請求并生成回應
- MW2:傳出回應
- MW1:傳出回應
現在將上面的輸出與微軟的官方檔案中的下圖集合起來,是不是就清晰明了啊,吐槽下,微軟的檔案有粗糙,

-
請記住,asp.net Core 中的中間件可以訪問傳入請求和傳出回應
-
請求先到達
Middleware1,它記錄**(MW1:傳入請求)**,因此我們首先看到此訊息, -
然后
Middleware1呼叫next(),next()會呼叫管道中的Middleware2, -
Middleware2記錄**(MW2:傳入請求)**, -
然后
Middleware2會呼叫next()再呼叫Middleware3. -
Middleware3處理請求并生成回應,因此,我們看到的下一條訊息是(MW3:處理請求并生成回應) -
此時管道開始逆轉,
-
此時控制權將,交回到
Middleware2,并將Middleware3生成的回應傳遞給它,Middleware2記錄**(MW2:傳出回應)**,這是我們接下來看到的, -
最后,
Middleware2將控制權交給Midleware1, -
Middleware1記錄 (MW1: 傳出回應), 這是我們最后看到的,
請求處理管道的中 3 個非常重要的知識點:#
- 所有的
請求都會在每個中間件組件呼叫next()方法之前觸發,請求按照圖中箭頭的所示方向,依次穿過所有管道, - 當中間件處理請求并產生回應時,請求處理流程在管道中開始反向傳遞,
- 所有的
回應都會在每個中間件組件呼叫next()方法之前觸發,回應按照圖中箭頭的所示方向,依次穿過所有管道,
小結
Response 為抽象類
亂碼問題
context.Response.ContentType = "text/plain; charset=utf-8";
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/236297.html
標籤:.NET技术
