如何在 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”)]
相关文章
|
2月前
|
API C++ Windows
Visual C++运行库、.NET Framework和DirectX运行库的作用及常见问题解决方案,涵盖MSVCP140.dll丢失、0xc000007b错误等典型故障的修复方法
本文介绍Visual C++运行库、.NET Framework和DirectX运行库的作用及常见问题解决方案,涵盖MSVCP140.dll丢失、0xc000007b错误等典型故障的修复方法,提供官方下载链接与系统修复工具使用指南。
581 2
|
2月前
|
开发框架 .NET C#
ASP.NET Core Blazor 路由配置和导航
大家好,我是码农刚子。本文系统介绍Blazor单页应用的路由机制,涵盖基础配置、路由参数、编程式导航及高级功能。通过@page指令定义路由,支持参数约束、可选参数与通配符捕获,结合NavigationManager实现页面跳转与参数传递,并演示用户管理、产品展示等典型场景,全面掌握Blazor路由从入门到实战的完整方案。
250 6
|
6月前
|
JSON 编解码 API
Go语言网络编程:使用 net/http 构建 RESTful API
本章介绍如何使用 Go 语言的 `net/http` 标准库构建 RESTful API。内容涵盖 RESTful API 的基本概念及规范,包括 GET、POST、PUT 和 DELETE 方法的实现。通过定义用户数据结构和模拟数据库,逐步实现获取用户列表、创建用户、更新用户、删除用户的 HTTP 路由处理函数。同时提供辅助函数用于路径参数解析,并展示如何设置路由器启动服务。最后通过 curl 或 Postman 测试接口功能。章节总结了路由分发、JSON 编解码、方法区分、并发安全管理和路径参数解析等关键点,为更复杂需求推荐第三方框架如 Gin、Echo 和 Chi。
|
12月前
|
开发框架 .NET 开发者
简化 ASP.NET Core 依赖注入(DI)注册-Scrutor
Scrutor 是一个简化 ASP.NET Core 应用程序中依赖注入(DI)注册过程的开源库,支持自动扫描和注册服务。通过简单的配置,开发者可以轻松地从指定程序集中筛选、注册服务,并设置其生命周期,同时支持服务装饰等高级功能。适用于大型项目,提高代码的可维护性和简洁性。仓库地址:&lt;https://github.com/khellang/Scrutor&gt;
303 5
|
6月前
|
自然语言处理 算法 API
阿里云增值税发票识别NET Rest API调用示例
本文介绍了使用NET代码调用阿里云增值税发票识别API的实现方式。通过示例代码,详细展示了如何构造请求、设置签名以及发送HTTP请求的具体步骤。代码中涵盖了请求参数的处理、签名生成逻辑(如HMAC-SHA256算法)以及调用API后的结果处理。此外,还提供了运行结果的截图和参考文档链接,帮助开发者更好地理解和应用该接口。
435 4
|
8月前
|
中间件 Go
Golang | Gin:net/http与Gin启动web服务的简单比较
总的来说,`net/http`和 `Gin`都是优秀的库,它们各有优缺点。你应该根据你的需求和经验来选择最适合你的工具。希望这个比较可以帮助你做出决策。
360 35
|
8月前
|
移动开发 前端开发 JavaScript
H5 页面与 Web 页面的制作方法
H5页面制作利用HTML5、CSS3和JavaScript技术,结合H5编辑器或框架(如Adobe Dreamweaver、Ionic),注重移动设备兼容性与响应式布局。Web页面制作则基于传统HTML、CSS和JavaScript,借助文本编辑器或IDE完成开发。两者区别在于技术版本、交互性和浏览器支持:H5更互动、现代,但可能不兼容旧浏览器;Web页面更静态、兼容性广。根据需求选择:高交互选H5,广泛兼容选Web。
1078 6
|
10月前
|
存储 JSON JavaScript
WEB CAD插件通过上下文对象MxPluginContext修改UI界面的方法
本文介绍了如何使用MxPluginContext动态控制MxCAD项目的UI界面。通过该上下文对象,开发者可以灵活设置UI配置,如控制操作栏显隐、编辑按钮、添加侧边栏等。具体方法包括调用`getUiConfig()`获取并修改`mxUiConfig.json`中的属性,实现界面的定制化。此外,还提供了控制命令行聚焦的功能,解决输入框焦点锁定问题。详细代码示例和效果对比图展示了具体实现步骤,帮助开发者更好地适配项目需求。
|
12月前
|
运维 前端开发 C#
一套以用户体验出发的.NET8 Web开源框架
一套以用户体验出发的.NET8 Web开源框架
313 7
一套以用户体验出发的.NET8 Web开源框架
|
11月前
|
开发框架 数据可视化 .NET
.NET 中管理 Web API 文档的两种方式
.NET 中管理 Web API 文档的两种方式
206 14

热门文章

最新文章