当前位置: 首页 > article >正文

.NET Core中的五种过滤器详解

目录

      • 过滤器概述
      • 1. 授权过滤器(Authorization Filters)
      • 2. 资源过滤器(Resource Filters)
      • 3. 动作过滤器(Action Filters)
      • 4. 异常过滤器(Exception Filters)
      • 5. 结果过滤器(Result Filters)
      • 6过滤器的使用方式
      • 7 测试过滤器执行
      • 8 过滤器中注入服务
      • 9 .NET Core中间件和过滤器的异同

过滤器概述

在 .NET Core 中,过滤器(Filters)和面向切面编程(AOP)有着紧密的联系,过滤器可以看作是 AOP 在 .NET Core 框架中的一种具体实现方式。
在.NET Core中过滤器是一种特殊的组件,它能够在请求处理管道的特定阶段执行自定义逻辑。借助过滤器,你可以把横切关注点(像日志记录、权限验证、异常处理等)从业务逻辑中分离出来,从而提升代码的可维护性与可复用性。

1. 授权过滤器(Authorization Filters)

作用:用于验证用户是否有权限访问某个资源,在请求进入控制器之前执行。若验证不通过,会阻止请求继续执行。

示例代码:

using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;

public class CtsAuthorizationAttribute : Attribute, IAuthorizationFilter
    {
        // 鉴权
        public void OnAuthorization(AuthorizationFilterContext context)
        {
            // 在进入控制器构造方法前执行,
            Console.WriteLine(" Authorization ========= OnAuthorization");
        }
    }

2. 资源过滤器(Resource Filters)

作用:在授权之后、模型绑定之前执行,主要用于缓存和资源管理

示例代码:

using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;

    /// <summary>
    /// 自定义资源验证过滤器
    /// </summary>
    public class CtsResourceFilterAttribute : Attribute, IResourceFilter
    {
        // 资源验证之后
        public void OnResourceExecuted(ResourceExecutedContext context)
        {
            Console.WriteLine("ResourceFilter=============OnResourceExecuted");

        }

        // 资源验证之前
        public void OnResourceExecuting(ResourceExecutingContext context)
        {
            // 当context的Result 不等于空时, 被短路,不再会像下执行业务逻辑
            // 节省资源的开销
            // 通常利用该性质 做数据的缓存处理,[直接在进入控制器的方法前就获得了返回数据]
            Console.WriteLine("ResourceFilter=============OnResourceExecuting");

        }
    }

3. 动作过滤器(Action Filters)

作用:在控制器方法执行前后执行,可用于日志记录、参数验证等。

示例代码:

using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;

    /// <summary>
    /// 自定义动作验证过滤器
    /// </summary>
    public class CtsActionFilterAttribute : Attribute, IActionFilter
    {
        // 进入方法后
        public void OnActionExecuted(ActionExecutedContext context)
        {
            Console.WriteLine(" ActionFilter ========= OnActionExecuted");
        }

        // 进入方法前
        public void OnActionExecuting(ActionExecutingContext context)
        {
            Console.WriteLine("ActionFilter ========= OnActionExecuting");
        }
    }

4. 异常过滤器(Exception Filters)

作用:在发生异常时执行,用于统一处理异常,避免异常信息直接暴露给客户端。

示例代码:

using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;

    /// <summary>
    /// 自定义异常过滤器
    /// </summary>
    public class CtsExceptionFilterAttribute : Attribute, IExceptionFilter
    {
        // 捕获异常处理[该异常只能捕获目标方法前后及过滤器本身抛出的异常[作用范围较小]
        // 异常中间件的放置的位置较为前面,能够捕获请求生命周期件发生的所有异常信息[作用范围大]
        public void OnException(ExceptionContext context)
        {

            // 异常处理逻辑
            System.Console.WriteLine($"An exception occurred: {context.Exception.Message}");
            context.Result = new JsonResult("Error"); // 过滤器可以通过设置 context.Result 属性来实现短路

        }
    }

5. 结果过滤器(Result Filters)

