前言:什么是 ActionFilterAttribute?
ActionFilterAttribute 是一种作用于控制器 Action 方法的特性(Attribute),通过它,你可以在操作执行前后、异常处理时等不同的阶段插入自定义逻辑。
比如在执行操作方法之前修改请求参数、记录日记、进行权限验证等操作,在执行操作方法之后发送邮件、同步数据等等。
本文主要通过一些例子来说明什么是 ActionFilterAttribute 及如何应用。
Step By Step 步骤:
- 创建一个 asp.net core webapi 的项目
- 直接继承 ActionFilterAttribute 抽象类创建自定义的 Test1ActionFilterAttribute 类并注入 ILogger
- using 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年+ 资深研发老鸟,是软件项目管理师,也是快乐的步伐猿,持续免费分享全栈实用编程技巧、项目管理经验和职场发展心得!接待关注老杨的公众号(名称:代码掌控者),和你共同探索代码世界的奥秘!
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。 |