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

过滤器及拦截器

ActionFilterAttribute 是ASP.NET MVC 框架引入的特性,随着ASP.NET MVC 的发展不断完善。ASP.NET MVC 框架于 2009 年发布,为开发者提供了基于 MVC 模式构建 Web 应用程序的方式,ActionFilterAttribute 作为其中重要的一部分,用于在控制器动作执行前后插入自定义逻辑。之后,随着ASP.NET Core 的推出,ActionFilterAttribute 也得到了延续和改进,更好地适应了现代 Web 开发的需求。

原理

ActionFilterAttribute 是一种过滤器,它基于 AOP(面向切面编程)的思想。在ASP.NET MVC 和ASP.NET Core 中,过滤器是一种特殊的类,用于在请求处理管道的特定阶段执行代码。ActionFilterAttribute 主要有两个关键的方法:

  • OnActionExecuting:在控制器动作执行之前调用。可以在此方法中对请求进行预处理,例如验证请求参数、记录日志等。如果在这个方法中设置了 filterContext.Result 属性,那么动作方法将不会被执行,直接返回该结果。
  • OnActionExecuted:在控制器动作执行之后调用。可以在此方法中对响应进行后处理,例如修改响应内容、记录响应时间等。

作用

  • 验证和授权:可以在动作执行前验证请求参数或用户权限,确保只有符合条件的请求才能执行动作。
  • 日志记录:在动作执行前后记录日志,方便调试和监控。
  • 缓存:在动作执行前检查缓存,如果缓存存在则直接返回缓存结果,避免重复执行动作。
  • 异常处理:在动作执行过程中捕获异常,并进行统一处理。

使用案例

以下是一个使用 ActionFilterAttribute 对接口入参进行优先判断的示例。假设我们有一个简单的 Web API,要求传入的参数 id 必须大于 0。

using System;
using System.Web.Http.Filters;
using System.Net;
using System.Net.Http;// 自定义ActionFilterAttribute
public class ParameterValidationFilterAttribute : ActionFilterAttribute
{public override void OnActionExecuting(System.Web.Http.Controllers.HttpActionContext actionContext){// 获取请求参数var id = actionContext.ActionArguments.ContainsKey("id") ? (int?)actionContext.ActionArguments["id"] : null;// 验证参数if (id == null || id <= 0){// 参数验证失败,返回错误信息actionContext.Response = actionContext.Request.CreateErrorResponse(HttpStatusCode.BadRequest,"参数 id 必须大于 0。");}}
}// 控制器
public class MyController : System.Web.Http.ApiController
{[ParameterValidationFilter]public IHttpActionResult Get(int id){// 只有参数验证通过才会执行到这里return Ok($"你传入的 id 是: {id}");}
}

代码解释

  1. 自定义过滤器 ParameterValidationFilterAttribute:继承自 ActionFilterAttribute,重写 OnActionExecuting 方法。在该方法中,获取请求参数 id,并验证其是否大于 0。如果验证失败,设置 actionContext.Response 属性,返回一个包含错误信息的 HTTP 响应。
  2. 控制器 MyController:在 Get 方法上应用 [ParameterValidationFilter] 特性,这样在执行 Get 方法之前,会先执行 ParameterValidationFilterAttribute 的 OnActionExecuting 方法进行参数验证。只有参数验证通过,才会继续执行 Get 方法的内容。

这个示例展示了如何使用 ActionFilterAttribute 对接口的入参进行优先判断,确保只有符合条件的请求才能执行接口内的内容。

其他

在 .NET 里,除了 ActionFilterAttribute 所在的过滤器体系,有一些具备相似功能或者可用于实现相似逻辑的库与机制,下面为你详细介绍:

1. 授权过滤器(Authorization Filters)

