【发布时间】:2013-11-05 20:15:13
【问题描述】:
相关问题:Web API ApiController PUT and POST methods receive null parameters intermittently
背景
在对现有 Web API 项目进行负载测试时,我注意到很多空引用异常,因为在发布到操作时参数为空。
原因似乎是在开发环境中运行时注册了一个自定义消息处理程序以记录请求。删除此处理程序可解决问题。
我了解在 Web API 中我只能读取一次请求正文,并且读取它总是会导致我的参数为空,因为无法进行模型绑定。出于这个原因,我使用带有 ContinueWith 的 ReadAsStringAsync() 方法来读取正文。看起来这在大约 0.2% 的请求中表现异常(在使用 Apache Bench 进行本地调试期间)。
代码
在最基本的层面上,我有以下几点:
型号
public class User
{
public string Name { get; set; }
}
API 控制器
public class UsersController : ApiController
{
[HttpPost]
public void Foo(User user)
{
if (user == null)
{
throw new NullReferenceException();
}
}
}
消息处理程序
public class TestMessageHandler : DelegatingHandler
{
protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
request.Content.ReadAsStringAsync().ContinueWith((task) =>
{
/* do stuff with task.Result */
});
return base.SendAsync(request, cancellationToken);
}
}
...在应用启动时注册
GlobalConfiguration.Configuration.MessageHandlers.Add(new TestMessageHandler());
我使用的是发布时最新的 WebAPI 4.0.30506.0。项目中的所有其他 MS 包也在运行最新版本(下面链接的演示项目现已更新以反映这一点)。
测试
初始测试是使用 Loadster 在带有 .NET 4.0.30319 的 Server 2008 R2 上针对负载平衡的 IIS 7.5 设置运行的。我正在使用 Apache Bench 使用 .NET 4.5.50709 在 Windows 7 上的 IIS 7.5 上本地复制它。
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%。
接下来的步骤...
如果您想亲自尝试,我已将我的演示项目放在GitHub,尽管除了我在上面发布的内容之外,它是一个标准的空 Web API 项目。
也很乐意尝试任何建议或发布更多信息。谢谢!
【问题讨论】:
-
你可能已经检查过了——但你确定是控制器方法抛出了 NullReferenceException 吗?另外,您还没有在任何地方发布实际的任务延续方法,也许这会有所帮助
-
@JoannaTurban 是的,这是我在检查参数是否为空时抛出的异常(我的演示控制器 github.com/jamesantrobus/WebAPI-ModelBindingError/blob/master/… 中的第 13 行)。例如,我实际上并没有在该任务中做任何事情,我仍然可以从我的生产应用程序中复制问题。
标签: c# asp.net-mvc asp.net-web-api model-binding