目录
- 
- 
- 过滤器概述
 - [1. 授权过滤器(Authorization Filters)](#1. 授权过滤器(Authorization Filters))
 - [2. 资源过滤器(Resource Filters)](#2. 资源过滤器(Resource Filters))
 - [3. 动作过滤器(Action Filters)](#3. 动作过滤器(Action Filters))
 - [4. 异常过滤器(Exception Filters)](#4. 异常过滤器(Exception Filters))
 - [5. 结果过滤器(Result Filters)](#5. 结果过滤器(Result Filters))
 - 6过滤器的使用方式
 - [7 测试过滤器执行](#7 测试过滤器执行)
 - [8 过滤器中注入服务](#8 过滤器中注入服务)
 - [9 .NET Core中间件和过滤器的异同](#9 .NET Core中间件和过滤器的异同)
 
 
 - 
 
过滤器概述
在 .NET Core 中,过滤器(Filters)和面向切面编程(AOP)有着紧密的联系,过滤器可以看作是 AOP 在 .NET Core 框架中的一种具体实现方式。
在.NET Core中过滤器是一种特殊的组件,它能够在请求处理管道的特定阶段执行自定义逻辑。借助过滤器,你可以把横切关注点(像日志记录、权限验证、异常处理等)从业务逻辑中分离出来,从而提升代码的可维护性与可复用性。
1. 授权过滤器(Authorization Filters)
作用:用于验证用户是否有权限访问某个资源,在请求进入控制器之前执行。若验证不通过,会阻止请求继续执行。
示例代码:
            
            
              csharp
              
              
            
          
          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)
作用:在授权之后、模型绑定之前执行,主要用于缓存和资源管理。
示例代码:
            
            
              csharp
              
              
            
          
          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)
作用:在控制器方法执行前后执行,可用于日志记录、参数验证等。
示例代码:
            
            
              csharp
              
              
            
          
          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)
作用:在发生异常时执行,用于统一处理异常,避免异常信息直接暴露给客户端。
示例代码:
            
            
              csharp
              
              
            
          
          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)
作用:在动作结果执行前后执行,用于对动作结果进行格式化、加密等处理。
示例代码:
            
            
              csharp
              
              
            
          
          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 及以上版本)中进行全局注册,会对所有的控制器和动作方法生效。
            
            
              csharp
              
              
            
          
          // .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();
        控制器级别过滤器:在控制器类上应用过滤器,会对该控制器中的所有动作方法生效。
            
            
              csharp
              
              
            
          
          [CtsActionFilter]
public class MyController : Controller
{
    // 控制器方法
}
        动作方法级别过滤器:在具体的动作方法上应用过滤器,仅对该动作方法生效。
            
            
              csharp
              
              
            
          
          public class MyController : Controller
{
    [CtsActionFilter]
    public IActionResult MyAction()
    {
        return Ok();
    }
}
        一般来说,在同级别的过滤器下,过滤器的执行顺序是从全局到控制器再到方法
7 测试过滤器执行
在目标方法上添加上述五种过滤器, 通过 /WeatherForecast 路径去请求Get方法
            
            
              bash
              
              
            
          
             [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注入日志服务
            
            
              csharp
              
              
            
          
          /// <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]特性添加方法级别的过滤器
 
            
            
              csharp
              
              
            
          
                 [TypeFilter(typeof(CtsActionFilterAttribute))]
       [HttpGet]
       public IEnumerable<WeatherForecast> Get()
      {
         /// 忽略执行逻辑
      }
        - 使用[ServiceFilter]特性添加方法级别的过滤器
 
            
            
              csharp
              
              
            
          
                 [ServiceFilter(typeof(CtsActionFilterAttribute))]
       [HttpGet]
       public IEnumerable<WeatherForecast> Get()
      {
         /// 忽略执行逻辑
      }
        同时需要在容器中注入CtsActionFilterAttribute
            
            
              csharp
              
              
            
          
             builder.Services.AddTransient<CtsActionFilterAttribute>();
        两者的区别在于是不是需要注入过滤器本身.
这是因为TypeFilterAttribute 会根据类型信息,尝试从容器中解析其依赖项,然后直接创建过滤器实例.
ServiceFilterAttribute直接从依赖注入容器中解析过滤器实例。这要求过滤器必须在依赖注入容器中进行注册。
9 .NET Core中间件和过滤器的异同
- 相同点
(1) 两者都用于对请求和响应进行预处理和后处理,以增强应用程序的功能。帮助开发者将横切关注点(如安全性、日志等)从核心业务逻辑中分离出来,提高代码的可维护性和可复用性。是.NET Core中AOP的不同实现方式
(2) 通常都以链式的方式工作。多个中间件或过滤器可以按照一定的顺序依次执行 - 不同点
(1) 中间件是更底层的组件,与 Web 服务器或应用程序的请求处理管道紧密相关,它直接处理 HTTP 请求和响应,能够在请求到达具体的业务处理逻辑之前进行拦截和处理,作用范围更广;过滤器主要应用于控制器和动作方法级别,可对特定的控制器或动作方法进行精细的控制,实现细粒度的功能增强,
(2) 中间件是对所有请求进行统一处理,难以针对特定的控制器或动作方法进行精细的配置。
过滤器具有较高的灵活性,能够针对不同的控制器和动作方法进行不同的配置。 
