ASP.Net Core的Filter


一、什么是Filter?

  • 切面编程机制,在ASP.Net Core特定的位置执行我们的自定义代码

  • ASP.NET Core中有Filter的五种类型:

    • Authorization filter(权限验证)
    • Resource filter(资源缓存)
    • Action filter(模型验证/日志记录)
    • Exception filter(异常捕获)
    • Result filter(处理返回结果)
  • 所有筛选器一般有两个版本,比如IActionFilterIAsyncActionFilter


二、Exception filter

当系统中出现未经处理的异常的时候,异常筛选器就会执行

  1. 新建一个API控制器TestController

  2. 在控制器中编写一个会抛异常的方法,代码如下:

    [HttpGet]
    public string Test1()
    {
    	string s = System.IO.File.ReadAllText("D:1.txt");
    	return s;
    }
    
  3. 调用方法Test1后,会出现以下界面
    出现未处理异常

  4. 当系统中出现未处理异常的时候,假设我们需要统一返回给客户端一个如下格式的响应报文:{"code":"500","message":"异常信息"},可以通过一个实现了IAsyncExceptionFilter接口的类来实现,类的代码如下:

    public class MyExceptionFilter : IAsyncExceptionFilter
    {
        private readonly IWebHostEnvironment webHost;
    
        public MyExceptionFilter(IWebHostEnvironment webHost)
        {
            this.webHost = webHost;
        }
    
        public Task OnExceptionAsync(ExceptionContext context)
        {
            string message;
            if (webHost.IsDevelopment())
            {
                message = context.Exception.ToString(); //context.Exception 代表异常信息对象
            }
            else
            {
                message = "服务器端发生未处理异常!";
            }
    
            ObjectResult objectResult = new ObjectResult(new { code = 500, message = message });
            context.Result = objectResult;  //context.Result的值会被输入给客户端
            context.ExceptionHandled = true;    //如果赋值为True,则其他的ExceptionFilter不会再执行
            return Task.CompletedTask;
        }
    }
    
  5. 全局注册

    builder.Services.Configure<MvcOptions>(opt =>
    {
        opt.Filters.Add<MyExceptionFilter>();
    });
    
  6. 调用方法Test1后,会出现以下界面:

    在这里插入图片描述

三、Action filter

  1. 实现IAsyncActionFilter接口

  2. 多个Action Filter的链式执行,执行顺序如下:
    Filter执行顺序

  3. 在TestController中插入以下代码:

    [HttpGet]
    public string Test1()
    {
        Console.WriteLine("开始执行 Test1");
        string s = System.IO.File.ReadAllText("D:1.txt");
        return s;
    }
    
    [HttpGet]
    public DateTime GetDateTime()
    {
        Console.WriteLine("开始执行 GetDateTime");
        return DateTime.Now;
    }
    
  4. 新建一个实现了IAsyncActionFilter接口的类MyActionFilter

    public class MyActionFilter : IAsyncActionFilter
    {
        public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)
        {
            Console.WriteLine("MyActionFilter 开始执行..."); //在Action之前执行
            ActionExecutedContext result = await next(); 
            
    		//在Action之后执行
            if(result.Exception == null)
            {
                Console.WriteLine("MyActionFilter 执行成功了!");
            }
            else
            {
                Console.WriteLine("MyActionFilter 发生异常了!");
            }
        }
    }
    
  5. 分别调用两个方法可以看到控制台中显示以下内容:
    -

四、实现一个自动启用事务的Action Filter

  1. 创建一个类NotTransactionAttribute ,继承自Attribute,且只能标注到方法上

    [AttributeUsage(AttributeTargets.Method)]
    public class NotTransactionAttribute : Attribute
    {
    }
    
  2. 创建一个类TransactionScopeFilter,实现了IAsyncActionFilter接口

    public class TransactionScopeFilter : IAsyncActionFilter
    {
        public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)
        {
            //context.ActionDescriptor  当前被执行的Action方法的描述信息
            ControllerActionDescriptor? controllerActionDescriptor = context.ActionDescriptor as ControllerActionDescriptor;
    
            bool isTx = false; //是否进行事务控制
            if (controllerActionDescriptor != null)
            {
                //查找当前Action方法的Attribute,是否标记了NotTransactionAttribute
                //如果标记了NotTransactionAttribute,则返回True,就不进行事务控制
                bool hasNotTransactionAttribute = controllerActionDescriptor.MethodInfo.GetCustomAttributes(typeof(NotTransactionAttribute), false).Any();
                isTx = !hasNotTransactionAttribute;
            }
    
            if (isTx)
            {
                using (TransactionScope ts = new TransactionScope(TransactionScopeAsyncFlowOption.Enabled))
                {
                    var r = await next();
                    if (r.Exception == null)
                    {
                        ts.Complete();
                    }
                }
            }
            else
            {
                await next();
            }
        }
    }
    
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值