GlobalExceptionMiddleware.cs 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161
  1. using Infrastructure;
  2. using Infrastructure.Attribute;
  3. using Infrastructure.Model;
  4. using Microsoft.AspNetCore.Http;
  5. using Microsoft.AspNetCore.Http.Features;
  6. using NLog;
  7. using System.Text.Encodings.Web;
  8. using ZR.Common;
  9. using ZR.Infrastructure.IPTools;
  10. using ZR.Model.System;
  11. using ZR.ServiceCore.Services;
  12. using textJson = System.Text.Json;
  13. namespace ZR.ServiceCore.Middleware
  14. {
  15. /// <summary>
  16. /// 全局异常处理中间件
  17. /// 调用 app.UseMiddlewareGlobalExceptionMiddleware>();
  18. /// </summary>
  19. public class GlobalExceptionMiddleware
  20. {
  21. private readonly RequestDelegate next;
  22. private readonly ISysOperLogService SysOperLogService;
  23. static readonly Logger Logger = LogManager.GetCurrentClassLogger();
  24. private readonly textJson.JsonSerializerOptions options = new()
  25. {
  26. Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping,
  27. PropertyNamingPolicy = textJson.JsonNamingPolicy.CamelCase,
  28. WriteIndented = true
  29. };
  30. /// <summary>
  31. ///
  32. /// </summary>
  33. /// <param name="next"></param>
  34. /// <param name="sysOperLog"></param>
  35. public GlobalExceptionMiddleware(RequestDelegate next, ISysOperLogService sysOperLog)
  36. {
  37. this.next = next;
  38. this.SysOperLogService = sysOperLog;
  39. }
  40. public async Task Invoke(HttpContext context)
  41. {
  42. try
  43. {
  44. await next(context);
  45. }
  46. catch (Exception ex)
  47. {
  48. await HandleExceptionAsync(context, ex);
  49. }
  50. }
  51. private async Task HandleExceptionAsync(HttpContext context, Exception ex)
  52. {
  53. LogLevel logLevel = LogLevel.Info;
  54. int code = (int)ResultCode.GLOBAL_ERROR;
  55. string msg;
  56. string error = string.Empty;
  57. bool notice = true;
  58. //自定义异常
  59. if (ex is CustomException customException)
  60. {
  61. code = customException.Code;
  62. msg = customException.Message;
  63. error = customException.LogMsg;
  64. notice = customException.Notice;
  65. }
  66. else if (ex is ArgumentException)//参数异常
  67. {
  68. code = (int)ResultCode.PARAM_ERROR;
  69. msg = ex.Message;
  70. }
  71. else
  72. {
  73. var q1 = "Exception has been thrown by the target of an invocation";
  74. var an1 = string.Empty;
  75. if (ex.Message.Contains(q1))
  76. {
  77. an1 = $"====请查看issue:https://gitee.com/izory/ZrAdminNetCore/issues/I6S4DZ";
  78. }
  79. msg = "服务器好像出了点问题,请联系系统管理员...";
  80. error = $"异常原因:{ex.Message}{an1}";
  81. logLevel = LogLevel.Error;
  82. context.Response.StatusCode = 500;
  83. }
  84. ApiResult apiResult = new(code, msg);
  85. #if DEBUG
  86. if (logLevel == LogLevel.Error)
  87. {
  88. apiResult.Add("error", "请在issue里面寻找答案或者官方文档查看常见问题:https://gitee.com/izory/ZrAdminNetCore/issues");
  89. }
  90. #endif
  91. string responseResult = textJson.JsonSerializer.Serialize(apiResult, options);
  92. string ip = HttpContextExtension.GetClientUserIp(context);
  93. var ip_info = IpTool.Search(ip);
  94. SysOperLog sysOperLog = new()
  95. {
  96. Status = 1,
  97. OperIp = ip,
  98. OperUrl = HttpContextExtension.GetRequestUrl(context),
  99. RequestMethod = context.Request.Method,
  100. JsonResult = responseResult,
  101. ErrorMsg = string.IsNullOrEmpty(error) ? msg : error,
  102. OperName = HttpContextExtension.GetName(context),
  103. OperLocation = ip_info.Province + " " + ip_info.City,
  104. OperTime = DateTime.Now,
  105. OperParam = HttpContextExtension.GetRequestValue(context, context.Request.Method)
  106. };
  107. var endpoint = GetEndpoint(context);
  108. if (endpoint != null)
  109. {
  110. var logAttribute = endpoint.Metadata.GetMetadata<LogAttribute>();
  111. if (logAttribute != null)
  112. {
  113. sysOperLog.BusinessType = (int)logAttribute.BusinessType;
  114. sysOperLog.Title = logAttribute?.Title;
  115. sysOperLog.OperParam = logAttribute.IsSaveRequestData ? sysOperLog.OperParam : "";
  116. sysOperLog.JsonResult = logAttribute.IsSaveResponseData ? sysOperLog.JsonResult : "";
  117. }
  118. }
  119. LogEventInfo ei = new(logLevel, "GlobalExceptionMiddleware", error)
  120. {
  121. Exception = ex,
  122. Message = error
  123. };
  124. ei.Properties["status"] = 1;//走正常返回都是通过走GlobalExceptionFilter不通过
  125. ei.Properties["jsonResult"] = responseResult;
  126. ei.Properties["requestParam"] = sysOperLog.OperParam;
  127. ei.Properties["user"] = sysOperLog.OperName;
  128. Logger.Log(ei);
  129. context.Response.ContentType = "text/json;charset=utf-8";
  130. await context.Response.WriteAsync(responseResult, System.Text.Encoding.UTF8);
  131. string errorMsg = $"> 操作人:{sysOperLog.OperName}" +
  132. $"\n> 操作地区:{sysOperLog.OperIp}({sysOperLog.OperLocation})" +
  133. $"\n> 操作模块:{sysOperLog.Title}" +
  134. $"\n> 操作地址:{sysOperLog.OperUrl}" +
  135. $"\n> 错误信息:{msg}\n\n> {error}";
  136. SysOperLogService.InsertOperlog(sysOperLog);
  137. if (!notice) return;
  138. WxNoticeHelper.SendMsg("系统异常", errorMsg, msgType: WxNoticeHelper.MsgType.markdown);
  139. }
  140. public static Endpoint GetEndpoint(HttpContext context)
  141. {
  142. if (context == null)
  143. {
  144. throw new ArgumentNullException(nameof(context));
  145. }
  146. return context.Features.Get<IEndpointFeature>()?.Endpoint;
  147. }
  148. }
  149. }