1. 程式人生 > >ASP.NET Core應用的錯誤處理[3]:ExceptionHandlerMiddleware中介軟體如何呈現“定製化錯誤頁面”

ASP.NET Core應用的錯誤處理[3]:ExceptionHandlerMiddleware中介軟體如何呈現“定製化錯誤頁面”

DeveloperExceptionPageMiddleware中介軟體利用呈現出來的錯誤頁面實現丟擲異常和當前請求的詳細資訊以輔助開發人員更好地進行糾錯診斷工作,而ExceptionHandlerMiddleware中介軟體則是面向終端使用者的,我們可以利用它來顯示一個友好的定製化的錯誤頁面。按照慣例,我們還是先來看看ExceptionHandlerMiddleware的型別定義。 [本文已經同步到《ASP.NET Core框架揭祕》之中]

   1: public class ExceptionHandlerMiddleware
   2: {    
   3:     public ExceptionHandlerMiddleware(RequestDelegate next, ILoggerFactory loggerFactory, IOptions<ExceptionHandlerOptions> options, DiagnosticSource diagnosticSource);  
   4:     public Task Invoke(HttpContext context);
   5: }
   6:  
   7: public class ExceptionHandlerOptions
   8: {
   9:     public RequestDelegate     ExceptionHandler { get; set; }
  10:     public PathString          ExceptionHandlingPath { get; set; }
  11: }

與DeveloperExceptionPageMiddleware類似,我們在建立一個ExceptionHandlerMiddleware物件的時候同樣需要提供一個攜帶配置選項的物件,從上面的程式碼可以看出這是一個ExceptionHandlerOptions。具體來說,一個ExceptionHandlerOptions物件通過其ExceptionHandler屬性提供了一個最終用來處理請求的RequestDelegate物件。如果希望發生異常後自動重定向到某個指定的路徑,我們可以利用ExceptionHandlerOptions物件的ExceptionHandlingPath屬性來指定這個路徑。我們一般會呼叫ApplicationBuilder的擴充套件方法UseExceptionHandler來註冊ExceptionHandlerMiddleware中介軟體,這些過載的UseExceptionHandler方法會採用如下的方式完整中介軟體的註冊工作。

   1: public static class ExceptionHandlerExtensions
   2: {
   3:     public static IApplicationBuilder UseExceptionHandler(this IApplicationBuilder app)=> app.UseMiddleware<ExceptionHandlerMiddleware>();
   4:  
   5:     public static IApplicationBuilder UseExceptionHandler(this IApplicationBuilder app, ExceptionHandlerOptions options) 
   6:        => app.UseMiddleware<ExceptionHandlerMiddleware>(Options.Create(options));
   7:  
   8:     public static IApplicationBuilder UseExceptionHandler(this IApplicationBuilder app, string errorHandlingPath)
   9:     { 
  10:         return app.UseExceptionHandler(new ExceptionHandlerOptions
  11:         {
  12:             ExceptionHandlingPath = new PathString(errorHandlingPath)
  13:         });
  14:     }
  15:  
  16:     public static IApplicationBuilder UseExceptionHandler(this IApplicationBuilder app, Action<IApplicationBuilder> configure)
  17:     {
  18:         IApplicationBuilder newBuilder = app.New();
  19:         configure(newBuilder);
  20:  
  21:         return app.UseExceptionHandler(new ExceptionHandlerOptions
  22:         {
  23:             ExceptionHandler = newBuilder.Build()
  24:         });
  25:     }     
  26: }

一、異常處理器

ExceptionHandlerMiddleware中介軟體處理請求的本質就是在後續請求處理過程中出現異常的情況下采用註冊的異常處理器來處理並響應請求,這個異常處理器就是我們再熟悉不過的RequestDelegate物件。該中介軟體採用的請求處理邏輯大體上可以通過如下所示的這段程式碼來體現。

   1: public class ExceptionHandlerMiddleware
   2: {
   3:     private RequestDelegate             _next;
   4:     private ExceptionHandlerOptions     _options;
   5:  
   6:     public ExceptionHandlerMiddleware(RequestDelegate next, IOptions<ExceptionHandlerOptions> options,…)
   7:     {
   8:         _next         = next;
   9:         _options      = options.Value;
  10:
  11:     }
  12:  
  13:     public async Task Invoke(HttpContext context)
  14:     {
  15:         try
  16:         {
  17:             await _next(context);
  18:         }
  19:         catch 
  20:         {
  21:             context.Response.StatusCode = 500;
  22:             context.Response.Clear();
  23:             if (_options.ExceptionHandlingPath.HasValue)
  24:             {
  25:                 context.Request.Path = _options.ExceptionHandlingPath;
  26:             }
  27:             RequestDelegate handler = _options.ExceptionHandler ?? _next;
  28:             await handler(context);
  29:         }
  30:     }
  31: }

