ASP.Net Core MVC基礎(chǔ)系列之中間件
上一節(jié)我們介紹了服務(wù)注冊(cè)和基本的管道執(zhí)行流程, 并且講到了中間件, 這一節(jié)我們就來(lái)詳細(xì)談?wù)勚虚g件這個(gè)東西
講中間件, 其實(shí)就是講Startup類里面的ConfigureServices 和Configure 這兩個(gè)方法
在程序啟動(dòng)類Program 中, 我們?cè)贑reateWebHostBuilder 方法中調(diào)用了UseStartup方法, 里面用泛型注入了 Startup 類, 那程序就會(huì)自動(dòng)實(shí)例化這個(gè)類, 并且去執(zhí)行它里面的ConfigureServices 和Configure 這兩個(gè)方法. 我們就可以做很多配置操作
首先調(diào)用的第一個(gè)方法當(dāng)然就是構(gòu)造函數(shù), 這里沒(méi)有沒(méi)有, 我們不說(shuō), 然后就是ConfigureServices 方法. 這個(gè)方法上一節(jié)已經(jīng)使用過(guò)了, 在這個(gè)方法里面, 我們可以注冊(cè)一些服務(wù)或者我們叫自定義服務(wù). 注冊(cè)完服務(wù), 我們就可以通過(guò)依奈注入的方式在其它地方使用這些服務(wù).
然后再執(zhí)行的方法就是Configure 這個(gè)方法. 我們能看到Configure 方法默認(rèn)的第一個(gè)參數(shù)是IApplicationBuilder 接口, 可以理解為整個(gè)程序的根, 我們通過(guò)這個(gè)接口對(duì)象, 可以精確的配置獲取啟用我們的中間件, 使我們的各種中間件組合起來(lái), 形成一個(gè)完美的Web應(yīng)用程序, 去處理我們的HTTP請(qǐng)求并且做出對(duì)應(yīng)的響應(yīng)等等.
講之前, 我們先把
if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); }
這幾行代碼注釋掉, 待會(huì)再用, 再去解釋這個(gè)是干嘛用的, 為什么要加個(gè)if, 這里先注釋掉
我們看這個(gè)代碼
app.Run(async (context) => { var msg = welcome.GetWelcomMsg(); await context.Response.WriteAsync(msg); });
這個(gè)app.Run方法, 可以理解為我們自己寫的一個(gè)中間件, 它什么都不干, 就是為響應(yīng)輸出一個(gè)字符串. 其實(shí)這是新建項(xiàng)目默認(rèn)生成的.
在真實(shí)的項(xiàng)目中, 我們基本上不會(huì)使用app.Run這個(gè)方法去處理我們的請(qǐng)求, 因?yàn)槲易龅氖虑檫h(yuǎn)遠(yuǎn)比輸出一個(gè)字符串復(fù)雜很多.
在實(shí)際開發(fā)中, 我們通常使用的中間件都是app.Usexxxx開頭的, 才能組成一個(gè)完成的Web項(xiàng)目, 比如 app.UseMvc / app.UseStaticFiles等等這些方法去啟用系統(tǒng)自帶的中間件獲取別的第三方中間件.
我們這里啟用個(gè)ASP.Net Core MVC自帶的彩蛋中間件吧, 代碼為:app.UseWelcomePage(); 啟用默認(rèn)的MVC歡迎頁(yè)面. 我們F5執(zhí)行.
我們能夠正??吹匠霈F(xiàn)了一個(gè)頁(yè)面, 而不是簡(jiǎn)單的一個(gè)字符串的輸出了
然后我們嘗試改變一下地址欄, 隨便寫個(gè)什么, 可以發(fā)現(xiàn), 我們隨便怎么輸入地址, 都是進(jìn)入到歡迎頁(yè), 如圖 :
到這里, 我們就可以發(fā)現(xiàn), 這個(gè)"彩蛋"中間件的"優(yōu)先級(jí)"還是很高的, 在ASP.Net Core MVC發(fā)現(xiàn)你使用了這個(gè)中間件的時(shí)候, 他就不會(huì)執(zhí)行后面的東西了, 或者說(shuō)不會(huì)執(zhí)行后面的中間件了.
還有呢, 在我們使用中間件的時(shí)候, 或者說(shuō)是在調(diào)用app.Usexxxx方法的時(shí)候, 一般來(lái)說(shuō), 這個(gè)方法都會(huì)接受一個(gè)對(duì)象參數(shù), 這個(gè)參數(shù)可以對(duì)這個(gè)中間件進(jìn)行一些配置, 下面我們嘗試配置一下"彩蛋"中間件, 告訴大家中間件是怎么配置的. 代碼是這樣的
app.UseWelcomePage(new WelcomePageOptions { Path = "/welcome" });
都能看到, 這里是為"彩蛋"配置了一個(gè)地址(路徑), 現(xiàn)在我們F5看看效果
會(huì)發(fā)現(xiàn)網(wǎng)頁(yè)輸出是個(gè)字符串, 那我們?cè)诘刂泛竺婕由?/welcome 再看看, 可以發(fā)現(xiàn)能正常出現(xiàn)"彩蛋"了, 說(shuō)明這個(gè)配置是有效的.
當(dāng)然我的目的不是講這個(gè)"彩蛋"怎么使用, 而是給大家介紹中間件怎么使用, 怎么去配置中間件, 基本上所有的中間件都是這個(gè)使用方式和配置方式.
既然說(shuō)到了這里, 那我們來(lái)說(shuō)說(shuō) app.Use 這個(gè)方法. 這個(gè)方法怎么說(shuō)呢, 就是它比較"底層", 因?yàn)閍pp.Use里面的參數(shù)類型是RequestDelegate , 也就是當(dāng)前請(qǐng)求對(duì)象的委托, 相對(duì)比較"底層", 可以說(shuō)是當(dāng)前請(qǐng)求管道的"原型". 我們來(lái)寫一些代碼試試吧.
app.Use(next => { return async context => { if (context.Request.Path.StartsWithSegments("/first")) { await context.Response.WriteAsync("First"); } else { await next(context); } }; });
我們寫的代碼如上, 它的意思就是: 當(dāng)前地址是/first 的時(shí)候, 輸出 First 這個(gè)字符串, 否則就不管, 繼續(xù)往下執(zhí)行, 去執(zhí)行別的中間件, 我們運(yùn)行看看效果. 可以發(fā)現(xiàn), 默認(rèn)輸出的是 你好, .Net Core 2.2, 當(dāng)我們把地址后面加上/first 的時(shí)候, 輸出的就是First, 如圖:
我們?cè)佥斎氲刂?/welcome 的是, 可以看到"彩蛋"正常出現(xiàn)了, 可以看到, 我們的Use方法是正常的
在實(shí)際開發(fā)過(guò)程中, 我們很少直接使用app.Use方法去處理我們的底層請(qǐng)求的, 這里只是簡(jiǎn)單介紹了這個(gè)方法, 以及它能干什么.
知道app.Use是干什么的, 那就把上面的app.Use方法刪掉吧, 或者注釋掉, 我們下面的教程不會(huì)用的.
接下來(lái), 我們干點(diǎn)壞事, 我們?cè)?app.Run 方法里面手動(dòng)報(bào)個(gè)異常出來(lái), 代碼如下:
app.Run(async (context) => { throw new Exception(); var msg = welcome.GetWelcomMsg(); await context.Response.WriteAsync(msg); });
我們執(zhí)行項(xiàng)目, 會(huì)看到出現(xiàn)了500錯(cuò)誤, Chrome瀏覽器是這樣的, 其它瀏覽器可能不一樣
但是我們不希望這樣, 我們希望我們能看到異常的詳細(xì)信息, 這時(shí)候, 我們就需要啟用一個(gè)異常中間件, 就是我們上面注釋掉的那個(gè) iif (env.IsDevelopment()) 的代碼, 我們把它啟用起來(lái), 那么我們的Configure 方法里面代碼就是這樣的, 如圖:
然后我們?cè)貴5運(yùn)行項(xiàng)目, 就是這樣的了, 如圖:
我們的異常就很明顯了, 很好排查錯(cuò)誤
至于為什么加個(gè)if (env.IsDevelopment()), 這個(gè)代碼一看就知道意思了吧, 就是當(dāng)前環(huán)境是開發(fā)環(huán)境的時(shí)候, 才啟用這個(gè)異常顯示中間件
因?yàn)槲覀冎幌M陂_發(fā)或者調(diào)試的時(shí)候, 才顯示異常的詳細(xì)信息, 別的環(huán)境不顯示, 這樣安全一些, 如果不加這個(gè) if , 會(huì)在任何環(huán)境都會(huì)顯示詳細(xì)的錯(cuò)誤信息, 這樣可能會(huì)給我們的Web應(yīng)用帶來(lái)安全隱患.
所以, 我們?cè)偌觽€(gè)else , 在else里面啟用一個(gè)別的中間件, 代碼如下:
if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); } else { app.UseExceptionHandler(); }
這樣我們不是在開發(fā)環(huán)境的時(shí)候, 發(fā)送異常就是這樣的:
不至于暴露一些敏感的信息
我們發(fā)現(xiàn)這個(gè)啟動(dòng)異常頁(yè)面中間件的代碼寫在最上面, 那我們把它移動(dòng)到Configure 方法的最后面, 會(huì)怎么樣呢 ? 我們?cè)囋? 代碼如圖:
可以看到, 我把異常頁(yè)面中間件移動(dòng)到最后面啟用了, 我們F5運(yùn)行項(xiàng)目, 會(huì)發(fā)現(xiàn), 瀏覽器不出先異常頁(yè)面了, 而是直接 500 錯(cuò)誤.
可以知道, 中間件的啟用順序是有依奈關(guān)系和順序的, 不能隨便啟用的, 需要在正確的位置啟用對(duì)應(yīng)的中間件, 如果順序錯(cuò)了, 可能會(huì)導(dǎo)致中間件失效, 如果你在開發(fā)過(guò)程中, 啟用了某個(gè)中間件, 但是它卻沒(méi)效果, 可以使用該思路進(jìn)行排查.
到這里, 這一節(jié)就結(jié)束了, 到目前為止, 我們的Web應(yīng)用功能很簡(jiǎn)單, 就是輸出一個(gè)字符串和啟用了一個(gè)"彩蛋".
我們還講到了"環(huán)境", 比如上面的if (env.IsDevelopment()) 判斷是不是開發(fā)環(huán)境, 那么怎么改變這個(gè)環(huán)境, 讓我們?cè)陂_發(fā)或者試運(yùn)行和運(yùn)營(yíng)環(huán)境切換, 加載不同的配置和啟用不同的中間件
到此這篇關(guān)于ASP.Net Core MVC基礎(chǔ)系列之中間件的文章就介紹到這了。希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
ASP.NET Core中的Razor頁(yè)面使用視圖組件
這篇文章介紹了ASP.NET Core中的Razor頁(yè)面使用視圖組件的方法,文中通過(guò)示例代碼介紹的非常詳細(xì)。對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-02-02一步步打造漂亮的新聞列表(無(wú)刷新分頁(yè)、內(nèi)容預(yù)覽)第二步
由于我們僅僅是項(xiàng)目中的一個(gè)小部分,但也差不多按照以上的順序進(jìn)行開發(fā),這是一個(gè)良好的習(xí)慣。我們將概要設(shè)計(jì)和詳細(xì)設(shè)計(jì)放在一起。2010-07-07System.Diagnostics.Metrics .NET 6 全新指標(biāo)API講解
本文詳細(xì)講解了.NET 6全新指標(biāo)System.Diagnostics.Metrics,文中通過(guò)示例代碼介紹的非常詳細(xì)。對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2021-11-11Asp.net中Request.Url的各個(gè)屬性對(duì)應(yīng)的意義介紹
網(wǎng)絡(luò)上關(guān)于Request.Url的說(shuō)明已經(jīng)很多也很豐富了,但是自己還是實(shí)踐了一下,看看最終的結(jié)果與網(wǎng)絡(luò)上的是否一致2012-05-05.Net行為型設(shè)計(jì)模式之狀態(tài)模式(State)
這篇文章介紹了.Net行為型設(shè)計(jì)模式之狀態(tài)模式(State),文中通過(guò)示例代碼介紹的非常詳細(xì)。對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-05-05Visual Studio快速開發(fā)以及Visual Studio 2010新功能介紹
一直以來(lái)都在摸索著vb6.0的一些用法和語(yǔ)法,趁這次培訓(xùn)的機(jī)會(huì)正好整理Visual Studio的一些快速開發(fā)的技巧,還有一些vs2010的新功能收集和體會(huì),把培訓(xùn)的一些文檔性質(zhì)的記錄下來(lái),希望對(duì)各位有用2011-12-12