Filter-Controller级别的捕捉异常

只能处理Controller级别的异常

新建GlobalExceptionsFilter

新建类GlobalExceptionsFilter继承自IAsyncExceptionFilter也可以集成同步的接口ExceptionFilter建议用异步的。

  1. /// <summary>
  2. /// 只能管到Controller 之外的异常无法捕获
  3. /// </summary>
  4. public class GlobalExceptionsFilter : IAsyncExceptionFilter
  5. {
  6. private readonly ILogHelper _log;
  7. public GlobalExceptionsFilter(ILogHelper log)
  8. {
  9. _log = log;//这就是之前做的日志方法
  10. }
  11. public Task OnExceptionAsync(ExceptionContext context)
  12. {
  13. if (context.ExceptionHandled == false)
  14. {
  15. Exception ex = context.Exception;
  16. //这里给系统分配标识,监控异常肯定不止一个系统。
  17. int sysId = 1;
  18. //这里获取服务器ip时,需要考虑如果是使用nginx做了负载,这里要兼容负载后的ip,
  19. //监控了ip方便定位到底是那台服务器出故障了
  20. string ip = context.HttpContext.Connection.RemoteIpAddress.ToString();
  21. var uri = context.HttpContext.Request.Path.Value;
  22. _log.LogErr("Controller全局异常", $"系统编号:{sysId},主机IP:{ip}\r\r<br>异常Uri:{uri}\r\r<br>异常描述:{ex.Message}\r\r<br>堆栈信息:{ex.StackTrace}");
  23. context.Result = new JsonResult(new CorePeoject.ViewModel.MessageModel<object>
  24. {
  25. Msg= "Controller全局异常拦截:" + ex.Message
  26. });
  27. }
  28. context.ExceptionHandled = true; //异常已处理了
  29. return Task.CompletedTask;
  30. }
  31. }

context.ExceptionHandled = true; //代表此异常已处理,无需后续拦截器处理

配置

API

Startup中ConfigureServices中增加配置

  1. services.AddControllers(options =>
  2. {
  3. options.Filters.Add(typeof(Filter.GlobalExceptionsFilter));
  4. });

MVC

Startup中ConfigureServices中增加配置

  1. services.AddMvc(option =>
  2. {
  3. option.Filters.Add(typeof(GlobalExceptionFilter));
  4. });

Middlerware级别异常捕捉

新建异常捕捉管道,在最外层进行捕捉,可以捕捉Controller以外的异常

新建GlobalExceptionMiddleware

  1. /// <summary>
  2. /// 全局异常拦截器 GlobalExceptionsFilter无法拦截的在此拦截
  3. /// </summary>
  4. public class GlobalExceptionMiddleware
  5. {
  6. private readonly RequestDelegate _next;
  7. private readonly ILogHelper _log;
  8. public GlobalExceptionMiddleware(RequestDelegate next, ILogHelper log)
  9. {
  10. _next = next;
  11. _log = log;
  12. }
  13. public async Task Invoke(HttpContext context)
  14. {
  15. try
  16. {
  17. await _next.Invoke(context);
  18. }
  19. catch (Exception ex)
  20. {
  21. await HandleExceptionAsync(context, ex);
  22. }
  23. }
  24. private async Task HandleExceptionAsync(HttpContext context, Exception e)
  25. {
  26. int sysId = 1;//可以配置
  27. string ip = context.Connection.RemoteIpAddress.ToString();
  28. var uri = context.Request.Path.Value;
  29. _log.LogErr("Middleware全局异常", $"系统编号:{sysId},主机IP:{ip}\r\r<br>异常Uri:{uri}\r\r<br>异常描述:{e.Message}\r\r<br>堆栈信息:\r\r<br>{e.StackTrace}");
  30. var result = JsonHelper.SerializeObjectAsync((new CorePeoject.ViewModel.MessageModel<object>
  31. {
  32. Msg = "Middleware全局异常拦截:"+e.Message
  33. }));
  34. context.Response.ContentType = "application/json;charset=utf-8";
  35. await context.Response.WriteAsync(await result);
  36. }
  37. }

