【问题标题】:ASP.NET Core - Use both UseDeveloperExceptionPage() and custom loggingASP.NET Core - 同时使用 UseDeveloperExceptionPage() 和自定义日志记录
【发布时间】:2019-08-27 05:46:39
【问题描述】:

我的 ASP.NET Core 应用程序中有以下代码来处理错误:

        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }
        else
        {
            app.UseExceptionHandler(builder =>
            {
                builder.Run(async context =>
                {
                    context.Response.StatusCode = (int)HttpStatusCode.InternalServerError;
                    var loggingService = context.RequestServices.GetService<ILoggingService>();
                    var exceptionFeature = context.Features.Get<IExceptionHandlerFeature>();
                    if (exceptionFeature != null)
                    {
                        Exception ex = exceptionFeature.Error;
                        Console.Error.WriteLine(ex.Message + "   " + ex.StackTrace);
                        loggingService.Error(ex);
                    }
                });
        }

但是,当处于Development 环境中时,我想同时使用UseDeveloperExceptionPage() 和数据库日志记录的自定义错误处理。但这似乎不起作用(UseExceptionHandler() 禁用了UseDeveloperExceptionPage() 的功能)。

有没有什么方法可以实现这一点,而无需编写UseDeveloperExceptionPage() 代码表单scratch?

【问题讨论】:

    标签: c# asp.net-core error-handling .net-core


    【解决方案1】:

    对于内置UseDeveloperExceptionPage,它没有暴露任何扩展方法来自定义错误过程,您可以尝试实现自己的中间件来记录错误,例如

    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
    };
    app.Use(async (context, next) =>
    {
        try
        {
            await next.Invoke();
        }
        catch (Exception ex)
        {
            //var loggingService = context.RequestServices.GetService<ILoggingService>();
            //loggingService.Error(ex);
            Console.Error.WriteLine(ex.Message + " My " + ex.StackTrace);
            throw;
        }
    
    });
    

    【讨论】:

    • 如果您有兴趣,现在可以选择在内置的 UseDeveloperExceptionPage 中添加一些自定义处理。详情见我的回答。
    【解决方案2】:

    我为此苦苦挣扎,找不到任何关于该主题的文档,但是通过查看源代码,我发现有一种方法可以将一些日志记录添加到 Developer ExceptionPage。源代码在这里,我将引用其中的一部分:https://github.com/dotnet/aspnetcore/blob/master/src/Middleware/Diagnostics/src/DeveloperExceptionPage/DeveloperExceptionPageMiddleware.cs

    我们关心的部分是这样的:

        _exceptionHandler = DisplayException;
    
        foreach (var filter in filters.Reverse())
        {
            var nextFilter = _exceptionHandler;
            _exceptionHandler = errorContext => filter.HandleExceptionAsync(errorContext, nextFilter);
        }
    

    本质上,它需要一组过滤器并将它们放入管道中,然后再运行默认的 DisplayExecution。

    过滤器由 DI 作为IEnumerable&lt;IDeveloperPageExceptionFilter&gt; 传入,这意味着我们需要做的就是添加我们自己的实现IDeveloperPageExceptionFilter 的类,它将被执行。这是我对此测试的示例过滤器:

    public class LoggingDeveloperPageExceptionFilter : IDeveloperPageExceptionFilter
    {
        private readonly ILogService _logService;
        public LoggingDeveloperPageExceptionFilter(ILogService logService)
        {
            _logService = logService;
        }
        public Task HandleExceptionAsync(ErrorContext errorContext, Func<ErrorContext, Task> next)
        {
            _logService.Error(errorContext.Exception);
            return next(errorContext);
        }
    }
    

    这是在我的 startup.cs 中注册的:

    services.AddSingleton<IDeveloperPageExceptionFilter, LoggingDeveloperPageExceptionFilter>();
    

    所以在这种情况下,它会在日志服务中调用我的错误记录,将异常传入,然后调用处理链中的下一项。因为我只有一个 next 对我来说将是原始的 DisplayException ,它会完成我们所有漂亮的错误输出。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-11-27
      • 2019-10-13
      • 1970-01-01
      • 1970-01-01
      • 2016-11-02
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多