如何在 ASP.NET Core Web API 方法执行前后 “偷偷“ 作一些 “坏“ 事?初识 ActionFilterAttribute

简介: 如何在 ASP.NET Core Web API 方法执行前后 “偷偷“ 作一些 “坏“ 事?初识 ActionFilterAttribute

前言:什么是 ActionFilterAttribute?

ActionFilterAttribute 是一种作用于控制器 Action 方法的特性(Attribute),通过它,你可以在操作执行前后、异常处理时等不同的阶段插入自定义逻辑。

比如在执行操作方法之前修改请求参数、记录日志、进行权限验证等操作,在执行操作方法之后发送邮件、同步数据等等。

本文主要通过一些例子来说明什么是 ActionFilterAttribute 及如何应用。

Step By Step 步骤:

  1. 创建一个 asp.net core webapi 的项目
  2. 直接继承 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);
    }
  }
}

3.通过实现 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("在控制器执行之后调用...");
    }
  }
}

4.直接继承 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";
    }
  }
}

5.在控制器中应用自定义的 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;
    }
  }
}

6.在 Swaager 测试,可以看到其执行顺序如下:

AttributeSample.Test1ActionFilterAttribute: Information: 在控制器执行之前调用...
AttributeSample.Test2ActionFilterAttribute: Information: 在控制器执行之前调用...
AttributeSample.Test3ActionFilterAttribute...
AttributeSample.Controllers.WeatherForecastController: Information: 执行方法...
AttributeSample.Test3ActionFilterAttribute...
AttributeSample.Test2ActionFilterAttribute: Information: 在控制器执行之后调用...
AttributeSample.Test1ActionFilterAttribute: Information: 在控制器执行之后调用...

总结:

  1. Asp.net core webapi 使用 ActionFilterAttribute,引用的是 Microsoft.AspNetCore.Mvc.Filters 而不是 System.Web.Http.Filters
  • System.Web.Http.Filters 是属于 .Net FrameWork 的命名空间
  1. ActionFilterAttribute 如果需要在构造方法中注入某些依赖,比如注入 ILogger,有几个使用方法:
  • TypeFilter,无需在IOC中注册,有自实现,本文例子即是使用这种方式
  • ServiceFilter,需要在 Program.cs 中针对该过滤器注册服务才能使用
  • 自定义 Custo
  • mIOCFilterFactoryAttribute 实现,依然需要对过滤器进行服务注册
  • 方法2和3比较复杂,以后有时间再针对这两种方式写一些例子
  1. 没有注入其他依赖的 ActionFilterAttribute 如一般 Attribute 使用即可,比如本文的第 3 个 ActionFilterAttribute
  • [Test3ActionFilter(“Jacky”)]
