【NetCore】新增自定義全域性異常攔截
阿新 • • 發佈:2021-10-07
引用
中介軟體程式碼
/// <summary> /// 全域性異常攔截中介軟體 /// </summary> public class MyGlobalExceptionMiddleware { private readonly RequestDelegate _next; /// <summary> /// 注入下一個中介軟體 /// </summary> public MyGlobalExceptionMiddleware(RequestDelegate next) { _next = next; } public async Task Invoke(HttpContext httpContext) { try { // 等待下一個中介軟體執行完成 await _next(httpContext); } // 異常時統一處理 catch (Exception ex) { httpContext.Response.ContentType = "application/problem+json"; ProblemDetails problem = new ProblemDetails { Status = 500, Title = "Exception: " + ex.Message }; problem.Extensions.Add("message", ex.Message); if (!string.IsNullOrWhiteSpace(ex.StackTrace)) { // 自定義正則:匹配 at [方法名] in [檔案路徑]:line [行號] var matches = Regex.Matches(ex.StackTrace, "at[ ](.+?)[ ]in[ ](.+?)[:]line[ ]([0-9]+)"); // 使用Linq的拓展方法,篩選出需要的資料 // 過濾掉: // 1. 包含了當前中介軟體相關的異常 // 2. TODO:可以過濾掉ASPNetCore相關的異常。 var filterdMatches = matches.Where(t => !t.Groups[0].ToString().Contains("Middlewares.MyGlobalExceptionMiddleware")); // 投影新的物件列表,方便呼叫者閱讀和使用 var extendExObject = filterdMatches.Select(x => new { method = x.Groups[1].ToString(), file = x.Groups[2].ToString(), line = x.Groups[3].ToString() }); // 往problem物件新增一個拓展屬性detail problem.Extensions.Add("detail", extendExObject); } // 暫時不清楚具體幹了什麼,表現上是把problem物件格式化到HTML文字中。 var stream = httpContext.Response.Body; await JsonSerializer.SerializeAsync(stream, problem); } } }
註冊中介軟體
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline. public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { // 註冊異常中介軟體(除此之外,全是.Net5 Api模板自動生成的程式碼) app.UseMiddleware<MyGlobalExceptionMiddleware>(); // 感覺沒必要使用異常頁面,所以註釋了UseDeveloperExceptionPage if (env.IsDevelopment()) { //app.UseDeveloperExceptionPage(); app.UseSwagger(); app.UseSwaggerUI(c => c.SwaggerEndpoint("/swagger/v1/swagger.json", "AbpTest1 v1")); } app.UseRouting(); app.UseAuthorization(); app.UseEndpoints(endpoints => { endpoints.MapControllers(); }); }
控制器程式碼
[ApiController]
[Route("api/filter")]
public class TestFilterController:ControllerBase
{
[HttpGet]
public string TestFilterXXX()
{
throw new NotImplementedException();
return "asdf";
}
}
Api呼叫結果
{ "title": "Exception: The method or operation is not implemented.", "status": 500, "message": "The method or operation is not implemented.", "detail": [ { "method": "AbpTest1.Controllers.TestFilterController.TestFilterXXX()", "file": "C:\\Users\\Administrator\\source\\repos\\AbpTest1\\AbpTest1\\Controllers\\TestFilterController.cs", "line": "14" } ] }