3

Not sure where I'm going wrong, I have an object that just won't get posted to my controller.

Model:

public class PostJsonModel
{
    public List<JsonModel> Things { get; set; }
}

public class JsonModel
{
    public int Id { get; set; }
    public string Tests { get; set; }
    public string MoreTests { get; set; }
}

Controller:

    [HttpPost]
    public async Task<IActionResult> DoSomething(PostJsonModel test)
    {
        //Save to the database

        return Json("Success");
    }

javascript:

    var test = {
        "Id": 5,
        "Tests": "Testing",
        "MoreTests": "More More More"
    };

    var more = [];

    more.push(test);
    more.push(test);
    more.push(test);

    var allSaveElements = {
        "Things": more
    };

    let xhr = new XMLHttpRequest();
    xhr.open('POST', '/Home/DoSomething', true);
    xhr.setRequestHeader('Content-Type', 'application/json');
    xhr.onload = function () {
        if (xhr.status === 200) {
           //Do something
        }
        else {
            alert('Request failed.  Returned status of ' + xhr.status);
        }
    };
    xhr.send(allSaveElements);

When I break into the controller, the PostJsonModel has "Things" with a count of 0. Looking at the network output in chrome, the allSaveElements is exactly what I expect it to be.

This works perfectly fine in a .NET Framework (4.7) application, but for some reason not in .NET Core (2.2)

I'm obviously missing something, can someone point it out?

4
  • 1
    Have you tried using the [FromBody] attribute before the action parameter? Commented Aug 27, 2019 at 16:03
  • I think you need to put [FromBody] before your parameter public async Task<IActionResult> DoSomething([FromBody] PostJsonModel test) Commented Aug 27, 2019 at 16:06
  • Are you using XMLHttpRequest for a reason? JQuery Ajax posts might be a better option. Commented Aug 27, 2019 at 16:13
  • @GaryStewart we're not using jQuery for this project. We've had some issues with it in the past, so we're trying to do this project without it. Commented Aug 28, 2019 at 1:25

2 Answers 2

3

You are binding to a complex object, and passing the data from the body, in that case, you need to use FromBody.

This works perfectly fine in a .NET Framework (4.7) application, but for some reason not in .NET Core (2.2)

You are right, and I have noticed it when I was transitioning to .NET Core 2.1 about a year ago. In .NET Framework, if you are sending only one parameter for the complex object, then you don't need to use FromBody, but in .NET Core, you need to use it

You may like to have a look at below link by Microsoft :

https://learn.microsoft.com/en-us/aspnet/core/mvc/models/model-binding?view=aspnetcore-2.2

Quoting from the same link

If the default behavior doesn't give the right results, you can use one of the following attributes to specify the source to use for any given target.

[FromQuery] - Gets values from the query string.

[FromRoute] - Gets values from route data.

[FromForm] - Gets values from posted form fields.

[FromBody] - Gets values from the request body.

[FromHeader] - Gets values from HTTP headers.

Sign up to request clarification or add additional context in comments.

2 Comments

Thanks for the outline and the docs, it really helps. I do have to say, I'm pretty embarrassed about this one.
you don't need to be embarrassed, I have been there. Glad to know that it helped you out :)
1

I think you need to put [FromBody] before your parameter

[HttpPost] public async Task<IActionResult> DoSomething([FromBody] PostJsonModel test) { ... }

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.