
异常处理中间件:区分真异常与逻辑异常
处理异常的方式
- 异常处理页
- 异常处理匿名委托方法
- IExceptionFilter
- ExceptionFilterAttribute
Demo
项目结构
创建相关Model
IKnownException.cs
public interface IKnownException
{
public string Message { get; }
public int ErrorCode { get; }
public object[] ErrorData { get; }
}
KnownException.cs
public class KnownException : IKnownException
{
public string Message { get; private set; }
public int ErrorCode { get; private set; }
public object[] ErrorData { get; private set; }
public readonly static IKnownException Unknown = new KnownException { Message = "未知错误", ErrorCode = 9999 };
public static IKnownException FromKnownException(IKnownException exception)
{
return new KnownException { Message = exception.Message, ErrorCode = exception.ErrorCode, ErrorData = exception.ErrorData };
}
}
MyExceptionFilter.cs
public class MyExceptionFilter : IExceptionFilter
{
public void OnException(ExceptionContext context)
{
IKnownException knownException = context.Exception as IKnownException;
if (knownException == null)
{
var logger = context.HttpContext.RequestServices.GetService<ILogger<MyExceptionFilterAttribute>>();
logger.LogError(context.Exception, context.Exception.Message);
knownException = KnownException.Unknown;
context.HttpContext.Response.StatusCode = StatusCodes.Status500InternalServerError;
}
else
{
knownException = KnownException.FromKnownException(knownException);
context.HttpContext.Response.StatusCode = StatusCodes.Status200OK;
}
context.Result = new JsonResult(knownException)
{
ContentType = "application/json; charset=utf-8"
};
}
}
MyServerException.cs
public class MyServerException : Exception, IKnownException
{
public MyServerException(string message, int errorCode, params object[] errorData) : base(message)
{
this.ErrorCode = errorCode;
this.ErrorData = errorData;
}
public int ErrorCode { get; private set; }
public object[] ErrorData { get; private set; }
}
创建错误处理MyExceptionFilterAttribute.cs过滤器
public class MyExceptionFilterAttribute : ExceptionFilterAttribute
{
public override void OnException(ExceptionContext context)
{
IKnownException knownException = context.Exception as IKnownException;
if (knownException == null)
{
var logger = context.HttpContext.RequestServices.GetService<ILogger<MyExceptionFilterAttribute>>();
logger.LogError(context.Exception, context.Exception.Message);
knownException = KnownException.Unknown;
context.HttpContext.Response.StatusCode = StatusCodes.Status500InternalServerError;
}
else
{
knownException = KnownException.FromKnownException(knownException);
context.HttpContext.Response.StatusCode = StatusCodes.Status200OK;
}
context.Result = new JsonResult(knownException)
{
ContentType = "application/json; charset=utf-8"
};
}
}
创建错误处理ErrorController.cs控制器
[AllowAnonymous]
public class ErrorController : Controller
{
[Route("/error")]
public IActionResult Index()
{
var exceptionHandlerPathFeature = HttpContext.Features.Get<IExceptionHandlerPathFeature>();
var ex = exceptionHandlerPathFeature?.Error;
var knownException = ex as IKnownException;
if (knownException == null)
{
var logger = HttpContext.RequestServices.GetService<ILogger<MyExceptionFilterAttribute>>();
logger.LogError(ex, ex.Message);
knownException = KnownException.Unknown;
}
else
{
knownException = KnownException.FromKnownException(knownException);
}
return View(knownException);
}
}
创建报错方法
WeatherForecastController.cs
[ApiController]
[Route("[controller]")]
public class WeatherForecastController : ControllerBase
{
[HttpGet]
public int Get()
{
throw new MyServerException("服务出错了", 65);
}
}
通过控制器处理错误
修改Startup.cs 的 Configure方法,添加处理异常路径
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
app.UseExceptionHandler("/error");
app.UseRouting();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
}
注意请修改ConfigureServices方法
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc();//.AddControllers();
}
运行结果
通过委托的方式处理错误
修改Startup.cs 的 Configure方法
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
app.UseExceptionHandler(errApp =>
{
errApp.Run(async context =>
{
var exceptionHandlerPathFeature = context.Features.Get<IExceptionHandlerPathFeature>();
IKnownException knownException = exceptionHandlerPathFeature.Error as IKnownException;
if (knownException == null)
{
var logger = context.RequestServices.GetService<ILogger<MyExceptionFilterAttribute>>();
logger.LogError(exceptionHandlerPathFeature.Error, exceptionHandlerPathFeature.Error.Message);
knownException = KnownException.Unknown;
context.Response.StatusCode = StatusCodes.Status500InternalServerError;
}
else
{
knownException = KnownException.FromKnownException(knownException);
context.Response.StatusCode = StatusCodes.Status200OK;
}
var jsonOptions = context.RequestServices.GetService<IOptions<JsonOptions>>();
context.Response.ContentType = "application/json; charset=utf-8";
await context.Response.WriteAsync(System.Text.Json.JsonSerializer.Serialize(knownException, jsonOptions.Value.JsonSerializerOptions));
});
});
app.UseRouting();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
}
运行结果(这里有部分乱码)
通过过滤器的方式处理错误
Configure方法
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc(mvcOptions =>
{
//mvcOptions.Filters.Add<MyExceptionFilter>();
mvcOptions.Filters.Add<MyExceptionFilterAttribute>();
}).AddJsonOptions(jsonoptions =>
{
jsonoptions.JsonSerializerOptions.Encoder = System.Text.Encodings.Web.JavaScriptEncoder.UnsafeRelaxedJsonEscaping;
});
}
运行结果
异常处理技巧
- 用特定的异常类活接口表示业务逻辑异常
- 为业务逻辑异常定义全局错误码
- 为未知异常定义特定的输出信息和错误码
- 对于已知业务逻辑异常响应 HTTP 200(监控系统友好)
- 对于未预见的异常响应 HTTP 500
- 为所有的异常记录详细的日志
欢迎加群讨论技术,1群:677373950(满了,可以加,但通过不了),2群:656732739
评价
排名
2
文章
657
粉丝
44
评论
93
docker中Sware集群与service
尘叶心繁 : 想学呀!我教你呀
一个bug让程序员走上法庭 索赔金额达400亿日元
叼着奶瓶逛酒吧 : 所以说做程序员也要懂点法律知识
.net core 塑形资源
剑轩 : 收藏收藏
映射AutoMapper
剑轩 :
好是好,这个对效率影响大不大哇,效率高不高
一个bug让程序员走上法庭 索赔金额达400亿日元
剑轩 : 有点可怕
ASP.NET Core 服务注册生命周期
剑轩 :
http://www.tnblog.net/aojiancc2/article/details/167
ICP备案 :渝ICP备18016597号-1
网站信息:2018-2025TNBLOG.NET
技术交流:群号656732739
联系我们:contact@tnblog.net
公网安备:
50010702506256


欢迎加群交流技术