異常是一種運行時錯誤,當異常沒有獲得適當的處理,極可能會致使你的程序意外終止,這篇就來討論一下如何在 ASP.Net Core MVC 中實現全局異常處理,我會用一些 樣例代碼 和 截圖 來講明這些概念。html
其實在 ASP.Net Core MVC 框架中已經有了全局異常處理的機制,你能夠在一箇中心化的地方使用 全局異常處理中間件
來進行異常攔截,若是不用這種中心化方式的話,你就只能在 Controller 或者 Action 做用域上單獨處理,這會致使異常處理代碼零散在項目各處,很差維護也特別麻煩,不是嗎?git
第二種處理 全局異常 的作法就是使用 exception filter,在本篇中,我準備跟你們聊一聊 全局異常處理中間件
和 UseExceptionHandler
方法來管控異常。github
UseExceptionHandler 擴展方法可以將 ExceptionHandler 中間件註冊到 Asp.net Core 的 請求處理管道
中,而後在 IExceptionHandlerFeature 接口的實例中獲取 異常對象,下面的代碼片斷展現瞭如何使用 UseExceptionHandler 方法來截獲全局異常。json
public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { app.UseExceptionHandler(builder => { builder.Run(async context => { context.Response.StatusCode = (int)HttpStatusCode.InternalServerError; context.Response.ContentType = "application/json"; var exception = context.Features.Get<IExceptionHandlerFeature>(); if (exception != null) { var error = new ErrorMessage() { Stacktrace = exception.Error.StackTrace, Message = exception.Error.Message }; var errObj = JsonConvert.SerializeObject(error); await context.Response.WriteAsync(errObj).ConfigureAwait(false); } }); } ); app.UseStaticFiles(); app.UseRouting(); app.UseAuthorization(); app.UseEndpoints(endpoints => { endpoints.MapControllerRoute( name: "default", pattern: "{controller=Home}/{action=Index}/{id?}"); }); }
下面是代碼中引用的 ErrorMessage 類的定義。mvc
public class ErrorMessage { public string Message { get; set; } public string Stacktrace { get; set; } }
你們都知道,ASP.Net Core MVC 項目中都會有一個 Startup.cs 文件,能夠在 Configure 方法下配置 全局異常攔截中間件
代碼,以下所示:app
public void Configure(IApplicationBuilder app, IHostingEnvironment env) { if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); } else { app.UseExceptionHandler("/Error"); } app.UseStaticFiles(); app.UseCookiePolicy(); app.UseMvc(routes => { routes.MapRoute( name: "default", template: "{controller=Home}/{action=Index}/{id?}"); }); }
能夠着重看一下上面的 app.UseExceptionHandler("/Error");
,這裏的 UseExceptionHandler 實現了 pipeline 註冊,一旦應用程序出現了未處理異常,那麼會自動將 用戶 導向 /Error
頁面。框架
你能夠用 UseStatusCodePagesWithReExecute 擴展方法給 pipeline 添加一些狀態碼頁面,這是什麼意思呢? 其實也就是 http 500 導向 500 頁面, http 404 導向 404 頁面,下面的代碼片斷展現了修改後的 Configure 方法代碼。async
public void Configure(IApplicationBuilder app, IHostingEnvironment env) { if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); } else { app.UseExceptionHandler("/Error"); app.UseStatusCodePagesWithReExecute("/Error/NotFound/{0}"); } //Other code }
在 HomeController 下有一個專門處理錯誤的 action 方法,這裏咱們不使用這個 action,你能夠把它刪掉,接下來我準備定義一個專門的 ErrorController,裏面包含了一個路由爲 /Error
的 action 方法。測試
public class ErrorController : Controller { [HttpGet("/Error")] public IActionResult Index() { IExceptionHandlerPathFeature iExceptionHandlerFeature = HttpContext.Features.Get<IExceptionHandlerPathFeature>(); if (iExceptionHandlerFeature != null) { string path = iExceptionHandlerFeature.Path; Exception exception = iExceptionHandlerFeature.Error; //Write code here to log the exception details return View("Error",iExceptionHandlerFeature); } return View(); } [HttpGet("/Error/NotFound/{statusCode}")] public IActionResult NotFound(int statusCode) { var iStatusCodeReExecuteFeature =HttpContext.Features.Get<IStatusCodeReExecuteFeature>(); return View("NotFound",iStatusCodeReExecuteFeature.OriginalPath); } }
你能夠用 IExceptionHandlerPathFeature
來獲取異常相關信息,也能夠用 IStatusCodeReExecuteFeature
來獲取 http 404 異常時當時的請求路徑,對了,要想用上 IExceptionHandlerPathFeature
和 IStatusCodeReExecuteFeature
,要記得在 nuget 上安裝了 Microsoft.AspNetCore.Diagnostics 包,下面的代碼展現瞭如何獲取異常發生時刻的路由地址。ui
string route = iExceptionHandlerFeature.Path;
若是想獲取異常的詳細信息,可使用以下語句。
var exception = HttpContext.Features.Get<IExceptionHandlerPathFeature>();
一旦獲取了這個路由地址和異常的詳細信息,就能夠將它記錄到你的日誌文件中,可供後續仔細分析。
能夠建立一個 View 來展現出現的錯誤信息,下面時 Error ViewPage
的詳細代碼。
@model Microsoft.AspNetCore.Diagnostics.IExceptionHandlerFeature @{ ViewData["Title"] = "Index"; Layout = "~/Views/Shared/_Layout.cshtml"; } <div class="row"> <div class="text-danger"> <h3>Error: @Model.Error.Message</h3> </div> </div> <div class="row"> <div class="col-12"> <p>@Model.Error.StackTrace</p> <p>@Model.Error.InnerException</p> </div> </div>
下面是 NotFound 頁面的 代碼
@model string @{ ViewData["Title"] = "NotFound"; Layout = "~/Views/Shared/_Layout.cshtml"; } <h1 class="text-danger"> Error: The requested URL @Model was not found!</h1> <hr />
如今能夠把程序跑起來了,你會看到以下的錯誤信息。
若是你嘗試打開一個不存在的頁面, 會自動跳轉到 ErrorController.NotFound
所包裝的 404 描述信息。
ASP.NET Core 中內置了 全局異常處理,你能夠利用這項技術在一個集中化的地方去截獲你應用程序中的全部異常信息,固然你也能夠基於環境的不一樣採起不用的異常處理措施,好比說:開發環境,測試環境,生產環境 等等。
譯文連接: https://www.infoworld.com/art...
更多高質量乾貨:參見個人 GitHub: dotnetfly