1. 程式人生 > >ASP.NET Core應用的錯誤處理[4]:StatusCodePagesMiddleware中介軟體如何針對響應碼呈現錯誤頁面

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

StatusCodePagesMiddleware中介軟體與ExceptionHandlerMiddleware中介軟體比較類似,它們都是在後續請求處理過程中“出錯”的情況下利用一個錯誤處理器來完成最終的請求處理與響應的任務。它們之間的差異在於對“錯誤”的界定上,對於ExceptionHandlerMiddleware中介軟體來說,它所謂的錯誤就是丟擲異常,但是對於StatusCodePagesMiddleware中介軟體來說,則將介於400~599之間的響應狀態碼視為錯誤。如下面的程式碼片段所示,StatusCodePagesMiddleware中介軟體也採用“標準”的定義方式,針對它的配置選項通過一個對應的物件以Options模式的形式提供給它。 [本文已經同步到《

ASP.NET Core框架揭祕》之中]

   1: public class StatusCodePagesMiddleware
   2: {
   3:     public StatusCodePagesMiddleware(RequestDelegate next, IOptions<StatusCodePagesOptions> options);
   4:     public Task Invoke(HttpContext context);
   5: }

除了針對錯誤的界定,StatusCodePagesMiddleware和ExceptionHandlerMiddleware這兩個中介軟體對於錯誤處理器的表達也不相同。我們知道ExceptionHandlerMiddleware中介軟體使用的錯誤處理器實際上就是一個型別為RequestDelegate的委託物件,但是錯誤處理器之於StatusCodePagesMiddleware中介軟體來說則是一個型別為Func<StatusCodeContext, Task>的委託物件。如下面的程式碼片段所示,為StatusCodePagesMiddleware中介軟體提供配置選項的StatusCodePagesOptions物件的唯一目的就是提供這個作為錯誤處理器的委託物件。

   1: public class StatusCodePagesOptions
   2: {
   3:     public Func<StatusCodeContext, Task> HandleAsync { get; set; }
   4: }

我們知道一個RequestDelegate物件相當於一個型別為Func<HttpContext, Task>型別的委託物件,而一個StatusCodeContext物件實際上也是對一個HttpContext物件的封裝,所以StatusCodePagesMiddleware中介軟體和ExceptionHandlerMiddleware中介軟體所使採用的錯誤處理器並沒有本質上的不同。如下面的程式碼片段所示,除了從StatusCodeContext物件中獲取代表當前請求上下文的HttpContext物件之外,我們還可以通過其Next屬性得到一個RequestDelegate物件,它代表由後續中介軟體組成的請求處理管道。至於另一個屬性Options,很明顯它返回我們在建立StatusCodePagesMiddleware中介軟體所指定的StatusCodePagesOptions物件。

   1: public class StatusCodeContext
   2: {    
   3:     public HttpContext             HttpContext { get; }
   4:     public RequestDelegate         Next { get; }
   5:     public StatusCodePagesOptions  Options { get; }
   6:  
   7:     public StatusCodeContext(HttpContext context, StatusCodePagesOptions options, RequestDelegate next);
   8: }

一、針對響應狀態碼的錯誤處理

由於採用了針對響應狀態碼的錯誤處理策略,所以實現在StatusCodePagesMiddleware中介軟體中的所有錯誤處理操作只會發生在當前響應狀態碼在400~599之間的情況,如下所示的程式碼片段體現了這一點。從下面給出的程式碼片段可以看出,StatusCodePagesMiddleware中介軟體在決定是否執行錯誤處理操作時除了會檢視當前響應狀態碼之外,還會檢視響應內容以及媒體型別,如果已經包含了響應內容或者設定了媒體型別,該中介軟體將不會執行任何操作。

   1: public class StatusCodePagesMiddleware
   2: {
   3:     private  RequestDelegate            _next;
   4:     private  StatusCodePagesOptions     _options;
   5:  
   6: public StatusCodePagesMiddleware(RequestDelegate next, 
   7:     IOptions<StatusCodePagesOptions> options)
   8:     {
   9:         _next         = next;
  10:         _options      = options.Value;
  11:     }
  12:  
  13:     public async Task Invoke(HttpContext context)
  14:     {          
  15:         await _next(context);
  16:         var response = context.Response;
  17:         if ((response.StatusCode >= 400 && response.StatusCode <= 599) &&!response.ContentLength.HasValue && string.IsNullOrEmpty(response.ContentType))
  18:         {
  19:             await _options.HandleAsync(new StatusCodeContext(context, _options, _next));
  20:         }
  21:     }
  22: }

