Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/sorting/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# Web API操作参数间歇性为空_C#_Asp.net Mvc_Asp.net Web Api_Model Binding - Fatal编程技术网

C# Web API操作参数间歇性为空

C# Web API操作参数间歇性为空,c#,asp.net-mvc,asp.net-web-api,model-binding,C#,Asp.net Mvc,Asp.net Web Api,Model Binding,相关问题: 背景 在对现有Web API项目进行负载测试时,我注意到许多空引用异常,这是由于在发布到操作时参数为空 原因似乎是在dev环境中运行时注册了一个自定义消息处理程序来记录请求。删除此处理程序可解决此问题 我知道在WebAPI中,我只能读取请求体一次,读取它总是会导致我的参数为null,因为模型绑定将无法发生。出于这个原因,我使用带有ContinueWith的ReadAsStringAsync()方法来读取正文。在约0.2%的请求中(在使用ApacheBench进行本地调试期间),这似乎

相关问题:

背景 在对现有Web API项目进行负载测试时,我注意到许多空引用异常,这是由于在发布到操作时参数为空

原因似乎是在dev环境中运行时注册了一个自定义消息处理程序来记录请求。删除此处理程序可解决此问题

我知道在WebAPI中,我只能读取请求体一次,读取它总是会导致我的参数为null,因为模型绑定将无法发生。出于这个原因,我使用带有ContinueWith的ReadAsStringAsync()方法来读取正文。在约0.2%的请求中(在使用ApacheBench进行本地调试期间),这似乎表现得很奇怪

代码 在最基本的层面上,我有以下几点:

模型 API控制器 消息处理程序 我正在使用WebAPI 4.0.30506.0,发布时的最新版本。项目中的所有其他MS软件包也运行最新版本(下面链接的演示项目现已更新以反映这一点)

测试 最初的测试是通过在服务器2008 R2上使用.NET 4.0.30319运行负载平衡的IIS 7.5设置进行的。我正在Windows 7上的IIS 7.5上使用Apache Bench通过.NET 4.5.50709本地复制此功能

ab -n 500 -c 25 -p testdata.post -T "application/json" http://localhost/ModelBindingFail/api/users/foo
其中testdata.post包含

{ "Name":"James" }
通过这次测试,我发现500个请求中大约有1个失败,因此约0.2%

下一步。。。 如果你想自己尝试的话,我已经打开了我的演示项目,尽管除了我上面发布的内容之外,它是一个标准的空WebAPI项目


也很乐意尝试任何建议或发布更多信息。谢谢

我仍在调查这一问题的根本原因,但到目前为止,我的直觉是ContinueWith()是在不同的上下文中执行的,或者是在处理请求流的某个点或类似的地方执行的(一旦我确定了这一点,我将更新这一段)

在修复方面,我已经快速地对三个进行了路试,它们可以处理500个请求而没有错误

最简单的方法是只使用
task.Result
,但这确实存在一些问题(虽然可能是YMMV)

受保护的覆盖任务SendAsync(HttpRequestMessage请求,CancellationToken CancellationToken)
{
var result=request.Content.ReadAsStringAsync().result;
返回base.sendaync(请求、取消令牌);
}
接下来,您可以确保正确链接您的延续,以避免任何关于上下文的歧义,但是它非常难看(我不能100%确定它是否没有副作用):

受保护的覆盖任务SendAsync(HttpRequestMessage请求,CancellationToken CancellationToken)
{
var result=request.Content.ReadAsStringAsync().ContinueWith(任务=>
{
/*完成任务。结果*/
});
返回result.ContinueWith(t=>base.SendAsync(request,cancellationToken)).Unwrap();
}
最后,最佳解决方案似乎是使用async/await to,显然,如果您停留在.NET4.0上,这可能是一个问题

protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
    var content = await request.Content.ReadAsStringAsync();
    Debug.WriteLine(content);
    return await base.SendAsync(request, cancellationToken);
}
protectedoverride async Task sendaync(HttpRequestMessage请求,CancellationToken CancellationToken)
{
var content=wait request.content.ReadAsStringAsync();
Debug.WriteLine(内容);
返回wait base.sendaync(请求、取消令牌);
}

您可能已经检查过了,但是您确定抛出NullReferenceException的是控制器方法吗?另外,您还没有在任何地方发布实际的任务延续方法,也许这可能会help@JoannaTurban是的,当我检查参数是否为null时(我的演示控制器中的第13行),抛出的是我的异常。例如,我在那个任务中没有做任何事情,我仍然可以从我的生产应用程序中复制这个问题。该死,忘了这个。我最终在MSDN论坛上得到了一个类似的答案,尽管这是更好的解释。使用async/await似乎是最好的解决方案,已经投入生产一个月左右了,没有任何问题。我也遇到了与OP相同的问题,这个答案非常有帮助。我遇到的一个问题是,问题发生在登台/测试环境(而不是本地开发人员)上,并且在连接fiddler之后,问题就停止了!可能与减慢请求速度有关的事情并没有真正深入到问题的根源,但注意到一堆
ContinueWith
,可以很容易地被
wait/async
取代,从而解决了问题
GlobalConfiguration.Configuration.MessageHandlers.Add(new TestMessageHandler());
ab -n 500 -c 25 -p testdata.post -T "application/json" http://localhost/ModelBindingFail/api/users/foo
{ "Name":"James" }
protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
    var result = request.Content.ReadAsStringAsync().Result;
    return base.SendAsync(request, cancellationToken);
}
protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
    var result = request.Content.ReadAsStringAsync().ContinueWith(task =>
    {
        /* do stuff with task.Result */
    });

    return result.ContinueWith(t => base.SendAsync(request, cancellationToken)).Unwrap();
}
protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
    var content = await request.Content.ReadAsStringAsync();
    Debug.WriteLine(content);
    return await base.SendAsync(request, cancellationToken);
}