.Net5 框架搭建(四):基于ActionFilter记录操作日志

2023-11-22 06:48

本文主要是介绍.Net5 框架搭建(四):基于ActionFilter记录操作日志,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

前言

在上篇文章《.Net5 框架搭建(三):基于ExceptionFilter+NLog封装异常日志收集》中我们提到了过滤器,也对异常信息做了日志记录,本文接着对五大过滤器中的操作过滤器Action Filter进一步实战功能的延续。
问:那么什么业务场景适合用到操作过滤器呢?
答:日志统计、权限过滤

ActionFilter/操作过滤器

官网截图
官网
大致意思,提供两种接口IActionFilter 或 IAsyncActionFilter 接口。

1、IActionFilter
这个接口提供两个方法
OnActionExecuted(ActionExecutedContext) 在操作执行之后、操作结果之前调用。

OnActionExecuting(ActionExecutingContext) 在模型绑定完成后,在执行操作之前调用。

2、IAsyncActionFilter
只提供一种方法
OnActionExecutionAsync(ActionExecutingContext, ActionExecutionDelegate)
模型绑定完成后,在操作之前以异步方式调用。

创建一个自定义操作过滤器

这里我是继承了IAsyncActionFilter,就是为了省麻烦
LogActionFilter.cs

    /// <summary>/// 操作日志过滤器/// </summary>public class LogActionFilter : IAsyncActionFilter{private readonly ILogHandler _logHandler;public LogActionFilter(ILogHandler logHandler){_logHandler = logHandler;}public Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next){if (context.ActionDescriptor.EndpointMetadata.Any(m => m.GetType() == typeof(NoLogAttribute))){return next();}return _logHandler.LogAsync(context, next);}}

新增一个自定义属性类,用于区别一些不想做操作日志记录的方法
NoLogAttribute.cs

    /// <summary>/// 不记录操作日志的属性/// </summary>[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = true)]public class NoLogAttribute : Attribute{}

LogHandler.cs

    /// <summary>/// 操作日志处理/// </summary>public class LogHandler : ILogHandler{private readonly ILogger _logger;private readonly ISystemOperateLogBLL _systemOperateLogBLL;public LogHandler(ILogger<LogHandler> logger, ISystemOperateLogBLL systemOperateLogBLL){_logger = logger;_systemOperateLogBLL = systemOperateLogBLL;}public async Task LogAsync(ActionExecutingContext context, ActionExecutionDelegate next){var sw = new Stopwatch();sw.Start();var actionExecutedContext = await next();sw.Stop();//操作参数var args = JsonConvert.SerializeObject(context.ActionArguments);//操作结果//var result1 = JsonConvert.SerializeObject(actionResult?.Value);try{var model = new SystemOperateLog{Params = args,ApiMethod = context.HttpContext.Request.Method.ToLower(),ApiPath = context.ActionDescriptor.AttributeRouteInfo.Template.ToLower(),ElapsedMilliseconds = sw.ElapsedMilliseconds.ObjToInt()};ObjectResult result = actionExecutedContext.Result as ObjectResult;if (result != null){model.Result = JsonConvert.SerializeObject(result.Value);model.LogStatus = 1;}string ua = context.HttpContext.Request.Headers["User-Agent"];//记得添加UAParservar client = UAParser.Parser.GetDefault().Parse(ua);var device = client.Device.Family;device = device.ToLower() == "other" ? "" : device;model.Browser = client.UA.Family;model.Os = client.OS.Family;model.Device = device;model.BrowserInfo = ua;model.IP = IPHelper.GetIP(context?.HttpContext?.Request);await _systemOperateLogBLL.AddLog(model);}catch (Exception ex){_logger.LogError("操作日志插入异常:{@ex}", ex);}}}

ILogHandler.cs

    /// <summary>/// 操作日志处理接口/// </summary>public interface ILogHandler{/// <summary>/// 写操作日志/// </summary>/// <param name="context"></param>/// <param name="next"></param>/// <returns></returns>Task LogAsync(ActionExecutingContext context, ActionExecutionDelegate next);}

