ASP.NET Core API POST parameter is always null
Solution 1
The problem is that the Content-Type
is application/json
, whereas the request payload is actually text/plain
. That will cause a 415 Unsupported Media Type HTTP error.
You have at least two options to align then Content-Type
and the actual content.
Use application/json
Keep the Content-Type
as application/json
and make sure the request payload is valid JSON. For instance, make your request payload this:
{
"cookie": "=sec_session_id=[redacted]; _ga=[redacted]; AWSELB=[redacted]"
}
Then the action signature needs to accept an object with the same shape as the JSON object.
public class CookieWrapper
{
public string Cookie { get; set; }
}
Instead of the CookieWrapper
class, or you can accept dynamic, or a Dictionary<string, string>
and access it like cookie["cookie"]
in the endpoint
public IActionResult GetRankings([FromBody] CookieWrapper cookie)
public IActionResult GetRankings([FromBody] dynamic cookie)
public IActionResult GetRankings([FromBody] Dictionary<string, string> cookie)
Use text/plain
The other alternative is to change your Content-Type
to text/plain
and to add a plain text input formatter to your project. To do that, create the following class.
public class TextPlainInputFormatter : TextInputFormatter
{
public TextPlainInputFormatter()
{
SupportedMediaTypes.Add("text/plain");
SupportedEncodings.Add(UTF8EncodingWithoutBOM);
SupportedEncodings.Add(UTF16EncodingLittleEndian);
}
protected override bool CanReadType(Type type)
{
return type == typeof(string);
}
public override async Task<InputFormatterResult> ReadRequestBodyAsync(
InputFormatterContext context,
Encoding encoding)
{
string data = null;
using (var streamReader = context.ReaderFactory(
context.HttpContext.Request.Body,
encoding))
{
data = await streamReader.ReadToEndAsync();
}
return InputFormatterResult.Success(data);
}
}
And configure Mvc to use it.
services.AddMvc(options =>
{
options.InputFormatters.Add(new TextPlainInputFormatter());
});
See also
https://github.com/aspnet/Mvc/issues/5137
Solution 2
Shaun Luttin's answer works, but it misses one important piece of information. The reason your string is not recognised is because it is not a JSON string.
Do this;
var payload=JSON.stringify("=sec_session_id=[redacted]; _ga=[redacted]; AWSELB=[redacted]");
Then you can leave the controller as it is;
$.ajax({
url: http://localhost:54093/getter/validatecookie,
type: 'POST',
contentType: 'application/json',
data: payload
});
It is embarassing how long this took me to figure out. I really hope it helps someone!
Solution 3
ridiculously, in dot net core you cannot use just "frombody string parameter". you should make a model class for just one string parameter.
public async Task<IActionResult> GetRankings([FromBody] string cookie)
=>
//1. make a model. MyCookie.cs
class MyCookie{
public string Cookie { get; set; }
}
//2. edit your parameter
public async Task<IActionResult> GetRankings([FromBody] MyCookie cookie)
Solution 4
I struggled with this for far to long and finally, after looking at what a DevExpress control was doing for "PUT"ting to a Razor Page, I discovered this nugget:
JavaScript
$.ajax({
type: "PUT",
url: "/GoalGrid?handler=Single",
dataType: "json",
contentType: "application/x-www-form-urlencoded; charset=UTF-8",
data: {values: single }
})
GoalGrid.cshtml.cs
public JsonResult OnPutSingle(string values)
{
// Do stuff with 'values' here
}
The trick is to use the "application/x-www-form-urlencoded; charset=UTF-8" as your contentType for the request. This way you don't need to create a class for a single string value. And things work as expected.
Solution 5
For me, just adding [FromBody]
to the parameters list solved the problem.
May this save someone's time.
Douglas Gaskell
Updated on July 31, 2022Comments
-
Douglas Gaskell almost 2 years
I have read the following:
- Asp.net Core Post parameter is always null
- asp.net webapi 2 post parameter is always null
- web-api POST body object always null
- Web Api Parameter always null
My endpoint:
[HttpPost] [Route("/getter/validatecookie")] public async Task<IActionResult> GetRankings([FromBody] string cookie) { int world = 5; ApiGetter getter = new ApiGetter(_config, cookie); if (!await IsValidCookie(getter, world)) { return BadRequest("Invalid CotG Session"); } HttpContext.Session.SetString("cotgCookie", cookie); return Ok(); }
My request:
$http.post(ENDPOINTS["Validate Cookie"], cookie , {'Content-Type': 'application/json'});
Where
cookie
is the a string I am sending from the user input.The request posts to the endpoint with the appropriate data. However, my string is always null. I have tried removing the
[FromBody]
tag, as well as adding a=
in front of the posted data with no luck. I have also tried adding and removing different content types with all combinations of the above.The reason why I am doing this specific action is long and does not matter for this question.
Why is my parameter always null no matter what I seem to do?
Edit: I have also tried using
{cookie: cookie}
Edit2: The request:
Request URL:http://localhost:54093/getter/validatecookie Request Method:POST Status Code:400 Bad Request Remote Address:[::1]:54093
Response Headers
Content-Type:text/plain; charset=utf-8 Date:Mon, 23 Jan 2017 03:12:54 GMT Server:Kestrel Transfer-Encoding:chunked X-Powered-By:ASP.NET X-SourceFiles:=?UTF-8?B?QzpcVXNlcnNcRG91Z2xhc2cxNGJcRG9jdW1lbnRzXFByb2dyYW1taW5nXENvdEdcQ290RyBBcHBcc3JjXENvdEdcZ2V0dGVyXHZhbGlkYXRlY29va2ll?=
Request Headers
POST /getter/validatecookie HTTP/1.1 Host: localhost:54093 Connection: keep-alive Content-Length: 221 Accept: application/json, text/plain, */* Origin: http://localhost:54093 User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 Safari/537.36 Content-Type: application/json;charset=UTF-8 Referer: http://localhost:54093/ Accept-Encoding: gzip, deflate, br Accept-Language: en-US,en;q=0.8
Request Payload
=sec_session_id=[redacted]; _ga=[redacted]; AWSELB=[redacted]
-
Douglas Gaskell over 7 yearsThanks for the reply, just tried, same deal. Do the ASP.NET parameters not accept data in the standard way other frameworks do?
-
Shaun Luttin over 7 yearsGot it... ASP.NET Core does not support
text/plain
as aContent-Type
out of the box. -
Douglas Gaskell over 7 yearsThe variable
cookie
is already a string, it is getting passed around the JS as a string. -
Haney over 7 yearsRight, but the request payload also needs to be encapsulated in double quote characters in order for the media type formatter to handle the
[FromBody]
attribute correctly. -
Douglas Gaskell over 7 yearsShaun, I ended up using
Dictionary<string,string>
with a{"cookie":cookie}
object. I then access it likecookie["cookie"]
in my endpoint. I will accept your answer if you can add that as one of the potential solutions. -
statler over 6 yearsThis should not be the answer. You can send a string really easily in .Net Core without all this jiggery pokery. Refer my answer below
-
Valuator about 6 yearsA plain text formatter is included with ASP.NET Core: docs.microsoft.com/en-us/aspnet/core/mvc/advanced/…
-
Guilherme Ferreira over 5 yearsWorked. Using axios to post payload
-
Jacob Foshee over 5 yearsYou can see he is deriving from the
TextInputFormatter
inMicrosoft.AspNetCore.Mvc.Formatters
. However that is an abstract class and the only derived classes at this time are for JSON and XML. That said, I really wishTextPlainInputFormatter
was included. Thanks so much, Shaun! -
RooSoft about 5 yearsThis thing should be included in the framework. MVC should also have that formatter added by default.