Related question: ApiController PUT and POST API periodically receive null parameters
Background
While testing an existing web API project, I noticed a lot of null support exceptions as a result of the parameter being empty when it was submitted to the action.
The reason, apparently, is a custom message handler registered for log requests while working in development environments. Removing this handler fixes the problem.
I understand that in the Web API I can only read the request body once, and this reading will always cause my parameter to be null, since there will be no binding to the model. For this reason, I use the ReadAsStringAsync () method with ContinueWith to read the body. This seems to behave strangely in ~ 0.2% of requests (during local debugging using Apache Bench).
the code
At the most basic level, I have the following:
Model
public class User { public string Name { get; set; } }
API controller
public class UsersController : ApiController { [HttpPost] public void Foo(User user) { if (user == null) { throw new NullReferenceException(); } } }
Message handler
public class TestMessageHandler : DelegatingHandler { protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) { request.Content.ReadAsStringAsync().ContinueWith((task) => { }); return base.SendAsync(request, cancellationToken); } }
... which is registered during application launch
GlobalConfiguration.Configuration.MessageHandlers.Add(new TestMessageHandler());
I am using WebAPI 4.0.30506.0, the latest at the time of publication. All other MS packages in the project also work with the latest version (the demo project linked below has now been updated to reflect this).
Testing
Initial testing was performed using Loadster , which works with load-balanced configuration of IIS 7.5 on Server 2008 R2 with .NET 4.0. 30319. I am replicating this locally in IIS 7.5 on Windows 7 with .NET 4.5.50709 using Apache Bench.
ab -n 500 -c 25 -p testdata.post -T "application/json" http:
where testdata.post contains
{ "Name":"James" }
With such testing, I see about 1 failure for 500 requests, so ~ 0.2%.
Next steps...
I put my demo project on GitHub if you want to try it myself, although besides the fact that I posted above it is a standard empty web API project.
We are also happy to try out any suggestions or publish additional information. Thanks!