我创建了使用接口作为post参数的控制器。由于参数是接口,因此我使用IModelBinder将request.Body转换为IQuery对象。由IModelBinder进行的解析没有问题,并且在Controller上的执行也没有问题。我唯一遇到的问题是请求有一个延迟。正文被解析为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); }
}
作为上面的代码,我将跟踪跟踪IQuery对象的解析时间以及Controller何时接收IQuery对象。我查看了输出窗口,发现在控制器上进行解析和接收后,有10多个s的延迟。 output
我认为这可能与日志记录有关,因此我在启动时禁用了日志记录:
services.AddLogging(builder =>
{
builder.AddFilter("Microsoft", LogLevel.None)
.AddFilter("System", LogLevel.None)
.AddFilter("NToastNotify", LogLevel.None)
.AddConsole();
});
结果仍然存在延迟,并且对IQuery对象的ToString方法的调用仍称为disabled
呼叫请求示例:postman
我没有找到ASP.Net Core ModelBindingContext的源代码或任何源代码,因此我不知道是什么原因导致由绑定器解析并在控制器上接收后对象延迟。
答案 0 :(得分:0)
发现了问题。读取ParameterBinder的源代码并启用登录到“跟踪”模式后,我找到了原因,原因是ObjectModelValidator。绑定程序完成解析后,验证程序将启动并验证IQuery。这会导致ParameterBinder
上的延迟要解决此问题,我使用SkorunkaFrantišek在disable validator上给出的临时解决方案
现在,我只需要找到只为我的特定IModelBinder禁用验证器的方法