【问题标题】:ASP.NET Core model binder result loggingASP.NET Core 模型绑定结果日志记录
【发布时间】:2019-09-25 05:41:37
【问题描述】:

我想增加/改进我的日志记录。

到目前为止,我在每个控制器中都有类似的操作代码

  public asyc Task<IActionResult> Action1(int id, [FromBody] RequestModel request) {
    string log = $"{nameof(Action1)}(id: {id}, request: {request?.ToJson()})";
    _logger.LogInformation(log);

主要目的是查看实际到达控制器操作的内容。

我删除了它,因为它使代码严重混乱(例如,对于具有大量参数的方法)。但现在我对日志不再显示信息的结果感到不满(我需要他们调查一些无法解释的错误)。

有没有办法连接到模型绑定结果(例如通过服务过滤器)以记录模型绑定结果?


像魅力一样工作:感谢 Shahzad Hassan

  public class MethodCallParameterLogger : IAsyncActionFilter
  {

    public ILoggerFactory LoggerFactory { get; set; }

    public MethodCallParameterLogger(ILoggerFactory loggerFactory)
    {
      LoggerFactory = loggerFactory;
    }

    public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)
    {

      LoggerFactory

        // the display name contains the controller name space, controller name, method name and the postfix " (ActionLogger)"
        .CreateLogger(context.ActionDescriptor.DisplayName.Split(" ")[0])

        // MIND THAT THIS LOGS EVEN SENSITIVE DATA (e.g. credentials) !!!
        .LogInformation(JsonConvert.SerializeObject(context.ActionArguments));

      var resultContext = await next();

    }

  }

【问题讨论】:

  • 模型绑定器可能是个坏主意,但您可以使用属性来实现。
  • 嗯,模型活页夹是我想到的第一件事,因为它产生了我想要记录的内容。任何指向方向的提示。我在黑暗中,看来你知道我在找什么。 :-)
  • 目前无法显示任何内容,有一台新笔记本电脑,但尚未设置。当然,记录所有参数是一个巨大的安全漏洞,我不会允许我的开发人员这样做。
  • 比记录完整的请求正文要好 :-) 是的,当然,在代码示例中,ToJson() 负责清除敏感数据。一旦我弄清楚如何连接到这个过程中,我就会考虑一个 SensitiveAttribute,我的日志代码尊重它并将这些值置空。而是一步一个脚印。当然,它只是用于测试机器。 :-)

标签: c# asp.net-core .net-core asp.net-core-2.2 .net-core-2.2


【解决方案1】:

我认为您可以改用 ActionFilter。 ActionFilters 在模型绑定之后执行,因此您可以从ActionExecutingContext 中检索参数。您可以覆盖 OnActionExecuting 方法并记录所需的任何内容:

public class LogParamsFilter : ActionFilterAttribute
{
    private readonly ILogger<LogsParamsFilter> _logger;

    public LogParamsFilter (ILogger<LogsParamsFilter> logger)
    {
        _logger = logger;
    }

    public override void OnActionExecuting(ActionExecutingContext context)
    {
        var id = (int)context.ActionArguments["id"];
        var request = context.ActionArguments["request"] as RequestModel;
        var action = context.ActionDescriptor.DisplayName;

        string log = $"{action)}(id: {id}, request: {request?.ToJson()})";
        _logger.LogInformation(log);

        base.OnActionExecuting(context);
    }
}

您需要在控制器操作上将其用作 TypeFilter,以便通过 DI 解析其依赖项,即 ILogger。

[TypeFilter(typeof(LogParamsFilter))]
public asyc Task<IActionResult> Action1(int id, [FromBody] RequestModel request)
{
    ...
}

或者您可以在所有控制器的启动中全局注册它:

services.AddMvc(options => options
    .Filters.Add(new TypeFilterAttribute(typeof(LogParamsFilter))));

为了将其用作所有控制器操作的通用过滤器,请遍历 context.ActionArguments.Keys 属性并记录每个键的值。如果ActionArgument 的类型是RequestModel,您需要进行一些类型检查并调用.ToJson()

希望对你有帮助。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-11-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-11-27
    • 2017-09-21
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多