日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > asp.net >内容正文

asp.net

深入探究ASP.NET Core异常处理中间件

發布時間:2023/12/4 asp.net 61 豆豆
生活随笔 收集整理的這篇文章主要介紹了 深入探究ASP.NET Core异常处理中间件 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

前言

????全局異常處理是我們編程過程中不可或缺的重要環節。有了全局異常處理機制給我們帶來了很多便捷,首先我們不用滿屏幕處理程序可能出現的異常,其次我們可以對異常進行統一的處理,比如收集異常信息或者返回統一的格式等等。ASP.NET Core為我們提供了兩種機制去處理全局異常,一是基于中間件的方式,二是基于Filter過濾器的方式。Filter過濾器的方式相對來說比較簡單,就是捕獲Action執行過程中出現的異常,然后調用注冊的Filter去執行處理異常信息,在這里就不過多介紹這種方式了,接下來我們主要介紹中間件的方式。

異常處理中間件

??? ASP.NET Core為我們提供了幾種不同處理異常方式的中間件分別是UseDeveloperExceptionPage、UseExceptionHandler、UseStatusCodePages、UseStatusCodePagesWithRedirects、UseStatusCodePagesWithReExecute。這幾種方式處理的思路是一致的都是通過捕獲該管道后續的管道執行過程中出現的異常,只是處理的方式不一樣。一般推薦全局異常處理相關中間件寫到所有管道的最開始,這樣可以捕獲到整個執行管道過程中的異常信息。接下來我們介紹一下最常用的三個異常處理中間件UseDeveloperExceptionPage、UseExceptionHandler、UseStatusCodePage。

UseDeveloperExceptionPage

UseDeveloperExceptionPage的使用場景大部分是開發階段,通過名稱我們就可以看出,通過它捕獲的異常會返回一個異常界面,它的使用方式很簡單

//這個判斷不是必須的,但是在正式環境中給用戶展示代碼錯誤信息,終究不是合理的 if (env.IsDevelopment()) {app.UseDeveloperExceptionPage(); }

如果程序出現異常,出現的效果是這個樣子的
這里包含了非常詳細的異常堆棧信息、請求參數、Cookie信息、Header信息、和路由終結點相關的信息。接下來我們找到UseDeveloperExceptionPage所在的擴展類

public static class DeveloperExceptionPageExtensions {public static IApplicationBuilder UseDeveloperExceptionPage(this IApplicationBuilder app){return app.UseMiddleware<DeveloperExceptionPageMiddleware>();}public static IApplicationBuilder UseDeveloperExceptionPage(this IApplicationBuilder app,DeveloperExceptionPageOptions options){return app.UseMiddleware<DeveloperExceptionPageMiddleware>(Options.Create(options));} }

我們看到有兩個擴展方法一個是無參的,另一個是可以傳遞DeveloperExceptionPageOptions的擴展方法,因為平時使用無參的方法所以我們看下DeveloperExceptionPageOptions包含了哪些信息,找到DeveloperExceptionPageOptions源碼

