We've been trying to post four-digit pins to an ASP Core 1.1 route.
Our controller is set up something like:
[Route("test")]
public class TestController : Controller
{
[HttpPost]
[Route("")]
public async Task <IActionResult> DoStuff([FromBody]string pin)
{
return Ok(pin);
}
}
Posting body data to this route has a strange behaviour: sometimes it's null and sometimes it isn't. I've managed to pick out a pattern for reproducing this, and I'm not really sure what's going on:
Posting a pin that doesn't start with a '0' works fine.
Posting a pin that starts with a '0' enables certain conditions as to whether the value will be parsed correctly. If any number in the pin that follows any '0' is greater than '7', then the value is parsed as null. However, any values that are '7' or less will work fine.
For example, the following will work fine:
But the following will set the pin variable as null:
This is solved by wrapping the pin value in a class and mapping to that, which I believe is the preferred way of using [FromBody].
Nonetheless, I'm curious to know what's actually going on here?
What's the data format/content type here?
My guess from the information you've provided that you're setting the content type to application/json and then posting the PIN is the only data with no formattiing correct?
This is then interpreted by JSON.NET as an octal number if it has a leading 0, which makes numbers such as 0708 invalid.
I would suggest embracing json and defining an object type on the server side to match it. If you ever need to include anything in this API besides a pin then you'd have to have to break your existing contract totally.
That would look like:
{
"pin": "0709",
}
My advice is also to treat the PIN as a string, not a number. JSON has some particular parsing rules around numbers like the handling of octal numbers.
Moreover, you should look at ModelState.IsValid. In all of the cases where the model isn't coming through, thats where the error messages will be.
Yeah that's all spot-on. We were just posting the pin value up without treating it as a string.
Thanks for the clarification!
Most helpful comment
What's the data format/content type here?
My guess from the information you've provided that you're setting the content type to
application/jsonand then posting the PIN is the only data with no formattiing correct?This is then interpreted by JSON.NET as an octal number if it has a leading
0, which makes numbers such as0708invalid.I would suggest embracing json and defining an object type on the server side to match it. If you ever need to include anything in this API besides a pin then you'd have to have to break your existing contract totally.
That would look like:
My advice is also to treat the PIN as a string, not a number. JSON has some particular parsing rules around numbers like the handling of octal numbers.
Moreover, you should look at
ModelState.IsValid. In all of the cases where the model isn't coming through, thats where the error messages will be.