StatusCodePagesMiddleware中介軟體針對錯誤的處理非常簡單,它只需要從StatusCodePagesOptions物件中提取出作為錯誤處理器的這個Func<StatusCodeContext, Task>物件,然後建立一個StatusCodeContext物件作為輸入引數呼叫這個委託物件即可。

二、阻止異常處理

如果當前響應已經被寫入了內容,或者響應的媒體型別已經被預先設定,那麼StatusCodePagesMiddleware中介軟體將不會再執行任何的錯誤處理操作。這種情況實際上代表由後續中介軟體構成的管道可能需要自行控制當前的響應,所以StatusCodePagesMiddleware中介軟體不應該再做任何的干預。從這個意義上來講,StatusCodePagesMiddleware中介軟體僅僅是作為一種後備的錯誤處理機制而已。

更進一步來將,如果後續的某個中介軟體返回了一個狀態碼在400~599之間的響應,並且這個響應只有報頭集合沒有主體(媒體型別自然也不會設定),那麼按照我們在上面給出的錯誤處理邏輯,StatusCodePagesMiddleware中介軟體還是會按照自己的策略來處理並響應請求。為了解決這種情況下,我們必須賦予後續中介軟體一個能夠阻止StatusCodePagesMiddleware中介軟體進行錯誤處理的能力。

阻止StatusCodePagesMiddleware中介軟體進行錯誤處理的機制是藉助於一個名為StatusCodePagesFeature的特性來實現的。StatusCodePagesFeature對應如下這個IStatusCodePagesFeature介面,它具有唯一的布林型別的屬性成員Enabled。預設使用的StatusCodePagesFeature型別實現了這個介面,預設情況下這個開關是開啟的。

   1: public interface IStatusCodePagesFeature
   2: {
   3:     bool Enabled { get; set; }
   4: }
   5:  
   6: public class StatusCodePagesFeature : IStatusCodePagesFeature
   7: {
   8:     public bool Enabled { get; set; } = true ;
   9: }

StatusCodePagesMiddleware中介軟體在將請求交付給後續管道之前,它會建立一個StatusCodePagesFeature特性物件並將其新增到當前HttpContext之中。當最終決定是否執行錯誤處理操作的時候,它還會通過這個特性檢驗是否某個後續的中介軟體不希望自己“畫蛇添足”地進行不必要的錯誤處理,如下的程式碼片段很好的體現了這一點。

   1: public class StatusCodePagesMiddleware
   2: {
   3:
   4:     public async Task Invoke(HttpContext context)
   5:     {
   6:         StatusCodePagesFeature feature = new StatusCodePagesFeature();
   7:         context.Features.Set<IStatusCodePagesFeature>(feature);
   8:  
   9:         await _next(context);
  10:         var response = context.Response;
  11:         if ((response.StatusCode >= 400 && response.StatusCode <= 599) && !response.ContentLength.HasValue &&string.IsNullOrEmpty(response.ContentType) &&
  12:             feature.Enabled)
  13:         {
  14:             await _options.HandleAsync(new StatusCodeContext(context, _options, _next));
  15:         }
  16:     }
  17: }

