Why is the HTTP POST request body always empty in your ASP.NET Web API controller action when you want to simply read the JSON data as a string?

Posted: (EET/GMT+2)

 

Today, I wanted to share a solution to a common problem: when you have an ASP.NET Web API controller that declares a "[FromBody]" parameter that is the type of string, the value is always empty, no matter what you try to submit to the controller.

Assume you want to create a generic HTTP POST handler, which can accept multiple formats of JSON data. Your first attempt might be something like this:

public IHttpActionResult Post([FromBody] string jsonData)
{
    // do something with the posted JSON data here...
    return Content(System.Net.HttpStatusCode.OK, "OK, data stored successfully.");
}

However, no matter how you try to POST JSON data (content type is "application/json"), the action parameter "jsonData" always stays empty.

Why does this happen? ASP.NET Web API supports multiple input types for incoming data, namely XML and JSON. When the API controller detects data as JSON (using the Content-Type header value), it tries to deserialize the body data into a string. The only format that would work would be a quoted string: "test". All other input values would fail, leaving the parameter an empty string (not null, however).

More precisely, the default formatter for JSON data is called "JsonMediaTypeFormatter". For more information about this class, check out the MSDN documentation.

Next, the solution. To solve the problem, you need to go a bit deeper, and request a HTTP request object. With this object, you can read the Content property, and convert it to a string asynchronously. Here's an improved controller:

public async Task Post(HttpRequestMessage request)
{
    string jsonData = await Request.Content.ReadAsStringAsync();
    // do something with the posted JSON data here...

    return Content(System.Net.HttpStatusCode.OK, "OK, data stored successfully.");
}

This allows you to read any content, work with it as a simple string, and then try to deserialize a JSON object out of it.

Hope this helps!