Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Passing an associative array using json: which type to expect in the controller?

On the client side I have an associative array where I store "Guid" - "int" pairs. I pass the array to the server by using json:

  $.ajax({
      url: methodUrl,
      type: 'POST',
      async: false,
      data: { values: items },
      dataType: 'json',
      success: function (data) {
          //...
      }
  });

The object I try to pass looks like this(taken from Chrome debugger):

  items: Object
  44f871e0-daee-4e1b-94c3-76d633a87634: 1
  698ce237-3e05-4f80-bb0d-de948c39cd96: 1

In the controller I have a method

  public ActionResult Method(Dictionary<Guid, int> values)
  {

  } 

However, property values remains null. With just a list of Guids on the client side and List in the controller everything works fine. I suspect that I should choose another type for values in the controller, not Dictionary. I also tried adding "traditional: true" to the ajax request, however with no success.

Any advice is appreciated!

like image 923
Anelook Avatar asked Apr 11 '13 13:04

Anelook


3 Answers

This is what I do when using a POST command:

var data = {
   values: items
}

var obj = $.toJSON(data);

$.ajax({
      url: methodUrl,
      type: 'POST',
      async: false,
      data: obj,
      dataType: 'json',
      success: function (data) {
          //...
      }
  });

This should send through to your Controller properly and you shouldn't have to use a Dictionary object, you should match objects up from client side to server side. I'd use a custom object that has a Guid and a int as properties in it, and use that - .NET will match the two up. That being said, it's perfectly reasonable to use a Dictionary, but that's personal preference.

i.e.

public CustomObject 
{
    public Guid MyGuid { get; set; }
    public int MyNumber { get; set; }
}

public ActionResult Method(List<CustomObject> values)
{

} 

With multiple parameters:

items.SecondNumber = yourVariable; 
// In reality, you'd have a loop around your items and set this SecondNumber.

var data = {
    values: items
}

var obj = $.toJSON(data);


public CustomObject 
{
     public Guid MyGuid { get; set; }
     public int MyNumber { get; set; }
     public int SecondNumber { get; set; } // This is why we use CustomObject
}
like image 62
Chris Dixon Avatar answered Nov 14 '22 06:11

Chris Dixon


Although I selected thedixon's answer as a solution, I managed in the end to avoid using any additional classes.

The most important part is that the type of the collection sent to the server should be a javascript array with key-value types. For instance, here is the object which I created in js before sending to the server:

items : Array[2]
0: Object
key: "ddac666f-310f-4022-a22c-c542355b765e"
value: 1
1: Object
key: "ce9ae5a6-e6a6-4bb6-b61c-b1cc324be049"
value: 1

After this it is necessary to stringify it and then send to the server.

    var obj = JSON.stringify(items);
    $.ajax({
        url: teilnahmen.AddNewTeilnahmenUrl,
        type: 'POST',
        traditional: true,
        dataType: 'json',
        data: obj,
        contentType: "application/json",
        success: function (data) {
            //...
        }
    });

On the server side:

    public ActionResult AddNewTeilnahmen(Dictionary<Guid, int> values)
    { ... }

I still believe that this solution is better, as it doesn't require creating classes which most probably will never be reused and already exist in .NET. But as thedixon correctly mentioned, it is a matter of taste.

like image 3
Anelook Avatar answered Nov 14 '22 06:11

Anelook


In addition to Anelook last comment, here is the creation of javascript array:

var items = [];
$(something).each(function (index, element) {
   var item = { "key": element.guid, "value": element.number };
   items.push(item);
});
like image 1
jeanie77 Avatar answered Nov 14 '22 08:11

jeanie77