我們通過一個簡單的例項來演示如果利用這個StatusCodePagesFeature特性來遮蔽StatusCodePagesMiddleware中介軟體。在下面這個應用中,我們將針對請求的處理定義在Invoke方法中,該方法會返回一個狀態碼為“401 Unauthorized”的響應。我們通過隨機數讓這個方法會在50%的情況下利用StatusCodePagesFeature特性來阻止StatusCodePagesMiddleware中介軟體自身對錯誤的處理。我們通過呼叫擴充套件方法UseStatusCodePages註冊的StatusCodePagesMiddleware中介軟體會直接響應一個內容為“Error occurred!”的字串。

   1: public class Program
   2: {
   3:     public static void Main()
   4:     {
   5:         new WebHostBuilder()
   6:             .UseKestrel()
   7:             .Configure(app => app
   8:                 .UseStatusCodePages(async context => await context.HttpContext.Response.WriteAsync("Error occurred!"))
   9:                 .Run(Invoke))
  10:             .Build()
  11:             .Run();
  12:     }
  13:  
  14:     private static Random _random = new Random();
  15:     private static Task Invoke(HttpContext context)
  16:     {
  17:         context.Response.StatusCode = 401;
  18:  
  19:         if (_random.Next() % 2 == 0)
  20:         {
  21:             context.Features.Get<IStatusCodePagesFeature>().Enabled = false;
  22:         }
  23:         return Task.CompletedTask;
  24:     }
  25: }

對於針對該應用的請求來說,我們會得到如下兩種不同的響應。沒有主體內容響應是通過Invoke方法產生的,這種情況下發生在StatusCodePagesMiddleware中介軟體通過StatusCodePagesFeature特性被遮蔽的時候。具有主體內容的響應則來源於StatusCodePagesMiddleware中介軟體。

   1: HTTP/1.1 401 Unauthorized
   2: Date: Sun, 18 Dec 2016 01:59:37 GMT
   3: Server: Kestrel
   4: Content-Length: 15
   5:  
   6: Error occurred!
   7:  
   8:  
   9: HTTP/1.1 401 Unauthorized
  10: Date: Sun, 18 Dec 2016 01:59:38 GMT
  11: Content-Length: 0
  12: Server: Kestrel

三、註冊StatusCodePagesMiddleware中介軟體

我們在大部分情況下都會呼叫ApplicationBuilder相應的擴充套件方法來註冊StatusCodePagesMiddleware中介軟體。對於StatusCodePagesMiddleware中介軟體的註冊來說,除了我們已經很熟悉的UseStatusCodePages方之外,還具有額外一些擴充套件方法供我們選擇。

UseStatusCodePages

我們可以呼叫如下三個UseStatusCodePages方法過載來註冊StatusCodePagesMiddleware中介軟體。不論我們呼叫那個過載,系統最終都會根據提供的StatusCodePagesOptions物件呼叫建構函式來建立這個中介軟體物件,而且這個StatusCodePagesOptions必須具有一個作為錯誤處理器的Func<StatusCodeContext, Task>物件。如果沒有指定任何引數,StatusCodePagesOptions物件需要以Options模式的形式註冊為服務。

   1: public static class StatusCodePagesExtensions
   2: {   
   3:     public static IApplicationBuilder UseStatusCodePages(this IApplicationBuilder app)
   4:     {      
   5:         return app.UseMiddleware<StatusCodePagesMiddleware>();

            
           

相關推薦

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

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

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

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

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

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

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應用針對靜態檔案請求的處理[4]: DirectoryBrowserMiddleware中介軟體如何呈現目錄結構

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

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

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

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

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

asp.net core mvc視頻A筆記4.高級數據綁定

前端 ade .net .net core 高級 指定 測試 如果 視頻 默認的綁定順序,如果需要取指定數據源裏的數據,需要通過屬性控制,比如[FromQuery] 前端 控制器方法 前端 此時並不能得到head中的數據 改造控制器方

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

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

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中的快取[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應用基本程式設計模式[3]配置多種使用形式

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

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。 選擇對應的系統版本進行安裝。安裝完成過後 輸入命令查