Question

The service method looks like this

public class UploadItem
{
  public string fileName { get; set; }
  public string fileDesc { get; set; }
}
[OperationContract, WebGet]
public int WriteUploadItem(UploadItem uploadItem)
{
  //implementation
}

The invocation looks like this

var data = {
  fileName: self.fileName(),
  fileDesc: self.fileDesc(),
};

$.ajax({
  url: "Fx.svc/WriteUploadItem",
  data: { uploadItem: data },
  success: function (result) {
    //implementation
  },
  error: function (result) { alert($.parseJSON(result.responseText).Message); }
});

which produces this

GET http://localhost:49701/Fx.svc/WriteUploadItem?uploadItem%5BfileName%5D
=2014-01-21.gif&uploadItem%5BfileDesc%5D=adesgfA HTTP/1.1
X-Requested-With: XMLHttpRequest
Accept: */*
Referer: http://localhost:49701/index.html#upload-queue
Accept-Language: en-AU,en;q=0.5
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/5.0 (Windows NT 6.3; WOW64; Trident/7.0; rv:11.0) like Gecko
Host: localhost:49701
DNT: 1
Connection: Keep-Alive

Those URL encoded parameters look like this when decoded

uploadItem[fileName]=2014-01-21.gif&uploadItem[fileDesc]=adesgfA 

The WebGet method is invoked but the parameter is null.

I'm successfully passing a single parameter to another method like this

var userId = "73c2e254-5440-45eb-9099-58fa08dd037b"; // me.UserID();
$.ajax({
  url: "Fx.svc/UserFiles",
  data: { userId: userId },
  success: function (result) {
    //implementation
  },
  error: function (result) { alert($.parseJSON(result.responseText).Message); }
});

As far as I can see, the only difference is that the value of the parameter is different. Originally there were a lot more fields but I removed the more troublesome data types and was intrigued to discover that the problem occurs even with simple strings.

What's wrong and what should I do about it? Is there some sort of attribute I need to put on the C# UploadItem class?

Was it helpful?

Solution

The default encoding used by $.ajax() is application/x-www-form-urlencoded.

To fix this, control the encoding and tell the other end exactly what encoding was used. Note the explicit stringification of the object, and the explicit encoding of text/json for the contentType.

var data = {
  fileName: self.fileName(),
  fileDesc: self.fileDesc(),
};

$.ajax({
  url: "Fx.svc/WriteUploadItem",
  data: JSON.stringify(data),
  contentType: "text/json"
}).done(function (result) { 
  //implementation
}).error(function (err) { 
  //handle error
});

The content type encoding you specify will also be used for the return value unless you specify a different encoding. Usually it's very satisfactory to get JSON back since $.ajax() will magically parse it into the result object, but when you are returning a simple type such as an int, you'll need to specify a return encoding of text/plain using the dataType parameter.

$.ajax({
  url: "Fx.svc/WriteUploadItem",
  data: JSON.stringify(data),
  contentType: "text/json",
  dataType: "text/plain"
}).done(function (result) { 
  //implementation
}).error(function (err) { 
  //handle error
});
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top