1

In my cshtml I'm calling this function

function checkOutGroup(listOfIDs, listOfSites, itemType, controller)

After an AJAX call that runs correctly, I have a second AJAX call that takes in some of the data from the first in the success function and calls the second AJAX call.

if(!haveCheckedOutItems)
            {
                alert(listOfIDs[0] + " " + listOfIDs[1]);
                alert(listOfSites);
                $.ajax({
                    type: 'POST',
                    url: '/WorkQueues/CheckOutMultiple',
                    data: {idsToCheckOut: listOfIDs, listOfSites:listOfSites, itemType : itemType, controller: controller, checkIn : false},
                    datatype: 'json',
                    beforesend: function() {},
                    complete: function() {},
                    success: function(checkedOutItems) {....

In the cs file, the WorkQueues controller has a method called CheckOutMultiple with the following method signature:

public ActionResult CheckOutMultiple(List<int> idsToCheckOut, List<int> listOfSites, string itemType, string controller, bool checkIn)

Inside this code, idsToCheckOut is null for some reason, but the other 4 things being passed have all of the correct data. I'm noting doing anything with the listOfIDs except passing a copy of it in the first method.

Any thoughts?

EDIT 1: The parsed version of the call from the chrome networknig tab is

    idsToCheckOut[]:72431
idsToCheckOut[]:56361
listOfSites[]:400216
listOfSites[]:549003
itemType:Visit
controller:Visits
checkIn:false

The non-parsed version is :

idsToCheckOut%5B%5D=72431&idsToCheckOut%5B%5D=56361&listOfSites%5B%5D=400216&listOfSites%5B%5D=549003&itemType=Visit&controller=Visits&checkIn=false

EDIT 2: Somehow I've managed to get the listOfSites broken in the same fashion, and regardless of how far back I go, I can't undo the break.

  • It would help to see the network trace of the data being posted to your server. Easiest way is to use chrome dev tools and find the ajax post in the networking tab. If you could update your answer to include that JSON sent to the server it might identify a conversion problem. – JonathanTech Dec 08 '14 at 19:10

2 Answers2

0

If you can verify that listOfIDs in the calling script is not null, then it should be serializing/deserializing correctly using the pattern you provided. One thing that sticks out to me however is that you're not surrounding the attributes in the data object with quotes; sometimes having the data in the form of { foo : bar } instead of { "foo" : bar } or even { "foo" : JSON.stringify(bar) } if the data is complex can present problems.

I also noticed that the name of the problematic variable differs between the script and server method signature (with the exception of the boolean, which could be defaulting to false since it's not nullable). You could be lucking into your method working when the variable names match.

moarboilerplate
  • 1,633
  • 9
  • 23
  • I have an alert right above the ajax call which prints out the two items in the listOfIDs field, so I know the data is there. I tried adding the quotes (both single and double), but that didn't change anything. I'll try editing the name of the variable in the server to see if it changes anything. – Michael Harrison Dec 08 '14 at 19:09
  • My gut says this is probably an issue with passing the data as an object and not a serialized JSON string. Try using the JSON library to stringify your data object with the names of the attributes encased in quotes. – moarboilerplate Dec 08 '14 at 19:12
  • Can a list be stringified? The main reason I'm doing it this way is because I have a list of unkown (well, greater than 1, but no upper bound) list. – Michael Harrison Dec 08 '14 at 19:32
  • Follow the last example in this article to create a "DTO" object on which you call stringify. http://encosia.com/using-complex-types-to-make-calling-services-less-complex/ Declare it along the lines of `var data = { "foo" : bar };` and in your data attribute do `JSON.stringify(data)`. Also make sure you have set your content type to application/json like the example shows (which also may be the root of your issue) – moarboilerplate Dec 08 '14 at 19:43
  • You shouldn't have to worry about anything with lists. An array will get correctly serialized by the JSON library and correctly deserialized into a List by ASP.NET. – moarboilerplate Dec 08 '14 at 19:47
  • So, I'm not sure what happened, but stringify is mangling the data before it gets passed. Its only passing three per item - An empty string, the ID number, and a boolean (which doesn't match the one boolean input I have): [{"Item1":"","Item2":56361,"Item3":true},{"Item1":"","Item2":72431,"Item3":true}]: – Michael Harrison Dec 08 '14 at 19:57
  • I doubt your problem is with stringify. Looking at your data it looks like you have mapping logic that is borked. If you're passing separate arrays of ints, why does your data take the form of one giant array of objects with multiple properties on them? Looks like instead of adding individual items to separate arrays you're accidentally creating an object and adding the items as separate properties on the same object. – moarboilerplate Dec 08 '14 at 20:12
0

Correction:

Your post to the server is using the form's protocol. This is because your jquery doesn't specify to use json when sending to the server.

If you want to continue to post using the forms posting method that it is using it seems that you need to tell jquery to post using the traditional method for array values as explained here.

Using forms:

$.ajax({
     type: 'POST',
     url: '/WorkQueues/CheckOutMultiple',
     data: {idsToCheckOut: listOfIDs, listOfSites:listOfSites, itemType : itemType, controller: controller, checkIn : false},
     ...
     traditional: true

Using json:

$.ajax({
     type: 'POST',
     url: '/WorkQueues/CheckOutMultiple',
     data: {idsToCheckOut: listOfIDs, listOfSites:listOfSites, itemType : itemType, controller: controller, checkIn : false},
     ...
     contentType : "application/json; charset=utf-8"
Community
  • 1
  • 1
JonathanTech
  • 228
  • 1
  • 12
  • Make sure to look at your casing for `beforesend` too. It should be `beforeSend` [jquery ajax docs](http://api.jquery.com/jQuery.ajax/) – JonathanTech Dec 08 '14 at 20:56
  • I'm corrected both casings, but it hasn't changed any of the behavior. – Michael Harrison Dec 08 '14 at 21:09
  • Just edited my answer. I jumped to the wrong conclusion for the purpose of the dataType property too soon from the network tab data. – JonathanTech Dec 08 '14 at 21:13
  • 1
    Adding the traditional tag fixed it! Thanks :) – Michael Harrison Dec 08 '14 at 21:18
  • If I had to venture a guess, I'd say your code currently has dataType: 'json' and traditional: true. If that's the case correct it because you're not using JSON. If you had changed the content type in your calls to application/json and stringified your data object your problem would have been solved. – moarboilerplate Dec 09 '14 at 01:38
  • Either way is a valid way of posting. Asp.net MVC, Michael Harrison's current server framework, will accept either and correctly model bind it. What was happening in his case is that jQuery moved on to using the format `arrayFieldName[]=` whereas MVC is using the traditional format of `arrayFieldName=` . I myself prefer json to be sent to the server as it's far more human legible but I think this is a case of if it's working, why change it. – JonathanTech Dec 09 '14 at 18:21