如上面的程式碼片段所示,如果後續的請求處理過程中出現異常,ExceptionHandlerMiddleware中介軟體會利用一個作為異常處理器的RequestDelegate物件來完成最終的請求處理工作。如果在建立ExceptionHandlerMiddleware時提供的ExceptionHandlerOptions攜帶著這麼一個RequestDelegate物件,那麼它將作為最終使用的異常處理器,否則作為異常處理器的實際上就是後續的中介軟體。換句話說,如果我們沒有通過ExceptionHandlerOptions顯式指定一個異常處理器,ExceptionHandlerMiddleware中介軟體會在後續管道處理請求丟擲異常的情況下將請求再次傳遞給後續管道

當ExceptionHandlerMiddleware最終利用異常處理器來處理請求之前,它會對請求做一些前置處理工作,比如它會將響應狀態碼設定為500,比如清空當前所有響應內容等。如果我們利用ExceptionHandlerOptions的ExceptionHandlingPath屬性設定了一個重定向路徑,它會將該路徑設定為當前請求的路徑。除了這些,ExceptionHandlerMiddleware中介軟體實際上做了一些沒有反應在上面這段程式碼片段中的工作。

二、異常的傳遞與請求路徑的恢復

由於ExceptionHandlerMiddleware中介軟體總會利用一個作為異常處理器的RequestDelegate物件來完成最終的異常處理工作,為了讓後者能夠得到丟擲的異常,該中介軟體應該採用某種方式將異常傳遞給它。除此之外,由於ExceptionHandlerMiddleware中介軟體會改變當前請求的路徑,當整個請求處理完成之後,它必須將請求路徑恢復成原始的狀態,否則前置的中介軟體就無法獲取到正確的請求路徑。

請求處理過程中丟擲的異常和原始請求路徑的恢復是通過相應的特性完成的。具體來說,傳遞這兩者的特性分別叫做ExceptionHandlerFeature和ExceptionHandlerPathFeature,對應的介面分別為IExceptionHandlerFeature和IExceptionHandlerPathFeature,如下面的程式碼片段所示,後者繼承前者。預設使用的ExceptionHandlerFeature實現了這兩個介面。

   1: public interface IExceptionHandlerFeature
   2: {
   3:     Exception Error { get; }
   4: }
   5:  
   6: public interface IExceptionHandlerPathFeature : IExceptionHandlerFeature
   7: {
   8:     string Path { get; }
   9: }
  10:  
  11: public class ExceptionHandlerFeature : IExceptionHandlerPathFeature, 
  12: {
  13:     public Exception  Error { get; set; }
  14:     public string     Path { get; set; }
  15: }

