【C#进阶】.NET Core 中的筛选器 Filter【ActionFilterAttribute 操作筛选器,实现日志记录】
筛选器 Filter介绍 :【C#进阶】.NET Core 中的筛选器 Filter - C#初级程序员 - 博客园 (cnblogs.com)
ActionFilterAttribute 操作筛选器,实现日志记录
第一步 创建.NET CORE项目
第二步 创建操作筛选器重写类BasicAuthAttribute ,继承ActionFilterAttribute
其中 AddRequestLog、EditRequestLog这两个方法为记录请求日志,本文为记录到数据库,可以自行修改
1 using Demo.Infrastructure; 2 using Microsoft.AspNetCore.Http; 3 using Microsoft.AspNetCore.Mvc; 4 using Microsoft.AspNetCore.Mvc.Controllers; 5 using Microsoft.AspNetCore.Mvc.Filters; 6 using System; 7 using System.Collections.Generic; 8 using System.Linq; 9 using System.Text; 10 using System.Threading.Tasks; 11 12 namespace Demo 13 { 14 /// <summary> 15 /// 重写请求拦截器 16 /// </summary> 17 public class BasicAuthAttribute : ActionFilterAttribute 18 { 19 /// <summary> 20 /// Action方法调用之前执行 21 /// </summary> 22 /// <param name="context "></param> 23 public override void OnActionExecuting(ActionExecutingContext context) 24 { 25 try 26 { 27 HttpRequest request = context.HttpContext.Request; 28 ////获取请求头中的Token和TimeSpan 29 //var token = context.HttpContext.Request.Headers["Token"].ToString(); 30 //var timespan = context.HttpContext.Request.Headers["TimeSpan"].ToString(); 31 32 //string token = request.Headers["token"]; 33 34 var descriptor = context.ActionDescriptor as ControllerActionDescriptor; 35 //记录进入请求的时间 36 descriptor.Properties["enterTime"] = DateTime.Now.ToBinary(); 37 string Id = Guid.NewGuid().ToString().Substring(0, 12); 38 //记录日志Id 39 descriptor.Properties["Id"] = Id; 40 41 //获取action名称 42 string actionName = descriptor.ActionName; 43 //获取Controller 名称 44 string controllerName = descriptor.ControllerName; 45 //获取action开始执行的时间 46 DateTime enterTime = DateTime.Now; 47 //获取访问的ip 及 端口 48 string ip = context.HttpContext.Connection.RemoteIpAddress.ToString() + ':' + context.HttpContext.Connection.RemotePort.ToString(); 49 //获取用户主机名 50 string userHostName = request.Host.Value; 51 52 //获取完整请求地址 53 string urlReferrer = new StringBuilder() 54 .Append(request.Scheme) 55 .Append("://") 56 .Append(request.Host) 57 .Append(request.PathBase) 58 .Append(request.Path) 59 .Append(request.QueryString) 60 .ToString(); 61 //获取请求的浏览器名称 62 string browser = request.Headers["User-Agent"]; 63 //string userHostName = request.UserHostName; 64 //string urlReferrer = request.UrlReferrer != null ? request.UrlReferrer.AbsoluteUri : ""; 65 //string browser = request.Browser.Browser + " - " + request.Browser.Version + " - " + request.Browser.Type; 66 67 //获取request提交的参数 68 string param = string.Empty; 69 string globalParam = string.Empty; 70 foreach (var arg in context.ActionArguments) 71 { 72 string value = Newtonsoft.Json.JsonConvert.SerializeObject(arg.Value); 73 param += $"{arg.Key} : {value} \r\n"; 74 globalParam += value; 75 } 76 //写入日志记录 77 AddRequestLog(Id, Newtonsoft.Json.JsonConvert.SerializeObject(request.Headers), actionName, controllerName, urlReferrer, param, enterTime, ip, userHostName, browser); 78 } 79 catch (Exception ex) { } 80 } 81 82 /// <summary> 83 /// Action 方法调用后。Result 方法调用前执行 84 /// </summary> 85 /// <param name="context"></param> 86 public override void OnActionExecuted(ActionExecutedContext context) { } 87 88 /// <summary> 89 /// Result 方法调用前执行 90 /// </summary> 91 /// <param name="context"></param> 92 public override void OnResultExecuting(ResultExecutingContext context) { } 93 94 /// <summary> 95 /// Result 方法调用后执行 96 /// </summary> 97 /// <param name="context"></param> 98 public override void OnResultExecuted(ResultExecutedContext context) 99 { 100 try 101 { 102 HttpResponse response = context.HttpContext.Response; 103 104 var descriptor = context.ActionDescriptor as ControllerActionDescriptor; 105 object beginTime = null; 106 double costTime = 0; 107 DateTime nowDate = DateTime.Now; 108 object id = ""; 109 if (descriptor.Properties.TryGetValue("enterTime", out beginTime)) 110 { 111 //获取进入请求的时间 112 DateTime time = DateTime.FromBinary(Convert.ToInt64(beginTime)); 113 //获取执行action的耗时 114 costTime = (nowDate - time).TotalMilliseconds; 115 } 116 if (descriptor.Properties.TryGetValue("Id", out id)) { } 117 //获取response响应的结果 118 string result = string.Empty; 119 if (context.Result is ObjectResult) 120 result = Newtonsoft.Json.JsonConvert.SerializeObject(((ObjectResult)context.Result).Value); 121 if (!string.IsNullOrEmpty(id.ToString()) && id.ToString() != "") 122 { 123 EditRequestLog(id.ToString(), Newtonsoft.Json.JsonConvert.SerializeObject(response.Headers), result, nowDate, costTime); 124 } 125 } 126 catch (Exception ex) { } 127 } 128 129 130 /// <summary> 131 /// 添加Api请求记录 132 /// </summary> 133 /// <param name="ApiRequestLogId">请求日志Id</param> 134 /// <param name="Headers">请求头部信息</param> 135 /// <param name="ActionName">请求方法名</param> 136 /// <param name="ControllerName">请求控制器名</param> 137 /// <param name="UrlReferrer">请求完整地址</param> 138 /// <param name="RequestParam">请求参数</param> 139 /// <param name="TimeOn">请求开始时间</param> 140 /// <param name="IpAddress">请求Ip地址</param> 141 /// <param name="HostName">请求主机名</param> 142 /// <param name="Browser">请求浏览器信息</param> 143 public void AddRequestLog(string ApiRequestLogId, string Headers, string ActionName, string ControllerName, string UrlReferrer, string RequestParam, DateTime TimeOn, string IpAddress, string HostName, string Browser) 144 { 145 // sapParameter = sapParameter.Replace("'","\""); 146 string sqlstr = $@"INSERT INTO dbo.ApiRequestLog 147 ( 148 ApiRequestLogId, 149 Headers, 150 ActionName, 151 ControllerName, 152 UrlReferrer, 153 RequestParam, 154 TimeOn, 155 IpAddress, 156 HostName, 157 Browser 158 ) 159 VALUES 160 ( '{ApiRequestLogId}', -- ApiRequestLogId - char(12) 161 '{Headers}', -- Headers - nvarchar(500) 162 '{ActionName}', -- ActionName - nvarchar(50) 163 '{ControllerName}', -- ControllerName - nvarchar(50) 164 '{UrlReferrer}', -- UrlReferrer - nvarchar(500) 165 '{RequestParam}', -- RequestParam - nvarchar(max) 166 '{TimeOn}', -- TimeOn - datetime 167 '{IpAddress}', -- IpAddress - nvarchar(50) 168 '{HostName}', -- HostName - nvarchar(50) 169 '{Browser}' -- Browser - nvarchar(500) 170 )"; 171 172 // _logger.LogError(sqlstr); 173 try 174 { 175 var count = DapperHelper<int>.Execute(sqlstr, null); 176 } 177 catch (Exception ex) { } 178 } 179 180 /// <summary> 181 /// 更新Api请求记录 182 /// </summary> 183 /// <param name="ApiRequestLogId">接口日志Id</param> 184 /// <param name="Response">响应头</param> 185 /// <param name="ResultParam">返回参数</param> 186 /// <param name="TimeOff">请求结束时间</param> 187 /// <param name="CostTime">请求耗时(ms)</param> 188 public void EditRequestLog(string ApiRequestLogId, string Response, string ResultParam, DateTime TimeOff, double CostTime) 189 { 190 string sqlstr = $@"UPDATE dbo.ApiRequestLog SET Response = '{Response}',ResultParam = '{ResultParam}',TimeOff = '{TimeOff}',CostTime = '{CostTime}' WHERE ApiRequestLogId = '{ApiRequestLogId}'"; 191 try 192 { 193 var count = DapperHelper<int>.Execute(sqlstr, null); 194 } 195 catch (Exception ex) { } 196 } 197 } 198 /// <summary> 199 /// 不需要登陆的地方加个这个空的拦载器 200 /// </summary> 201 public class NoSignAttribute : ActionFilterAttribute { } 202 203 }
第三步:依赖注入 在Startup.cs中进行依赖注入
1 public void ConfigureServices(IServiceCollection services) 2 { 3 4 #region 全局注册自定义特性 5 services.AddControllers(options => 6 { 7 //全局注册请求拦截器 8 options.Filters.Add(typeof(BasicAuthAttribute)); 9 }); 10 #endregion 11 }
第四步:新建控制器测试
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Net.Http; 5 using System.Threading.Tasks; 12 using Microsoft.AspNetCore.Http; 13 using Microsoft.AspNetCore.Mvc; 14 using Microsoft.Extensions.Configuration;
19 namespace API.JMGO.COM.Controllers 20 { 21 [Route("api/[controller]/[action]")] 22 [ApiController] 23 public class ActivationDataController : ControllerBase 24 {163 /// <summary> 164 /// 测试 165 /// </summary> 166 /// <returns></returns> 167 [HttpGet("TestGet")] 168 public IActionResult TestGet() 169 { 170 var cfRt = appSettingsJson["apiurl"];//读取配置文件 171 return Ok(cfRt); 172 }188 } 189 }
第五步:查看数据库日志是否记录