Filter-Controller级别的捕捉异常
新建GlobalExceptionsFilter
新建类GlobalExceptionsFilter继承自IAsyncExceptionFilter也可以集成同步的接口ExceptionFilter建议用异步的。
/// <summary>/// 只能管到Controller 之外的异常无法捕获/// </summary>public class GlobalExceptionsFilter : IAsyncExceptionFilter{private readonly ILogHelper _log;public GlobalExceptionsFilter(ILogHelper log){_log = log;//这就是之前做的日志方法}public Task OnExceptionAsync(ExceptionContext context){if (context.ExceptionHandled == false){Exception ex = context.Exception;//这里给系统分配标识,监控异常肯定不止一个系统。int sysId = 1;//这里获取服务器ip时,需要考虑如果是使用nginx做了负载,这里要兼容负载后的ip,//监控了ip方便定位到底是那台服务器出故障了string ip = context.HttpContext.Connection.RemoteIpAddress.ToString();var uri = context.HttpContext.Request.Path.Value;_log.LogErr("Controller全局异常", $"系统编号:{sysId},主机IP:{ip}\r\r<br>异常Uri:{uri}\r\r<br>异常描述:{ex.Message}\r\r<br>堆栈信息:{ex.StackTrace}");context.Result = new JsonResult(new CorePeoject.ViewModel.MessageModel<object>{Msg= "Controller全局异常拦截:" + ex.Message});}context.ExceptionHandled = true; //异常已处理了return Task.CompletedTask;}}
context.ExceptionHandled = true; //代表此异常已处理,无需后续拦截器处理
配置
API
Startup中ConfigureServices中增加配置
services.AddControllers(options =>{options.Filters.Add(typeof(Filter.GlobalExceptionsFilter));});
MVC
Startup中ConfigureServices中增加配置
services.AddMvc(option =>{option.Filters.Add(typeof(GlobalExceptionFilter));});
Middlerware级别异常捕捉
新建异常捕捉管道,在最外层进行捕捉,可以捕捉Controller以外的异常
新建GlobalExceptionMiddleware
/// <summary>/// 全局异常拦截器 GlobalExceptionsFilter无法拦截的在此拦截/// </summary>public class GlobalExceptionMiddleware{private readonly RequestDelegate _next;private readonly ILogHelper _log;public GlobalExceptionMiddleware(RequestDelegate next, ILogHelper log){_next = next;_log = log;}public async Task Invoke(HttpContext context){try{await _next.Invoke(context);}catch (Exception ex){await HandleExceptionAsync(context, ex);}}private async Task HandleExceptionAsync(HttpContext context, Exception e){int sysId = 1;//可以配置string ip = context.Connection.RemoteIpAddress.ToString();var uri = context.Request.Path.Value;_log.LogErr("Middleware全局异常", $"系统编号:{sysId},主机IP:{ip}\r\r<br>异常Uri:{uri}\r\r<br>异常描述:{e.Message}\r\r<br>堆栈信息:\r\r<br>{e.StackTrace}");var result = JsonHelper.SerializeObjectAsync((new CorePeoject.ViewModel.MessageModel<object>{Msg = "Middleware全局异常拦截:"+e.Message}));context.Response.ContentType = "application/json;charset=utf-8";await context.Response.WriteAsync(await result);}}
配置中间件
Startup的Configure中配置
///全局异常拦截中间件 建议放在最外围app.UseMiddleware<GlobalExceptionMiddleware>();
测试
在Controller中直接抛出 异常测试GlobalExceptionsFilter的捕捉 关闭Filter拦截 测试中间件捕捉
附录:Jsonhelper
public static class JsonHelper{//static JsonConvertHelp jsonConvertHelp = new JsonConvertHelp();static private JsonSerializerSettings w = null;static private JsonSerializerSettings r = null;static private readonly object locker = new object();static JsonHelper(){if (w == null || r == null){lock (locker){w = new JsonSerializerSettings();w.ContractResolver = new CamelCasePropertyNamesContractResolver();w.DateFormatString = "yyyy-MM-dd HH:mm:ss.fff";//w.Converters.Add(jsonConvertHelp);r = new JsonSerializerSettings{ContractResolver = new CamelCasePropertyNamesContractResolver()};// s1.Converters.Add(jsonConvertHelp);}}}/// <summary>/// 将对象序列化为JSON格式/// </summary>/// <param name="o">对象</param>/// <param name="isCamel">是否转换成驼峰式命名</param>/// <returns>json字符串</returns>public static Task<string> SerializeObjectAsync<T>(T o, bool isCamel = false) where T : class{if (o == null) return Task.FromResult("");return isCamel ? Task.Run(() => JsonConvert.SerializeObject(o, w)) :Task.Run(() => JsonConvert.SerializeObject(o));// return json;}/// <summary>/// 解析JSON字符串生成对象实体/// </summary>/// <typeparam name="T">对象类型</typeparam>/// <param name="json">json字符串(eg.{"ID":"112","Name":"石子儿"})</param>/// <param name="isCamel">是否转换成驼峰式命名</param>/// <returns>对象实体</returns>public static Task<T> DeserializeJsonToObjectAsync<T>(string json, bool isCamel = false) where T : class{return isCamel ?Task.Run(() => JsonConvert.DeserializeObject<T>(json, r)): Task.Run(() => JsonConvert.DeserializeObject<T>(json));}/// <summary>/// 将对象序列化为JSON格式/// </summary>/// <param name="o">对象</param>/// <param name="isCamel">是否转换成驼峰式命名</param>/// <returns>json字符串</returns>public static string SerializeObject<T>(T o, bool isCamel = false) where T : class{if (o == null) return "";return isCamel ? JsonConvert.SerializeObject(o, w) :JsonConvert.SerializeObject(o);}/// <summary>/// 解析JSON字符串生成对象实体/// </summary>/// <typeparam name="T">对象类型</typeparam>/// <param name="json">json字符串(eg.{"ID":"112","Name":"石子儿"})</param>/// <param name="isCamel">是否转换成驼峰式命名</param>/// <returns>对象实体</returns>public static T DeserializeJsonToObject<T>(string json, bool isCamel = false) where T : class{return isCamel ?JsonConvert.DeserializeObject<T>(json, r):JsonConvert.DeserializeObject<T>(json);}}
