Tell me more ×
Stack Overflow is a question and answer site for professional and enthusiast programmers. It's 100% free, no registration required.

I hope anyone can help me (Sorry for my english). I have a problem when I want to send un array of arrays in ajax. My model is:

public class SJSonModel
{
    public string Name { get; set; }
    public bool isChecked { get; set; }     
}

public class SJSonModelList
{
    public List<SJSonModel> Features { get; set; }
    public List<SJSonModel> MenuItems { get; set; }
}

The controller:

    [HttpPost]
    public ActionResult CheckPreferences(SJSonModelList postData)
    {
        BindUserFeatures(postData.Features);

        return Json(new { status = "Success", message = "Passed" });
    }

The View simplified:

<div class="Feature borderRadius Items">
    <h2>Title
        <input type="checkbox" class="Item" name="featureName"/>
    </h2> 

   <div class="FeatureDetails subItems">                 
        <a href="@Url…">featureName</a>
        <input type="checkbox" class="subItem" name="subItemName"/>
   </div> <!-- endOf FeatureDetails -->

The JQuery code:

    var isChecked = false;
    var features = new Array();
    var menuItems = new Array();
    var postData = new Array();

Here I fill the features, the menuItems with the featureName/menuItemName and isChecked boolean for each feature/menuItem

menuItems.push({ "Name": $(this).attr('name'), "isChecked": isChecked });
features.push({ "Name": $(this).attr('name'), "isChecked": isChecked });

postData.push({ "features": features, "menuItems": menuItems });
postData = JSON.stringify(postData);

The ajax function:

    $(':submit').click(function () {

        postData.push({ "features": features, "menuItems": menuItems });
        postData = JSON.stringify(postData);

        $.ajax({
                 url: '@Url.Action("CheckPreferences")',
                 type: 'POST',
                 data: postData, 
                 contentType: "application/json; charset=utf-8",
                 dataType: "json",
                 traditional: true,
                 success: function () { window.alert('@Resource.AjaxSuccess'); },
                 error: function (event, request, settings) {  window.alert('@Resource.AjaxError' + ' : ' + settings); },
                 timeout: 20000
        }); //endOf $.ajax
    }); //endOf :submit.click function

When I do alert(postData), in client side it contains the true values for each item but in the conroller the postData.Features and postData.MenuItems are null.

I have tried to pass just one array to the controller too:

 features = JSON.stringify(features);

in $.ajax:

{… data: features,…}

in controller:

 ActionResult CheckPreferences(IEnumerable<SJSonModel> features)

and it works fine, but I don't know how to pass the array of json objects to my contoller. So I hope to retrieve the answer here :)

Thank you very much.

share|improve this question
is there anyway you could post up the JSON Object that is actually going back to the server? could be that its not getting pushed right. try fiddler and see what the request for the ajax is – Qpirate Apr 13 '12 at 14:27

2 Answers

up vote 6 down vote accepted

Instead of combining your arrays into another array, you're best of sending them as individual parameters to the action method, something like:

Assume we still have your two arrays:

var features = new Array();
var menuItems = new Array();
menuItems.push({ "Name": $(this).attr('name'), "isChecked": isChecked });
features.push({ "Name": $(this).attr('name'), "isChecked": isChecked });

Then in your JQuery ajax call do the following:

$.ajax({
        url: '@Url.Action("CheckPreferences")',
        type: 'POST',
        datatype: "json",
        traditional: true,
        data: { 
            menuItems: JSON.stringify(menuItems),
            features: JSON.stringify(features)
        },
        success: function () { window.alert('@Resource.AjaxSuccess'); },
        error: function (event, request, settings) {  
            window.alert('@Resource.AjaxError' + ' : ' + settings); },
        timeout: 20000
});

Then your controller method should be:

[HttpPost]
public ActionResult CheckPreferences(string menuItems, string features)
{
    var js = new JavaScriptSerializer();
    var deserializedMenuItems = (object[])js.DeserializeObject(menuItems);
    var deserializedFeatures = (object[])js.DeserializeObject(features);
    var myFeatures = new List<SJSonModel>();
    var myMenuItems = new List<SJSonModel>();

    if (deserializedFeatures != null)
    {
        foreach (Dictionary<string, object> newFeature in deserializedFeatures)
        {
            myFeatures.Add(new SJSonModel(newFeature));
        }
    }

    if (deserializedMenuItems != null)
    {
        foreach (Dictionary<string, object> newMenuItem in deserializedMenuItems)
        {
            myMenuItems.Add(new SJSonModel(newMenuItem));
        }
    }

    var myModelList = new SJSonModelList(myFeatures, myMenuItems);

    return Json("");

I also edited your classes by putting in a constructor to work with the above code, like so:

public class SJSonModel
{
    public SJSonModel(Dictionary<string, object> newFeature)
    {
        if (newFeature.ContainsKey("Name"))
        {
            Name = (string)newFeature["Name"];
        }
        if (newFeature.ContainsKey("isChecked"))
        {
            isChecked = bool.Parse((string)newFeature["isChecked"]);
        }
    }

    public string Name { get; set; }
    public bool isChecked { get; set; }
}

public class SJSonModelList
{
    public SJSonModelList(List<SJSonModel> features, List<SJSonModel> menuItems )
    {
        Features = features;
        MenuItems = menuItems;
    }

    public List<SJSonModel> Features { get; set; }
    public List<SJSonModel> MenuItems { get; set; }
}
share|improve this answer
Hi, thank you for your message. I've done it yet it doesn't work, the values of menuItems and features are null – Lilit MR Apr 13 '12 at 14:37
Hi @LilitMR, check my new edit of my answer. I've tested that exact code and it works fine :) – mattytommo Apr 13 '12 at 15:01
Hi , thank you so much for your message. I'll try it this monday at the office and I answer you quickly. Pass a fine WE :) – Lilit MR Apr 14 '12 at 20:19
Hi, thank you so much, it works fine !!! :) – Lilit MR Apr 16 '12 at 7:57
Sweet :). Could you put the tick next to my answer and mark me as the answer? :) – mattytommo Apr 16 '12 at 8:34
show 2 more comments

Since you are passing serialized data from the client define postData as type string in your controller and then use JavascriptSerializer.Deserialize to deserialize the JSON into your object. This way you can also catch any errors that may occur during deserialization and debug the JSON that is sent over. One thing I am not sure if is if the Deserializer expects to match field names on case sensitivity. You define your arrays in the Model as "Features" and "MenuItems" whereas in the Javascript they are defined as "features" and "menuItems".

share|improve this answer
idem, it doesn't work – Lilit MR Apr 13 '12 at 14:40
What exactly did not work? If you debug the application can you see JSON in the string that is returned to the controller? Or does it fail on deserialization? – Kevin Junghans Apr 13 '12 at 18:32
Hi Kevin, thanks for your messages. I've just not used the serialization correctly, but it works fine now :) – Lilit MR Apr 16 '12 at 7:59
The problem was not the serialization but the postData: postData.push({ "features": features, "menuItems": menuItems }); postData = JSON.stringify(postData); ...$.ajax {...data: postData...} – Lilit MR Apr 16 '12 at 8:16
I shoud do data: { menuItems: JSON.stringify(menuItems), features: JSON.stringify(features) } – Lilit MR Apr 16 '12 at 8:17

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.