Part4 – (38) ExceptionFilter 异常筛选器
什么是Filter
1、切面编程机制,在ASP.NET Core特定的位置执行我们自定义的代码。
- 例如记录日志,检查用户权限,尽量不影响业务逻辑代码。
2、ASP.NET Core中的Filter的五种类型:Authorization filter、Resource filter、Action filter、Exception filter、Result filter。这里重点讲解Exception filter和Action filter。
3、所有筛选器一般有同步和异步两个版本,比如IActionFilter、IAsyncActionFilter接口。
Exception Filter
1、当系统中出现未经处理的异常的时候,异常筛选器就会执行。
实现
1、当系统中出现未处理异常的时候,我们需要统一给客户端返回如下格式的响应报文:{“code”:”500”,”message”:”异常信息”}。
对于开发环境中message是异常堆栈,对于其他环境message用一个general的报错信息。
2、实现IAsyncExceptionFilter接口。注入IHostEnvironment 得知运行环境。
这里我们一共设计两个异常捕获,一个处理结果,另一个记录日志,如下:
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;
namespace Part4_38
{
public class MyExceptionFilter : IAsyncExceptionFilter
{
private readonly IWebHostEnvironment hostEnv;
public MyExceptionFilter(IWebHostEnvironment hostEnv)
{
this.hostEnv = hostEnv;
}
public Task OnExceptionAsync(ExceptionContext context)
{
//context.Exception 代表异常信息对象
//context.ExceptionHandled = true; //如果赋值为true 则其他ExceptionFilter不会执行
//context.Result 的值会被输出给客户端
string message = string.Empty;
if (hostEnv.IsDevelopment())
{
message = context.Exception.ToString();
}
else
{
message = "服务器发生未处理异常";
}
ObjectResult result = new ObjectResult(new { code = 500, message = message });
result.StatusCode = 500;
context.Result = result;
context.ExceptionHandled = true;//执行到这,其他异常捕获就不会执行了
return Task.CompletedTask;
}
}
}
using Microsoft.AspNetCore.Mvc.Filters;
namespace Part4_38
{
public class LogExceptionFilter : IAsyncExceptionFilter
{
public Task OnExceptionAsync(ExceptionContext context)
{
return File.AppendAllTextAsync("f:/error.log", context.Exception.ToString());
}
}
}
然后在Program.cs中注入这两个异常捕获,要注意这个注入的顺序会影响执行顺序,先注入的会后执行:
builder.Services.Configure<MvcOptions>(options =>
{
options.Filters.Add<MyExceptionFilter>();
options.Filters.Add<LogExceptionFilter>();
});
Part4 – (38) ActionFilter Action筛选器
Action Filter
1、IAsyncActionFilter接口
2、多个Action Filter的链式执行。(一个ActionFilter中包含前代码和后代码,在执行方法的前后都可以执行一些逻辑)
有两个ActionFilter 来进行编排,代码如下:
using Microsoft.AspNetCore.Mvc.Filters;
namespace Part4_38
{
public class MyActionFilter1 : IAsyncActionFilter
{
public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)
{
//next 指向下一个筛选器 如果没有下一个筛选器 那么执行真正的Action方法
Console.WriteLine("MyActionFilter 1:开始执行");
ActionExecutedContext result = await next(); // next之前的是
if (result.Exception != null)
{
Console.WriteLine("MyActionFilter 1:执行失败");
}
else
{
Console.WriteLine("MyActionFilter 1:执行成功");
}
}
}
}
using Microsoft.AspNetCore.Mvc.Filters;
namespace Part4_38
{
public class MyActionFilter2 : IAsyncActionFilter
{
public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)
{
Console.WriteLine("MyActionFilter 2:开始执行");
ActionExecutedContext result = await next();
if (result.Exception != null)
{
Console.WriteLine("MyActionFilter 2:执行失败");
}
else
{
Console.WriteLine("MyActionFilter 2:执行成功");
}
}
}
}
builder.Services.Configure<MvcOptions>(opt => {
opt.Filters.Add<MyActionFilter1>();
opt.Filters.Add<MyActionFilter2>();
});
这样的话,就可以按照注入的顺序来执行:Action1前–> Action2前 –> Action2后 –> Action1后
注意:同步和异步的Action都可以被ActionFilter拦截。
本文版权归个人技术分享站点所有,发布者:chaoqiang,转转请注明出处:https://www.zhengchaoqiang.com/1534.html