【问题标题】:How to use ILogger without dependency injection?如何在没有依赖注入的情况下使用 ILogger?
【发布时间】:2020-12-08 09:07:26
【问题描述】:

网络核心项目。我正在使用 Azure 应用程序洞察力进行日志记录。我在 services.AddApplicationInsightsTelemetry(); 中添加了以下行在我的startup.cs中。在控制器和业务层中,我将通过依赖注入获得 ILogger。但我想出了一些不同的东西。我创建了 ApiExceptionFilter,代码如下所示。

public class ApiExceptionFilter : ExceptionFilterAttribute
    {  
        public override void OnException(ExceptionContext context)
        {
            ApiError apiError = null;
            if (context.Exception is ApiException)
            {
                // handle explicit 'known' API errors
                var ex = context.Exception as ApiException;
                context.Exception = null;
                apiError = new ApiError(ex.Message);

                context.HttpContext.Response.StatusCode = ex.StatusCode;
            }
            else if (context.Exception is UnauthorizedAccessException)
            {
                apiError = new ApiError("Unauthorized Access");
                context.HttpContext.Response.StatusCode = 401;

                // handle logging here
            }
            else if (context.Exception is NotImplementedException)
            {
                apiError = new ApiError("Not Implemented");
                context.HttpContext.Response.StatusCode = 401;

                // handle logging here
            }
            else if (context.Exception is ArgumentNullException)
            {
                apiError = new ApiError(string.Format("Parameter: {0} is required, it cannot be empty", (context.Exception as ArgumentNullException).ParamName));
                context.HttpContext.Response.StatusCode = 401;

                // handle logging here
            }
            else
            {
                // Unhandled errors
                var msg = context.Exception.GetBaseException().Message;
                string stack = context.Exception.StackTrace;
                apiError = new ApiError(msg);
                apiError.detail = stack;

                context.HttpContext.Response.StatusCode = 500;

                // handle logging here
            }

            // always return a JSON result
            context.Result = new JsonResult(apiError);

            base.OnException(context);
        }
    }

但是在这里我不能做类似的事情

private readonly ILogger _logger;
        public ApiExceptionFilter(ILogger logger)
        {
            _logger = logger;
        }

如果我进行上述更改,那么

  [ApiController]
    [ApiExceptionFilter] //here it asking for paramter ilogger
    public class MyController : ControllerBase

在上面的代码中 [ApiExceptionFilter] 它会要求我传递 ILogger 参数。

我只是想知道在 ApiExceptionFilter 中添加 ILogger 的正确方法是什么。有人可以帮助我吗?任何帮助,将不胜感激。谢谢

【问题讨论】:

  • 请注意,401 是“未实现”和“ArgumentNullException”异常的错误代码。 401 是针对未经授权的,不应该在其他错误时返回,因为大多数客户端会对此进行登录过程(即刷新令牌,重定向到登录页面等)。
  • 404 (NotFound) 更适合未实现,并且您通常也不应该捕获 ArgumentNullExceptions,因为它们不能来自控制器(如果可以,它可以转换为 400 Bad Request),但是从您的逻辑,它可能意味着任何东西(代码逻辑中的错误),其中代码 400 错误请求意味着客户端发送了错误/不足的数据
  • 问题的标题似乎与内容、标签和答案不匹配。

标签: c# asp.net-core logging dependency-injection ilogger


【解决方案1】:

您可以通过以下方式添加您的异常过滤器:

[TypeFilter(typeof(ApiExceptionFilter))]

这将允许您的过滤器使用 DI 容器中的服务,因为框架将在请求时创建过滤器。

例如

public class ApiExceptionFilter : ExceptionFilterAttribute
{
    public ApiExceptionFilter(ILogger logger)
    {
        // Assign the logger to a field etc.
    }
}

您也可以使用[ServiceFilter(typeof(ApiExceptionFilter))] 并将过滤器本身注册到 DI 容器中。

【讨论】:

  • 您好,我进行了上述更改,但是当我运行应用程序时,现在开始出现“ErrorDetail”:“尝试激活“SGRE.SiteEnrichment”时无法解析类型“Microsoft.Extensions.Logging.ILogger”的服务.WebApi.Filters.ApiExceptionFilter'.",
  • 嗯...您可以尝试注入 ILoggerFactory 或 ILogger<ApiExceptionFilter> 吗?
  • 我添加了 services.AddScoped>();但在运行 System.ArgumentException 时出现异常:'无法实例化实现类型'Microsoft.Extensions.Logging.ILogger1[WebApi.Filters.ApiExceptionFilter]' for service type 'Microsoft.Extensions.Logging.ILogger1[WebApi.Filters.ApiExceptionFilter]'。'
  • 正常日志是用services.AddLogging()我想添加的
【解决方案2】:

要在动作过滤器中使用 DependencyInjection,您需要使用 TypeFilterAttribute,

例子:

public class HandleExceptionAttribute : TypeFilterAttribute
{
        public HandleExceptionAttribute() : base(typeof(HandleExceptionPrivate))
        {
        }

        class HandleExceptionPrivate : ExceptionFilterAttribute
        {
            private readonly ILogger _logger;
            private readonly IHostingEnvironment _env;
          
            public HandleExceptionPrivate(ILoggerFactory logger, IHostingEnvironment env)
            {
                _logger = logger.CreateLogger("Exeption Filter");
                _env = env;
            }

            public override void OnException(ExceptionContext context)
            {
                _logger.LogError(Constants.LoggingEvents.EXCEPTION, context.Exception, "message");
               
                context.ExceptionHandled = true;
                context.Exception = null;
            }
        }
}

【讨论】:

  • 当我运行应用程序时,现在开始出现“ErrorDetail”:“尝试激活“SGRE.SiteEnrichment.WebApi.Filters.ApiExceptionFilter”时无法解析类型“Microsoft.Extensions.Logging.ILogger”的服务.",
  • 所以我需要添加 ILoggerin 启动这样的东西吗?
  • 您应该在启动时添加 Logger 配置。 loggerFactory.AddMsSql(null, Configuration.GetConnectionString("LoggerConnection"), httpContextAccessor, applicationName: "API");例如
  • 我需要使用loggerFactory吗?而且我没有使用 AddMsSql
  • 那是一个例子,不管你用什么来记录,只要把Logger添加到服务提供者。见:docs.microsoft.com/en-us/aspnet/core/fundamentals/logging/…
猜你喜欢
  • 1970-01-01
  • 2018-07-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-12-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多