Ведение журнала результатов связывания модели ASP.NET Core

Я хотел бы увеличить/улучшить свое ведение журнала.

До сих пор у меня был в каждом коде действия контроллера, например

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

Основная цель состояла в том, чтобы увидеть, что на самом деле достигает действия контроллера.

Я удалил его, так как он сильно загромождал код (например, для методов с большим количеством параметров). Но теперь я недоволен тем, что в логах больше не отображается информация (а они мне были нужны для расследования каких-то необъяснимых багов).

Есть ли способ подключиться к результату связывания модели (например, через сервисный фильтр), чтобы зарегистрировать результат связывания модели?


Работает как шарм: благодаря Шахзаду Хасану

  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();

    }

  }

Связывание модели, вероятно, было бы плохой идеей, но вы можете сделать это с помощью атрибута.

DavidG 07.05.2019 16:18

Первое, что пришло мне в голову, это связыватель моделей, поскольку он производит то, что я хочу регистрировать. Любые намеки в направлении. Я в темноте, и, кажется, вы знаете, что я ищу. :-)

monty 07.05.2019 16:20

Пока ничего не могу показать, есть новый ноутбук, и он еще не настроен. Конечно, регистрация всех параметров — это огромная дыра в безопасности, и я бы не позволил своим разработчикам делать это.

DavidG 07.05.2019 16:21

Лучше, чем регистрировать полные тела запросов :-) Да, конечно, в примере кода avove ToJson() позаботился об удалении конфиденциальных данных. Как только я понял, как подключиться к процессу, я подумал о SensitiveAttribute, который мой код регистрации учитывает и очищает эти значения. Но один шаг за другим. И конечно это только для тестовых машин. :-)

monty 07.05.2019 16:24
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
4
613
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 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);
    }
}

Вам нужно будет использовать его как ТипФильтр в действии контроллера, чтобы его зависимости, т.е. ILogger, разрешались через DI.

[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 и запишите значение для каждого ключа. Вам нужно будет выполнить некоторые проверки типов и вызвать .ToJson(), если тип ActionArgument — RequestModel.

Надеюсь, это поможет.

Другие вопросы по теме