.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
相关推荐
布鲁飞丝7 小时前
vivo Pulsar 万亿级消息处理实践()-Ansible运维部署
运维·ansible
XR1234567887 小时前
企业全光网络架构选型技术白皮书:从物理层到运维层的全链路分析
运维·网络·架构
HiDev_7 小时前
【非标自动化】2、认识元器件(直线模组)
运维·自动化
龙仔7258 小时前
人大金仓 KingbaseES V8 只读账号创建完整运维笔记
运维·笔记·sql·人大金仓
我不管我就要叫小猪8 小时前
嵌入式Linux----网络通信
linux·运维·服务器
江湖有缘9 小时前
Docker实战 :使用Docker部署OneTerm堡垒机
运维·docker·容器
姜太小白9 小时前
【Linux】df -h 卡住问题的通用排查与解决方案总结
linux·运维·php
界面开发小八哥9 小时前
界面控件DevExpress Blazor v26.1新版亮点 - 辅助功能增强
.net·界面控件·blazor·devexpress·ui开发
fengyehongWorld10 小时前
Linux 终端快捷键
linux·运维
看昭奚恤哭10 小时前
平滑加权轮询负载均衡的底层逻辑
运维·负载均衡