作用:在动作结果执行前后执行,用于对动作结果进行格式化、加密等处理。

示例代码:

using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;

    /// <summary>
    /// 自定义结果过滤器
    /// 仅仅当操作过滤器生成操作结果时,才会执行结果过滤器.不会授权过滤器或者资源过滤器或者异常过滤器短路[Result有值]时
    /// </summary>
    public class CtsResultFilterAttribute : Attribute, IResultFilter
    {
        /// <summary>
        /// 结果赋值后,此时获得目标方法的响应结果数据
        /// </summary>
        /// <param name="context"></param>
        public void OnResultExecuted(ResultExecutedContext context)
        {
            Console.WriteLine(" ResultFilter ========= OnResultExecuted");

        }

        /// <summary>
        /// 结果赋值前
        /// </summary>
        /// <param name="context"></param>
        public void OnResultExecuting(ResultExecutingContext context)
        {
            Console.WriteLine(" ResultFilter ========= OnResultExecuting");

        }
    }

6过滤器的使用方式

全局过滤器:在 Startup.cs(.NET 5 及以下版本)或者 Program.cs(.NET 6 及以上版本)中进行全局注册,会对所有的控制器和动作方法生效。

// .NET 6 及以上版本的 Program.cs
var builder = WebApplication.CreateBuilder(args);

// 注册全局过滤器
builder.Services.AddControllers(options =>
{
   // 这里全局注册自定义的方法过滤器
    options.Filters.Add(typeof(CtsActionFilterAttribute));
});

var app = builder.Build();
app.MapControllers();
app.Run();

控制器级别过滤器:在控制器类上应用过滤器,会对该控制器中的所有动作方法生效。

[CtsActionFilter]
public class MyController : Controller
{
    // 控制器方法
}

动作方法级别过滤器:在具体的动作方法上应用过滤器,仅对该动作方法生效。

public class MyController : Controller
{
    [CtsActionFilter]
    public IActionResult MyAction()
    {
        return Ok();
    }
}

一般来说,在同级别的过滤器下,过滤器的执行顺序是从全局到控制器再到方法

7 测试过滤器执行

在目标方法上添加上述五种过滤器, 通过 /WeatherForecast 路径去请求Get方法

   [ApiController]
    [Route("[controller]")]
    public class WeatherForecastController : ControllerBase
    {
        private static readonly string[] Summaries = new[]
        {
            "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
        };

        private readonly ILogger<WeatherForecastController> _logger;

        public WeatherForecastController(ILogger<WeatherForecastController> logger)
        {
            Console.WriteLine("Into  WeatherForecastController Constructor Function");
            _logger = logger;
        }


        [CtsResourceFilter]
        [CtsAuthorization]
        [CtsActionFilter]
        [CtsExceptionFilter]
        [CtsResultFilter]
        [HttpGet]
        public IEnumerable<WeatherForecast> Get()
        {
            var rng = new Random();
            return Enumerable.Range(1, 5).Select(index => new WeatherForecast
            {
                Date = DateTime.Now.AddDays(index),
                TemperatureC = rng.Next(-20, 55),
                Summary = Summaries[rng.Next(Summaries.Length)]
            })
            .ToArray();
        }
    }

测试结果如下
在这里插入图片描述

. 过滤器的执行存在着一定的先后顺序通常是:授权过滤器 -> 资源过滤器(执行前) -> 动作过滤器(执行前) -> 控制器方法 -> 动作过滤器(执行后) -> 结果过滤器(执行前) -> 动作结果执行 -> 结果过滤器(执行后) -> 资源过滤器(执行后)。若在任何阶段发生异常,异常过滤器会被触发。
在这里插入图片描述

8 过滤器中注入服务

在 .NET Core 中,在过滤器中注入服务是一种常见的操作,这样可以让过滤器使用其他服务提供的功能,例如数据库访问、日志记录等 。有两种主要的过滤器类型可以注入服务:[TypeFilter] 特性[ServiceFilter]特性。 这里以记录ActionFilter中的请求信息为例,在ActionFilter注入日志服务

