.NET 6 API + Middleware + Audit rail

Request相关的参数。 需要在Program.cs 注入IHttpContextAccessor

cs 复制代码
 //Below services used to get token
         services.AddHttpContextAccessor();
         services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
cs 复制代码
        public string GetClientIpAddress()
        {
            var clientIp = _httpContextAccessor?.HttpContext?.Connection?.RemoteIpAddress?.ToString();

            return clientIp!;
        }

        public string GetBrowserInfo()
        {
            var browserInfo = _httpContextAccessor?.HttpContext?.Request?.Headers["User-Agent"].ToString();

            return string.IsNullOrEmpty(browserInfo) ? string.Empty : browserInfo;
        }

        public string GetMethodName()
        {
            var url = _httpContextAccessor?.HttpContext?.Request.Path;
            return string.IsNullOrEmpty(url) ? string.Empty : url;
        }


        public string GetParametersInfo()
        {
            var parameter = string.Empty;
            try
            {
                var request = _httpContextAccessor?.HttpContext?.Request;
                if (request != null)
                {
                    var methond = request.Method;
                    Dictionary<string, object> keyValuePairs = new Dictionary<string, object>();

                    if (methond == "GET")
                    {
                        if (request.Query != null && request.Query.Count() > 0)
                        {
                            foreach (var item in request.Query)
                            {
                                keyValuePairs.Add(item.Key, item.Value);
                            }
                            parameter = JsonConvert.SerializeObject(keyValuePairs);
                        }
                    }
                    else
                    {
                        if (request.HasFormContentType)
                        {
                            //For Upload documents
                            if (request.Form.Keys != null)
                            {
                                foreach (var itemFormKey in request.Form.Keys)
                                {
                                    keyValuePairs.Add(itemFormKey, request.Form[itemFormKey]);
                                }
                            }

                            if (request.Form.Files != null && request.Form.Files.Count() > 0)
                            {
                                keyValuePairs.Add($"Attachments-{Guid.NewGuid()}", string.Join("; ", request.Form.Files.Select(x => x.FileName)));
                            }

                            parameter = JsonConvert.SerializeObject(keyValuePairs);
                        }
                        else if (request.Query != null && request.Query.Count() > 0)
                        {
                            foreach (var item in request.Query)
                            {
                                keyValuePairs.Add(item.Key, item.Value);
                            }
                            parameter = JsonConvert.SerializeObject(keyValuePairs);
                        }
                        if (request.HasJsonContentType())
                        {
                            var rawMessage = GetRawBodyAsync(request).Result;
                            parameter += rawMessage;
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                parameter = ex.Message;
                Log.Error(ex, $"GetParametersInfo failed. {ex.Message}");
            }

            return parameter;
        }

Create GlobalRequestHandlingMiddleware

cs 复制代码
using Microsoft.AspNetCore.Http;
using Newtonsoft.Json;
using System.Net;
using Microsoft.AspNetCore.Builder;
using Newtonsoft.Json.Serialization;
using NotImplementedException = System.NotImplementedException;
using UnauthorizedAccessException = System.UnauthorizedAccessException;
using KeyNotFoundException = System.Collections.Generic.KeyNotFoundException;
using Serilog;
using System.Diagnostics;
	
	/// <summary>
    /// Web API Audit Trail and Exception Result handler
    /// </summary>
    public class GlobalRequestHandlingMiddleware
    {
        private readonly RequestDelegate _next;

        private readonly IAuditTrailManager _auditTrailManager;

        public GlobalRequestHandlingMiddleware(RequestDelegate next, IAuditTrailManager auditTrailManager)
        {
            _next = next;
            _auditTrailManager = auditTrailManager ?? throw new ArgumentNullException(nameof(auditTrailManager));
        }

        public async Task Invoke(HttpContext context)
        {

            Stopwatch stopwatch = new();
            stopwatch.Start();

            try
            {
                auditTrailLogDto auditInfo = _auditTrailManager.GenerateWebAPIAuditTrailLogWithoutSaveToDb();

                await _next(context);

                stopwatch.Stop();
                auditInfo.ExecutionDuration = (int)stopwatch.ElapsedMilliseconds;
                _auditTrailManager.InsertWebAPIAuditTrailLogs(auditInfo);
            }
            catch (Exception ex)
            {
                await HandleExceptionAsync(context, ex, stopwatch);
            }
        }

        private Task HandleExceptionAsync(HttpContext context, Exception exception, Stopwatch stopwatch)
        {
			/**
			//GenerateWebAPIAuditTrailLogWithoutSaveToDb
			 var auditInfo = new AbpAuditLogDto
			 {
				 ServiceName = serviceName,//_httpContextAccessor?.HttpContext?.Request.Path
				 ClientIpAddress = GetClientIpAddress(),
				 BrowserInfo = GetBrowserInfo(),
				 Parameters = GetParametersInfo(),
				 MethodName = GetMethodName(),
				 ExecutionTime = DateTime.UtcNow,
			 };
			
			
			*/
            AuditTrailLogDto auditInfo = _auditTrailManager.GenerateWebAPIAuditTrailLogWithoutSaveToDb();//generate audittrail

            HttpStatusCode status = HttpStatusCode.BadRequest;
            var stackTrace = exception.StackTrace;
            string message = string.Empty;
            Guid errorCode = Guid.NewGuid();

            var exceptionType = exception.GetType();
            if (exceptionType == typeof(UserFriendlyException))
            {
                var userException = (exception as UserFriendlyException);
                status = userException?.Code ?? HttpStatusCode.BadRequest;
                message = userException?.Details ?? exception.Message;
            }
            else if (exceptionType == typeof(BadRequestException))
            {
                message = exception.Message;
                status = HttpStatusCode.BadRequest;
            }
            else if (exceptionType == typeof(NotFoundException) || exceptionType == typeof(KeyNotFoundException))
            {
                message = exception.Message;
                status = HttpStatusCode.NotFound;
                stackTrace = exception.StackTrace;
            }
            else if (exceptionType == typeof(NotImplementedException))
            {
                status = HttpStatusCode.NotImplemented;
                message = exception.Message;
            }
            else if (exceptionType == typeof(UnauthorizedAccessException))
            {
                status = HttpStatusCode.Unauthorized;
                message = exception.Message;
            }
            else
            {
                status = HttpStatusCode.InternalServerError;
                message = exception.Message;
                stackTrace = exception.StackTrace;
            }
            Log.Error(exception, $"ServiceName: {auditInfo.ServiceName}. Status Code: {status},message: {message}.");
  

            GlobalExceptionResponse exceptionResponseBase = new()
            {
                Success = false,
                Error = new()
                {
                    Message = message,
                    Code = (int)status,
                    Details = message,
                    StackTrace = stackTrace,
                    Id = errorCode,
                    DateTime = DateTime.UtcNow
                }
            };

            stopwatch.Stop();
            auditInfo.Exception = $"Status Code: {status},message: {message}. Details: {exception}";
            auditInfo.ExecutionDuration = (int)stopwatch.ElapsedMilliseconds;
            _auditTrailManager.InsertWebAPIAuditTrailLogs(auditInfo);//save to db

            var exceptionResult = JsonConvert.SerializeObject(exceptionResponseBase, new JsonSerializerSettings { ContractResolver = new CamelCasePropertyNamesContractResolver() });
            context.Response.ContentType = HttpHeaderConstant.RESPONSE_HEADER_APPLICATION_JSON;
            context.Response.StatusCode = (int)status;
            Log.Error(exception, $"ServiceName: {auditInfo.ServiceName}. Status Code: {status},message: {message}. User Id: {auditInfo.UserId}. RemoteIpAddress: {auditInfo.ClientIpAddress}. {exceptionResult}");
            if (context != null)
            {
                return context.Response.WriteAsync(exceptionResult);
            }
            else
            {
                return Task.FromResult(exceptionResult);
            }
        }
    }

Use Middleware

cs 复制代码
    /// <summary>
    /// Web API Audit Trail and Exception Result handler
    /// </summary>
    public static class ApplicationBuilderExtensions
    {
        /// <summary>
        /// Web API Audit Trail and Exception Result handler
        /// </summary>
        /// <param name="applicationBuilder"></param>
        /// <returns></returns>
        public static IApplicationBuilder UseGlobalRequestHandling(this IApplicationBuilder applicationBuilder)
            => applicationBuilder.UseMiddleware<GlobalRequestHandlingMiddleware>();
    }

Register in Program.cs

cs 复制代码
         //Below services used to get token
         services.AddHttpContextAccessor();
         services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
         services.AddSingleton<IPrincipalAccessor, PrincipalAccessor>();

           app.UseGlobalRequestHandling();//add Global Resust HandlingMiddleware
相关推荐
冬天vs不冷5 分钟前
Linux用户与权限管理详解
linux·运维·chrome
凯子坚持 c1 小时前
深入Linux权限体系:守护系统安全的第一道防线
linux·运维·系统安全
摸鱼也很难4 小时前
Docker 镜像加速和配置的分享 && 云服务器搭建beef-xss
运维·docker·容器
woshilys5 小时前
sql server 查询对象的修改时间
运维·数据库·sqlserver
疯狂飙车的蜗牛5 小时前
从零玩转CanMV-K230(4)-小核Linux驱动开发参考
linux·运维·驱动开发
恩爸编程6 小时前
探索 Nginx:Web 世界的幕后英雄
运维·nginx·nginx反向代理·nginx是什么·nginx静态资源服务器·nginx服务器·nginx解决哪些问题
Michaelwubo7 小时前
Docker dockerfile镜像编码 centos7
运维·docker·容器
好像是个likun8 小时前
使用docker拉取镜像很慢或者总是超时的问题
运维·docker·容器
数据的世界0110 小时前
.NET开发人员学习书籍推荐
学习·.net
cominglately10 小时前
centos单机部署seata
linux·运维·centos