配置中间件

Startup的Configure中配置

  1. ///全局异常拦截中间件 建议放在最外围
  2. app.UseMiddleware<GlobalExceptionMiddleware>();

测试

在Controller中直接抛出 异常测试GlobalExceptionsFilter的捕捉 关闭Filter拦截 测试中间件捕捉

附录:Jsonhelper

  1. public static class JsonHelper
  2. {
  3. //static JsonConvertHelp jsonConvertHelp = new JsonConvertHelp();
  4. static private JsonSerializerSettings w = null;
  5. static private JsonSerializerSettings r = null;
  6. static private readonly object locker = new object();
  7. static JsonHelper()
  8. {
  9. if (w == null || r == null)
  10. {
  11. lock (locker)
  12. {
  13. w = new JsonSerializerSettings();
  14. w.ContractResolver = new CamelCasePropertyNamesContractResolver();
  15. w.DateFormatString = "yyyy-MM-dd HH:mm:ss.fff";
  16. //w.Converters.Add(jsonConvertHelp);
  17. r = new JsonSerializerSettings
  18. {
  19. ContractResolver = new CamelCasePropertyNamesContractResolver()
  20. };
  21. // s1.Converters.Add(jsonConvertHelp);
  22. }
  23. }
  24. }
  25. /// <summary>
  26. /// 将对象序列化为JSON格式
  27. /// </summary>
  28. /// <param name="o">对象</param>
  29. /// <param name="isCamel">是否转换成驼峰式命名</param>
  30. /// <returns>json字符串</returns>
  31. public static Task<string> SerializeObjectAsync<T>(T o, bool isCamel = false) where T : class
  32. {
  33. if (o == null) return Task.FromResult("");
  34. return isCamel ? Task.Run(() => JsonConvert.SerializeObject(o, w)) :
  35. Task.Run(() => JsonConvert.SerializeObject(o));
  36. // return json;
  37. }
  38. /// <summary>
  39. /// 解析JSON字符串生成对象实体
  40. /// </summary>
  41. /// <typeparam name="T">对象类型</typeparam>
  42. /// <param name="json">json字符串(eg.{"ID":"112","Name":"石子儿"})</param>
  43. /// <param name="isCamel">是否转换成驼峰式命名</param>
  44. /// <returns>对象实体</returns>
  45. public static Task<T> DeserializeJsonToObjectAsync<T>(string json, bool isCamel = false) where T : class
  46. {
  47. return isCamel ?
  48. Task.Run(() => JsonConvert.DeserializeObject<T>(json, r))
  49. : Task.Run(() => JsonConvert.DeserializeObject<T>(json));
  50. }
  51. /// <summary>
  52. /// 将对象序列化为JSON格式
  53. /// </summary>
  54. /// <param name="o">对象</param>
  55. /// <param name="isCamel">是否转换成驼峰式命名</param>
  56. /// <returns>json字符串</returns>
  57. public static string SerializeObject<T>(T o, bool isCamel = false) where T : class
  58. {
  59. if (o == null) return "";
  60. return isCamel ? JsonConvert.SerializeObject(o, w) :
  61. JsonConvert.SerializeObject(o);
  62. }
  63. /// <summary>
  64. /// 解析JSON字符串生成对象实体
  65. /// </summary>
  66. /// <typeparam name="T">对象类型</typeparam>
  67. /// <param name="json">json字符串(eg.{"ID":"112","Name":"石子儿"})</param>
  68. /// <param name="isCamel">是否转换成驼峰式命名</param>
  69. /// <returns>对象实体</returns>
  70. public static T DeserializeJsonToObject<T>(string json, bool isCamel = false) where T : class
  71. {
  72. return isCamel ?
  73. JsonConvert.DeserializeObject<T>(json, r):
  74. JsonConvert.DeserializeObject<T>(json);
  75. }
  76. }