如何在 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”)]
相关文章
|
8天前
|
XML JSON API
ServiceStack:不仅仅是一个高性能Web API和微服务框架,更是一站式解决方案——深入解析其多协议支持及简便开发流程,带您体验前所未有的.NET开发效率革命
【10月更文挑战第9天】ServiceStack 是一个高性能的 Web API 和微服务框架,支持 JSON、XML、CSV 等多种数据格式。它简化了 .NET 应用的开发流程,提供了直观的 RESTful 服务构建方式。ServiceStack 支持高并发请求和复杂业务逻辑,安装简单,通过 NuGet 包管理器即可快速集成。示例代码展示了如何创建一个返回当前日期的简单服务,包括定义请求和响应 DTO、实现服务逻辑、配置路由和宿主。ServiceStack 还支持 WebSocket、SignalR 等实时通信协议,具备自动验证、自动过滤器等丰富功能,适合快速搭建高性能、可扩展的服务端应用。
46 3
|
18天前
|
存储 开发框架 JSON
ASP.NET Core OData 9 正式发布
【10月更文挑战第8天】Microsoft 在 2024 年 8 月 30 日宣布推出 ASP.NET Core OData 9,此版本与 .NET 8 的 OData 库保持一致,改进了数据编码以符合 OData 规范,并放弃了对旧版 .NET Framework 的支持,仅支持 .NET 8 及更高版本。新版本引入了更快的 JSON 编写器 `System.Text.UTF8JsonWriter`,优化了内存使用和序列化速度。
|
18天前
mcr.microsoft.com/dotnet/core/aspnet:2.1安装libgdiplus
mcr.microsoft.com/dotnet/core/aspnet:2.1安装libgdiplus
25 1
|
28天前
|
开发框架 监控 前端开发
在 ASP.NET Core Web API 中使用操作筛选器统一处理通用操作
【9月更文挑战第27天】操作筛选器是ASP.NET Core MVC和Web API中的一种过滤器,可在操作方法执行前后运行代码,适用于日志记录、性能监控和验证等场景。通过实现`IActionFilter`接口的`OnActionExecuting`和`OnActionExecuted`方法,可以统一处理日志、验证及异常。创建并注册自定义筛选器类,能提升代码的可维护性和复用性。
|
28天前
|
开发框架 .NET 中间件
ASP.NET Core Web 开发浅谈
本文介绍ASP.NET Core,一个轻量级、开源的跨平台框架,专为构建高性能Web应用设计。通过简单步骤,你将学会创建首个Web应用。文章还深入探讨了路由配置、依赖注入及安全性配置等常见问题,并提供了实用示例代码以助于理解与避免错误,帮助开发者更好地掌握ASP.NET Core的核心概念。
64 3
|
8天前
|
开发框架 JavaScript 前端开发
一个适用于 ASP.NET Core 的轻量级插件框架
一个适用于 ASP.NET Core 的轻量级插件框架
|
14天前
|
设计模式 测试技术 持续交付
开发复杂Web应用程序
【10月更文挑战第3天】开发复杂Web应用程序
28 2
|
16天前
|
Java PHP
PHP作为广受青睐的服务器端脚本语言,在Web开发中占据重要地位。理解其垃圾回收机制有助于开发高效稳定的PHP应用。
【10月更文挑战第1天】PHP作为广受青睐的服务器端脚本语言,在Web开发中占据重要地位。其垃圾回收机制包括引用计数与循环垃圾回收,对提升应用性能和稳定性至关重要。本文通过具体案例分析,详细探讨PHP垃圾回收机制的工作原理,特别是如何解决循环引用问题。在PHP 8中,垃圾回收机制得到进一步优化,提高了效率和准确性。理解这些机制有助于开发高效稳定的PHP应用。
35 3
|
1月前
|
数据可视化 图形学 UED
只需四步,轻松开发三维模型Web应用
为了让用户更方便地应用三维模型,阿里云DataV提供了一套完整的三维模型Web模型开发方案,包括三维模型托管、应用开发、交互开发、应用分发等完整功能。只需69.3元/年,就能体验三维模型Web应用开发功能!
221 8
只需四步,轻松开发三维模型Web应用
|
1月前
|
安全 API 开发者
Web 开发新风尚!Python RESTful API 设计与实现,让你的接口更懂开发者心!
在当前的Web开发中,Python因能构建高效简洁的RESTful API而备受青睐,大大提升了开发效率和用户体验。本文将介绍RESTful API的基本原则及其在Python中的实现方法。以Flask为例,演示了如何通过不同的HTTP方法(如GET、POST、PUT、DELETE)来创建、读取、更新和删除用户信息。此示例还包括了基本的路由设置及操作,为开发者提供了清晰的API交互指南。
95 6