I am using jquery to call an ajax wcf method that returns a list of objects as a JSON string. The JSON string looks like this when inspecting it in fiddler2 (in TextView):
{"d":"[{\"ID\":\"6b2b8c62-31ce-4df2-982b-054ff5f6be72\",\"Name\":\"Carol\",\"Surname\":\"IrishWife\"},{\"ID\":\"d254740a-0a0f-4a1e-9e4f-0812227dd5af\",\"Name\":\"Willie\",\"Surname\":\"Le Roux\"},{\"ID\":\"660bf0dd-436a-4588-a9c0-19fd6fdcee23\",\"Name\":\"Emmas\",\"Surname\":\"Mum\"},{\"ID\":\"6b9403c5-b728-4e96-bcb1-203e7472eec3\",\"Name\":\"Owen\",\"Surname\":\"Lima\"},{\"ID\":\"d52c08fb-4418-4600-960f-243ff4443ee6\",\"Name\":\"Tim\",\"Surname\":\"Lee\"},{\"ID\":\"e2aacf5b-8855-44ce-9338-3d39f8ab3349\",\"Name\":\"Marcello\",\"Surname\":\"MT\"},{\"ID\":\"578be087-8385-46d6-89de-3db31d352cbc\",\"Name\":\"Carlyn\",\"Surname\":\"Homegroup\"},{\"ID\":\"4c805825-2bee-447a-8b75-41ead17db33e\",\"Name\":\"George\",\"Surname\":\"Homegroup\"},{\"ID\":\"ae48804f-5e78-42c8-9ba0-4214c98a5a89\",\"Name\":\"Isla\",\"Surname\":\"Le Roux\"},{\"ID\":\"f8be2f4f-fedb-4863-8a84-44fddea84ea9\",\"Name\":\"Peter\",\"Surname\":\"Anderson\"},{\"ID\":\"15e7644d-ec43-44ff-a959-47e00112da6b\",\"Name\":\"Kitty\",\"Surname\":\"Corbett\"},{\"ID\":\"8fd7fccc-335c-4d5c-93b5-4b00f96a9950\",\"Name\":\"Natalie\",\"Surname\":\"Archibald\"},{\"ID\":\"09b5aad2-2cf1-488a-962b-4d692b05ddea\",\"Name\":\"Miku\",\"Surname\":\"Heally\"},{\"ID\":\"affa369e-5af3-4537-a0f4-71422956da41\",\"Name\":\"Steven\",\"Surname\":\"Corbett\"},{\"ID\":\"65f57da3-4f88-4798-9590-83b4ccecfc44\",\"Name\":\"Tim\",\"Surname\":\"Archibald\"},{\"ID\":\"53bfb451-f66f-4b6e-b430-8d13c95b30d8\",\"Name\":\"Philip\",\"Surname\":\"MT\"},{\"ID\":\"c7f22b9b-4030-4f82-9f75-bbb726cabb73\",\"Name\":\"Vincent\",\"Surname\":\"Van Der Walt\"},{\"ID\":\"232577be-3165-4316-a20d-c2f2a09c5382\",\"Name\":\"Scott\",\"Surname\":\"Lynn\"},{\"ID\":\"913508a1-5dca-4504-8caf-c8e3dc386fc0\",\"Name\":\"Dan\",\"Surname\":\"MT\"},{\"ID\":\"36054a07-b14d-4c1c-b35f-e00875dde7e5\",\"Name\":\"Sarah\",\"Surname\":\"MT\"},{\"ID\":\"f14e7d98-e040-4ba9-928f-f2ff48116b0b\",\"Name\":\"Josh\",\"Surname\":\"IrishDude\"}]"}
When I inspect the result in fiddler's JSON View, it shows the following JSON:
d=[{"ID":"6b2b8c62-31ce-4df2-982b-054ff5f6be72","Name":"Carol","Surname":"IrishWife"},{"ID":"d254740a-0a0f-4a1e-9e4f-0812227dd5af","Name":"Willie","Surname":"Le Roux"},{"ID":"660bf0dd-436a-4588-a9c0-19fd6fdcee23","Name":"Emmas","Surname":"Mum"},{"ID":"6b9403c5-b728-4e96-bcb1-203e7472eec3","Name":"Owen","Surname":"Lima"},{"ID":"d52c08fb-4418-4600-960f-243ff4443ee6","Name":"Tim","Surname":"Lee"},{"ID":"e2aacf5b-8855-44ce-9338-3d39f8ab3349","Name":"Marcello","Surname":"MT"},{"ID":"578be087-8385-46d6-89de-3db31d352cbc","Name":"Carlyn","Surname":"Homegroup"},{"ID":"4c805825-2bee-447a-8b75-41ead17db33e","Name":"George","Surname":"Homegroup"},{"ID":"ae48804f-5e78-42c8-9ba0-4214c98a5a89","Name":"Isla","Surname":"Le Roux"},{"ID":"f8be2f4f-fedb-4863-8a84-44fddea84ea9","Name":"Peter","Surname":"Anderson"},{"ID":"15e7644d-ec43-44ff-a959-47e00112da6b","Name":"Kitty","Surname":"Corbett"},{"ID":"8fd7fccc-335c-4d5c-93b5-4b00f96a9950","Name":"Natalie","Surname":"Archibald"},{"ID":"09b5aad2-2cf1-488a-962b-4d692b05ddea","Name":"Miku","Surname":"Heally"},{"ID":"affa369e-5af3-4537-a0f4-71422956da41","Name":"Steven","Surname":"Corbett"},{"ID":"65f57da3-4f88-4798-9590-83b4ccecfc44","Name":"Tim","Surname":"Archibald"},{"ID":"53bfb451-f66f-4b6e-b430-8d13c95b30d8","Name":"Philip","Surname":"MT"},{"ID":"c7f22b9b-4030-4f82-9f75-bbb726cabb73","Name":"Vincent","Surname":"Van Der Walt"},{"ID":"232577be-3165-4316-a20d-c2f2a09c5382","Name":"Scott","Surname":"Lynn"},{"ID":"913508a1-5dca-4504-8caf-c8e3dc386fc0","Name":"Dan","Surname":"MT"},{"ID":"36054a07-b14d-4c1c-b35f-e00875dde7e5","Name":"Sarah","Surname":"MT"},{"ID":"f14e7d98-e040-4ba9-928f-f2ff48116b0b","Name":"Josh","Surname":"IrishDude"}]
So fiddler can parse it successfully, but on the client, the jquery ajax error callback function displays the following error:
Error: No conversion from text to application/json
The wcf method is defined as follows:
[OperationContract]
[WebGet(ResponseFormat=WebMessageFormat.Json)]
public string GetPeople(Guid groupId)
{
using (SchedulerContext context = new SchedulerContext())
{
JavaScriptSerializer ser = new JavaScriptSerializer();
var query = from p in context.People
where p.Group_ID == groupId
select new
{
p.ID,
p.Name,
p.Surname
};
return ser.Serialize(query.ToArray());
}
}
And finally, the calling jquery is:
$.ajax(
{
type: "GET",
dataType: "application/json",
contentType: "json",
data: { groupId: 'ae09a080-5d7c-4e92-9a87-591574b7c4b8' },
url: "WebAPI.svc/GetPeople",
error: function (jqXHR, textStatus, errorThrown) {
alert("error");
},
success: function (msg) {
alert(msg.d[0].Name);
}
}
);
Thanks in advance!
UPDATE: Thanks to @user1370958, one step closer to the solution.
When changing the error callback function to the following it successfully returns the result...
error: function (jqXHR, textStatus, errorThrown) {
var test = $.parseJSON(jqXHR.responseText);
var test2 = $.parseJSON(test.d);
alert(test2[0].Name);
},
Not sure why, but I have to parse the result and then parse the nested objects inside that. I'm assuming if any of my returned types contained complex objects it would also have needed another parse...
I assume you want to return the value of
ser.Serialize(query.ToArray())
to the client (an array). But you're returning it as a string, so WCF will escape that JSON into a string, and what you'll end up is not an array, but a string.Since you're using anonymous types, which aren't natively supported by WCF, you need to use the
JavaScriptSerializer
. So to prevent the double-encoding of the JSON (into the string) you should return the data as aStream
instead, so that WCF won't touch your data (see sample code below).One more thing: I see your response has a
{"d":...}
wrapper, which suggests that you're using the<enableWebScript/>
/WebScriptEnablingBehavior
/WebScriptServiceHostFactory
when defining your service / endpoint. Since you're not using the ASP.NET AJAX library, you don't need that wrapping, so you can use the "simpler"<webHttp/>
/WebHttpBehavior
/WebServiceHostFactory
instead, and your response won't be wrapped in that "d" object.With WCF 4.0, you can add an attribute called
automaticFormatSelectionEnabled
which allows the service to look at theAccept
header in the HTTP request to determine what format to return. As long as what you are returning is serializable, WCF will handle the correct serialization for you. In your jQuery ajax call, the Accept header is added by includingaccepts: {json: "application/json"}
.Try adding the MIME type in your server-side code:
Here,
"application/json"
is not a valid value for thedataType
property. I changed it to"json"
in my project and the same problem was solved.Please check details here (comment #7): http://bugs.jquery.com/ticket/8216
I've found a workaround:
The first problem was the circular reference exception on the entity model. To overcome this I use the following code to Detach my entities from the context and then serialize them to strings. I then serialize them on the client using the code below that.
Service
Client