正文
1 2 3 4 | if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); } |
这样写入中间件哈,那么在env环境下就会去执行UseDeveloperExceptionPage。
1 2 3 4 5 6 7 8 9 | public static IApplicationBuilder UseDeveloperExceptionPage( this IApplicationBuilder app) { if (app == null ) { throw new ArgumentNullException(nameof(app)); } return app.UseMiddleware<DeveloperExceptionPageMiddleware>(); } |
那么我们应该去看DeveloperExceptionPageMiddleware中间件哈。
那么这里介绍它是如何能够捕获其他中间件的异常的哈。
里面的invoke:
其实它的操作是很简单的,直接在外面套了try catch。
里面的异常处理怎么处理的可以直接去看DeveloperExceptionPageMiddleware 中间件,里面的操作也比较简单处理。
测试:
1 2 3 4 5 6 | [HttpGet] public int GetService([FromServices]ISelfService selfService) { throw new System.Exception( "错误" ); return 1; } |
结果:
因为上面说了,这个是dev环境下,那么生产环境不能直接给用户看到错误信息。
正式环境:
1 | app.UseExceptionHandler( "/error" ); |
将错误转移到/error 处理。具体UseExceptionHandler细节篇里面介绍,有许多可以借鉴的地方。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | [ApiController] [Route( "[controller]" )] public class ErrorController : Controller { public ILogger<ErrorController> _logger; public ErrorController(ILogger<ErrorController> logger) { this ._logger = logger; } public IActionResult Index() { var exceptionHandlerPathFeature = HttpContext.Features.Get<IExceptionHandlerPathFeature>(); var ex = exceptionHandlerPathFeature?.Error; var knownException = ex as IKnownException; if (knownException == null ) { _logger.LogError(ex, ex.Message); knownException = KnownException.Unknow; } else { knownException = KnownException.FromKnowException(knowException); } return View(knownException); } } |
视图:
1 2 3 4 5 6 7 8 9 10 11 12 13 | < html > < head > </ head > < body > < div > 错误码: @Model.ErrorCode </ div > < div > 错误信息: @Model.Message </ div > </ body > </ html > |
IKnownException:
1 2 3 4 5 6 7 8 | public interface IKnownException { public string Message { get ; } public int ErrorCode { get ; } public object [] ErrorData { get ; } } |
KnownException:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | 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 Unknow = new KnownException { Message = "未知错误" , ErrorCode = 99 }; public static IKnownException FromKnowException(IKnownException Exception) { return new KnownException{Message = Exception.Message, ErrorCode = Exception.ErrorCode, ErrorData = Exception.ErrorData}; } } |
测试1:
1 2 3 4 5 6 | [HttpGet] public int GetService([FromServices]ISelfService selfService) { throw new System.Exception( "错误" ); return 1; } |
这种属于未知异常,结果:
现在弄一个支付异常:
1 2 3 4 5 6 7 8 9 10 11 12 | public class PayErrorException : Exception, IKnownException { public PayErrorException( 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 ; } } |
测试2:
1 2 3 4 5 6 7 | [HttpGet] public int GetService([FromServices]ISelfService selfService) { throw new PayErrorException( "支付错误" ,405, null ); return 1; } |
将异常处理放入到中间件分支中。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | 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)); }); }); |
效果一样就不演示了。如果是已知异常错误码应该为200,一个是500异常是系统无法处理,系统错误,但是已知错误是属于系统正常处理。另一个是监控系统,认为报500错误,是会持续放出系统警告。
还有一种局部异常,只在mvc中生效,而不是全局生效:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | 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" }; } } |
在mvc 中注册:
1 2 3 4 5 6 7 | services.AddMvc(mvcOptions => { mvcOptions.Filters.Add<MyExceptionFilter>(); }).AddJsonOptions(jsonOptions => { jsonOptions.JsonSerializerOptions.Encoder = System.Text.Encodings.Web.JavaScriptEncoder.UnsafeRelaxedJsonEscaping; }); |
最后介绍一种,只作用于某个控制器,或者action:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | 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" }; } } |
查看一下ExceptionFilterAttribute头部:
1 2 | [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = true , Inherited = true )] public abstract class ExceptionFilterAttribute : Attribute, IAsyncExceptionFilter, IExceptionFilter, IOrderedFilter |
上面标志了可以放于类上也可以放于方法上。所以可以放至在controller上,也可以action上,看需求了。
结
以上就是.net core异常中间件的使用的详细内容,更多关于.net core异常中间件的资料请关注自学编程网其它相关文章!
- 本文固定链接: https://zxbcw.cn/post/214964/
- 转载请注明:必须在正文中标注并保留原文链接
- QQ群: PHP高手阵营官方总群(344148542)
- QQ群: Yii2.0开发(304864863)