Question

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?

Was it helpful?

Solution

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;
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top