OperLogFilter.cs 4.48 KB
using HHECS.WebCommon.Config;
using HHECS.WebCommon.Json;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc.Controllers;
using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.Net.Http.Headers;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Dynamic;

namespace HHECS.Web.Aop
{
    /// <summary>
    ///  操作记录日志
    ///  action 请求前,请求后 
    /// </summary>
    public class OperLogFilter : ActionFilterAttribute
    {
        #region  property
        /// <summary>
        /// action 请求参数
        /// </summary>
        private string actionArguments { get; set; }

        private Stopwatch Stopwatch { get; set; }

        /// <summary>
        /// ioc 数据库访问层注入
        /// </summary>
        //private readonly WorkshopService _app;

        /// <summary>
        /// action操作 标识 (新增,删除,编辑,上传等等)
        /// </summary>
        private static Dictionary<string, string> operType { get; set; }

        /// <summary>
        /// 请求体上下文
        /// </summary>
        private HttpContext httpContext { get; set; }

        /// <summary>
        /// 用户信息
        /// </summary>
        //private AuthStrategyContext currentUser { get; set; }

        #endregion

        public OperLogFilter()
        {
            operType = ConfigRead.GetInstance.GetOperType();
        }

        public override void OnActionExecuting(ActionExecutingContext context)
        {
            base.OnActionExecuting(context);
            Stopwatch = new Stopwatch();
            Stopwatch.Start();
            httpContext = context.HttpContext;
            actionArguments = JsonConvert.SerializeObject(context.ActionArguments).Replace("\r", "").Replace("\n", "");
        }

        public override void OnActionExecuted(ActionExecutedContext context)
        {
            base.OnActionExecuted(context);
            Stopwatch.Stop();
            //Net Core 2.1Filter里面获取Controller、Action,请求方法,请求头部,请求参数
            //https://blog.csdn.net/mango_love/article/details/84992020
            var description = (ControllerActionDescriptor)context.ActionDescriptor;
            var actionName = description.ActionName;
            var otype = operType.ContainsKey(actionName) ? operType[actionName] : "其他";
            dynamic response;
            if (context.HttpContext.Request.Method.ToLower() == "get")
            {
                //get直接取地址参数
                response = context.HttpContext.Request.QueryString.ToString();
            }
            else
            {
                dynamic result = context.Result;
                response = IsPropertyExist(result, "Value") ? result.Value : "在返回结果前发生了异常";
            }
            InserSysoperLog(otype, response, Stopwatch.Elapsed.TotalMilliseconds);
        }

        #region 自定义方法
        /// <summary>
        /// 写入日志 异步
        /// </summary>
        private void InserSysoperLog(string otype, dynamic response, double totalMilliseconds)
        {
            bool isOk = response is string;
            if (!isOk) response = JsonHelper.Instance.Serialize(response);

            string url = httpContext.Request.Host + httpContext.Request.Path + httpContext.Request.QueryString;
            var dc = new Dictionary<string, object>
            {
                {"url", url},
                {"operType", otype},
                {"method", httpContext.Request.Method},
                {"request",httpContext.Request.Headers[HeaderNames.UserAgent].ToString()},
                {"parameter", actionArguments},

                {"response", response},
                {"totalMilliseconds", totalMilliseconds},
                {"logTime", DateTime.Now},
                {"name", ""},
                {"ip", httpContext.Connection.RemoteIpAddress.ToString()},
                {"createTime", DateTime.Now},
                {"createBy", "currentUser.User.Account"}
            };
            //字典 异步写入日志

        }

        /// <summary>
        /// 动态类型 dynamic 是否存在某个属性
        /// </summary>
        public static bool IsPropertyExist(dynamic data, string propertyname)
        {
            if (data is ExpandoObject)
                return ((IDictionary<string, object>)data).ContainsKey(propertyname);
            return data.GetType().GetProperty(propertyname) != null;
        }
        #endregion
    }
}