Search code examples
jqueryajaxwcfstringify

Stringifying an array in ajax payload to WCF endpoint


I have the follow bit of Javascript:

 $.ajax({
    url: "/Web/WebServices/Operation.svc/SetScope",
    type: "POST",
    contentType: "application/json; charset=utf-8",
    beforeSend: function () {
    },
    dataType: "json",
    cache: false,
    data: JSON.stringify({
        Id: Id,
        RIds: RIds,
        rScope: rScope 
    }),
    success: function (data) { onSuccess(data); },
    error: function (data) { onError(data); }
    });

If you look at the data bit --

  • Id is an int
  • RIds is array of ints
  • rScope is an array of objects each containing an int and a string

The result of

data: JSON.stringify({
            Id: Id,
            RIds: RIds,
            rScope: rScope 
        })

is

'{"Id":1,"rIds":[1,2,3,4],"rScope":[{"id":3,"type":"barney"},{"id":2,"type":"ted"}]}'

Passing it into $.parseJSON returns the expected object.

The problem is that it returns 400 Bad Request.

The signature waiting for the call is in WCF hosted in IIS

public OperationResult SetScope(int rId, string rIds, string rScope)

If I remove rScope from the code, everything is fine, but it seems to be having trouble with an array populated with objects as opposed to just primitives.

What am I missing here?

I found similar questions but none that really explained my scenario.


Solution

  • If I'm not mistaken the result of your parsing implies that rScope is an object array with each object having an id and a type property and not just a simply string.

    "rScope":[{"id":3,"type":"barney"},{"id":2,"nodetype":"ted"}]
    

    If you have a class similar to this:

    public class ScopeClass{
        public int Id {get; set;}
        public string Type {get; set;}
    }
    

    And use it in your method like this:

    public OperationResult SetScope(int rId, string rIds, IList<ScopeClass> rScope)
    

    Edit

    Actually, I just noticed you also have the second object named nodetype instead of type.

    If you use the above aproach you need to make sure in your data you pass up the nodetype is also named type, otherwise you can't match the values.

    Also, using the property name Type might not be a good idea due to C#'s type of Type. If you have any influence you can update Type to something more meaningfull as in GroupType or what ever it represents and then name it the same in the data passed up. The model binder should then simply magic-match it.