Cannot read Request.Content in ASP.NET WebApi controller

I realise this is old, and has been answered, but for what it's worth, the reason you can't use ReadAsStringAsync() isn't because it 'eats the data' as has been suggested, it's because the content is being processed as a stream and since the data has been consumed by the message formatter the Position of the stream is already at the end.

In order to use ReadAsStringAsync() you first need to reset the content stream Position to the beginning.

I do it like this: response.RequestMessage.Content.ReadAsStreamAsync().Result.Seek( 0, System.IO.SeekOrigin.Begin ) because I only have the HttpResponseMessage, but if you have direct access to the HttpRequestMessage (as you do inside the Controller) you can use Request.Content.ReadAsStreamAsync().Result.Seek( 0, System.IO.SeekOrigin.Begin ) which is functionally equivalent I suppose.

Late Edit

Reading async streams with Result as above will cause deadlocks and blocked threads under a number of circumstances. If you have to read from an async stream in a synchronous way, it's better to use the form:

 new TaskFactory( CancellationToken.None, 
                  TaskCreationOptions.None, 
                  TaskContinuationOptions.None, 
                  TaskScheduler.Default )
      .StartNew<Task<TResult>>( func )
      .Unwrap<TResult>()
      .GetAwaiter()
      .GetResult();

where func is the async action you want to run, so in this case it would be something like async () => { await Request.Content.ReadAsStreamAsync(); } … in this way you can put the async parts of the method inside the StartNew part and properly unwrap any exceptions that happen when marshalling back to your synchronous code.

Better still, make the whole stack async.


I too struggled with this. ReadAsStringAsync and ReadAsAsync return a task object. Referencing the Result property returns the content. It may be referencing the Result property causes the async read request to block.

Example:

string str = response.Content.ReadAsStringAsync().Result;