1、自定义中间件处理异常(推荐) 参考:https://www.csframework.com/archive/1/arc-1-20211230-4180.htm
注入中间件
方式1:app.UseMiddleware<ExceptionHandlingMiddleware>();然后在Action或者Service中直接抛异常,就会走异常处理。
方式2:使用扩展方法
using System.Net; using System.Text.Json; using ExceptionHandling.Models.Responses; namespace ExceptionHandling.Middlewares; public class ExceptionHandlingMiddleware { private readonly RequestDelegate _next; // 用来处理上下文请求 private readonly ILogger<ExceptionHandlingMiddleware> _logger; public ExceptionHandlingMiddleware(RequestDelegate next,ILogger<ExceptionHandlingMiddleware> logger) { _next = next; _logger = logger; } public async Task InvokeAsync(HttpContext httpContext) { try { await _next(httpContext); //要么在中间件中处理,要么被传递到下一个中间件中去 } catch (Exception ex) { //_logger.LogError(ex, "##异常来源:{0}", httpContext.Request.Path);//直接记录ex await HandleExceptionAsync(httpContext, ex); // 捕获异常了在HandleExceptionAsync中处理 } } private async Task HandleExceptionAsync(HttpContext context, Exception exception) { context.Response.ContentType = "application/json"; // 返回json 类型 var response = context.Response; var errorResponse = new ErrorResponse { Success = false }; // 自定义的异常错误信息类型 switch (exception) { case ApplicationException ex: if (ex.Message.Contains("Invalid token")) { response.StatusCode = (int) HttpStatusCode.Forbidden; errorResponse.Message = ex.Message; break; } response.StatusCode = (int) HttpStatusCode.BadRequest; errorResponse.Message = ex.Message; break; case KeyNotFoundException ex: response.StatusCode = (int) HttpStatusCode.NotFound; errorResponse.Message = ex.Message; break; default: response.StatusCode = (int) HttpStatusCode.InternalServerError; errorResponse.Message = "Internal Server errors. Check Logs!"; break; } _logger.LogError(exception.Message); var result = JsonSerializer.Serialize(errorResponse); await context.Response.WriteAsync(result); } } public class ErrorResponse { public int StatusCode { get; set; } public string Message { get; set; } = string.Empty; public bool Success { get; set; } }
方式1:app.UseMiddleware<ExceptionHandlingMiddleware>();然后在Action或者Service中直接抛异常,就会走异常处理。
方式2:使用扩展方法
// Extension method used to add the middleware to the HTTP request pipeline. public static class ExceptionHandlingMiddlewareExtensions { public static IApplicationBuilder UseExceptionHandlingMiddleware(this IApplicationBuilder builder) { return builder.UseMiddleware<ExceptionHandlingMiddleware>(); } }
2、使用过滤器 参考:https://blog.csdn.net/Daniel_yka/article/details/121062319
public class CustomExceptionFilterAttribute: ExceptionFilterAttribute { private readonly ILogger<WeatherForecastController> _logger; public CustomExceptionFilterAttribute(ILogger<WeatherForecastController> logger) { _logger = logger; } public override void OnException(ExceptionContext context) { //判断该异常有没有处理 if (!context.ExceptionHandled) { _logger.LogError($"Path:{context.HttpContext.Request.Path}Message:{context.Exception.Message}"); context.Result = new JsonResult(new {Reslut = false,Msg = "发生异常,请联系管理员"}); context.ExceptionHandled = true; } } }
然后再在Startup下面的ConfigureServices注册这个类:services.AddControllers(o=>o.Filters.Add(typeof(CustomExceptionFilterAttribute)));
此时当程序中有异常,便会进入该方法,我们就能在这里统一管理异常。
log4net使用:
引入包:Microsoft.Extensions.Logging
Microsoft.Extensions.Logging.Log4Net.AspNetCore
配置日志
builder.Host.ConfigureDefaults(args).ConfigureLogging(p => { p.AddFilter("System", LogLevel.Warning); //过滤掉系统默认的一些日志 p.AddFilter("Microsoft", LogLevel.Warning);//过滤掉系统默认的一些日志 var path = Directory.GetCurrentDirectory() + "\\log4net.config"; //不带参数:表示log4net.config的配置文件就在应用程序根目录下,也可以指定配置文件的路径 p.AddLog4Net(path); });
根目录log4net.config
<log4net> <appender name="ConsoleAppender" type="log4net.Appender.ConsoleAppender"> <layout type="log4net.Layout.PatternLayout" value="%date [%thread] %-5level %logger - %message%newline" /> </appender> <appender name="FileAppender" type="log4net.Appender.FileAppender"> <file value="log-file.log" /> <appendToFile value="true" /> <layout type="log4net.Layout.PatternLayout"> <conversionPattern value="%date [%thread] %-5level %logger [%property{NDC}] - %message%newline" /> </layout> </appender> <appender name="RollingLogFileAppender" type="log4net.Appender.RollingFileAppender"> <file value="logfile/" /> <appendToFile value="true" /> <rollingStyle value="Composite" /> <staticLogFileName value="false" /> <datePattern value="yyyyMMdd'.log'" /> <maxSizeRollBackups value="10" /> <maximumFileSize value="1MB" /> <layout type="log4net.Layout.PatternLayout"> <conversionPattern value="%date [%thread] %-5level %logger [%property{NDC}] - %message%newline" /> </layout> </appender> <!-- Setup the root category, add the appenders and set the default level --> <root> <level value="ALL" /> <appender-ref ref="ConsoleAppender" /> <appender-ref ref="FileAppender" /> <appender-ref ref="RollingLogFileAppender" /> </root> </log4net>
构造函数注入:private readonly ILogger<HomeController> _logger;
_logger.LogInformation("test log info");