Error Handling in ASP.NET Core
前言
?在程序中,經常需要處理比如?404,500?,502等錯誤,如果直接返回錯誤的調用堆棧的具體信息,顯然大部分的用戶看到是一臉懵逼的,你應該需要給用戶返回那些看得懂的界面。比如,“當前頁面不存在了” 等等,本篇文章主要來講講.NET-Core?中異常處理,以及如何自定義異常顯示界面?,還有 如何定義自己的異常處理中間件?。
.NET-Core 中的異常處理
?讓我們從下面這段代碼講起,寫過.Net-Core?的應該不陌生,在?Startup?的?Configure?中定義異常處理的中間件。
if (env.IsDevelopment()){app.UseDeveloperExceptionPage(); }else{app.UseExceptionHandler("/error"); }? 上面兩種情況分別是一個是使用自帶的異常處理,另外一個是將錯誤異常的處理,進行自己處理。兩種情況如下所示:
我在HomeController?中定義了一個Test Action如下所示(僅僅為了演示,并無實際意義)
//Controllerpublic string Test(int id){ ? ?if(id == 1){ ? ? ? ?return new System.NullReferenceException("It's not equals to 1, robert!");} ?return "Bingo,Robert!"; }//Routingroutes.MapRoute(name: "Error", ?template: "error/",defaults: new { controller = "Home", action = "error" } );?使用?localhost:{port}/home/test/2?的結果像下面這樣
對我localhost:{port}/home/test/1?這樣呢,在不同環境下是不一樣的,具體如下所示:
UseDeveloperException?
UseExceptionHandler?
這些呢,就是比較平常的?.NET-Core?的處理方式。但是看不見StatusCode,發現沒有,除了自定義的時候,默認時是不提供Status Code?的。這時候,就可以用到這個
UseStatusCodePages()?想要看源碼的在這?StatusCodePagesExtension Source Code。
效果怎么樣的呢?如下所示:
?這是默認的處理方式,看了源碼我們知道,UseStatusCodePages 有4個重載。還可以自己定義,是不是感覺比前面的高級點,下面是自定義:具體就不演示了。
app.UseStatusCodePages(async context =>{context.HttpContext.Response.ContentType = "text/plain"; ?await context.HttpContext.Response.WriteAsync($"What's the statusCode you got is {context.HttpContext.Response.StatusCode}"); });app.UseStatusCodePages("text/plain","What's the statusCode you got is {0}");?截止到上面為止,基本的異常處理其實已經介紹的差不多了。但是,總感覺那么普遍呢,好像還不夠特殊,并且還滿足不了我們的需求,我們想要自定義錯誤的處理方式。比如我們想要遇到 404 時就顯示 404 界面。
定義異常處理中間件
?其實上面的自定義自己的異常處理時,其實已經可以做到我們需要的情況了。我們在Error Action?中對HttpContext.Response.StatusCode?進行判斷,根據不同的StatusCode?return 不同的View就可以了。但是為什么我們還需要定義特定處理的中間件,主要目的是為了其他項目服務的,如果你只有一個項目,一個站點,其實并沒什么必要。但是如果有很多子站點時,還是需要考慮的一下的。
?模仿了一下?UseStatusCodePagesWithReExecute這個,寫了一個
using System;using System.Collections.Generic;
using System.Text;
using Microsoft.AspNetCore.Builder;
using System.Globalization;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Diagnostics;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Options;
namespace MiddlewareDemo.CustomMiddleware{ ?
?/// <summary>/// Adds a StatusCodePages middleware to the pipeline. Specifies that the response body should be generated by /// re-executing the request pipeline using an alternate path. This path may contain a '{0}' placeholder of the status code./// </summary>/// <param name="app"></param>/// <param name="pathFormat"></param> //因為直接 處理404 所以就不給參數啦。/// <param name="queryFormat"></param>/// <returns></returns>public static class ErrorHandlerMiddlewareExtension{ ? ?
?? ?public static IApplicationBuilder UseErrorHandler( ? ? ? ? ? ?this IApplicationBuilder app, ? ? ? ? ? ? ? ? ? ?string pathFormat = "/error", ? ? ? ? ? ?string queryFormat = null) ? ? ? ?{ ? ? ?
?? ? ? ? ?if (app == null){ ? ? ? ? ? ? ?
?? ? ? ? ? ?throw new ArgumentNullException(nameof(app));} ? ? ? ? ?
?? ? ? ? ? ?return app.UseStatusCodePages(async context =>{ ? ? ? ? ? ? ?
?? ? ? ? ? ???if (context.HttpContext.Response.StatusCode == StatusCodes.Status404NotFound){ ? ? ? ? ? ? ? ?
?? ? ? ? ? ???? ?var newPath = new PathString( ? ? ? ? ? ? ? ? ? ? ? ?string.Format(CultureInfo.InvariantCulture, pathFormat, context.HttpContext.Response.StatusCode)); ? ? ? ? ? ? ? ? ? ?var formatedQueryString = queryFormat == null ? null : ? ? ? ? ? ? ? ? ? ? ? ?string.Format(CultureInfo.InvariantCulture, queryFormat, context.HttpContext.Response.StatusCode); ? ? ? ? ? ? ? ? ?
?? ? ? ? ? ???? ??var newQueryString = queryFormat == null ? QueryString.Empty : new QueryString(formatedQueryString); ? ? ? ? ? ? ? ? ?
?? ? ? ? ? ???? ? ?var originalPath = context.HttpContext.Request.Path; ? ? ? ? ? ? ?
?? ? ? ? ? ???? ?? ?var originalQueryString = context.HttpContext.Request.QueryString; ? ? ? ? ? ? ? ? ? ?// Store the original paths so the app can check it.context.HttpContext.Features.Set<IStatusCodeReExecuteFeature>(new StatusCodeReExecuteFeature(){OriginalPathBase = context.HttpContext.Request.PathBase.Value,OriginalPath = originalPath.Value,OriginalQueryString = originalQueryString.HasValue ? originalQueryString.Value : null,});context.HttpContext.Request.Path = newPath;context.HttpContext.Request.QueryString = newQueryString; ? ? ? ? ? ? ? ?
?? ? ? ? ? ???? ?? ?try{ ? ? ? ? ? ? ? ? ?
?? ? ? ? ? ???? ?? ?? ? ?await context.Next(context.HttpContext);} ? ? ? ? ? ? ? ?
?? ? ? ? ? ???? ?? ?finally{context.HttpContext.Request.QueryString = originalQueryString;context.HttpContext.Request.Path = originalPath;context.HttpContext.Features.Set<IStatusCodeReExecuteFeature>(null);}}});}} }
這樣就會只處理404啦。
如下所示 :
最后分享一個 Re-execute vs Redirect 的一位大神的分析
? 其實在?StatusCodePagesExtensions中還有兩個方法,這兩個方法也會比較實用,主要是用來當遇到異常,給你跳轉到其他界面的。
//使用的話就像下面這樣就可以啦app.UseStatusCodePagesWithReExecute("/error","?StatusCode={0}");app.UseStatusCodePagesWithRedirects("/error");//具體可以用哪些參數呢,可以去看源碼,這里就不多介紹了。這兩個的雖然都可以得到我們想要的結果,但是過程差的有點多。先盜一下大神的兩張圖:
第一張是?Redirect的 :
下面一張是 ReExecute` 的
區別呢,我用Chrome Developer Console?來給你們展示一下,你們就明白啦。
這個是?redirect?的 ,很神奇吧,它返回的是200 ok. 由于是?redirect?所以 地址 redirect 到了?localhost:52298/error?。看Network可知,進行了兩次請求,第一次,http://localhost:52298/home/testpage?時 返回302 Found. 我們知道這個是 404 的狀態碼,被 middleware “抓到”后,于是,我們再次發起請求,?http://localhost:52298/error這個請求當然返回的狀態碼是 200 啦。所以我們在下圖的結果中可以看見。200 OK。
302 : The 302 (Found) status code is used where the redirection is temporary or generally subject to change, such that the client shouldn't store and reuse the redirect URL in the future
下面的是ReExecute?的
結語
? 如有陳述的不正確處,請多多評論指正。
文章推薦及參考鏈接
Use statusCodeWithReExecute and pic reference
StatusCodePagesExtensions Source Code
相關文章:?
.NET Core 2.0 正式發布信息匯總
.NET Standard 2.0 特性介紹和使用指南
.NET Core 2.0 的dll實時更新、https、依賴包變更問題及解決
.NET Core 2.0 特性介紹和使用指南
Entity Framework Core 2.0 新特性
體驗 PHP under .NET Core
.NET Core 2.0使用NLog
升級項目到.NET Core 2.0,在Linux上安裝Docker,并成功部署
解決Visual Studio For Mac Restore失敗的問題
ASP.NET Core 2.0 特性介紹和使用指南
.Net Core下通過Proxy 模式 使用 WCF
.NET Core 2.0 開源Office組件 NPOI
ASP.NET Core - Razor頁面之Handlers處理方法
ASP.NET Core Razor頁面 vs MVC
Razor Page–Asp.Net Core 2.0新功能 ?Razor Page介紹
ASP.Net Core 2.0中的Razor Page不是WebForm
原文地址:http://www.cnblogs.com/xiyin/p/7507405.html
.NET社區新聞,深度好文,微信中搜索dotNET跨平臺或掃描二維碼關注
總結
以上是生活随笔為你收集整理的Error Handling in ASP.NET Core的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: ASP.NET Core Razor 视
- 下一篇: asp.net ajax控件工具集 Au