public class DeveloperExceptionPageOptions {public DeveloperExceptionPageOptions(){SourceCodeLineCount = 6;}/// <summary>/// 展示出現異常代碼的地方上下展示多少行的代碼信息,默認是6行/// </summary>public int SourceCodeLineCount { get; set; }/// <summary>/// 通過這個文件提供程序我們可以猜測到,我們可以自定義異常錯誤界面/// </summary>public IFileProvider FileProvider { get; set; } }

接下來我們就看核心的DeveloperExceptionPageMiddleware中間件大致是如何工作的

public class DeveloperExceptionPageMiddleware {private readonly RequestDelegate _next;private readonly DeveloperExceptionPageOptions _options;private readonly ILogger _logger;private readonly IFileProvider _fileProvider;private readonly DiagnosticSource _diagnosticSource;private readonly ExceptionDetailsProvider _exceptionDetailsProvider;private readonly Func<ErrorContext, Task> _exceptionHandler;private static readonly MediaTypeHeaderValue _textHtmlMediaType = new MediaTypeHeaderValue("text/html");public DeveloperExceptionPageMiddleware(RequestDelegate next,IOptions<DeveloperExceptionPageOptions> options,ILoggerFactory loggerFactory,IWebHostEnvironment hostingEnvironment,DiagnosticSource diagnosticSource,IEnumerable<IDeveloperPageExceptionFilter> filters){_next = next;_options = options.Value;_logger = loggerFactory.CreateLogger<DeveloperExceptionPageMiddleware>();//默認使用ContentRootFileProvider_fileProvider = _options.FileProvider ?? hostingEnvironment.ContentRootFileProvider;//可以發送診斷日志_diagnosticSource = diagnosticSource;_exceptionDetailsProvider = new ExceptionDetailsProvider(_fileProvider, _options.SourceCodeLineCount);_exceptionHandler = DisplayException;//構建IDeveloperPageExceptionFilter執行管道,說明我們同時還可以通過程序的方式捕獲異常信息foreach (var filter in filters.Reverse()){var nextFilter = _exceptionHandler;_exceptionHandler = errorContext => filter.HandleExceptionAsync(errorContext, nextFilter);}}public async Task Invoke(HttpContext context){try{await _next(context);}catch (Exception ex){_logger.UnhandledException(ex);if (context.Response.HasStarted){_logger.ResponseStartedErrorPageMiddleware();throw;}try{//清除輸出相關信息,將狀態碼設為500context.Response.Clear();context.Response.StatusCode = 500;//核心處理await _exceptionHandler(new ErrorContext(context, ex));//發送名稱為Microsoft.AspNetCore.Diagnostics.UnhandledException診斷日志,我們可以自定義訂閱者處理異常if (_diagnosticSource.IsEnabled("Microsoft.AspNetCore.Diagnostics.UnhandledException")){_diagnosticSource.Write("Microsoft.AspNetCore.Diagnostics.UnhandledException", new { httpContext = context, exception = ex });}return;}catch (Exception ex2){_logger.DisplayErrorPageException(ex2);}throw;}} }

通過上面代碼我們可以了解到我們可以通過自定義IDeveloperPageExceptionFilter的方式攔截到異常信息做處理

public class MyDeveloperPageExceptionFilter : IDeveloperPageExceptionFilter {private readonly ILogger<MyDeveloperPageExceptionFilter> _logger;public MyDeveloperPageExceptionFilter(ILogger<MyDeveloperPageExceptionFilter> logger){_logger = logger;}public async Task HandleExceptionAsync(ErrorContext errorContext, Func<ErrorContext, Task> next){_logger.LogInformation($"狀態碼:{errorContext.HttpContext.Response.StatusCode},異常信息:{errorContext.Exception.Message}");await next(errorContext);} }

自定義的MyDeveloperPageExceptionFilter是需要注入的

services.AddSingleton<IDeveloperPageExceptionFilter,MyDeveloperPageExceptionFilter>();

同時還可以通過診斷日志的方式處理異常信息,我使用了Microsoft.Extensions.DiagnosticAdapter擴展包,所以可以定義強類型類

public class DiagnosticCollector {private readonly ILogger<DiagnosticCollector> _logger;public DiagnosticCollector(ILogger<DiagnosticCollector> logger){_logger = logger;}[DiagnosticName("Microsoft.AspNetCore.Diagnostics.UnhandledException")]public void OnRequestStart(HttpContext httpContext, Exception exception){_logger.LogInformation($"診斷日志收集到異常,狀態碼:{httpContext.Response.StatusCode},異常信息:{exception.Message}");} }

通過這里可以看出,異常處理擴展性還是非常強的,這僅僅是.Net Core設計方式的冰山一角。剛才我們提到_exceptionHandler才是處理的核心,通過構造函數可知這個委托是通過DisplayException方法初始化的,接下來我們看這里的相關實現

private Task DisplayException(ErrorContext errorContext) {var httpContext = errorContext.HttpContext;var headers = httpContext.Request.GetTypedHeaders();var acceptHeader = headers.Accept;//如果acceptHeader不存在或者類型不是text/plain,將以字符串的形式輸出異常,比如通過代碼或者Postman的方式調用并未設置頭信息if (acceptHeader == null || !acceptHeader.Any(h => h.IsSubsetOf(_textHtmlMediaType))){httpContext.Response.ContentType = "text/plain";var sb = new StringBuilder();sb.AppendLine(errorContext.Exception.ToString());sb.AppendLine();sb.AppendLine("HEADERS");sb.AppendLine("=======");foreach (var pair in httpContext.Request.Headers){sb.AppendLine($"{pair.Key}: {pair.Value}");}return httpContext.Response.WriteAsync(sb.ToString());}//判斷是否為編譯時異常,比如視圖文件可以動態編譯if (errorContext.Exception is ICompilationException compilationException){return DisplayCompilationException(httpContext, compilationException);}//處理運行時異常return DisplayRuntimeException(httpContext, errorContext.Exception); }

關于DisplayCompilationException我們這里就不做過多解釋了,在Asp.Net Core中cshtml文件可以動態編譯,有興趣的同學可以自行了解。我們重點看下DisplayRuntimeException處理

private Task DisplayRuntimeException(HttpContext context, Exception ex) {//獲取終結點信息var endpoint = context.Features.Get<IEndpointFeature>()?.Endpoint;EndpointModel endpointModel = null;if (endpoint != null){endpointModel = new EndpointModel();endpointModel.DisplayName = endpoint.DisplayName;if (endpoint is RouteEndpoint routeEndpoint){endpointModel.RoutePattern = routeEndpoint.RoutePattern.RawText;endpointModel.Order = routeEndpoint.Order;var httpMethods = endpoint.Metadata.GetMetadata<IHttpMethodMetadata>()?.HttpMethods;if (httpMethods != null){endpointModel.HttpMethods = string.Join(", ", httpMethods);}}}var request = context.Request;//往視圖還是個輸出的模型,對于我們上面截圖展示的信息對應的數據var model = new ErrorPageModel{Options = _options,//異常詳情ErrorDetails = _exceptionDetailsProvider.GetDetails(ex),//查詢參數相關Query = request.Query,//Cookie信息Cookies = request.Cookies,//頭信息Headers = request.Headers,//路由信息RouteValues = request.RouteValues,//終結點信息Endpoint = endpointModel};var errorPage = new ErrorPage(model);//執行輸出視圖頁面,也就是我們看到的開發者頁面return errorPage.ExecuteAsync(context); }

其整體實現思路就是捕獲后續執行過程中出現的異常,如果出現異常則包裝異常信息以及Http上下文和路由相關信息到ErrorPageModel模型中,然后這個模型作為異常展示界面的數據模型進行展示。

UseExceptionHandler

UseExceptionHandler可能是我們在實際開發過程中使用最多的方式。UseDeveloperExceptionPage固然強大,但是返回的終究還是供開發者使用的界面,通過UseExceptionHandler我們可以通過自己的方式處理異常信息,這里就需要我自己編碼

app.UseExceptionHandler(configure => {configure.Run(async context =>{var exceptionHandlerPathFeature = context.Features.Get<IExceptionHandlerPathFeature>();var ex = exceptionHandlerPathFeature?.Error;if (ex != null){context.Response.ContentType = "text/plain;charset=utf-8";await context.Response.WriteAsync(ex.ToString());}}); }); //或 app.UseExceptionHandler(new ExceptionHandlerOptions {ExceptionHandler = async context =>{var exceptionHandlerPathFeature = context.Features.Get<IExceptionHandlerPathFeature>();var ex = exceptionHandlerPathFeature?.Error;if (ex != null){context.Response.ContentType = "text/plain;charset=utf-8";await context.Response.WriteAsync(ex.ToString());}} }); //或 app.UseExceptionHandler(new ExceptionHandlerOptions {ExceptionHandlingPath = new PathString("/exception") });

通過上面的實現方式我們大概可以猜出擴展方法的幾種類型找到源碼位置ExceptionHandlerExtensions擴展類

public static class ExceptionHandlerExtensions {public static IApplicationBuilder UseExceptionHandler(this IApplicationBuilder app){return app.UseMiddleware<ExceptionHandlerMiddleware>();}public static IApplicationBuilder UseExceptionHandler(this IApplicationBuilder app, string errorHandlingPath){return app.UseExceptionHandler(new ExceptionHandlerOptions{ExceptionHandlingPath = new PathString(errorHandlingPath)});}public static IApplicationBuilder UseExceptionHandler(this IApplicationBuilder app, Action<IApplicationBuilder> configure){//創建新的執行管道var subAppBuilder = app.New();configure(subAppBuilder);var exceptionHandlerPipeline = subAppBuilder.Build();return app.UseExceptionHandler(new ExceptionHandlerOptions{ExceptionHandler = exceptionHandlerPipeline});}public static IApplicationBuilder UseExceptionHandler(this IApplicationBuilder app, ExceptionHandlerOptions options){return app.UseMiddleware<ExceptionHandlerMiddleware>(Options.Create(options));} }

通過UseExceptionHandler擴展方法我們可以知道這么多擴展方法其實本質都是在構建ExceptionHandlerOptions我們來看一下大致實現

public class ExceptionHandlerOptions {/// <summary>/// 指定處理異常的終結點路徑/// </summary>public PathString ExceptionHandlingPath { get; set; }/// <summary>/// 指定處理異常的終結點委托/// </summary>public RequestDelegate ExceptionHandler { get; set; } }

這個類非常簡單,要么指定處理異常信息的具體終結點路徑,要么自定義終結點委托處理異常信息。通過上面的使用示例可以很清楚的看到這一點,接下來我們查看一下ExceptionHandlerMiddleware中間件的大致實現

public class ExceptionHandlerMiddleware {private readonly RequestDelegate _next;private readonly ExceptionHandlerOptions _options;private readonly ILogger _logger;private readonly Func<object, Task> _clearCacheHeadersDelegate;private readonly DiagnosticListener _diagnosticListener;public ExceptionHandlerMiddleware(RequestDelegate next,ILoggerFactory loggerFactory,IOptions<ExceptionHandlerOptions> options,DiagnosticListener diagnosticListener){_next = next;_options = options.Value;_logger = loggerFactory.CreateLogger<ExceptionHandlerMiddleware>();_clearCacheHeadersDelegate = ClearCacheHeaders;_diagnosticListener = diagnosticListener;//ExceptionHandler和ExceptionHandlingPath不同同時不存在if (_options.ExceptionHandler == null){if (_options.ExceptionHandlingPath == null){throw new InvalidOperationException(Resources.ExceptionHandlerOptions_NotConfiguredCorrectly);}else{_options.ExceptionHandler = _next;}}}public Task Invoke(HttpContext context){ExceptionDispatchInfo edi;try{var task = _next(context);//task未完成情況if (!task.IsCompletedSuccessfully){return Awaited(this, context, task);}return Task.CompletedTask;}catch (Exception exception){edi = ExceptionDispatchInfo.Capture(exception);}return HandleException(context, edi);//處理未完成taskstatic async Task Awaited(ExceptionHandlerMiddleware middleware, HttpContext context, Task task){ExceptionDispatchInfo edi = null;try{//等待完成await task;}catch (Exception exception){//收集異常信息edi = ExceptionDispatchInfo.Capture(exception);}if (edi != null){await middleware.HandleException(context, edi);}}} }

通過這段處理我們可以看出所有的異常處理都指向當前類的HandleException方法

private async Task HandleException(HttpContext context, ExceptionDispatchInfo edi) {_logger.UnhandledException(edi.SourceException);// 如果輸出已經開始執行了,后續的代碼就沒必要執行了,直接重新拋出if (context.Response.HasStarted){_logger.ResponseStartedErrorHandler();edi.Throw();}PathString originalPath = context.Request.Path;//如果指定處理異常的終結點,將異常處理交給指定的終結點去處理if (_options.ExceptionHandlingPath.HasValue){//將處理路徑指向,異常處理終結點路徑context.Request.Path = _options.ExceptionHandlingPath;}try{//清除原有HTTP上下文信息,為了明確指定程序出現異常,防止異常未被處理而后續當做正常操作執行ClearHttpContext(context);//將異常信息包裝成ExceptionHandlerFeature,后續處理程序獲取異常信息都是通過ExceptionHandlerFeaturevar exceptionHandlerFeature = new ExceptionHandlerFeature(){//異常信息Error = edi.SourceException,//原始路徑Path = originalPath.Value,};//將包裝的ExceptionHandlerFeature放入到上下文中,后續處理程序可通過HttpContext獲取異常信息context.Features.Set<IExceptionHandlerFeature>(exceptionHandlerFeature);context.Features.Set<IExceptionHandlerPathFeature>(exceptionHandlerFeature);//設置狀態碼context.Response.StatusCode = 500;context.Response.OnStarting(_clearCacheHeadersDelegate, context.Response);//調用給定的異常處理終結點處理異常信息await _options.ExceptionHandler(context);//同樣也可以發送診斷日志,可以利用處理程序返回輸出,診斷日志記錄異常將職責分離if (_diagnosticListener.IsEnabled() && _diagnosticListener.IsEnabled("Microsoft.AspNetCore.Diagnostics.HandledException")){_diagnosticListener.Write("Microsoft.AspNetCore.Diagnostics.HandledException", new { httpContext = context, exception = edi.SourceException });}return;}catch (Exception ex2){_logger.ErrorHandlerException(ex2);}finally{//異常處理結束后,恢復原始的請求路徑,供后續執行程序能拿到原始的請求信息context.Request.Path = originalPath;}//如果異常沒被處理則重新拋出edi.Throw(); }

最后還有一段清除上下文和清除輸出緩存的方法,因為程序一旦發生了異常,可能創建了新的終結點,所以執行管道會有所調整,所以需要重新計算。而且異常信息保留輸出緩存是沒有意義的。

private static void ClearHttpContext(HttpContext context) {context.Response.Clear();//因為可能創建了新的終結點,所以執行管道會有所調整,所以需要重新計算context.SetEndpoint(endpoint: null);var routeValuesFeature = context.Features.Get<IRouteValuesFeature>();routeValuesFeature?.RouteValues?.Clear(); }private static Task ClearCacheHeaders(object state) {//清除輸出緩存相關var headers = ((HttpResponse)state).Headers;headers[HeaderNames.CacheControl] = "no-cache";headers[HeaderNames.Pragma] = "no-cache";headers[HeaderNames.Expires] = "-1";headers.Remove(HeaderNames.ETag);return Task.CompletedTask; }

從上面的代碼我們可以看出UseExceptionHandler要比UseDeveloperExceptionPage實現方式簡單很多。其大致思路就是捕獲后續管道執行異常,如果存在異常則將異常包裝成ExceptionHandlerFeature,放入到Http上下文中。之所以相對簡單主要原因還是UseExceptionHandler最終處理異常由我們自定義的終結點去處理,所以它只是負責包裝異常相關信息,并將它交于我們定義的異常處理終結點。

UseStatusCodePages

無論是UseDeveloperExceptionPage還是UseExceptionHandler都是通過捕獲異常的方式去處理異常信息,UseStatusCodePages則是通過Http狀態碼去判斷是否為成功的返回并進行處理,使用方式如下

app.UseStatusCodePages(); //或 app.UseStatusCodePages("text/plain;charset=utf-8", "狀態碼:{0}"); //或 app.UseStatusCodePages(async context => {context.HttpContext.Response.ContentType = "text/plain;charset=utf-8";await context.HttpContext.Response.WriteAsync($"狀態碼:{context.HttpContext.Response.StatusCode}"); }); //或 app.UseStatusCodePages(new StatusCodePagesOptions { HandleAsync = async context=> {context.HttpContext.Response.ContentType = "text/plain;charset=utf-8";await context.HttpContext.Response.WriteAsync($"狀態碼:{context.HttpContext.Response.StatusCode}"); }}); //或 app.UseStatusCodePages(configure => {configure.Run(async context =>{await context.Response.WriteAsync($"狀態碼:{context.Response.StatusCode}");}); });

接下來我們查看一下UseStatusCodePages擴展方法相關實現

public static IApplicationBuilder UseStatusCodePages(this IApplicationBuilder app, StatusCodePagesOptions options) {return app.UseMiddleware<StatusCodePagesMiddleware>(Options.Create(options)); }public static IApplicationBuilder UseStatusCodePages(this IApplicationBuilder app) {return app.UseMiddleware<StatusCodePagesMiddleware>(); }public static IApplicationBuilder UseStatusCodePages(this IApplicationBuilder app, Func<StatusCodeContext, Task> handler) {return app.UseStatusCodePages(new StatusCodePagesOptions{HandleAsync = handler}); }public static IApplicationBuilder UseStatusCodePages(this IApplicationBuilder app, string contentType, string bodyFormat) {return app.UseStatusCodePages(context =>{var body = string.Format(CultureInfo.InvariantCulture, bodyFormat, context.HttpContext.Response.StatusCode);context.HttpContext.Response.ContentType = contentType;return context.HttpContext.Response.WriteAsync(body);}); }

雖然擴展方法比較多,但是本質都是組裝StatusCodePagesOptions,所以我們直接查看源碼

public class StatusCodePagesOptions {public StatusCodePagesOptions(){//初始化HandleAsync = context =>{var statusCode = context.HttpContext.Response.StatusCode;var body = BuildResponseBody(statusCode);context.HttpContext.Response.ContentType = "text/plain";return context.HttpContext.Response.WriteAsync(body);};}private string BuildResponseBody(int httpStatusCode){//組裝默認消息模板var internetExplorerWorkaround = new string(' ', 500);var reasonPhrase = ReasonPhrases.GetReasonPhrase(httpStatusCode);return string.Format(CultureInfo.InvariantCulture, "Status Code: {0}{1}{2}{3}",httpStatusCode,string.IsNullOrWhiteSpace(reasonPhrase) ? "" : "; ",reasonPhrase,internetExplorerWorkaround);}public Func<StatusCodeContext, Task> HandleAsync { get; set; } }

看著代碼不少,其實都是嚇唬人的,就是給HandleAsync一個默認值,這個默認值里有默認的輸出模板。接下來我們查看一下StatusCodePagesMiddleware中間件源碼

public class StatusCodePagesMiddleware {private readonly RequestDelegate _next;private readonly StatusCodePagesOptions _options;public StatusCodePagesMiddleware(RequestDelegate next, IOptions<StatusCodePagesOptions> options){_next = next;_options = options.Value;}public async Task Invoke(HttpContext context){//初始化StatusCodePagesFeaturevar statusCodeFeature = new StatusCodePagesFeature();context.Features.Set<IStatusCodePagesFeature>(statusCodeFeature);await _next(context);if (!statusCodeFeature.Enabled){return;}//這個范圍外的Http狀態碼直接忽略,不受程序處理只處理值為400-600之間的狀態碼if (context.Response.HasStarted|| context.Response.StatusCode < 400|| context.Response.StatusCode >= 600|| context.Response.ContentLength.HasValue|| !string.IsNullOrEmpty(context.Response.ContentType)){return;}//將狀態信息包裝到StatusCodeContext,傳遞給自定義處理終結點var statusCodeContext = new StatusCodeContext(context, _options, _next);await _options.HandleAsync(statusCodeContext);} }

這個中間件的實現思路更為簡單,主要就是攔截請求判斷Http狀態碼,判斷是否是400-600,也就是4xx 5xx相關的狀態碼,如果符合則包裝成StatusCodeContext,交由自定義的終結點去處理。

總結

關于常用異常處理中間件我們介紹到這里就差不多了,接下來我們總結對比一下三種中間件的異同和大致實現的方式

  • UseDeveloperExceptionPage中間件主要工作方式就是捕獲后續中間件執行異常,如果存在異常則將異常信息包裝成ErrorPageModel視圖模型,然后通過這個模型去渲染開發者異常界面。

  • UseExceptionHandler中間件核心思路和UseDeveloperExceptionPage類似都是通過捕獲后續中間件執行異常,不同之處在于UseExceptionHandler將捕獲的異常信息包裝到ExceptionHandlerFeature然后將其放入Http上下文中,后續的異常處理終結點通過Http上下文獲取到異常信息進行處理。

  • UseStatusCodePages中間件相對于前兩種中間件最為簡單,其核心思路就是獲取執行完成后的Http狀態碼判斷是否是4xx 5xx相關,如果是則執行自定義的狀態碼攔截終結點。這個中間件核心是圍繞StatusCode其實并不包含處理異常相關的邏輯,所以整體實現相對簡單。

最后我們再來總結下使用中間件的方式和使用IExceptionFilter的方式的區別

  • 中間件的方式是對整個請求執行管道進行異常捕獲,主要是負責整個請求過程中的異常捕獲,其生命周期更靠前,捕獲異常的范圍更廣泛。畢竟MVC只是Asp.Net Core終結點的一種實現方式,目前Asp.Net Core還可以處理GRPC Signalr等其它類型的終結點信息。

  • IExceptionFilter主要是針對Action執行過程中的異常,畢竟終結點只是中間件的一種形式,所以可處理范圍比較有限,主要適用于MVC程序。對于其它終結點類型有點無能為力。

以上就是文章的全部內容,由于能力有限,如果存在理解不周之處請多多諒解。我覺得學習一個東西,如果你能了解到它的工作方式或者實現原理,肯定會對你的編程思路有所提升,看過的代碼用過的東西可能會忘,但是思路一旦形成,將會改變你以后的思維方式。

????歡迎掃碼關注我的公眾號????

總結

以上是生活随笔為你收集整理的深入探究ASP.NET Core异常处理中间件的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 影音先锋二区 | 91五月天 | 激情小说在线 | 刘亦菲毛片一区二区三区 | 日韩aⅴ在线观看 | 自拍欧美亚洲 | 少妇太爽了 | 91精品国产综合久久国产大片 | xxxxhd欧美 | 中文字幕在线观看亚洲 | 欧美性xxxxx极品娇小 | 第四色影音先锋 | 亚洲一区电影网 | 亚洲九九色 | 我会温柔一点的日剧 | 欧美一区二区免费在线观看 | 日本视频www色 | 人妻少妇精品一区二区三区 | 少妇69xx| 午夜影院污 | 四虎视频在线 | 中文字幕+乱码+中文 | 全部孕妇毛片 | 婷婷激情图片 | 91久久精品无码一区二区 | 村上凉子av| 91在线免费观看网站 | 欧美射射射 | 中文字幕一区二区三区夫目前犯 | www.香蕉.com | 欧美一区二区视频免费观看 | 国产一区二区在线电影 | 亚洲av无码国产精品久久 | 免费毛片小视频 | 亚洲最大免费视频 | www.狠狠插 | 一区二区伦理 | 日韩久久成人 | 精品在线播放 | 欧美整片第一页 | 欧美性猛交乱大交3 | 欧美日韩国产图片 | 日本高清不卡在线观看 | 99riAv国产精品无码鲁大师 | 国产精品久久久久一区二区三区 | 久久久久久一 | 国产精品第 | 亚洲男人网 | 金瓶狂野欧美性猛交xxxx | 精品一区二区久久久久久按摩 | 亚洲无吗在线 | 国产福利免费在线观看 | 在线观看黄色免费视频 | 国产又粗又猛又爽视频 | 激情小视频在线观看 | 国产精品免费看片 | 欧美com| 97超碰资源总站 | 国产精品男人的天堂 | 超碰五月天 | 波多野结衣激情视频 | 免费无码肉片在线观看 | 色狠狠一区二区三区香蕉 | 少妇高潮av久久久久久 | 欧美在线日韩在线 | 强开乳罩摸双乳吃奶羞羞www | 国产精品99久久久久久久久 | 黄色aaa毛片| 香蕉久久网站 | 男人天堂网在线观看 | 国产女人呻吟高潮抽搐声 | 6080午夜伦理 | 午夜性福利 | 国产精品视频一二区 | 午夜99| 爱如潮水3免费观看日本高清 | 黄色小视频大全 | 美女裸片| 黄色理论片| 国产白丝喷水 | 国产一级18片视频 | 女人性高潮视频 | 免费看黄色片网站 | 少妇高潮灌满白浆毛片免费看 | 伦一理一级一a一片 | 天天躁日日躁狠狠躁免费麻豆 | 一区二区高清 | 国产毛片久久久久久久 | 精品人妻一区二区三区四区五区 | 69亚洲精品久久久蜜桃小说 | 西西人体高清44rt·net | 男女激情视频网站 | 久久不雅视频 | 日韩三级一区二区三区 | 69av在线 | 伊人色综合久久天天 | 日韩一级欧美一级 | 最近最好的2019中文 | 亚洲乱轮 |