3

I am sending json data to my controller action via jquery ajax post. The IEnumerable in my action is alway null.

Is my json wrong or why does the model binder not convert the json to the IEnumerable ?

public ActionResult Update(IEnumerable<Teststep> teststeps)
{
   //
}

$.ajax({
            url: '@Url.Action("Update", "Teststep")',
            type: 'POST',
            data: [{ "errortext": "oh something bad happended.", "unitid": "10" }, { "errortext": "you got it man.", "unitid": "20"}],
            success: function (response) {
                debugger;
                if (response.success) {
                    dlg.dialog("close");
                    // Update UI

                }
                else {
                    // Reload the dialog with the form to show model/validation errors 
                    dlg.html(response);
                }
            }
        });

public class Teststep
{

 [HiddenInput(DisplayValue = false)]
 public int UnitId { get; set; }    

 public string ErrorText { get; set; }  

 // some other props removed for readability   

}
Elisabeth
  • 20,496
  • 52
  • 200
  • 321
  • Try to use **Teststep[] teststeps** as parameter for method and serialize JSON: JSON.stringity([{ "errortext": "oh something bad happended.", "unitid": "10" }, { "errortext": "you got it man.", "unitid": "20"}]) – cycaHuH Jun 05 '12 at 14:50
  • Sorry I dont get the "Try to use Teststep[] teststeps as..." Can you rewrite that please? – Elisabeth Jun 05 '12 at 14:53
  • `public ActionResult Update(Teststep[] teststeps)` – cycaHuH Jun 05 '12 at 14:59
  • Could you provide `Teststep` class content? – cycaHuH Jun 05 '12 at 15:01
  • ah I always thought as parameter for the json... now it makes sense :P, but it did not work still null the parameter. I also added Teststep class content. – Elisabeth Jun 05 '12 at 15:03
  • Try to pass the following as data: `data: [{ "ErrorText": "oh something bad happended.", "UnitId":"10"}]` – cycaHuH Jun 05 '12 at 15:05
  • I have this now: data: JSON.stringify([{ "ErrorText": "oh something bad happended.", "UnitId": "10"}]), and this: public ActionResult Update(Teststep teststep) {} and the teststep object is created but the properties like ErrorText are null. – Elisabeth Jun 05 '12 at 15:13
  • Looks like there is only one way to do it: [link]http://stackoverflow.com/questions/320291/how-to-post-an-array-of-complex-objects-with-json-jquery-to-asp-net-mvc-control[link] – cycaHuH Jun 05 '12 at 15:32
  • No thats not a solution for now. It was in MVC1/2 but not in MVC3 with the modelbinder this should work! – Elisabeth Jun 05 '12 at 16:22

2 Answers2

1

In order to get collections (arrays, ienumerables, etc) to pass correctly through the modelbinder to the action method, I've always had to set the traditional: true option on the ajax call:

$.ajax({
    url: '@Url.Action("Update", "Teststep")',
    type: 'POST',
    traditional: true,
    ...
danludwig
  • 46,965
  • 25
  • 159
  • 237
  • I doubt it. I've only been passing enumerations of primitives, not complex types. It works great using `.serialize()` instead of `.stringify()`. In your case stringify might be better since it appears you want to specify the values manually rather than get them from form input elements. – danludwig Jun 05 '12 at 18:17
  • well I just tried this: var data = [ '11', '22' , '33' ]; JSON.stringify(data) and my action has an IEnumerable. I get a count of 3. So it works. Wether I specifiy them manually for test purposes because I do not yet know the datagrid I will use later or I get the data from input elements via .val() should play no role. – Elisabeth Jun 05 '12 at 19:34
  • Your answer also includes the `dataType: 'json'` parameter, whereas your original question does not. You may be able to achieve the same result by simply using the `traditional: true` option instead of `dataType: 'json'`. I have never encountered a reason to submit the POST data as a serialized JSON string in MVC. The default model binder should extract your collection parameters as long as you tell jQuery to do a shallow encoding. Deep object recursion was introduced in jQuery 1.4: http://api.jquery.com/jQuery.param/ – danludwig Jun 05 '12 at 19:48
  • the dataType: 'json' can be removed. Jquery can infer its datatype. Only the contentType is needed. – Elisabeth Jun 05 '12 at 21:32
1

Now it works! I get 1 item in the IEnumerable. The problem was the messed up json ;-)

 var data = { teststeps: [{ ErrorText: 'bla', UnitId: 10}] };
        $.ajax({
            url: '@Url.Action("Update", "Teststep")',
            type: 'POST',
            data: JSON.stringify(data),
            dataType: 'json',
            contentType: 'application/json'            
        });

[HttpPost]
public ActionResult Update(IEnumerable<Teststep> teststeps)
{

}
Elisabeth
  • 20,496
  • 52
  • 200
  • 321