  • 相关 DLLMicrosoft.AspNetCore.Authorization(ASP.NET Core);System.Web.Mvc(ASP.NET MVC)。
  • 原理:在动作方法执行之前,它的作用是验证用户是否具备访问该资源的权限。它是基于角色、策略或者自定义授权规则来判定的。
  • 作用:对用户访问资源进行管控,避免未授权的用户访问特定的接口或者页面。
  • 示例代码
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;[Authorize(Roles = "Admin")]
public class AdminController : Controller
{public IActionResult Index(){return View();}
}

在这个示例中,AuthorizeAttribute 充当授权过滤器,它保证只有具备 “Admin” 角色的用户才能访问 AdminController 的 Index 方法。

2. 异常过滤器(Exception Filters)

  • 相关 DLLMicrosoft.AspNetCore.Mvc.Core(ASP.NET Core);System.Web.Mvc(ASP.NET MVC)。
  • 原理:在动作方法执行期间一旦发生异常,异常过滤器就会捕获该异常,并且能够对异常进行统一处理。
  • 作用:实现全局异常处理,增强应用程序的健壮性与用户体验。
  • 示例代码

csharp

using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;
using System;public class CustomExceptionFilterAttribute : ExceptionFilterAttribute
{public override void OnException(ExceptionContext context){// 记录日志Console.WriteLine($"An exception occurred: {context.Exception.Message}");// 返回统一的错误响应context.Result = new ObjectResult("An error occurred. Please try again later."){StatusCode = 500};}
}[CustomExceptionFilter]
public class MyController : Controller
{public IActionResult Index(){throw new Exception("Something went wrong!");}
}

在这个例子中,CustomExceptionFilterAttribute 是自定义的异常过滤器,它会捕获 Index 方法抛出的异常,记录日志并返回统一的错误响应。

3. 结果过滤器(Result Filters)

  • 相关 DLLMicrosoft.AspNetCore.Mvc.Core(ASP.NET Core);System.Web.Mvc(ASP.NET MVC)。
  • 原理:在动作方法执行之后、结果返回之前被调用,可用于对动作结果进行修改或者后处理。
  • 作用:对响应结果进行统一处理,例如添加响应头、压缩响应内容等。
  • 示例代码

csharp

using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;public class CustomResultFilterAttribute : ResultFilterAttribute
{public override void OnResultExecuting(ResultExecutingContext context){// 在结果执行前添加响应头context.HttpContext.Response.Headers.Add("X-Custom-Header", "Custom Value");base.OnResultExecuting(context);}
}[CustomResultFilter]
public class MyController : Controller
{public IActionResult Index(){return Ok("Hello, World!");}
}

在这个示例中,CustomResultFilterAttribute 是自定义的结果过滤器,它会在 Index 方法返回结果之前添加一个自定义的响应头。

4. 管道过滤器(Pipeline Filters)

  • 相关 DLLMicrosoft.AspNetCore.Mvc.Core(ASP.NET Core)。
  • 原理:它是 ASP.NET Core 里的一种新过滤器类型,能够在请求处理管道的多个阶段进行拦截和处理。
  • 作用:实现更灵活、更细粒度的请求处理逻辑。
  • 示例代码
using Microsoft.AspNetCore.Mvc.Filters;
using System.Threading.Tasks;public class CustomPipelineFilter : IAsyncResourceFilter
{public async Task OnResourceExecutionAsync(ResourceExecutingContext context, ResourceExecutionDelegate next){// 在资源执行前处理// ...var resultContext = await next();// 在资源执行后处理// ...}
}

在这个例子中,CustomPipelineFilter 实现了 IAsyncResourceFilter 接口,可在资源执行前后进行处理。

Castle.Core.dll

Castle.Core.dll 算是具备与 ActionFilterAttribute 类似功能的库,下面从几个方面为你分析:

功能概述

Castle.Core.dll 是 Castle 项目中的核心库,该项目提供了一系列的工具和框架,其中的动态代理(Dynamic Proxy)组件和 ActionFilterAttribute 一样,都能实现面向切面编程(AOP)的功能。而 ActionFilterAttribute 是 ASP.NET 中用于在控制器动作执行前后插入自定义逻辑的特性,也是 AOP 思想的一种体现。

实现原理对比

  • ActionFilterAttribute:在 ASP.NET 框架里,它是基于过滤器管道来工作的。当请求进入 MVC 或 Web API 应用时,框架会按特定顺序执行不同类型的过滤器,ActionFilterAttribute 可在动作方法执行前后执行代码。
  • Castle.Core 的动态代理:借助运行时生成代理类,将横切关注点(如日志记录、事务管理等)织入到目标对象的方法调用中。它在不修改目标对象代码的情况下,为其添加额外功能。

作用对比

  • ActionFilterAttribute:主要用于 ASP.NET 应用中控制器动作的预处理和后处理,像参数验证、日志记录、性能监控等,一般在 Web 开发场景下使用。
  • Castle.Core:可用于各类 .NET 应用程序,不仅能在 Web 应用中使用,还能在桌面应用、服务应用等场景使用。它能实现日志记录、事务管理、缓存、安全检查等横切关注点,具有更广泛的适用性。

使用案例

下面是使用 Castle.Core 实现简单 AOP 功能的示例:

using Castle.DynamicProxy;
using System;// 定义一个拦截器类
public class LoggingInterceptor : IInterceptor
{public void Intercept(IInvocation invocation){Console.WriteLine($"Before method {invocation.Method.Name}");invocation.Proceed();Console.WriteLine($"After method {invocation.Method.Name}");}
}// 定义一个接口
public interface IService
{void DoSomething();
}// 实现接口
public class MyService : IService
{public void DoSomething(){Console.WriteLine("Doing something...");}
}class Program
{static void Main(){// 创建代理生成器var proxyGenerator = new ProxyGenerator();// 创建拦截器实例var interceptor = new LoggingInterceptor();// 创建目标对象var service = new MyService();// 生成代理对象var proxy = proxyGenerator.CreateInterfaceProxyWithTarget<IService>(service, interceptor);// 调用代理对象的方法proxy.DoSomething();}
}

代码解释

  • LoggingInterceptor 类实现了 IInterceptor 接口,在 Intercept 方法中定义了在目标方法执行前后要执行的逻辑。
  • MyService 类实现了 IService 接口,代表目标对象。
  • 在 Main 方法中,使用 ProxyGenerator 生成代理对象,并将拦截器和目标对象关联起来。调用代理对象的方法时,拦截器的逻辑就会被执行。

从上述分析可以看出,Castle.Core.dll 能实现和 ActionFilterAttribute 类似的 AOP 功能,不过它的应用场景更为广泛。

1. Autofac.Extras.DynamicProxy

  • 概述:Autofac 是一个流行的依赖注入容器,而 Autofac.Extras.DynamicProxy 是它的一个扩展,结合了 Autofac 的依赖注入能力与 Castle DynamicProxy 的 AOP 功能。它允许你在应用程序中使用 AOP 模式,将横切关注点(如日志记录、事务管理等)应用到服务的方法调用上。
  • 原理:借助 Autofac 的容器来管理对象的生命周期,同时利用 Castle DynamicProxy 在运行时生成代理类,把拦截器逻辑织入到目标对象的方法调用中。
  • 使用案例
using Autofac;
using Autofac.Extras.DynamicProxy;
using Castle.DynamicProxy;
using System;// 定义拦截器
public class LoggingInterceptor : IInterceptor
{public void Intercept(IInvocation invocation){Console.WriteLine($"Before method: {invocation.Method.Name}");invocation.Proceed();Console.WriteLine($"After method: {invocation.Method.Name}");}
}// 定义服务接口
public interface IMyService
{void DoWork();
}// 实现服务
public class MyService : IMyService
{public void DoWork(){Console.WriteLine("Doing work...");}
}class Program
{static void Main(){var builder = new ContainerBuilder();// 注册拦截器builder.RegisterType<LoggingInterceptor>();// 注册服务并应用拦截器builder.RegisterType<MyService>().As<IMyService>().EnableInterfaceInterceptors().InterceptedBy(typeof(LoggingInterceptor));var container = builder.Build();var service = container.Resolve<IMyService>();service.DoWork();}
}

2. PostSharp

  • 概述:PostSharp 是一个强大的 AOP 框架,它通过编译时织入的方式将横切关注点集成到代码中。与运行时生成代理不同,PostSharp 在编译时修改 IL 代码,把额外的逻辑插入到目标方法中。
  • 原理:在代码编译期间,PostSharp 分析代码中的特性(Attributes),并根据这些特性对 IL 代码进行修改,从而实现 AOP 功能。
  • 使用案例
using PostSharp.Aspects;
using System;// 定义切面
[Serializable]
public class LoggingAspect : OnMethodBoundaryAspect
{public override void OnEntry(MethodExecutionArgs args){Console.WriteLine($"Before method: {args.Method.Name}");}public override void OnExit(MethodExecutionArgs args){Console.WriteLine($"After method: {args.Method.Name}");}
}// 应用切面
[LoggingAspect]
public class MyClass
{public void MyMethod(){Console.WriteLine("Method is executing...");}
}class Program
{static void Main(){var obj = new MyClass();obj.MyMethod();}
}

3.NLog.Extensions.MicrosoftLogging

  • 概述:NLog 是一个用于 .NET 平台的日志记录库,NLog.Extensions.MicrosoftLogging 是它与 Microsoft 日志框架集成的扩展。虽然它主要用于日志记录,但可以通过配置和自定义实现类似 ActionFilterAttribute 的功能,例如在方法执行前后记录日志。
  • 原理:借助 Microsoft 的日志抽象层,将日志记录逻辑集成到应用程序中。可以在不同的代码位置插入日志记录语句,实现对方法执行过程的监控。
  • 使用案例
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using NLog.Extensions.Logging;
using System;public class MyService
{private readonly ILogger<MyService> _logger;public MyService(ILogger<MyService> logger){_logger = logger;}public void DoSomething(){_logger.LogInformation("Before doing something");Console.WriteLine("Doing something...");_logger.LogInformation("After doing something");}
}class Program
{static void Main(){var serviceCollection = new ServiceCollection();serviceCollection.AddLogging(loggingBuilder =>{loggingBuilder.ClearProviders();loggingBuilder.SetMinimumLevel(Microsoft.Extensions.Logging.LogLevel.Trace);loggingBuilder.AddNLog();});serviceCollection.AddTransient<MyService>();var serviceProvider = serviceCollection.BuildServiceProvider();var myService = serviceProvider.GetRequiredService<MyService>();myService.DoSomething();}
}

这些库或机制都以不同的方式实现了面向切面编程的思想,能够在方法执行前后插入自定义逻辑,与 ActionFilterAttribute 的功能有相似之处。

相关文章:

  • 一文掌握RK3568开发板Android13挂载Windows共享目录
  • C++Cherno 学习笔记day21 [86]-[90] 持续集成、静态分析、参数计算顺序、移动语义、stdmove与移动赋值操作符
  • 蓝桥杯 8. 分巧克力
  • oracle判断同表同条件查出两条数据,根据长短判断差异
  • leetcode_344.反转字符串_java
  • CS5346 - CHARTS: Chart with Point / Bar / Line / Box
  • matlab中simulink的快捷使用方法
  • 用友U8在参照生产订单界面显示各个仓别的可用量
  • 机器学习03——K近邻
  • 【漫话机器学习系列】204.不确定性的来源(Sources Of Uncertainty)
  • 算力狂飙时代:解码2024年上海及周边区域IDC市场的三重构局
  • 神经网络模型应用到机器学习时的难点
  • 4.16学习总结
  • 数据中台(大数据平台)之数据资源目录
  • Redisson分布式锁深度解析:原理、源码与最佳实践
  • DAY09:【pytorch】nn网络层
  • Spring Boot 整合 Redis 实现点赞功能:从基础到实践
  • 2000-2017年各省原油消费量数据
  • 第2.4节:学会像AWK一样思考
  • 从标准九九表打印解读单行表达式的书写修炼(Python)
  • 济南网站哪家做的好/2022年关键词排名
  • 物流企业网站有哪些/淘宝优秀软文范例100字
  • 护肤品网站建设的摘要/如何推广引流
  • 诸城网站建设定制/以服务营销出名的企业
  • 校园网共青团网站建设方案/苏州手机关键词优化
  • 做一个旅游团网站怎么做/图片识别 在线百度识图