引用
TODO
- 正則匹配錯誤碼,可能會因為系統語言導致不通用,考慮換成提供默認的正則匹配,另外加一個委托參數傳進來
中間件代碼
/// <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. 包含了當前中間件名字的錯誤信息
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);
}
}
}
/// <summary>
/// 添加拓展方法
/// </summary>
public static class MyGlobalExceptionMiddlewareExtensions
{
public static IApplicationBuilder UseMyGlobalExceptionMiddleware(this IApplicationBuilder app)
{
return app.UseMiddleware<MyGlobalExceptionMiddleware>();
}
}
注冊中間件
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
// 注冊自定義異常中間件(也可以使用 app.UseMiddleware<MyGlobalExceptionMiddleware>();)
app.UseMyGlobalExceptionMiddleware();
// 省略的其他項
}
控制器代碼
[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"
}
]
}