.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
相关推荐
xuanwojiuxin1 小时前
linux panic-propagation
linux·运维·服务器
藥瓿亭3 小时前
K8S认证|CKS题库+答案| 9. 网络策略 NetworkPolicy
linux·运维·docker·云原生·容器·kubernetes·cks
liuzhenghua664 小时前
Python任务调度模型
java·运维·python
黎相思4 小时前
应用层自定义协议与序列化
运维·服务器·网络
测试开发Kevin4 小时前
详解Jenkins Pipeline 中git 命令的使用方法
运维·jenkins
什么半岛铁盒4 小时前
Linux线程与进程关系及底层实现
java·linux·运维
langmeng1105 小时前
使用docker在3台服务器上搭建基于版本redis 6.x的一主两从模式
运维·redis·docker·容器·集群
jllllyuz5 小时前
如何为服务器生成TLS证书
运维·服务器·数据库
简朴-ocean5 小时前
如何删除linux空的文件夹
linux·运维·服务器
leblancAndSherry6 小时前
Gitlab + Jenkins 实现 CICD
linux·运维·docker·kubernetes·gitlab·jenkins