相关文章
|
4天前
|
开发框架 监控 前端开发
在 ASP.NET Core Web API 中使用操作筛选器统一处理通用操作
【9月更文挑战第27天】操作筛选器是ASP.NET Core MVC和Web API中的一种过滤器,可在操作方法执行前后运行代码,适用于日志记录、性能监控和验证等场景。通过实现`IActionFilter`接口的`OnActionExecuting`和`OnActionExecuted`方法,可以统一处理日志、验证及异常。创建并注册自定义筛选器类,能提升代码的可维护性和复用性。
|
5天前
|
开发框架 .NET 中间件
ASP.NET Core Web 开发浅谈
本文介绍ASP.NET Core,一个轻量级、开源的跨平台框架,专为构建高性能Web应用设计。通过简单步骤,你将学会创建首个Web应用。文章还深入探讨了路由配置、依赖注入及安全性配置等常见问题,并提供了实用示例代码以助于理解与避免错误,帮助开发者更好地掌握ASP.NET Core的核心概念。
17 3
|
26天前
|
开发框架 NoSQL .NET
利用分布式锁在ASP.NET Core中实现防抖
【9月更文挑战第5天】在 ASP.NET Core 中,可通过分布式锁实现防抖功能,仅处理连续相同请求中的首个请求,其余请求返回 204 No Content,直至锁释放。具体步骤包括:安装分布式锁库如 `StackExchange.Redis`;创建分布式锁服务接口及其实现;构建防抖中间件;并在 `Startup.cs` 中注册相关服务和中间件。这一机制有效避免了短时间内重复操作的问题。
|
1月前
|
数据库 开发者 Python
web应用开发
【9月更文挑战第1天】web应用开发
38 1
|
20天前
|
数据可视化 图形学 UED
只需四步,轻松开发三维模型Web应用
为了让用户更方便地应用三维模型,阿里云DataV提供了一套完整的三维模型Web模型开发方案,包括三维模型托管、应用开发、交互开发、应用分发等完整功能。只需69.3元/年,就能体验三维模型Web应用开发功能!
41 8
只需四步,轻松开发三维模型Web应用
|
10天前
|
安全 API 开发者
Web 开发新风尚!Python RESTful API 设计与实现,让你的接口更懂开发者心!
在当前的Web开发中,Python因能构建高效简洁的RESTful API而备受青睐,大大提升了开发效率和用户体验。本文将介绍RESTful API的基本原则及其在Python中的实现方法。以Flask为例,演示了如何通过不同的HTTP方法(如GET、POST、PUT、DELETE)来创建、读取、更新和删除用户信息。此示例还包括了基本的路由设置及操作,为开发者提供了清晰的API交互指南。
44 6
|
9天前
|
存储 JSON API
实战派教程!Python Web开发中RESTful API的设计哲学与实现技巧,一网打尽!
在数字化时代,Web API成为连接前后端及构建复杂应用的关键。RESTful API因简洁直观而广受欢迎。本文通过实战案例,介绍Python Web开发中的RESTful API设计哲学与技巧,包括使用Flask框架构建一个图书管理系统的API,涵盖资源定义、请求响应设计及实现示例。通过准确使用HTTP状态码、版本控制、错误处理及文档化等技巧,帮助你深入理解RESTful API的设计与实现。希望本文能助力你的API设计之旅。
31 3
|
10天前
|
JSON API 数据库
从零到英雄?一篇文章带你搞定Python Web开发中的RESTful API实现!
在Python的Web开发领域中,RESTful API是核心技能之一。本教程将从零开始,通过实战案例教你如何使用Flask框架搭建RESTful API。首先确保已安装Python和Flask,接着通过创建一个简单的用户管理系统,逐步实现用户信息的增删改查(CRUD)操作。我们将定义路由并处理HTTP请求,最终构建出功能完整的Web服务。无论是初学者还是有经验的开发者,都能从中受益,迈出成为Web开发高手的重要一步。
32 4
|
8天前
|
开发框架 JSON 缓存
震撼发布!Python Web开发框架下的RESTful API设计全攻略,让数据交互更自由!
在数字化浪潮推动下,RESTful API成为Web开发中不可或缺的部分。本文详细介绍了在Python环境下如何设计并实现高效、可扩展的RESTful API,涵盖框架选择、资源定义、HTTP方法应用及响应格式设计等内容,并提供了基于Flask的示例代码。此外,还讨论了版本控制、文档化、安全性和性能优化等最佳实践,帮助开发者实现更流畅的数据交互体验。
25 1
|
10天前
|
JSON API 开发者
惊!Python Web开发新纪元,RESTful API设计竟能如此性感撩人?
在这个Python Web开发的新纪元里,RESTful API的设计已经超越了简单的技术实现,成为了一种追求极致用户体验和开发者友好的艺术表达。通过优雅的URL设计、合理的HTTP状态码使用、清晰的错误处理、灵活的版本控制以及严格的安全性措施,我们能够让RESTful API变得更加“性感撩人”,为Web应用注入新的活力与魅力。
24 3
下一篇
无影云桌面