ASP.NET Core中HTTP管道和中间件的二三事
本文出自《從零開(kāi)始學(xué)ASP.NET CORE MVC》
推薦文章:中間件是什么?在.NET?Core中的工作原理又是怎樣的呢?
配置ASP.NET Core請(qǐng)求(Request)處理管道
在本視頻中,我們將討論使用中間件組件為asp.net?core?應(yīng)用程序配置請(qǐng)求處理管道。
作為應(yīng)用程序啟動(dòng)的一部分,我們要在Configure()方法中設(shè)置請(qǐng)求處理管道。
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個(gè)中間件在管道中?:UseDeveloperExceptionPage()方法和Run()方法
UseDeveloperExceptionPage?中間件:顧名思義,如果存在異常并且環(huán)境是Development,此中間件會(huì)被調(diào)用,顯示開(kāi)發(fā)異常頁(yè)面。?我們將在后面的視頻中討論這個(gè)DeveloperExceptionPage中間件和環(huán)境變量的使用。
第二個(gè)中間件是注冊(cè)Run()方法到管道中,它只能處理將一個(gè)信息傳入Response對(duì)象。?目前,它是一個(gè)響應(yīng)每個(gè)請(qǐng)求的中間件,返回Hello?world。
在這種情況下,無(wú)論您的請(qǐng)求路徑是什么。?所有請(qǐng)求都會(huì)被這個(gè)中間件所處理,我們得到的返回值都是這個(gè)中間件調(diào)用Response對(duì)象,返回的string類(lèi)型的字符串。
返回的值是純文本而不是html。?我們可以通過(guò)檢查頁(yè)面源代碼來(lái)確認(rèn)這一點(diǎn)。
可以看到,我們?cè)谠创a中沒(méi)有任何html標(biāo)記。?只是純文本。
即使您現(xiàn)在創(chuàng)建一個(gè)為52abp.html的文件,并且您在請(qǐng)求中包含該文件的路徑,我們的應(yīng)用程序也無(wú)法返回該靜態(tài)文件。?這是因?yàn)?#xff0c;目前我們的請(qǐng)求處理管道沒(méi)有可以提供靜態(tài)文件的中間件,如html文件,圖像,CSS和JavaScript文件。
在后面的課程中,我們將添加所需的中間件以便能夠提供靜態(tài)文件。
研究下?Configure()方法中的代碼。
app.Run(async (context) =>{
await context.Response.WriteAsync("Hello?World!");
});
代碼說(shuō)明:
我們調(diào)用Run()?方法添加中間件到請(qǐng)求處理管道中。
如果將鼠標(biāo)懸停在Run()方法上,則可以從 智能提示中看到Run()方法是作為IApplicationBuilder接口的擴(kuò)展方法實(shí)現(xiàn)的。這就是我們能夠在IApplicationBuilder對(duì)象應(yīng)用程序上調(diào)用此Run()方法的原因。
我們傳遞給Run()方法的參數(shù)是一個(gè)RequestDelegate,我們可以從智能提示中看到它。
RequestDelegate是一個(gè)作為HttpContext對(duì)象的參數(shù)委托。
通過(guò)這個(gè)HttpContext對(duì)象,中間件可以訪問(wèn)傳入的http請(qǐng)求和傳出的http響應(yīng)。
目前,我們使用lambda將請(qǐng)求,它通過(guò)委托內(nèi)聯(lián)的方式作為匿名方法傳遞,所以很多人都說(shuō)lambda表達(dá)式是一種特殊的委托。如果你聽(tīng)不明白lambda表達(dá)式,委托,及內(nèi)聯(lián),你可以參考學(xué)習(xí):
委托(delegate)
Lambda簡(jiǎn)介?,或者等我錄制C#的基礎(chǔ)視頻吧。
使用Run()擴(kuò)展方法,我們只能將一個(gè)終端中間件添加到請(qǐng)求管道。
終端中間件是我們之前已經(jīng)說(shuō)到過(guò),他會(huì)使管道短路,不會(huì)去調(diào)用下一個(gè)中間件。
研究下面的代碼
app.Run(async (context) =>{
await context.Response.WriteAsync("從第一個(gè)中間件中打印Hello World");
});
app.Run(async (context) =>
{
await context.Response.WriteAsync("從第二個(gè)中間件中打印Hello World");
});
我們使用Run()方法注冊(cè)了2個(gè)中間件。
運(yùn)行此項(xiàng)目時(shí),我們只看到第一個(gè)中間件的響應(yīng),有返回值。
我們沒(méi)有看到第二個(gè)中間件的響應(yīng)。
這是因?yàn)?#xff0c;使用Run()方法注冊(cè)的中間件無(wú)法調(diào)用管道中的下一個(gè)中間件。
因此,我們使用Run()方法注冊(cè)的中間件是終端中間件
如果您希望中間件能夠調(diào)用管道中的下一個(gè)中間件,則使用Use()方法注冊(cè)中間件,如下所示。
app.Use(async (context, next) =>{
await context.Response.WriteAsync("從第一個(gè)中間件中打印Hello World");
await next();
});
app.Run(async (context) =>
{
await context.Response.WriteAsync("從第二個(gè)中間件中打印Hello World");
});
注意,Use()方法有2個(gè)參數(shù)。第一個(gè)參數(shù)是HttpContext上下文對(duì)象,第二個(gè)參數(shù)是Func類(lèi)型,即它是代表管道中下一個(gè)中間件的通用委托。
我們?cè)倏纯匆韵麓a
public void Configure(IApplicationBuilder app, IHostingEnvironment env,ILogger<Startup> logger)
{
app.Use(async (context, next) =>
{
logger.LogInformation("MW1:傳入請(qǐng)求");
await next();
logger.LogInformation("MW1:傳出響應(yīng)");
});
app.Use(async (context, next) =>
{
logger.LogInformation("MW2:?傳入請(qǐng)求");
await next();
logger.LogInformation("MW2:?傳出響應(yīng)");
});
app.Run(async (context) =>
{
await context.Response.WriteAsync("MW3:?處理請(qǐng)求并生成響應(yīng)");
logger.LogInformation("MW3:?處理請(qǐng)求并生成響應(yīng)");
});
}
ILogger < Startup >被注入到Configure()方法中
Main()方法調(diào)用的CreateDefaultBuilder()配置日志記錄
您可以通過(guò)查看在GitHub的源代碼驗(yàn)證這一點(diǎn)
:https://github.com/aspnet/MetaPackages/blob/release/2.2/src/Microsoft.AspNetCore/WebHost.cs檢查方法ConfigureLogging(),* 您會(huì)發(fā)現(xiàn),ILogger配置了Console,Debug和EventSource三種.
我們使用依賴(lài)注入的方式將ILogger記錄到系統(tǒng)中。
如果使用.NET Core CLI運(yùn)行項(xiàng)目,則可以在“控制臺(tái)”窗口中查看記錄的信息
如果直接從Visual Studio運(yùn)行項(xiàng)目,則可以在輸出窗口中查看記錄的信息。從輸出窗口的下拉列表中選擇ASP.NET?Core?Web?Server。
您將看到,信息按以下順序記錄
MW1:傳入請(qǐng)求
MW2:傳入請(qǐng)求
MW3:處理請(qǐng)求并生成響應(yīng)
MW2:傳出響應(yīng)
MW1:傳出響應(yīng)
現(xiàn)在將上面的輸出與微軟的官方文檔中的下圖集合起來(lái),是不是就清晰明了啊。吐槽下,微軟的文檔有粗糙。
image.png
請(qǐng)記住,asp.net Core中的中間件可以訪問(wèn)傳入請(qǐng)求和傳出響應(yīng)
請(qǐng)求先到達(dá)Middleware1,它記錄(MW1:傳入請(qǐng)求),因此我們首先看到此消息。
然后Middleware1調(diào)用next()。next()會(huì)調(diào)用管道中的Middleware2。
Middleware2?記錄(MW2:傳入請(qǐng)求)。
然后?Middleware2?會(huì)調(diào)用next()再調(diào)用?Middleware3.
Middleware3處理請(qǐng)求并生成響應(yīng)。因此,我們看到的下一條消息是(MW3:處理請(qǐng)求并生成響應(yīng))
此時(shí)管道開(kāi)始逆轉(zhuǎn)。
此時(shí)控制權(quán)將,交回到Middleware2,并將Middleware3生成的響應(yīng)傳遞給它。Middleware2記錄(MW2:傳出響應(yīng)),這是我們接下來(lái)看到的。
最后,?Middleware2將控制權(quán)交給?Midleware1。
Middleware1?記錄?(MW1:?傳出響應(yīng)),?這是我們最后看到的。
請(qǐng)求處理管道的中3個(gè)非常重要的知識(shí)點(diǎn):
所有的請(qǐng)求都會(huì)在每個(gè)中間件組件調(diào)用next()方法之前觸發(fā)。請(qǐng)求按照?qǐng)D中箭頭的所示方向,依次穿過(guò)所有管道。
當(dāng)中間件處理請(qǐng)求并產(chǎn)生響應(yīng)時(shí),請(qǐng)求處理流程在管道中開(kāi)始反向傳遞。
所有的響應(yīng)都會(huì)在每個(gè)中間件組件調(diào)用next()方法之前觸發(fā)。響應(yīng)按照?qǐng)D中箭頭的所示方向,依次穿過(guò)所有管道。
小結(jié)
亂碼問(wèn)題
硬廣專(zhuān)區(qū)
如果您覺(jué)得我的文章質(zhì)量還不錯(cuò),歡迎打賞,也可以訂閱我的視頻哦
未得到授權(quán)不得擅自轉(zhuǎn)載本文內(nèi)容,52abp.com保留版權(quán)
文字版目錄:?https://www.52abp.com/Wiki/mvc/latest/1.Intro?
交流QQ群:952387474《微軟MVP帶你學(xué)ASP.NET?CORE》
【收費(fèi)】騰訊課堂:?https://ke.qq.com/course/392589?tuin=2522cdf3?
【免費(fèi)】youtube視頻專(zhuān)區(qū):http://t.cn/Ei0F2EB?
免費(fèi)的更新慢,收費(fèi)的更新快,僅此而已。就這樣。?
「好看」的人都【在看】↓↓↓
總結(jié)
以上是生活随笔為你收集整理的ASP.NET Core中HTTP管道和中间件的二三事的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: [翻译] ASP.NET Core 利用
- 下一篇: asp.net ajax控件工具集 Au