當ExceptionHandlerMiddleware中介軟體將程式碼當前請求的HttpContext傳遞給請求處理器之前,它會按照如下所示的方式根據丟擲的異常的原始的請求路徑建立一個ExceptionHandlerFeature物件,該物件最終被新增到HttpContext之上。當整個請求處理流程完全結束之後,ExceptionHandlerMiddleware中介軟體會藉助這個特性得到原始的請求路徑,並將其重新應用到當前請求上下文上。

   1: public class ExceptionHandlerMiddleware
   2: {
   3:     ...
   4:     public async Task Invoke(HttpContext context)
   5:     {
   6:         try
   7:         {
   8:             await _next(context);
   9:         }
  10:         catch(Exception ex)
  11:         {
  12:             context.Response.StatusCode = 500;
  13:  
  14:             var feature = new ExceptionHandlerFeature()
  15:             {
  16:                 Error = ex,
  17:                 Path = context.Request.Path,
  18:             };
  19:             context.Features.Set<IExceptionHandlerFeature>(feature);
  20:             context.Features.Set<IExceptionHandlerPathFeature>(feature);
  21:  
  22:             if (_options.ExceptionHandlingPath.HasValue)
  23:             {
  24:                 context.Request.Path = _options.ExceptionHandlingPath;
  25:             }
  26:             RequestDelegate handler = _options.ExceptionHandler ?? _next;
  27:  
  28:             try
  29:             {
  30:                 await handler(context);
  31:             }
  32:             finally
  33:             {
            
           

相關推薦

ASP.NET Core應用錯誤處理[3]ExceptionHandlerMiddleware中介軟體如何呈現定製錯誤頁面

DeveloperExceptionPageMiddleware中介軟體利用呈現出來的錯誤頁面實現丟擲異常和當前請求的詳細資訊以輔助開發人員更好地進行糾錯診斷工作,而ExceptionHandlerMiddleware中介軟體則是面向終端使用者的,我們可以利用它來顯示一個友好的定製化的錯誤頁面。按照慣例,我們

15.ASP.NET Core 應用程式中的靜態檔案中介軟體

在這篇文章中,我將向大家介紹,如何使用中介軟體元件來處理靜態檔案。這篇文章中,我們討論下面幾個問題:在ASP.NET Core中,我們需要把靜態檔案存放在哪裡?在ASP.NET Core中 wwwroot資料夾是啥?怎樣在ASP.NET Core應用程式中,配置靜態檔案中介軟體?UseFileServer中介

ASP.NET Core應用錯誤處理[4]StatusCodePagesMiddleware中介軟體如何針對響應碼呈現錯誤頁面

StatusCodePagesMiddleware中介軟體與ExceptionHandlerMiddleware中介軟體比較類似,它們都是在後續請求處理過程中“出錯”的情況下利用一個錯誤處理器來完成最終的請求處理與響應的任務。它們之間的差異在於對“錯誤”的界定上,對於ExceptionHandlerMiddl

ASP.NET Core應用錯誤處理[2]DeveloperExceptionPageMiddleware中介軟體如何呈現“開發者異常頁面

在《ASP.NET Core應用的錯誤處理[1]:三種呈現錯誤頁面的方式》中,我們通過幾個簡單的例項演示瞭如何呈現一個錯誤頁面,這些錯誤頁面的呈現分別由三個對應的中介軟體來完成,接下來我們將對這三個中介軟體進行詳細介紹。在開發環境呈現的異常頁面是通過一個型別為DeveloperExceptionPageMid

ASP.NET Core 使用app.UseStaticFiles配置靜態檔案中介軟體,達到類似IIS中虛擬目錄的效果,可訪問位於 Web 根目錄之外的檔案

1、專案中靜態檔案存放在wwwroot資料夾之下,如下:要訪問nihao.jpg這個資料夾,url路徑可以這樣寫: <img src="~/images/inhao.jpg" alt="pic"/> wwwroot css images nihao

ASP.NET Core應用錯誤處理[1]三種呈現錯誤頁面的方式

由於ASP.NET Core應用是一個同時處理多個請求的伺服器應用,所以在處理某個請求過程中丟擲的異常並不會導致整個應用的終止。出於安全方面的考量,為了避免敏感資訊的外洩,客戶端在預設的情況下並不會得到詳細的出錯資訊,這無疑會在開發環境下增加查錯糾錯的難度。對於生產環境來說,我們也希望終端使用者能夠根據具體的

ASP.NET Core應用錯誤處理

最近在學習蔣金楠的ASP.NET Core 系列 真的是長知識了,博主地址:https://www.cnblogs.com/artech 一、顯示開發者異常頁面 由於ASP.NET Core應用是面向多個客戶端請求,如果一個錯誤,它並不會影響整個應用的終止,出於安全的考慮,客戶端在預設情況下應該得不到報錯

ASP.NET Core應用針對靜態檔案請求的處理[3]: StaticFileMiddleware中介軟體如何處理針對檔案請求

我們通過《以Web的形式釋出靜態檔案》和《條件請求與區間請求》中的例項演示,以及上面針對條件請求和區間請求的介紹,從提供的功能和特性的角度對這個名為StaticFileMiddleware的中間進行了全面的介紹,接下來我們將更近一步,將從實現原理的角度來進一步認識這個中介軟體。 [本文已經同步到《ASP.NE

ASP.NET Core應用基本程式設計模式[1]管道式的請求處理

HTTP協議自身的特性決定了任何一個Web應用的工作模式都是監聽、接收並處理HTTP請求,並且最終對請求予以響應。HTTP請求處理是管道式設計典型的應用場景:可以根據具體的需求構建一個管道,接收的HTTP請求像水一樣流入這個管道,組成這個管道的各個環節依次對其做相應的處理。雖然ASP.NET Core的請求處

ASP.NET Core應用基本程式設計模式[3]配置多種使用形式

通過《服務承載系統[2]: 承載長時間執行的服務[下篇]》的介紹可知,IHostBuilder介面中定義了ConfigureHostConfiguration方法和ConfigureAppConfiguration方法,它們可以幫助我們設定面向宿主(IHost物件)和應用(承載服務)的配置。針對配置的初始化也

ASP.NET core webapi RouteAttribute _平臺windows (3)

ASP.NET core webapi RouteAttribute _平臺:windows (3) 簡版(後面還有囉嗦版本 點我進入囉嗦版本): 問題: 1、介紹RouteAttribute特性。 這個東西其實很簡單:主要用處就是設定路由罷了 什麼?不懂路由是什麼? 那麼你就理

ASP.NET Core應用針對靜態檔案請求的處理[2]: 條件請求與區間請求

通過呼叫ApplicationBuilder的擴充套件方法UseStaticFiles註冊的StaticFileMiddleware中介軟體幫助我們處理針對檔案的請求。對於StaticFileMiddleware處理請求的邏輯,大部分讀者都應該想得到:它根據請求的地址找到目標檔案的路徑,然後利用註冊的Cont

ASP.NET Core應用針對靜態檔案請求的處理[1]: 以Web的形式釋出靜態檔案

雖然ASP.NET Core是一款“動態”的Web服務端框架,但是在很多情況下都需要處理針對靜態檔案的請求,最為常見的就是這對JavaScript指令碼檔案、CSS樣式檔案和圖片檔案的請求。針對不同格式的靜態檔案請求的處理,ASP.NET Core為我們提供了三個中介軟體,它們將是本系列文章論述的重點。不過在

ASP.NET Core應用針對靜態檔案請求的處理[4]: DirectoryBrowserMiddleware中介軟體如何呈現目錄結構

和StaticFileMiddleware中介軟體一樣,DirectoryBrowserMiddleware中間本質上還是定義了一個請求地址與某個物理目錄之間的對映關係,而目標目錄體現為一個FileProvider物件。當這個中介軟體接收到匹配的請求後,會根據請求地址解析出對應目錄的相對路徑,並利用這個Fil

ASP.NET Core中的快取[1]如何在一個ASP.NET Core應用中使用快取

.NET Core針對快取提供了很好的支援 ,我們不僅可以選擇將資料快取在應用程序自身的記憶體中,還可以採用分散式的形式將快取資料儲存在一個“中心資料庫”中。對於分散式快取,.NET Core提供了針對Redis和SQL Server的原生支援。除了這個獨立的快取系統之外,ASP.NET Core還藉助一箇中

ASP.NET Core應用針對靜態檔案請求的處理[5]: DefaultFilesMiddleware中介軟體如何顯示預設頁面

DefaultFilesMiddleware中介軟體的目的在於將目標目錄下的預設檔案作為響應內容。我們知道,如果直接請求的就是這個預設檔案,那麼前面介紹的StaticFileMiddleware中介軟體會將這個檔案響應給客戶端。如果我們能夠將針對目錄的請求重定向到這個預設檔案上,一切就迎刃而解了。實際上Def

Kubernetes初探[1]部署你的第一個ASP.NET Core應用到k8s叢集

Kubernetes簡介 Kubernetes是Google基於Borg開源的容器編排排程引擎,作為CNCF(Cloud Native Computing Foundation)最重要的元件之一,它的目標不僅僅是一個編排系統,而是提供一個規範,可以讓你來描述叢集的架構,定義服務的最終狀態,Kubernete

ASP.NET Core應用基本程式設計模式[4]基於承載環境的程式設計

基於IHostBuilder/IHost的承載系統通過IHostEnvironment介面表示承載環境,我們利用它不僅可以得到當前部署環境的名稱,還可以獲知當前應用的名稱和存放內容檔案的根目錄路徑。對於一個Web應用來說,我們需要更多的承載環境資訊,額外的資訊定義在IWebHostEnvironment介面中

ASP.NET Core應用基本程式設計模式[5]如何放置你的初始程式碼

一個ASP.NET Core應用的核心就是由一個伺服器和一組有序中介軟體組成的請求處理管道,伺服器只負責監聽、接收和分發請求,以及最終完成對請求的響應,所以一個ASP.NET Core應用針對請求的處理能力和處理方式由註冊的中介軟體來決定。一個ASP.NET Core在啟動過程中的核心工作就是註冊中介軟體,本

Linux使用Jexus托管Asp.Net Core應用程序

技術 文件目錄 只需要 true 沒有 repr tag 博文 env 第一步 安裝.Net Core環境 安裝 dotnet 環境參見官方網站 https://www.microsoft.com/net/core。 選擇對應的系統版本進行安裝。安裝完成過後 輸入命令查