首页 > 编程语言 >如何在 ASP.NET Core Web API 方法执行前后 “偷偷“ 作一些 “坏“ 事?初识 ActionFilterAttribute

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

时间:2024-09-19 22:45:24浏览次数:10  
标签:Web 控制器 ASP Core ... AttributeSample ActionFilterAttribute logger public

image

前言:什么是 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 的命名空间
  2. ActionFilterAttribute 如果需要在构造方法中注入某些依赖,比如注入 ILogger,有几个使用方法:
    • TypeFilter,无需在IOC中注册,有自实现,本文例子即是使用这种方式
    • ServiceFilter,需要在 Program.cs 中针对该过滤器注册服务才能使用
    • 自定义 CustomIOCFilterFactoryAttribute 实现,依然需要对过滤器进行服务注册
    • 方法2和3比较复杂,以后有时间再针对这两种方式写一些例子
  3. 没有注入其他依赖的 ActionFilterAttribute 如一般 Attribute 使用即可,比如本文的第 3 个 ActionFilterAttribute
    • [Test3ActionFilter("Jacky")]

我是老杨,一个执着于编程乐趣、至今奋斗在一线的 10年+ 资深研发老鸟,是软件项目管理师,也是快乐的程序猿,持续免费分享全栈实用编程技巧、项目管理经验和职场成长心得!欢迎关注老杨的公众号(名称:代码掌控者),和你共同探索代码世界的奥秘!

标签:Web,控制器,ASP,Core,...,AttributeSample,ActionFilterAttribute,logger,public
From: https://www.cnblogs.com/JackyGz/p/18421535

相关文章

  • ssm基于javaweb的疫情管理系统的设计与实现
    系统包含:源码+论文所用技术:SpringBoot+Vue+SSM+Mybatis+Mysql免费提供给大家参考或者学习,获取源码请私聊我需要定制请私聊目录摘要 IAbstract II第1章绪论 11.1研究背景及意义 11.2研究内容 1第2章开发环境与技术 32.1Java语言 32.2MYSQL数据库 3......
  • web - JavaScript
    JavaScript1,JavaScript简介JavaScript是一门跨平台、面向对象的脚本语言,而Java语言也是跨平台的、面向对象的语言,只不过Java是编译语言,是需要编译成字节码文件才能运行的;JavaScript是脚本语言,不需要编译,由浏览器直接解析并执行。JavaScript是用来控制网页行为的,它能使......
  • 基于MicroPython的Raspberry Pi Pico控制LED灯闪烁的设计方案
       以下是一个基于MicroPython的RaspberryPiPico控制LED灯闪烁的设计方案:一、硬件准备:1. RaspberryPiPico开发板2. 一个LED灯3. 一个220Ω4. 杜邦线若干。5.3.3V直流电源二、硬件连接:1.将Pico开发板的VSYS连接到3.3V直流电源的正极,开发板的GND引脚连......
  • Framebuffer core
    Framebuffercore,在Linux系统中,主要指的是与Framebuffer设备驱动相关的核心代码和功能。Framebuffer是Linux内核为显示设备提供的一套应用程序接口(API),它抽象了显示硬件的底层差异,使得开发者可以通过操作内存中的帧缓冲区来间接控制显示设备,从而实现图形的显示和渲染。Framebuffer......
  • .net core使用RabbitMQ
    目录1.基本概念2.环境搭建3.使用 RabbitMQ是一个可靠且成熟的消息传递和流代理,它很容易部署在云环境、内部部署和本地机器上。它目前被全世界数百万人使用。1.基本概念生产者(Producer)生产者是一个发送消息的程序。发送消息的程序可以是任何语言编写的,只要它能够......
  • dotnet framework 4.7.2 webapi 配置的swagger添加登录验证
    项目是.netframework4.7.2加webapi写的接口,使用Swashbuckle包添加的swagger支持 App_Start\SwaggerConfig.cs中加c.CustomAsset("index",thisAssembly,"WebApi.Jwt.SwaggerExtensions.index.html",false);1usingSystem.Web.Http;2usingWebActivato......
  • ASP.NET Core中如何对不同类型的用户进行区别限流
    老板提出了一个新需求,从某某天起,免费用户每天只能查询100次,收费用户100W次。这是一个限流问题,聪明的你也一定想到了如何去做:记录用户每一天的查询次数,然后根据当前用户的类型使用不同的数字做比较,超过指定的数字就返回错误。嗯,原理就是这么简单。不过真正写起来还要考虑更多问题......
  • 易优eyoucms网站报错 \core\library\think\App.php Fatal error: Call to undefin
    当你遇到 Fatalerror:Calltoundefinedfunctionthink\switch_citysite() 这样的错误时,说明在代码中调用了一个未定义的函数 think\switch_citysite()。这种情况通常是因为函数没有被正确地引入或者该函数根本不存在于当前的代码库中。解决方案确认函数的存在检查 s......
  • 易优eyoucms网站详情页报错报错 \core\library\think\Loader.php 类不存在:app\co
    类不存在:app\common\model\Pic,这个错误表明PHP无法找到类 app\common\model\Pic。这通常是因为类文件未被正确加载或命名空间配置不正确导致的。以下是一些可能的解决步骤:1.确认类文件路径确保类文件 Pic 的路径正确并且文件存在。检查文件路径确认 app\common\model......
  • 易优eyoucms网站报错,\\core\\library\\think\\db\\Connection.php
     报错\\\\core\\\\library\\\\think\\\\db\\\\Connection.php第380行左右数据表或视图不存在,请联系技术处理。[错误代码]SQLSTATE[42S02]:Basetableorviewnotfound:1146Table'eyoucms.ey_channeltype'doesn'texist根据提供的错误信息 SQLSTATE[42S02]:......