相关问题:Web API ApiController PUT 和 POST 方法间歇性接收空参数
背景
在对现有 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 项目。
也很高兴尝试任何建议或发布更多信息。谢谢!