AspNet Core 中的全局处理
IExceptionFilter
在 Asp.Net Core 中我们可以使用 IExceptionFilter 过滤器来捕获 AspNet Core 中控制器产生的错误,它也提供更推荐使用的异步版本 IAsyncExceptionFilter。
首先我们创建一个 Asp.Net Core MVC Web 应用程序,新建 MyExceptionFilter 类,使其实现 IAsyncExceptionFilter 接口。
1public class MyExceptionFilter : IAsyncExceptionFilter2{3 public Task OnExceptionAsync(ExceptionContext context)4 {5 if (context.ExceptionHandled == false)6 {7 string msg = context.Exception.Message;8 context.Result = new ContentResult9 {10 Content = msg,11 StatusCode = StatusCodes.Status200OK,12 ContentType = "text/html;charset=utf-8"13 };14 }15 context.ExceptionHandled = true; //异常已处理了4 collapsed lines
16
17 return Task.CompletedTask;18 }19}在 startup.cs 类中修改 services 类
1services.AddControllersWithViews(options => options.Filters.Add(new MyExceptionFilter()));添加 MyExceptionController 控制器
1public class MyExceptionController : Controller2{3 [HttpGet]4 public IActionResult GetException()5 {6 throw new Exception("手动抛出异常");7 }8}我们访问 /MyException/GetException 页面输出
1Exception: 手动抛出异常这样我们就能捕获到控制器抛出的异常然后将之更改为我们想要的功能,比如让其返回一个 Status Code 为 200 的页面。
中间件处理异常
AspNet Core 使用管道机制,管道的特点就是层层传递,这样我们可以在管道中捕获全局异常。
添加 MyExceptionMiddleware 管道类
1public class MyExceptionMiddleware2{3 private readonly RequestDelegate _next;4 public MyExceptionMiddleware(RequestDelegate next)5 {6 _next = next;7 }8 public async Task Invoke(HttpContext httpContext)9 {10 try11 {12 await _next(httpContext);13 }14 catch (Exception ex)15 {18 collapsed lines
16 httpContext.Response.ContentType = "application/problem+json";17
18 var title = "异常: " + ex.Message;19 var details = ex.ToString();20
21 var problem = new ProblemDetails22 {23 Status = 200,24 Title = title,25 Detail = details26 };27
28 var stream = httpContext.Response.Body;29 var options = new JsonSerializerOptions { Encoder = JavaScriptEncoder.Create(UnicodeRanges.All) };30 await JsonSerializer.SerializeAsync(stream, problem, options);31 }32 }33}在 startup.cs 类中添加管道,如果你想捕获其他管道中的异常那就放在最前面,如果只想捕获控制器异常则放在最后,当然也可放在你认为合适的位置。
1app.UseMiddleware<MyExceptionMiddleware>();运行有输出
1"title":"异常: 手动抛出异常"注:项目默认会有一个给我们处理异常的中间件
在开发环境和生产环境分别对应,一个会输出详细的错误信息,供调试使用,另一个则跳转到错误页面。如果要使用自己的,可将这两个去除或者在其上进行配置拓展。
1app.UseDeveloperExceptionPage();2
3app.UseExceptionHandler("/Home/Error");UseExceptionHandler 中间件
我们重新配置此中间件
1app.UseExceptionHandler(appbuilder => appbuilder.Use(ExceptionHandlerDemo));1private async Task ExceptionHandlerDemo(HttpContext httpContext, Func<Task> next)2{3 //该信息由ExceptionHandlerMiddleware中间件提供,里面包含了ExceptionHandlerMiddleware中间件捕获到的异常信息。4 var exceptionDetails = httpContext.Features.Get<IExceptionHandlerFeature>();5 var ex = exceptionDetails?.Error;6
7 if (ex != null)8 {9 httpContext.Response.ContentType = "application/problem+json";10
11 var title = "An error occured: " + ex.Message;12 var details = ex.ToString();13
14 var problem = new ProblemDetails15 {10 collapsed lines
16 Status = 500,17 Title = title,18 Detail = details19 };20
21 var stream = httpContext.Response.Body;22 var options = new JsonSerializerOptions { Encoder = JavaScriptEncoder.Create(UnicodeRanges.All) };23 await JsonSerializer.SerializeAsync(stream, problem, options);24 }25}输出
1"title":"异常: 手动抛出异常"本文章抄袭自: