我创建了使用接口作为 post 参数的控制器。由于参数是一个接口,我使用 IModelBinder 将 request.Body 转换为 IQuery 对象。IModelBinder解析没有问题,在Controller上执行也没有问题。我得到的唯一问题是 request.Body 被解析为 IQuery 对象直到在 Controller 主体上收到之前存在延迟。
我用来解析请求正文的 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 对象何时完成解析以及 Controller 何时收到 IQuery 对象。我查看输出窗口,发现在控制器上解析和接收后有 10+s 的延迟。 输出
我认为这可能与日志记录有关,所以我在启动时禁用了日志记录:
services.AddLogging(builder =>
{
builder.AddFilter("Microsoft", LogLevel.None)
.AddFilter("System", LogLevel.None)
.AddFilter("NToastNotify", LogLevel.None)
.AddConsole();
});
结果仍然存在延迟,并且对 IQuery 对象的 ToString 方法的调用仍然被称为禁用
呼叫请求示例:邮递员
我没有找到 ASP.Net Core ModelBindingContext 的源代码或任何源代码,所以我不知道是什么原因导致对象在被绑定器解析并在控制器上接收后延迟。