.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
相关推荐
wclass-zhengge9 分钟前
SpringBoot篇(运维实用篇 - 临时属性)
运维·spring boot·后端
速盾cdn10 分钟前
速盾:什么是高防CDN?高防CDN的用处有哪些?
运维·服务器·网络·web安全
海绵波波10740 分钟前
Webserver(1.6)Linux系统IO函数
linux·运维·服务器
江水三千里1 小时前
NFS服务器
运维·服务器
forestqq1 小时前
构建后端为etcd的CoreDNS的容器集群(七)、编写适合阅读的域名管理脚本
运维·数据库·etcd
dessler1 小时前
Linux系统-开关机
linux·运维·云计算
CYRUS STUDIO1 小时前
frida脚本,自动化寻址JNI方法
android·运维·自动化·逆向·移动安全·jni·frida
petaexpress2 小时前
云存储的费用是多少?2024年最新价格表
运维·服务器·云存储·云存储的费用是多少·云存储的费用是多少最新·云存储费用
taolichao303 小时前
架设一台NFS服务器,按照要求配置
linux·运维·服务器
程序员yt3 小时前
2025秋招八股文--服务器篇
linux·运维·服务器·c++·后端·面试