IPHelper.cs

    public class IPHelper{/// <summary>/// 是否为ip/// </summary>/// <param name="ip"></param>/// <returns></returns>public static bool IsIP(string ip){return Regex.IsMatch(ip, @"^((2[0-4]\d|25[0-5]|[01]?\d\d?)\.){3}(2[0-4]\d|25[0-5]|[01]?\d\d?)$");}/// <summary>/// 获得IP地址/// </summary>/// <param name="request"></param>/// <returns></returns>public static string GetIP(HttpRequest request){if (request == null){return "";}string ip = request.Headers["X-Real-IP"].FirstOrDefault();if (!ip.IsNotEmptyOrNull()){ip = request.Headers["X-Forwarded-For"].FirstOrDefault();}if (!ip.IsNotEmptyOrNull()){ip = request.HttpContext?.Connection?.RemoteIpAddress?.ToString();}if (!ip.IsNotEmptyOrNull() || !IsIP(ip.Split(":")[0])){ip = "127.0.0.1";}return ip;}/// <summary>/// 获得MAC地址/// </summary>/// <returns></returns>public static string GetMACIp(){//本地计算机网络连接信息//IPGlobalProperties computerProperties = IPGlobalProperties.GetIPGlobalProperties();//获取本机电脑名//var HostName = computerProperties.HostName;//获取域名//var DomainName = computerProperties.DomainName;//获取本机所有网络连接NetworkInterface[] nics = NetworkInterface.GetAllNetworkInterfaces();if (nics == null || nics.Length < 1){return "";}var MACIp = "";foreach (NetworkInterface adapter in nics){var adapterName = adapter.Name;var adapterDescription = adapter.Description;var NetworkInterfaceType = adapter.NetworkInterfaceType;if (adapterName == "本地连接" || adapterName == "WLAN"){PhysicalAddress address = adapter.GetPhysicalAddress();byte[] bytes = address.GetAddressBytes();for (int i = 0; i < bytes.Length; i++){MACIp += bytes[i].ToString("X2");if (i != bytes.Length - 1){MACIp += "-";}}}}return MACIp;}}

全局注册

            services.AddControllers(options =>{//添加全局异常过滤器options.Filters.Add<GlobalExceptionsFilter>();//日志过滤器options.Filters.Add<LogActionFilter>();});

测试

        [HttpGet("getUser")]public async Task<dynamic> Get(long id){//_logger.LogError("LogError3333");var obj = await _systemUserBLL.GetUser(id);return obj;}[NoLog][HttpPost("updateUser")]public dynamic UpdateUser(SystemUser user){var obj = _systemUserBLL.Update(user);return obj;}

期望效果:记录getUser、不记录updateUser

运行截图

在这里插入图片描述
在这里插入图片描述

完整代码已上传码云:https://gitee.com/shao-jiayong/cuo-ding

这篇关于.Net5 框架搭建(四):基于ActionFilter记录操作日志的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/408282

相关文章

搭建Kafka+zookeeper集群调度

前言 硬件环境 172.18.0.5        kafkazk1        Kafka+zookeeper                Kafka Broker集群 172.18.0.6        kafkazk2        Kafka+zookeeper                Kafka Broker集群 172.18.0.7        kafkazk3

【IPV6从入门到起飞】5-1 IPV6+Home Assistant(搭建基本环境)

【IPV6从入门到起飞】5-1 IPV6+Home Assistant #搭建基本环境 1 背景2 docker下载 hass3 创建容器4 浏览器访问 hass5 手机APP远程访问hass6 更多玩法 1 背景 既然电脑可以IPV6入站,手机流量可以访问IPV6网络的服务,为什么不在电脑搭建Home Assistant(hass),来控制你的设备呢?@智能家居 @万物互联

cross-plateform 跨平台应用程序-03-如果只选择一个框架,应该选择哪一个?

跨平台系列 cross-plateform 跨平台应用程序-01-概览 cross-plateform 跨平台应用程序-02-有哪些主流技术栈? cross-plateform 跨平台应用程序-03-如果只选择一个框架,应该选择哪一个? cross-plateform 跨平台应用程序-04-React Native 介绍 cross-plateform 跨平台应用程序-05-Flutte

Node.js学习记录(二)

目录 一、express 1、初识express 2、安装express 3、创建并启动web服务器 4、监听 GET&POST 请求、响应内容给客户端 5、获取URL中携带的查询参数 6、获取URL中动态参数 7、静态资源托管 二、工具nodemon 三、express路由 1、express中路由 2、路由的匹配 3、路由模块化 4、路由模块添加前缀 四、中间件

pico2 开发环境搭建-基于ubuntu

pico2 开发环境搭建-基于ubuntu 安装编译工具链下载sdk 和example编译example 安装编译工具链 sudo apt install cmake gcc-arm-none-eabi libnewlib-arm-none-eabi libstdc++-arm-none-eabi-newlib 注意cmake的版本,需要在3.17 以上 下载sdk 和ex

Spring框架5 - 容器的扩展功能 (ApplicationContext)

private static ApplicationContext applicationContext;static {applicationContext = new ClassPathXmlApplicationContext("bean.xml");} BeanFactory的功能扩展类ApplicationContext进行深度的分析。ApplicationConext与 BeanF

flume系列之:查看flume系统日志、查看统计flume日志类型、查看flume日志

遍历指定目录下多个文件查找指定内容 服务器系统日志会记录flume相关日志 cat /var/log/messages |grep -i oom 查找系统日志中关于flume的指定日志 import osdef search_string_in_files(directory, search_string):count = 0

我在移动打工的日志

客户:给我搞一下录音 我:不会。不在服务范围。 客户:是不想吧 我:笑嘻嘻(气笑) 客户:小姑娘明明会,却欺负老人 我:笑嘻嘻 客户:那我交话费 我:手机号 客户:给我搞录音 我:不会。不懂。没搞过。 客户:那我交话费 我:手机号。这是电信的啊!!我这是中国移动!! 客户:我不管,我要充话费,充话费是你们的 我:可是这是移动!!中国移动!! 客户:我这是手机号 我:那又如何,这是移动!你是电信!!

数据治理框架-ISO数据治理标准

引言 "数据治理"并不是一个新的概念,国内外有很多组织专注于数据治理理论和实践的研究。目前国际上,主要的数据治理框架有ISO数据治理标准、GDI数据治理框架、DAMA数据治理管理框架等。 ISO数据治理标准 改标准阐述了数据治理的标准、基本原则和数据治理模型,是一套完整的数据治理方法论。 ISO/IEC 38505标准的数据治理方法论的核心内容如下: 数据治理的目标:促进组织高效、合理地

ZooKeeper 中的 Curator 框架解析

Apache ZooKeeper 是一个为分布式应用提供一致性服务的软件。它提供了诸如配置管理、分布式同步、组服务等功能。在使用 ZooKeeper 时,Curator 是一个非常流行的客户端库,它简化了 ZooKeeper 的使用,提供了高级的抽象和丰富的工具。本文将详细介绍 Curator 框架,包括它的设计哲学、核心组件以及如何使用 Curator 来简化 ZooKeeper 的操作。 1