4

I am using ASP.NET MVC 3 and I'm trying to model bind a simple json array to a List<JsonPositions>. JsonPositions is a custom object with the same properties as the json objects in the array.

Here is what my array looks like on the client:

var widgetPositions = [
    { col: 5, row: 1, id: 2 },
    { col: 4, row: 5: id: 40 }
];

$.ajax({
    url: 'the url',
    data: { positions: widgetPositions },
    success: function () {
        alert('Save successful.');
    },
    error: function () {
        alert('An error occurred while trying to update the widget positions.');
    }
});

This code appears to be working correctly when the request is examined in Chrome.

In the controller we have the following action method:

public void UpdatePositions(List<JsonPosition> positions)
{
    // debugging here
}

When I examine the widgetPositions list it does have two items just like the json array, but the objects' properties do not match the values from the objects on the client. Here is what the object JsonPosition looks like:

public class JsonPosition
{
    public int id { get; set; }
    public int col { get; set; }
    public int row { get; set; }
}

Thanks for any help you can offer :)

2 Answers 2

3

I think you may need to add the content-type:

$.ajax({
    url: 'the url',
    data: JSON.stringify({ positions: widgetPositions }),
    contentType: 'application/json',
    success: function () {
        alert('Save successful.');
    },
    error: function () {
        alert('An error occurred while trying to update the widget positions.');
    }
});

Also you're not specifying a request type, so it will do a GET by default, do you mean to be doing a POST? That would make it

$.ajax({
    url: 'the url',
    type: 'POST',
    data: JSON.stringify({ positions: widgetPositions }),
    contentType: 'application/json',
    success: function () {
        alert('Save successful.');
    },
    error: function () {
        alert('An error occurred while trying to update the widget positions.');
    }
});
Sign up to request clarification or add additional context in comments.

6 Comments

When I do that I get a new error from the server. "Invalid JSON primitive: positions."
Oh yeah my bad - you also need to JSON.stringify the JSON object. See @Darin's answer
This was accurate except it was missing one thing. I had to also include dataType: 'json' or model binding wouldn't happen at all. I played around to find the minimum necessary properties and in fact contentType, JSON.stringify, and dataType were all necessary. Removing any one of them caused it to fail either by not binding the list at all, binding but not populating the properties, or throwing the invalid json primitive error. Thanks for the help.
No, you don't need to include dataType. jQuery infers it from the response Content-Type header. People usually include this in poorly written PHP scripts that doesn't properly set this response header. For example they set Content-Type: 'text/html' but actually return JSON. With ASP.NET MVC you don't need anything like that. You simply return a JsonResult from your controller action and the framework takes care for everything.
On another note I do believe it should be contentType not content-type as hyphens are not allowed in json property names are they?
|
2

You could send them as a JSON object:

var widgetPositions = [
    { col: 5, row: 1, id: 2 },
    { col: 4, row: 5: id: 40 }
];

$.ajax({
    url: 'the url',
    data: JSON.stringify({ positions: widgetPositions }),
    contentType: 'application/json',
    success: function () {
        alert('Save successful.');
    },
    error: function () {
        alert('An error occurred while trying to update the widget positions.');
    }
});

Things to notice that you hadn't in your code and which will make it work:

  • contentType: 'application/json', - set the proper request content type header
  • data: JSON.stringify({ positions: widgetPositions }) - send a JSON request

Now you will happily get all you need here:

public void UpdatePositions(List<JsonPosition> positions)
{
    // debugging here
}

Remark: The JSON.stringify method is natively defined in all modern browsers (even in IE8, even if this is far from being a modern browser). But if you need to support some prehistoric browsers you could include the json2.js script to your page which will check whether the browser natively supports this method and if not provide an implementation.

4 Comments

This is accurate except for there was one other missing property. I described what was missing under applechewer's answer. Thanks for the help :)
@AlexFord, no you are mistaking something. dataType: 'json' has strictly nothing to do with model binding. This specifies the response type. But jQuery is intelligent enough to deduce it from the response Content-Type header. So if in your controller action you return a JsonResult it will automatically parse the argument passed to the success function. dataType is not necessary.
All I can tell you is that if I didn't include it then it didn't work. I don't know the specifics but I was very thorough with my testing.
Well it appears you are correct. Not sure what the heck I was doing, but I just tried to remove it so I could screen capture the error for you but it worked without it. I swear I'm not crazy, but I must have had another error that was throwing me off.

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.