Click here to Skip to main content
15,885,782 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
My ASP.NET Core 2.2 web api POST Calls are not getting anything from the body. Even when using a single field on the body, the value read in is null on POST. How do I resolve this?

What I have tried:

This is the current code in the API Controller:
[HttpPost("TestUser")]
 public async Task<IActionResult> TestUserAsync(string userName)
 {
     if (ModelState.IsValid)
     {
         return Ok(userName);
     }
     else
     {
         return BadRequest();
     }
 }

I have also tried this code with the [FromBody] in place (then the response from postman becomes "invalid input" and the method is not called.

I am calling it from postman:
"http://localhost:5502/LDH/User/TestUser"


Content Type is Application/Json and this is the raw string passed in as the body:
{"userName" : "testUser"}


Some of my research suggested that custom middleware logging could cause it by consuming the stream and not ressetting it- I use log4Net. I cannot find anything on how to reset the stream so am unable to rule that out.

The modelstate is valid, and not showing anything wrong
Posted
Updated 12-Nov-19 4:57am

By default, Web API uses the following rules to bind parameters:
  • If the parameter is a "simple" type, Web API tries to get the value from the URI. Simple types include the .NET primitive types (int, bool, double, and so forth), plus TimeSpan, DateTime, Guid, decimal, and string, plus any type with a type converter that can convert from a string. (More about type converters later.)
  • For complex types, Web API tries to read the value from the message body, using a media-type formatter.

Your parameter is a string, so model binding will try to get the value from the URL.

If you add [FromBody] to the parameter, it will use the media type formatter to read the parameter from the request body. For a string parameter with the application/json content type, it expects a single string enclosed in quotes:
POST http://localhost:5076/api/values HTTP/1.1
User-Agent: Fiddler
Host: localhost:5076
Content-Type: application/json
Content-Length: 7

"Alice"
Your body doesn't match that - you're passing in a whole object:
{"userName" : "testUser"}

Rick Strahl posted an approach to bind a string parameter directly to the raw request body back in 2013, which you might be able to adapt:
Accepting Raw Request Body Content with ASP.NET Web API - Rick Strahl's Web Log[^]

Otherwise, the simplest solution is probably to create a class to represent your parameter:
C#
public class TestUserParameters
{
    public string UserName { get; set; }
}
...
[HttpPost("TestUser")]
public async Task<IActionResult> TestUserAsync(TestUserParameters model) { ... }
 
Share this answer
 
v2
Comments
Ger Hayden 12-Nov-19 12:23pm    
Absolutely perfect - the reality is that I will be passing a complex class rather than a simple type and your example sends me in the direction I want to go.
Ger Hayden 12-Nov-19 12:34pm    
And for the benefit of future readers, this definition is closer to my real solution:
  public class TestSubClass
    {
        public string SampleStr { get; set; }
    }
    public class TestUserParameters
    {
        public string UserName { get; set; }
        public TestSubClass MySubClass {get; set;}
    }
 


and the postman Body
{"UserName" : "testUser", "MySubClass" : {"SampleStr" : "Mysample"}}


Again, thanks to Richard for setting me on the right path.
LMGTFY[^]
And read the first 5 links...
 
Share this answer
 
Comments
Ger Hayden 12-Nov-19 5:30am    
Sorry, that is pretty much what I have been doing (that is how I learned that the stream may be getting hijacked by the logger). I had a quick look at your search string and 3 of the first 5 hits deal with multiple parameters. This is not a multiple parameter scenario, and common fixes like FromBody have been tried to no avail.

I will try block off log4Net and see if that resolves the issue.

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900