如何在 ASP.NET Core Web API 方法执行前后 “偷偷“ 作一些 “坏“ 事?初识 ActionFilterAttribute
1.看看 Asp.net core Webapi 项目如何优雅地使用分布式缓存2.Asp.net core Webapi 如何执行定时任务?3.试试这 6 个小技巧,提升 EF Core 性能4.C# 完美实现物联网 MQTT 数据通信5.Asp.net Webapi 的 Post 方法不能把参数加到 URL 中?试试这样写
6.如何在 ASP.NET Core Web API 方法执行前后 “偷偷“ 作一些 “坏“ 事?初识 ActionFilterAttribute
7.在 ASP.NET Core Web API 中使用异常筛选器捕获和统一处理异常8.操作筛选器的 1 个应用实例:自动启用事务9.并发请求太多,服务器崩溃了?试试使用 ASP.NET Core Web API 操作筛选器对请求进行限流10.一个简单的 ASP.NET Core 依赖注入例子,提高代码的可维护性和可扩展性11.由一个业务需求引发的对 ASP.NET 全局变量的调研及结果12.服务注册自治,降低 ASP.NET Core Web API 依赖注入的耦合度和复杂度13.ASP.NET Core 标识(Identity)框架系列(一):如何使用 ASP.NET Core 标识(Identity)框架创建用户和角色?14.ASP.NET Core 标识(Identity)框架系列(二):使用标识(Identity)框架生成 JWT Token15.ASP.NET Core 标识(Identity)框架系列(三):在 ASP.NET Core Web API 项目中使用标识(Identity)框架进行身份验证16.ASP.NET Core 标识(Identity)框架系列(四):闲聊 JWT 的缺点,和一些解决思路前言:什么是 ActionFilterAttribute?
ActionFilterAttribute 是一种作用于控制器 Action 方法的特性(Attribute),通过它,你可以在操作执行前后、异常处理时等不同的阶段插入自定义逻辑。
比如在执行操作方法之前修改请求参数、记录日志、进行权限验证等操作,在执行操作方法之后发送邮件、同步数据等等。
本文主要通过一些例子来说明什么是 ActionFilterAttribute 及如何应用。
Step By Step 步骤:
-
创建一个 asp.net core webapi 的项目
-
直接继承
ActionFilterAttribute
抽象类创建自定义的Test1ActionFilterAttribute
类并注入 ILoggerusing Microsoft.AspNetCore.Mvc.Filters; namespace AttributeSample { [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false)] public class Test1ActionFilterAttribute: ActionFilterAttribute { private ILogger<Test1ActionFilterAttribute> _logger; // 在构造方法里注入 ILogger public Test1ActionFilterAttribute(ILogger<Test1ActionFilterAttribute> logger) { _logger = logger; } /// <summary> /// 在控制器执行之前调用 /// </summary> /// <param name="context"></param> public override void OnActionExecuting(ActionExecutingContext context) { _logger.LogInformation("在控制器执行之前调用..."); base.OnActionExecuting(context); } /// <summary> /// 在控制器执行之后调用 /// </summary> /// <param name="context"></param> public override void OnActionExecuted(ActionExecutedContext context) { _logger.LogInformation("在控制器执行之后调用..."); base.OnActionExecuted(context); } } } -
通过实现
IActionFilter
接口创建自定义的Test2ActionFilterAttribute
类并注入 ILogger(推荐方式)using Microsoft.AspNetCore.Mvc.Filters; namespace AttributeSample { [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false)] public class Test2ActionFilterAttribute: Attribute, IActionFilter { private ILogger<Test2ActionFilterAttribute> _logger; // 在构造方法里注入 ILogger public Test2ActionFilterAttribute(ILogger<Test2ActionFilterAttribute> logger) { _logger = logger; } /// <summary> /// 在控制器执行之前调用 /// </summary> /// <param name="context"></param> public void OnActionExecuting(ActionExecutingContext context) { _logger.LogInformation("在控制器执行之前调用..."); } /// <summary> /// 在控制器执行之后调用 /// </summary> /// <param name="context"></param> public void OnActionExecuted(ActionExecutedContext context) { _logger.LogInformation("在控制器执行之后调用..."); } } } -
直接继承
ActionFilterAttribute
抽象类创建自定义的Test3ActionFilterAttribute
类,不注入其他依赖using Microsoft.AspNetCore.Mvc.Filters; namespace AttributeSample { [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false)] public class Test3ActionFilterAttribute: Attribute, IActionFilter { private string _myName; public Test3ActionFilterAttribute(string myName) { _myName = myName; } /// <summary> /// 在控制器执行之前调用 /// </summary> /// <param name="context"></param> public void OnActionExecuting(ActionExecutingContext context) { _myName += " before"; } /// <summary> /// 在控制器执行之后调用 /// </summary> /// <param name="context"></param> public void OnActionExecuted(ActionExecutedContext context) { _myName += " after"; } } } -
在控制器中应用自定义的
ActionFilterAttribute
using Microsoft.AspNetCore.Mvc; using AttributeSample; using System.Reflection; namespace AttributeSample.Controllers { [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; /// <summary> /// /// </summary> /// <param name="logger"></param> public WeatherForecastController(ILogger<WeatherForecastController> logger) { _logger = logger; } [HttpGet(Name = "GetWeatherForecast")] [TypeFilter(typeof(Test1ActionFilterAttribute))] [TypeFilter(typeof(Test2ActionFilterAttribute))] [Test3ActionFilter("Jacky")] public IEnumerable<WeatherForecast> Get() { var list = Enumerable.Range(1, 5).Select(index => new WeatherForecast { Date = DateTime.Now.AddDays(index), TemperatureC = Random.Shared.Next(-20, 55), Summary = Summaries[Random.Shared.Next(Summaries.Length)] }) .ToArray(); _logger.LogInformation("执行方法..."); return list; } } } -
在
Swaager
测试,可以看到其执行顺序如下:AttributeSample.Test1ActionFilterAttribute: Information: 在控制器执行之前调用... AttributeSample.Test2ActionFilterAttribute: Information: 在控制器执行之前调用... AttributeSample.Test3ActionFilterAttribute... AttributeSample.Controllers.WeatherForecastController: Information: 执行方法... AttributeSample.Test3ActionFilterAttribute... AttributeSample.Test2ActionFilterAttribute: Information: 在控制器执行之后调用... AttributeSample.Test1ActionFilterAttribute: Information: 在控制器执行之后调用...
总结:
- Asp.net core webapi 使用 ActionFilterAttribute,引用的是 Microsoft.AspNetCore.Mvc.Filters 而不是 System.Web.Http.Filters
- System.Web.Http.Filters 是属于 .Net FrameWork 的命名空间
- ActionFilterAttribute 如果需要在构造方法中注入某些依赖,比如注入 ILogger,有几个使用方法:
- TypeFilter,无需在IOC中注册,有自实现,本文例子即是使用这种方式
- ServiceFilter,需要在 Program.cs 中针对该过滤器注册服务才能使用
- 自定义 CustomIOCFilterFactoryAttribute 实现,依然需要对过滤器进行服务注册
- 方法2和3比较复杂,以后有时间再针对这两种方式写一些例子
- 没有注入其他依赖的 ActionFilterAttribute 如一般 Attribute 使用即可,比如本文的第 3 个 ActionFilterAttribute
- [Test3ActionFilter("Jacky")]
我是老杨,一个执着于编程乐趣、至今奋斗在一线的 10年+ 资深研发老鸟,是软件项目管理师,也是快乐的程序猿,持续免费分享全栈实用编程技巧、项目管理经验和职场成长心得!欢迎关注老杨的公众号(名称:代码掌控者),和你共同探索代码世界的奥秘!
合集:
.NET
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek “源神”启动!「GitHub 热点速览」
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· C# 集成 DeepSeek 模型实现 AI 私有化(本地部署与 API 调用教程)
· DeepSeek R1 简明指南:架构、训练、本地部署及硬件要求
· NetPad:一个.NET开源、跨平台的C#编辑器