简体   繁体   English

ASP.NET Core模型绑定程序结果记录

[英]ASP.NET Core model binder result logging

I would like to increase / improve my logging. 我想增加/改善日志记录。

So far I had in each controller action code like 到目前为止,我在每个控制器中都有动作代码,例如

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

The main purpose was to see whats actually reaching the controller action. 主要目的是查看实际达到控制器动作的内容。

I removed it since it cluttered the code heavily (eg for methods with a lot of paramters). 我删除了它,因为它使代码变得很混乱(例如,对于具有很多参数的方法)。 But now I am unhappy with the result that the logs do not show the information any more (and I needed them to investigate some unexplainable bugs). 但是,现在我对日志不再显示信息的结果感到不满意(我需要它们调查一些无法解释的错误)。

Is there a way to hook up into the model binder result (eg via a service filter) to log the model binder result? 有没有办法挂钩到模型绑定器结果(例如,通过服务过滤器)以记录模型绑定器结果?


Works like charm: thanks to Shahzad Hassan 魅力十足:感谢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();

    }

  }

I think you can use an ActionFilter instead. 我认为您可以改用ActionFilter。 ActionFilters are executed after the model binding, so you can retrieve the parameters from the ActionExecutingContext . 在模型绑定之后执行ActionFilter,因此您可以从ActionExecutingContext检索参数。 You can override the OnActionExecuting method and log whatever is required: 您可以覆盖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);
    }
}

You would need to use it as TypeFilter on the controller action so that its dependencies ie ILogger is resolved via DI. 您将需要在控制器操作上将其用作TypeFilter ,以便通过DI来解决其依赖性(即ILogger)。

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

Or you can register it globally in the startup for all controllers: 或者,您可以在启动时为所有控制器全局注册它:

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

In order to use it as a generic filter for all controller actions, iterate through the context.ActionArguments.Keys property and log the value for each key. 为了将其用作所有控制器操作的通用过滤器,请遍历context.ActionArguments.Keys属性并记录每个键的值。 You would need to do some type checkings and call .ToJson() if the type of the ActionArgument is RequestModel. 您需要做一些类型checkings并调用.ToJson()如果类型ActionArgument是RequestModel。

I hope that helps. 希望对您有所帮助。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM