IModelBinder Задержка - PullRequest
       28

IModelBinder Задержка

0 голосов
/ 04 апреля 2019

Я создал контроллер, который использует интерфейс в качестве параметра post. Поскольку параметр интерфейс, я использую IModelBinder, чтобы перевести request.Body в объект IQuery. Синтаксический анализ IModelBinder не имеет проблем, и выполнение на контроллере также не имеет проблем. Единственная проблема, с которой я столкнулся, - это задержка запроса. Когда он анализируется в объекте IQuery, его получают в теле контроллера.

IModelBinder, который я использую для анализа тела запроса:

public Task BindModelAsync(ModelBindingContext bindingContext)
{
    string _queryJson = String.Empty;
    try
    {
        StreamReader _reader = new StreamReader(bindingContext.HttpContext.Request.Body);
        _queryJson = _reader.ReadToEnd();
        if (_queryJson.IsEmpty())
        {
            bindingContext.Result = ModelBindingResult.Failed();
            goto done;
        }
    }
    catch
    {
        bindingContext.Result = ModelBindingResult.Failed();
        goto done;
    }

    bindingContext.Result = ModelBindingResult.Success(QueryBuilder.ParseJson(DataContext, _queryJson));
    System.Diagnostics.Trace.WriteLine($"QUERY PARSING COMPLETE {DateTime.Now.ToString("HH:mm:ss.fffffff")}");
    done:
    return Task.CompletedTask;
}

Контроллер:

[HttpPost]
public IActionResult Query(IQuery query)
{
    try
    {
        System.Diagnostics.Trace.WriteLine($"QUERY ON CONTROLLER {DateTime.Now.ToString("HH:mm:ss.fffffff")}");
        query.ThrowArgumentNullException("query", "Missing query to execute");
        if (query is ISelectQuery)
        {
            var _rows = ((ISelectQuery)query)
                .ReadAll()
                .ToArray();
            return new EntitiesResult(((ISelectQuery)query).ViewEntity, _rows.Length, _rows);
        }
        else
            throw new InvalidCastException($"Only select query can be executed for now");
    }
    catch (Exception ex) { return new ExceptionResult(ex); }
}

Как и в приведенном выше коде, я использовал Trace для отслеживания того, когда объект IQuery завершит анализ и когда контроллер получит объект IQuery. Я заглянул в окно вывода и обнаружил, что после анализа и получения на контроллере задержка составляет 10 с. выход

Я подумал, что это может быть связано с ведением журнала, поэтому я отключаю ведение журнала при запуске:

services.AddLogging(builder =>
{
    builder.AddFilter("Microsoft", LogLevel.None)
                 .AddFilter("System", LogLevel.None)
                 .AddFilter("NToastNotify", LogLevel.None)
                 .AddConsole();
});

В результате все еще сохраняется задержка, и вызов метода ToString объекта IQuery все еще вызывается отключен

Пример запроса звонка: почтальон

Я не нашел исходный код для ASP.Net Core ModelBindingContext или какой-либо другой, поэтому я понятия не имел, что вызывает задержку объекта после анализа связывателем и получения на контроллере.

1 Ответ

0 голосов
/ 04 апреля 2019

Нашел проблему. После прочтения источника ParameterBinder и включения входа в режим Trace я обнаружил причину, которая является ObjectModelValidator. Валидатор запускает и проверяет мой IQuery после того, как мой переплет завершил анализ. Это вызывает задержку на ParameterBinder

Чтобы исправить это, я использую временное решение, которое дано на отключить валидатор от Skorunka František

Теперь мне просто нужно найти способ отключить валидатор только для моего конкретного IModelBinder

...