ASP.NET Core 中文文档 第三章 原理(5)错误处理
原文:Error Handling
作者:Steve Smith
翻譯:謝煬(Kiler)
校對(duì):高嵩(jack2gs)、何鎮(zhèn)汐
當(dāng)你的ASP.NET應(yīng)用發(fā)生錯(cuò)誤的時(shí)候, 你可以采用本文所述的各種方法來(lái)處理這些問(wèn)題。
配置錯(cuò)誤處理頁(yè)面
你在 Startup 類(lèi)的 Configure() 方法中為每一個(gè)請(qǐng)求配置管道 (更多內(nèi)容請(qǐng)參考 Application Startup)。 你可以輕松的添加一個(gè)僅僅適用于開(kāi)發(fā)階段的簡(jiǎn)單異常頁(yè)面。只需要在項(xiàng)目中添加 Microsoft.AspNetCore.Diagnostics 依賴(lài),并且添加一行代碼到 Startup.cs 的 Configure() 方法里面:
public void Configure(IApplicationBuilder app,IHostingEnvironment env){app.UseIISPlatformHandler(); ?
? ? ?if (env.IsDevelopment()){app.UseDeveloperExceptionPage();}
以上代碼包含一個(gè)檢查,以確保添加調(diào)用 UseDeveloperExceptionPage 的環(huán)境是開(kāi)發(fā)環(huán)境。這是一個(gè)好的實(shí)踐,因?yàn)槟阃ǔG闆r下并不希望在應(yīng)用程序已經(jīng)處于生產(chǎn)環(huán)境的情況下,將你的應(yīng)用程序的詳細(xì)異常信息對(duì)外公開(kāi). 詳細(xì)了解如何配置環(huán)境。
示例應(yīng)用程序包括一個(gè)創(chuàng)建異常的簡(jiǎn)單機(jī)制的例子:
? ? ? ? ?if (context.Request.Query.ContainsKey("throw")){ ? ? ? ? ? ?
? ? ? ? ? ? ? ?throw new Exception("Exception triggered!");} ? ? ? ?var builder = new StringBuilder();builder.AppendLine("<html><body>Hello World!");builder.AppendLine("<ul>");builder.AppendLine("<li><a href=\"/?throw=true\">
Throw Exception</a></li>");builder.AppendLine("<li><a href=\"/missingpage\"
>Missing Page</a></li>");builder.AppendLine("</ul>");builder.AppendLine("</body></html>");context.Response.ContentType = "text/html"; ?
? ? ?await context.Response.WriteAsync(builder.ToString());}); }
如果請(qǐng)求中包含一個(gè)變量名為 throw 的非空查詢(xún)字符串 (例如,路徑: /?throw=true), 那么就會(huì)拋出一個(gè)異常。如果環(huán)境被設(shè)置為 Development , 開(kāi)發(fā)者異常頁(yè)面將會(huì)被顯示:
當(dāng)不在開(kāi)發(fā)模式下, 建議使用 UseExceptionHandler 方法來(lái)配置一個(gè)錯(cuò)誤處理路徑:
app.UseExceptionHandler("/Error");使用開(kāi)發(fā)者異常頁(yè)面
當(dāng)Web請(qǐng)求中發(fā)生無(wú)法捕獲異常的時(shí)候,開(kāi)發(fā)者異常頁(yè)面會(huì)顯示有用的調(diào)試信息。頁(yè)面包含幾個(gè)選項(xiàng)卡頁(yè)面來(lái)顯示W(wǎng)eb請(qǐng)求中引發(fā)的異常信息。 第一個(gè)選項(xiàng)卡頁(yè)面包含錯(cuò)誤堆棧跟蹤信息:
第二個(gè)選項(xiàng)卡頁(yè)面顯示查詢(xún)字符串信息,如果有的話(huà):
在這個(gè)案例里面,你可以看到 throw 參數(shù)的值被傳遞到了請(qǐng)求。這個(gè)請(qǐng)求不包含任何cookies,但是如果有任何cookies,他們的值會(huì)顯示在cookies選項(xiàng)卡頁(yè)面。你可以在最后一個(gè)選項(xiàng)卡頁(yè)面查看到頭信息:
配置狀態(tài)碼頁(yè)面
在默認(rèn)情況下,你的應(yīng)用程序無(wú)法為Http狀態(tài)碼返回(例如:500 (服務(wù)器內(nèi)部錯(cuò)誤) or 404 (文件無(wú)法找到))提供一個(gè)富文本的HTTP狀態(tài)碼頁(yè)面。你可以在 Configure 方法中加入一行 StatusCodePagesMiddleware 代碼:
app.UseStatusCodePages();在默認(rèn)情況下,系統(tǒng)會(huì)為普通的http狀態(tài)碼添加一個(gè)非常簡(jiǎn)單純文本的處理,例如,下面是404無(wú)法找到文件狀態(tài)碼返回的結(jié)果。
中間件提供不同的擴(kuò)展方法,你也可以使用自定義lambda表達(dá)式來(lái)配置參數(shù):
?app.UseStatusCodePages(context =>context.HttpContext.Response.SendAsync("Handler,status code: " +context.HttpContext.Response.StatusCode, "text/plain"));
另外, 你也可以簡(jiǎn)單的傳遞一個(gè)內(nèi)容類(lèi)型和格式化字符串:
app.UseStatusCodePages("text/plain", "Response, status code: {0}");中間件也能處理重定向請(qǐng)求 (無(wú)論是絕對(duì)路徑還是相對(duì)路徑), 把狀態(tài)碼作為URL的一部分進(jìn)行傳遞:
app.UseStatusCodePagesWithRedirects("~/errors/{0}");在上面的案例中, 客戶(hù)端瀏覽器遇到 302 / Found狀態(tài)碼返回時(shí),會(huì)重定向到指定的頁(yè)面.
另外,中間件也提供設(shè)置一個(gè)新的路徑字符串的方式來(lái)重新執(zhí)行請(qǐng)求。
方法 UseStatusCodePagesWithReExecute 會(huì)返回原始的瀏覽器狀態(tài)碼頁(yè)面,但是也會(huì)執(zhí)行路徑中指定的處理程序。
如果你需要對(duì)某些請(qǐng)求禁止?fàn)顟B(tài)碼頁(yè)面, 可以使用以下代碼:
var statusCodePagesFeature =context.Features.Get<IStatusCodePagesFeature>();
if (statusCodePagesFeature != null) {statusCodePagesFeature.Enabled = false; }
錯(cuò)誤處理在CS交互模式下的限制
Web應(yīng)用在錯(cuò)誤處理功能上因?yàn)閿嚅_(kāi)HTTP請(qǐng)求和響應(yīng)的特性有些特別的限制,有的應(yīng)用程序,在你設(shè)計(jì)錯(cuò)誤處理行為時(shí)請(qǐng)注意以下幾點(diǎn)。
一旦響應(yīng)文件頭發(fā)送出去以后,你就無(wú)法再修改響應(yīng)的狀態(tài)碼了,無(wú)論是任何異常頁(yè)面或處理程序都無(wú)法執(zhí)行。響應(yīng)必須完成或者連接中斷退出。
如果客戶(hù)端在響應(yīng)中期斷開(kāi),你無(wú)法把當(dāng)前響應(yīng)的剩余內(nèi)容發(fā)送給客戶(hù)端。
在你的錯(cuò)誤處理層之下,總是有可能存在有例外的一層。
不要忘了,錯(cuò)誤處理頁(yè)面也會(huì)產(chǎn)生異常. 生產(chǎn)環(huán)境異常頁(yè)面采用純靜態(tài)頁(yè)面是個(gè)不錯(cuò)的建議。
遵從上述建議將有助于確保您的應(yīng)用程序保持響應(yīng),并且能很好地處理應(yīng)用程序可能發(fā)生的異常。
服務(wù)器錯(cuò)誤處理
除了你的應(yīng)用程序中的錯(cuò)誤處理邏輯,托管應(yīng)用程序的服務(wù)器也將執(zhí)行一些錯(cuò)誤處理。如果服務(wù)器在頭信息發(fā)送出去之前捕獲到異常,它會(huì)發(fā)出不帶主體的500內(nèi)部服務(wù)器錯(cuò)誤響應(yīng)。如果在頭文件發(fā)送出去之后捕獲到異常必須關(guān)閉連接。那些不是被你的應(yīng)用程序處理的請(qǐng)求將被服務(wù)器處理,并且發(fā)生的任何異常將被服務(wù)器的錯(cuò)誤處理機(jī)制來(lái)處理。任何在你的應(yīng)用程序里面配置好自定義錯(cuò)誤頁(yè)、錯(cuò)誤處理中間件、過(guò)濾器都無(wú)法影響此行為。
Startup 錯(cuò)誤處理
處理異常最為棘手的地方是在你的應(yīng)用程序啟動(dòng)的時(shí)候。只有承載層可以處理應(yīng)用程序的啟動(dòng)過(guò)程中發(fā)生的異常。應(yīng)用程序啟動(dòng)時(shí)發(fā)生的異常也會(huì)影響服務(wù)器的行為。例如,要啟用SSL in Kestrel,有些必須用 KestrelServerOptions.UseHttps() 配置服務(wù)器。如果一個(gè)異常在 Startup 代碼行之前發(fā)生,則默認(rèn)情況下托管將捕獲異常,并啟動(dòng)服務(wù)器,然后在非SSL端口上顯示一個(gè)錯(cuò)誤頁(yè)面。如果有異常情況發(fā)生在該行執(zhí)行之后, 則錯(cuò)誤頁(yè)面將通過(guò)HTTPS服務(wù)生效。
ASP.NET MVC 錯(cuò)誤處理
異常過(guò)濾器
異常過(guò)濾器可以在 MVC 應(yīng)用程序的全局范圍內(nèi)或者每個(gè)Controller或者每個(gè)Action上進(jìn)行配置。這些過(guò)濾器會(huì)處理controller action或其他過(guò)濾器的執(zhí)行過(guò)程中發(fā)生的任何未處理的異常,其他情況則不會(huì)被調(diào)用。異常過(guò)濾器更多內(nèi)容請(qǐng)見(jiàn) 過(guò)濾器。
小技巧
異常過(guò)濾器捕獲MVC Action中發(fā)生的異常是很好的,但他們不如錯(cuò)誤處理中間件靈活。一般情況下盡可能使用中間件,只有當(dāng)在你需要在處理異常的時(shí)候需要特別指定某些MVC action的時(shí)候,過(guò)濾器才被建議使用。
處理模型狀態(tài)錯(cuò)誤
模型驗(yàn)證 在每個(gè)controller action被調(diào)用之前發(fā)生,Action方法的職責(zé)是檢查 ModelState.IsValid 并作出適當(dāng)?shù)慕换シ磻?yīng)。在大部分情況下,特定的交互會(huì)返回特定的錯(cuò)誤響應(yīng),最好詳細(xì)說(shuō)明模型驗(yàn)證失敗的原因。
有些應(yīng)用程序會(huì)選擇遵循標(biāo)準(zhǔn)慣例處理模型驗(yàn)證錯(cuò)誤,在這種情況下,過(guò)濾器可以作為某些策略的實(shí)現(xiàn)場(chǎng)所。您應(yīng)該測(cè)試你的Action是否與有效和無(wú)效的模型狀態(tài)有關(guān)聯(lián)(了解更多有關(guān) 測(cè)試controller邏輯)的行為。
相關(guān)文章:
ASP.NET Core 中文文檔 第一章 入門(mén)
ASP.NET Core 中文文檔 第三章 原理(1)應(yīng)用程序啟動(dòng)
ASP.NET Core 中文文檔 第三章 原理(2)中間件
ASP.NET Core 中文文檔 第三章 原理(3)靜態(tài)文件處理
ASP.NET Core 中文文檔 第三章 原理(4)路由
原文地址:http://www.cnblogs.com/dotNETCoreSG/p/aspnetcore-3_5-error-handling.html
.NET社區(qū)新聞,深度好文,微信中搜索dotNET跨平臺(tái)或掃描二維碼關(guān)注
總結(jié)
以上是生活随笔為你收集整理的ASP.NET Core 中文文档 第三章 原理(5)错误处理的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 有关技术分享
- 下一篇: ASP.NET Core Kestrel