异常处理的几种方式:
1、通过异常过滤器捕获异常进行处理
2、自定义异常处理中间件,自定义异常处理中间件,中间件依托于请求管道运行,并且中间件的执行是有序的,与业务隔离开的,将中间件放置在请求管道开始能够捕获到全局异常。
配置异常处理中间件:
1、 编写自定义异常处理中间件,CustomExceptionHandleMiddleware.cs
using IPSP.Common; using Microsoft.IdentityModel.Tokens; using System.Net; using System.Text.Json; namespace IPSP.Middlewares { public static class CutomExceptionHandleMiddlewareExtension { public static IApplicationBuilder UseCustomExceptionHandleMiddleware(this IApplicationBuilder builder) { return builder.UseMiddleware<CustomExceptionHandleMiddleware>(); } } public class CustomExceptionHandleMiddleware { private readonly RequestDelegate _next; private readonly IWebHostEnvironment _env; private readonly ILogger<CustomExceptionHandleMiddleware> _logger; public CustomExceptionHandleMiddleware(RequestDelegate next, IWebHostEnvironment env, ILogger<CustomExceptionHandleMiddleware> logger) { _next = next; _env = env; _logger = logger; } public async Task InvokeAsync(HttpContext context) { string message = string.Empty; HttpStatusCode code = HttpStatusCode.InternalServerError; ResposeResult result = new ResposeResult(code,message); try { await _next(context); } catch (SecurityTokenExpiredException exception) { _logger.LogError(exception,exception.Message); SetUnAuthorizeRespose(exception,ref result); await WriteToResposeAsync(context,result); } catch (UnauthorizedAccessException exception) { _logger.LogError(exception,exception.Message); SetUnAuthorizeRespose(exception,ref result); await WriteToResposeAsync(context,result); } catch (Exception exception) { //asp.net core 引入了 HttpContext.RequestAborted 来监听用户取消请求 //由用户取消请求触发的异常 if (context.RequestAborted.IsCancellationRequested && (exception is TaskCanceledException || exception is OperationCanceledException)) { _logger.LogInformation(exception, exception.Message); } else { _logger.LogError(exception, exception.Message); } if (_env.IsDevelopment()) { var dic = new Dictionary<string, string> { ["Exception"] = exception.Message, ["StackTrace"] = exception.StackTrace, }; result.Message = JsonSerializer.Serialize(dic); } else { result.Message = message; } await WriteToResposeAsync(context,result); } } public async Task WriteToResposeAsync(HttpContext context,ResposeResult result) { if (context.Response.HasStarted) { throw new InvalidOperationException("The response has already started, the http status code middleware will not be executed."); } string json = JsonSerializer.Serialize(result); context.Response.StatusCode = (int)result.Code; context.Response.ContentType = "application/json"; await context.Response.WriteAsync(json); } public void SetUnAuthorizeRespose(Exception exception,ref ResposeResult result) { result.Code = HttpStatusCode.Unauthorized; if (_env.IsDevelopment()) { var dic = new Dictionary<string, string> { ["Exception"] = exception.Message, ["StackTrace"] = exception.StackTrace }; if (exception is SecurityTokenExpiredException tokenException) { dic.Add("Expires",tokenException.Expires.ToString()); result.Message = JsonSerializer.Serialize(dic); } } } } }
public class ResposeResult { public HttpStatusCode Code { get; set; } public string Message { get; set; } public ResposeResult(HttpStatusCode code, string message="") { Code = code; Message = message; } }
2、 在Program.cs文件将中间件放置在请求管道的开始处,这样才能捕获到全局的异常
var app = builder.Build(); //注意请将异常处理中间件放置在请求管道的开始处,这样才能捕获到全局的异常 //使用自定义异常处理中间件 app.UseCustomExceptionHandleMiddleware();
3、 测试捕捉异常,查看日志记录
[HttpGet] public async Task<IActionResult> UserLogin([FromQuery]LoginModel model) { User user = new User(); user.Badge = model.Badge; user.Password = model.Password; int num = 0; int value = 10 / num; var result = await _userservice.Login(user.Badge,user.Password); if (result != null) { _logger.LogInformation($"{result.Badge}-{result.CName}在{DateTime.Now.ToString("yyyy-dd-MM HH:mm:ss")}登入了IPSP系统!"); } return Ok(result); }
查看日志记录:
注意:异常处理中间件和异常过滤器都可以用来捕获程序的异常,只是捕获异常的范围不一样。IExceptionFilter 作为过滤器的一种,它只能捕获控制器内部的异常,如果我们的异常发生控制器之外就无法捕获了,将异常中间件放置在请求管道的第一个,可以捕获到全局的异常。
标签:Core,exception,自定义,中间件,result,context,异常,public From: https://www.cnblogs.com/xjxue/p/17589787.html