.NET Core通过过滤器和中间件两种方式实现全局异常捕获和日志记录

1.一共有五类过滤器IAsyncAuthorizationFilter  IAsyncResourceFilter   IAsyncActonFilter  IAsyncExceptionFilter    IAsyncResultFilter 去掉Async就是同步的

2.注册过滤器  全局注册和Attribute注册 用在特定的Action上

通过过滤器实现全局异常处理

1.建立自己的一个过滤器

public class CustomerExceptionFilter : Attribute, IExceptionFilter
{
    private readonly ILogger logger = null;
    private readonly IHostingEnvironment environment = null;
    public CustomerExceptionFilter(ILogger<CustomerExceptionFilter> logger, IHostingEnvironment environment)
    {
        this.logger = logger;
        this.environment = environment;
    }

    public void OnException(ExceptionContext context)
    {
        Exception exception = context.Exception;
        string error = string.Empty;

        void ReadException(Exception ex)
        {
            error += string.Format("{0} | {1} | {2}", ex.Message, ex.StackTrace, ex.InnerException);
            if (ex.InnerException != null)
            {
                ReadException(ex.InnerException);
            }
        }

        ReadException(context.Exception);
        logger.LogError(error);

        ContentResult result = new ContentResult
        {
            StatusCode = 500,
            ContentType = "text/json;charset=utf-8;"
        };

        if (environment.IsDevelopment())
        {
            var json = new { message = exception.Message, detail = error };
            result.Content = JsonConvert.SerializeObject(json);
        }
        else
        {
            result.Content = "抱歉,出错了";
        }
        context.Result = result;
        context.ExceptionHandled = true;
    }
}

2.添加Nugut包 NLog.Extensions.Logging   NLog.Web.AspNetCore ,并在 Startup.cs 文件的 Configure 方法中添加扩展

public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory factory)
        {
            // 将 NLog
            factory.AddConsole(Configuration.GetSection("Logging"))
                   .AddNLog()
                   .AddDebug();

            var nlogFile = System.IO.Path.Combine(env.ContentRootPath, "nlog.config");
            env.ConfigureNLog(nlogFile);

            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }

            app.UseMvc();
        }

3.日志配置文件信息

<?xml version="1.0" encoding="utf-8" ?>
<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" autoReload="true" internalLogLevel="info">

  <!-- Load the ASP.NET Core plugin -->
  <extensions>
    <add assembly="NLog.Web.AspNetCore"/>
  </extensions>

  <!-- Layout: https://github.com/NLog/NLog/wiki/Layout%20Renderers -->
  <targets>
    <target xsi:type="File" name="errorfile" fileName="/data/logs/logfilter/error-${shortdate}.log" layout="${longdate}|${logger}|${uppercase:${level}}|  ${message} ${exception}|${aspnet-Request-Url}" />
    <target xsi:type="Null" name="blackhole" />
  </targets>

  <rules>
    <logger name="Microsoft.*" minlevel="Error" writeTo="blackhole" final="true" />
    <logger name="*" minlevel="Error" writeTo="errorfile" />
  </rules>
</nlog>

4.把这个过滤器注入到容器中

            services.AddMvc(
                options =>
                {
                    options.Filters.Add(typeof(CustomerExceptionFilter));
                })
                .SetCompatibilityVersion(CompatibilityVersion.Version_2_1);

只要请求进入到了MVC中间件中之后抛的异常 都会进到自定义的Filter中

************************

通过中间件实现全局异常处理

1.建立一个自定义的全局异常处理中间件

    public class ExceptionMiddleware
    {
        private readonly RequestDelegate next;
        private readonly ILogger logger;
        private IHostingEnvironment environment;

        public ExceptionMiddleware(RequestDelegate next, ILogger<ExceptionMiddleware> logger, IHostingEnvironment environment)
        {
            this.next = next;
            this.logger = logger;
            this.environment = environment;
        }

        public async Task Invoke(HttpContext context)
        {
            try
            {
                await next.Invoke(context);
                var features = context.Features;
            }
            catch (Exception e)
            {
                await HandleException(context, e);
            }
        }

        private async Task HandleException(HttpContext context, Exception e)
        {
            context.Response.StatusCode = 500;
            context.Response.ContentType = "text/json;charset=utf-8;";
            string error = "";

            void ReadException(Exception ex)
            {
                error += string.Format("{0} | {1} | {2}", ex.Message, ex.StackTrace, ex.InnerException);
                if (ex.InnerException != null)
                {
                    ReadException(ex.InnerException);
                }
            }

            ReadException(e);
            if (environment.IsDevelopment())
            {
                var json = new { message = e.Message, detail = error };
                error = JsonConvert.SerializeObject(json);
            }
            else
                error = "抱歉,出错了";

            await context.Response.WriteAsync(error);
        }
    }

2.在管道中加入自定义中间件

app.UseMiddleware<ExceptionMiddleware>();

2.在管道中通过try catch进行异常捕获      这个中间件后面的所有代码都在 try catch里面 只要出发了异常  就会给当前中间件捕获   

   注意   在某个中间件中发生了异常  但是他抛出的时候  在当前中间件就处理掉了  没有继续往上抛出   这时候就捕获不到

 

https://www.cnblogs.com/viter/p/10013195.html

原文地址:https://www.cnblogs.com/jiangchengbiao/p/10482979.html