Take the 2-minute tour ×
Stack Overflow is a question and answer site for professional and enthusiast programmers. It's 100% free, no registration required.

Say I have a javascript object like:

function Parent(n, c) {
    this.Name = n;
    this.Children = c;
}

var p = new Parent("asdf", [1,2,3]);

And I want to pass an array of the parent object and its children to an MVC 4 controller via JSON.

How would I go about formatting the ajax request? I've seen quite a few other questions along these lines, although none that use an array as a member variable.

This is what I have so far:

var parents = [];
parents.push(new Parent("qwer", "child1"));
parents.push(new Parent("sdfg", 12345));
parents.push(new Parent("zxcv", [4,5,6]));

$.ajax({
    url: MakeUrl("Ctlr/Action"),
    type: "POST",
    contentType: 'application/json;charset=utf-8',
    data: JSON.stringify({
       parents : parents
    }),
    success: function (data, state, xhr) {
        $("#someDiv").html(data);
    },
    error: function (xhr, state, err) {
        Utility.displayError(xhr.reponseText);
    }
});

The result of stringify actually looks reasonable:

"{"parents":[{"Name":"qwer","Value":"child1"}, {"Name":"sdfg","Value":12345}, {"Name":"zxcv","Value":[4,5,6]}]}"

Here is the Controller action:

public ActionResult Action(IEnumerable<Parent> parents) {
    ...
}

And in case it's relevant, the server-side Parent object:

public class Parent {
    public string Name { get; set; }
    public object Children { get; set; }
}

Children is an object because it is sometimes another data type - I realize this may be a slight code-smell, but the ultimate function of this class is to pass arbitrary parameters to our reporting engine.

The simple data types seem to work just fine in this way (date, integer, string, etc), but the Children array just comes through as {object}, which as far as I can tell is not even a string, but some generic System object. Is there a way to do this in MVC without resorting to, say, pushing it into a string and parsing it out?

share|improve this question
 
Have you tried dynamic instead of object? The issue here is that object isn't inherently convertible to an IEnumerable. –  Michael Perrenoud Nov 29 '13 at 20:21
 
@MichaelPerrenoud Using dynamic gives the same behavior. –  Hannele Nov 29 '13 at 20:26
add comment

1 Answer

up vote 0 down vote accepted

For now, I've settled for submitting a flat list via javascript, which is then built out on the server side.

The javascript:

var parents = [];
parents.push(new Parent("asdf", "qwer"));
parents.push(new Parent("zxcv", 123456));

[4,5,].forEach(function (e, i) {
    params.push(new Parent("Children[" + i + "]", e));
});

Which looks like this after JSON.stringify:

[{"Name":"asdf","Value":"qwer"},{"Name":"zxcv","Value":123456},{"Name":"Children[0]","Value":4},{"Name":"Children[1]","Value":5},{"Name":"Children[2]","Value":6}]

And is then un-flattened in the Controller via the following function:

private IEnumerable<Parent> Unzip(IEnumerable<Parent> parameters) {
    var unzipped = new Dictionary<string, Parent>();
    var r = new Regex(@"(.*)\[.*\]");

    foreach (var p in parameters)
    {
        var match = r.Match(p.Name.ToString());
        if (match.Success)
        {
            var name = match.Groups[1].Value;
            if (!unzipped.ContainsKey(name))
                unzipped.Add(name, new Parent() { Name = name, Value = new List<object>() { } });

            ((List<object>)(unzipped[name].Value)).Add(p.Value);
        }
        else
            unzipped.Add(p.Name, p);
    }

    return unzipped.Values;
}
share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.