'Post FromBody Always Null

I've got a new API that I'm building with ASP.NET Core, and I can't get any data POST'ed to an endpoint.

Here's what the endpoint looks like:

[HttpPost]
[Route("StudentResults")]
public async Task<IActionResult> GetStudentResults([FromBody]List<string> userSocs, [FromBody]int collegeId)
{
    var college = await _collegeService.GetCollegeByID(collegeId);
    // var occupations = await _laborMarketService.GetOccupationProgramsBySocsAndCollege(userSocs, college);
    return Ok();
}

And here's what my payload that I'm sending through Postman looks like:

{
    "userSocs": [
            "291123",
            "291171",
            "312021",
            "291071",
            "152031",
            "533011"
        ],
    "collegeId": 1
}

I'm making sure that I have postman set as a POST, with Content-Type application/json. What am I doing wrong?



Solution 1:[1]

You get always null because you need to encapsulate all your post variables inside only one object. Like this:

public class MyPostModel {
    public List<string> userSocs {get; set;}
    public int collegeId {get; set;}
}

and then

public async Task<IActionResult> GetStudentResults([FromBody] MyPostModel postModel)

Solution 2:[2]

If the model is null, check:

1) Where the data is sent: body, form? and based on that add the decorator to the action. For ex:

[HttpPost]
public JsonResult SaveX([FromBody]MyVM vm) { ... }

2) Check ModelState: if it's invalid the vm will not be bound so it will be null.

if (ModelState.IsValid) { ... }

Solution 3:[3]

Another reason for the model binding to fail (always null) is if the data type for a property doesn't match. For example here is a simple model:

public class MyService {
    public string JobId { get; set; }
    public int ServiceType {get; set;}
}

And here is some json that doesn't match:

{"JobId":1, "ServiceType":1}

I got caught with this when I was retrieving the JobId using jquery's .data function, it was automatically converting it to an int. Fixed it by using .attr function instead.

Solution 4:[4]

Also, make sure those variables inside your parameter class are declared as Public, (or they'll just keep returning as null)..

Solution 5:[5]

If you want to send two or more models, you should use this example:

[HttpPost]
public async Task<ActionResult> addUsuario([FromBody] Newtonsoft.Json.Linq.JObject datos)
{
    Usuarios user = datos["usuario"].ToObject<Usuarios>();
    Empresas empresa = datos["empresa"].ToObject<Empresas>();
    return Json(await _srv.addUsuario(user, empresa));
}

Solution 6:[6]

I know it is not related to your case, still, I am posting my answer here.

It is a silly mistake that I had done in my code. I just copied one of my Get requests and changed it to a Post request, and forgot to decorate the parameter with [FromBody]. If anyone else is having the same problem, please make sure that you are decorating the parameter with [FromBody].

[HttpPost]
public IApiResponse Update([FromBody] User user) {
    if (user == null) return new ApiBadRequestResponse(ModelState);
    return _userService.Post(user) ? new ApiOkResponse(user) : new ApiResponse(500);
}

Solution 7:[7]

Assuming the [FromBody] class is made up of primitive data types;

  1. [FromBody] is public
  2. [FromBody] has an empty constructor ()
  3. [FromBody] is serializable.

Solution 8:[8]

For me, all values were coming in as null because my object had an enum that was not being parsed. If you have having this problem, I'd recommend turning on enum parsing at the Startup.cs per this SO

Solution 9:[9]

Make sure that your data transfer object has "Public" as Access modifier and also your oject properties have getter and setter methods.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Tinwor
Solution 2 Piotr Kula
Solution 3 gsxrboy73
Solution 4 Kingsley
Solution 5 Bill Tür stands with Ukraine
Solution 6 CarenRose
Solution 7 Juls
Solution 8 Negatar
Solution 9 MaybeNextTime