0

I have created controller that use an interface as the post parameter. Since the parameter an interface I use IModelBinder to translate the request.Body into IQuery object. The parsing by IModelBinder has no issue, and execution on Controller also have no issue. The only issue that I got is that there's a delay from the request.Body being parsed into IQuery object till get received on Controller body.

The IModelBinder that I use to parse the request body:

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;
}

The controller:

[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); }
}

As the code above I put Trace to track when the IQuery object finish parsed and when the Controller receive the IQuery object. I look into the output window and found that after being parsed and received on controller there's a 10+s delay. output

I thought this might related to Logging, so I disable the logging on the start up:

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

The result still there's delay and the call to ToString method of IQuery object still being called disabled

Call request example : postman

I didn't found the source code for ASP.Net Core ModelBindingContext or any so I didn't have clue what cause the object delay after being parsed by binder and received on controller.

1 Answers1

0

Found the problem. After reading the source of ParameterBinder and enable the logging into Trace mode, I found the cause which is ObjectModelValidator. The validator kicks in and validate my IQuery after my binder done parsing. This cause the delay on ParameterBinder

To fix this, I use temporary solution that given on disable validator by Skorunka FrantiĊĦek

Now I just need to find the way to disable the validator only for my specific IModelBinder