/// <summary>
    /// 自定义动作验证过滤器
    /// </summary>
    public class CtsActionFilterAttribute : Attribute, IActionFilter
    {
        ILogger<CtsActionFilterAttribute> _logger;
        public CtsActionFilterAttribute(ILogger<CtsActionFilterAttribute> logger)
        {
            _logger = logger;
        }
        // 进入方法后
        public void OnActionExecuted(ActionExecutedContext context)
        {
            _logger.LogInformation("ActionFilter ========= OnActionExecuted");
        }

        // 进入方法前
        public void OnActionExecuting(ActionExecutingContext context)
        {
            _logger.LogInformation("ActionFilter ========= OnActionExecuting");
        }
    }
  • 使用[TypeFilter]特性添加方法级别的过滤器
       [TypeFilter(typeof(CtsActionFilterAttribute))]
       [HttpGet]
       public IEnumerable<WeatherForecast> Get()
      {
         /// 忽略执行逻辑
      }
  • 使用[ServiceFilter]特性添加方法级别的过滤器
       [ServiceFilter(typeof(CtsActionFilterAttribute))]
       [HttpGet]
       public IEnumerable<WeatherForecast> Get()
      {
         /// 忽略执行逻辑
      }

同时需要在容器中注入CtsActionFilterAttribute

   builder.Services.AddTransient<CtsActionFilterAttribute>();

两者的区别在于是不是需要注入过滤器本身.
这是因为TypeFilterAttribute 会根据类型信息,尝试从容器中解析其依赖项,然后直接创建过滤器实例.
ServiceFilterAttribute直接从依赖注入容器中解析过滤器实例。这要求过滤器必须在依赖注入容器中进行注册。

9 .NET Core中间件和过滤器的异同

  • 相同点
    (1) 两者都用于对请求和响应进行预处理和后处理,以增强应用程序的功能。帮助开发者将横切关注点(如安全性、日志等)从核心业务逻辑中分离出来,提高代码的可维护性和可复用性。是.NET Core中AOP的不同实现方式
    (2) 通常都以链式的方式工作。多个中间件或过滤器可以按照一定的顺序依次执行
  • 不同点
    (1) 中间件是更底层的组件,与 Web 服务器或应用程序的请求处理管道紧密相关,它直接处理 HTTP 请求和响应,能够在请求到达具体的业务处理逻辑之前进行拦截和处理,作用范围更广;过滤器主要应用于控制器和动作方法级别,可对特定的控制器或动作方法进行精细的控制,实现细粒度的功能增强,
    (2) 中间件是对所有请求进行统一处理,难以针对特定的控制器或动作方法进行精细的配置。
    过滤器具有较高的灵活性,能够针对不同的控制器和动作方法进行不同的配置。

http://www.kler.cn/a/554559.html

相关文章:

  • OneNote手机/平板“更多笔记本”中有许多已经删掉或改名的,如何删除
  • 内部知识库:安全协作驱动数字化转型新路径
  • Reactor模型说明
  • 前端构建工具——Webpack和Vite的主要区别
  • DHCPV6
  • C语言基础20:函数的递归调用、数组做函数的参数
  • VSCode配置C/C++开发环境|最新教程202502
  • 【Spring详解一】Spring整体架构和环境搭建
  • 【Matlab】Matlab基于遗传算法的指纹识别(源码)【独一无二】
  • 如何在Windows 10操作系统中安装并配置PHP集成软件XAMPP
  • HTML5 面试题
  • AI大模型驱动的智能音视频通信:视频通话SDK工具EasyRTC在嵌入式设备中的应用探索
  • 深入理解 NoSQL 数据库:MongoDB 与 Cassandra
  • TCP 三次握手与四次挥手:构建与终止可靠通信的核心机制
  • 调用click.getchar()时Windows PyCharm无法模拟键盘输入
  • RT-Thread+STM32L475VET6实现红外遥控实验
  • HTTP请求状态码
  • RV1126解码—ffmpeg_read_thread线程的讲解
  • 什么是pytest.ini及如何在Pytest中应用以提升配置效率
  • 万能头文件