在上篇文章《.Net5 框架搭建(三):基于ExceptionFilter+NLog封装异常日志收集》中我们提到了过滤器,也对异常信息做了日志记录,本文接着对五大过滤器中的操作过滤器Action Filter进一步实战功能的延续。
问:那么什么业务场景适合用到操作过滤器呢?
答:日志统计、权限过滤
官网截图
大致意思,提供两种接口IActionFilter 或 IAsyncActionFilter 接口。
1、IActionFilter
这个接口提供两个方法
OnActionExecuted(ActionExecutedContext) 在操作执行之后、操作结果之前调用。
OnActionExecuting(ActionExecutingContext) 在模型绑定完成后,在执行操作之前调用。
2、IAsyncActionFilter
只提供一种方法
OnActionExecutionAsync(ActionExecutingContext, ActionExecutionDelegate)
模型绑定完成后,在操作之前以异步方式调用。
这里我是继承了IAsyncActionFilter,就是为了省麻烦
LogActionFilter.cs
////// 操作日志过滤器 /// 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
////// 不记录操作日志的属性 /// [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = true)] public class NoLogAttribute : Attribute { }
LogHandler.cs
////// 操作日志处理 /// public class LogHandler : ILogHandler { private readonly ILogger _logger; private readonly ISystemOperateLogBLL _systemOperateLogBLL; public LogHandler(ILoggerlogger, 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"]; //记得添加UAParser var 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
////// 操作日志处理接口 /// public interface ILogHandler { ////// 写操作日志 /// /// /// ///Task LogAsync(ActionExecutingContext context, ActionExecutionDelegate next); }
IPHelper.cs
public class IPHelper
{
///
/// 是否为ip
///
///
///
public static bool IsIP(string ip)
{
return Regex.IsMatch(ip, @"^((2[0-4]d|25[0-5]|[01]?dd?).){3}(2[0-4]d|25[0-5]|[01]?dd?)$");
}
///
/// 获得IP地址
///
///
///
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;
}
///
/// 获得MAC地址
///
///
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();
//日志过滤器
options.Filters.Add();
});
测试
[HttpGet("getUser")]
public async Task 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



