【C#/.NET】.NET6中全局异常处理
微信公眾號:趣編程ACE
關(guān)注可了解每日一更的.NET日常實戰(zhàn)開發(fā)技巧,歡迎公眾號留言開發(fā) 獲取源碼;
.NET6中全局異常處理
異常處理是我們在程序開發(fā)中不可或缺的一環(huán),下文我將會結(jié)合程序Sample講解如何在.NET6中有效處理異常。
Try-Ctach 塊包裹
自定義異常中間件
Try-Catch 塊
Try-Catch 是最基本的異常處理方法,下面我們看下例子。
創(chuàng)建一個基于.net6的Asp.Net Core Web Api項目
我們在VsCode里面按照一個Postman插件PostCode 調(diào)用上面接口https://localhost:7218/api/User
通過結(jié)果可知,當(dāng)我們沒有獲取到用戶的時候,代碼將會拋出一個Get User failed的異常(見上圖)。對于初學(xué)者來說,這是最常見最基礎(chǔ)的方法,但是這個方法對于大項目來說也有一個缺點。
如果項目中有許多控制器和動作方法,然后我們需要對每一個動作方法都使用try-catch,那么在這種情況下,用try-catch就很累贅,也會增加代碼行數(shù)。此時就需要自定義一個處理全局異常的中間件啦!
使用這個方法的好處就是我們可以在一個地方捕獲未處理的異常,而不需要在每個動作方法中使用try-catch。
自定義中間件處理異常
在根目錄下創(chuàng)建一個Middlewares文件夾,新建一個名為ExceptionHandlingMiddleware.cs類
1using?System.Net;2using?System.Text.Json;3using?ExceptionHandling.Models.Responses;45namespace?ExceptionHandling.Middlewares;67public?class?ExceptionHandlingMiddleware8{9????private?readonly?RequestDelegate?_next;??//?用來處理上下文請求?? 10????private?readonly?ILogger<ExceptionHandlingMiddleware>?_logger; 11????public?ExceptionHandlingMiddleware(RequestDelegate?next,?ILogger<ExceptionHandlingMiddleware>?logger) 12????{ 13????????_next?=?next; 14????????_logger?=?logger; 15????} 16 17????public?async?Task?InvokeAsync(HttpContext?httpContext) 18????{ 19????????try 20????????{ 21????????????await?_next(httpContext);?//要么在中間件中處理,要么被傳遞到下一個中間件中去 22????????} 23????????catch?(Exception?ex) 24????????{ 25????????????await?HandleExceptionAsync(httpContext,?ex);?//?捕獲異常了?在HandleExceptionAsync中處理 26????????} 27????} 28????private?async?Task?HandleExceptionAsync(HttpContext?context,?Exception?exception) 29????{ 30????????context.Response.ContentType?=?"application/json";??//?返回json?類型 31????????var?response?=?context.Response; 32 33????????var?errorResponse?=?new?ErrorResponse 34????????{ 35????????????Success?=?false 36????????};??//?自定義的異常錯誤信息類型 37????????switch?(exception) 38????????{ 39????????????case?ApplicationException?ex: 40????????????????if?(ex.Message.Contains("Invalid?token")) 41????????????????{ 42????????????????????response.StatusCode?=?(int)?HttpStatusCode.Forbidden; 43????????????????????errorResponse.Message?=?ex.Message; 44????????????????????break; 45????????????????} 46????????????????response.StatusCode?=?(int)?HttpStatusCode.BadRequest; 47????????????????errorResponse.Message?=?ex.Message; 48????????????????break; 49????????????case?KeyNotFoundException?ex: 50????????????????response.StatusCode?=?(int)?HttpStatusCode.NotFound; 51????????????????errorResponse.Message?=?ex.Message; 52????????????????break; 53????????????default: 54????????????????response.StatusCode?=?(int)?HttpStatusCode.InternalServerError; 55????????????????errorResponse.Message?=?"Internal?Server?errors.?Check?Logs!"; 56????????????????break; 57????????} 58????????_logger.LogError(exception.Message); 59????????var?result?=?JsonSerializer.Serialize(errorResponse); 60????????await?context.Response.WriteAsync(result); 61????} 62}這就是我們自定義的中間件,在ExceptionHandlingMiddleware中,我們首先通過依賴注入ILogger和RequestDelegate服務(wù)。委托類型_next用來處理上下文請求,要么將上下文放在中間件中處理,要么傳遞到下個中間鏈里的下一個中間件中去。
如果我們的請求發(fā)生異常,那么就會執(zhí)行HandleExceptionAsync這個方法。這個方法里面會根據(jù)異常類型來返回不同的狀態(tài)碼并且記錄到日志中去,不需要返回給調(diào)用的客戶端,然后我們就可以通過檢查日志來發(fā)現(xiàn)異常信息。
我們在Program.cs中添加自定義異常
1?app.UseMiddleware<ExceptionHandlingMiddleware>();接著我們修改下控制器里GetUsers()這個方法,去掉try-catch,直接拋出異常
1[HttpGet]2????public?IActionResult?GetUsers()3????{45??????_logger.LogInformation("Get?User?Details");67???????????var?result?=?_userService.GetUsers();8???????????if(result.Count==0)9????????????throw?new?KeyNotFoundException("Get?User?failed");?//?此處拋出一個KeyNotFoundException異常 10 11???????????return?Ok(result); 12????}通過調(diào)試我們可以發(fā)現(xiàn),當(dāng)發(fā)生異常的時候,程序?qū)?zhí)行到HandleExceptionAsync()方法中去,接著根據(jù)類型KeyNotFoundException 返回404的狀態(tài)碼和異常信息。
如需理解中間件管道執(zhí)行過程可參考上篇文章:【C#/.NET】控制臺上動態(tài)構(gòu)建中間件管道
總結(jié)
以上是生活随笔為你收集整理的【C#/.NET】.NET6中全局异常处理的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: C#不要再使用Npoi啦,使用MiniE
- 下一篇: 如何保证执行异步方法时不会遗漏 awai