68

I have an MVC API controller with the following action.

I don't understand how to read the actual data/body of the Message?

[HttpPost]
public void Confirmation(HttpRequestMessage request)
{
    var content = request.Content;
}
Hakan Fıstık
  • 16,800
  • 14
  • 110
  • 131
user1615362
  • 3,657
  • 9
  • 29
  • 46

4 Answers4

93

From this answer:

[HttpPost]
public void Confirmation(HttpRequestMessage request)
{
    var content = request.Content;
    string jsonContent = content.ReadAsStringAsync().Result;
}

Note: As seen in the comments, this code could cause a deadlock and should not be used. See this blog post for more detail.

Mansfield
  • 14,445
  • 18
  • 76
  • 112
31
using System.IO;

string requestFromPost;
using( StreamReader reader = new StreamReader(HttpContext.Current.Request.InputStream) )
{
    reader.BaseStream.Position = 0;
    requestFromPost = reader.ReadToEnd();
}
Lee Taylor
  • 7,761
  • 16
  • 33
  • 49
Zebing Lin
  • 371
  • 4
  • 6
  • Request.Content is a stream. Depending on when precisely your code ran, the stream may have already been consumed. – stannius May 10 '16 at 18:07
  • 2
    This works for MVC, while accepted answer for Web Api only – Sel Dec 06 '16 at 09:02
  • The BaseStream.Position = 0 clued me into the fact that if the content is eaten by the framework to fill in a parameter for the HttpPost method, that the stream might be reset. Which it was. Thank you. – Rangoric Apr 16 '18 at 20:49
  • This worked for me as well, should be the accepted answer. – John Spax Oct 04 '18 at 07:06
15

I suggest that you should not do it like this. Action methods should be designed to be easily unit-tested. In this case, you should not access data directly from the request, because if you do it like this, when you want to unit test this code you have to construct a HttpRequestMessage.

You should do it like this to let MVC do all the model binding for you:

[HttpPost]
public void Confirmation(YOURDTO yourobj)//assume that you define YOURDTO elsewhere
{
        //your logic to process input parameters.

}

In case you do want to access the request. You just access the Request property of the controller (not through parameters). Like this:

[HttpPost]
public void Confirmation()
{
    var content = Request.Content.ReadAsStringAsync().Result;
}

In MVC, the Request property is actually a wrapper around .NET HttpRequest and inherit from a base class. When you need to unit test, you could also mock this object.

Khanh TO
  • 48,509
  • 13
  • 99
  • 115
3

In case you want to cast to a class and not just a string:

YourClass model = await request.Content.ReadAsAsync<YourClass>();
codeMonkey
  • 4,134
  • 2
  • 31
  • 50