zoukankan      html  css  js  c++  java
  • .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

  • 相关阅读:
    用DD-WRT自建计费WiFi热点
    docker安全最佳实践概述
    2014年8月25日,收藏家和杀手——面向对象的C++和C(一)
    Maven
    做QA的日子——iOS測试入门(四)
    小贝_mysql select连接查询
    FFmpeg源码简单分析:结构体成员管理系统-AVOption
    Keepalived+nginx+redis主从+tomcat一机多实例实现会话共享
    Redis主从配置及通过Keepalived实现Redis自动切换高可用
    CentOS 安装jdk1.7 32位
  • 原文地址:https://www.cnblogs.com/jiangchengbiao/p/10482979.html
Copyright © 2011-2022 走看看