1、自定义中间件处理异常(推荐) 参考:https://www.csframework.com/archive/1/arc-1-20211230-4180.htm
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");

posted on 2022-07-25 21:26  邢帅杰  阅读(622)  评论(0编辑  收藏  举报