J'utilise jquery pour appeler une méthode ajax wcf qui renvoie une liste d'objets sous forme de chaîne JSON. La chaîne JSON ressemble à ceci lors de son inspection dans fiddler2 (dans 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\"}]"}
Lorsque j'inspecte le résultat dans la vue JSON du violoneux, il affiche le code JSON suivant:
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"}]
Donc Fiddler peut l’analyser avec succès, mais sur le client, la fonction de rappel d’erreur jax ajax affiche l’erreur suivante:
Error: No conversion from text to application/json
La méthode wcf est définie comme suit:
[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());
}
}
Et enfin, l’appel jQuery est:
$.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);
}
}
);
Merci d'avance!
UPDATE: Merci à @ user1370958, un pas de plus vers la solution.
Lorsque vous modifiez la fonction de rappel d'erreur comme suit, le résultat est renvoyé avec succès ...
error: function (jqXHR, textStatus, errorThrown) {
var test = $.parseJSON(jqXHR.responseText);
var test2 = $.parseJSON(test.d);
alert(test2[0].Name);
},
Je ne sais pas pourquoi, mais je dois analyser le résultat, puis analyser les objets imbriqués à l'intérieur de celui-ci. Je suppose que si l'un de mes types retournés contenait des objets complexes, il aurait également fallu une autre analyse ...
Ici, "application/json"
n'est pas une valeur valide pour la propriété dataType
. Je l'ai changée en "json"
dans mon projet et le même problème a été résolu.
Veuillez vérifier les détails ici (commentaire n ° 7): http://bugs.jquery.com/ticket/8216
Essayez d'ajouter le type MIME dans votre code côté serveur:
Response.ContentType = "application/json";
Avec WCF 4.0 , vous pouvez ajouter un attribut appelé automaticFormatSelectionEnabled
qui permet au service de regarder l’en-tête Accept
de la demande HTTP pour déterminer le format à renvoyer. Tant que ce que vous retournez est sérialisable, WCF gérera la sérialisation appropriée pour vous. Dans votre appel ajax jQuery, l'en-tête Accept est ajouté en incluant accepts: {json: "application/json"}
.
Je suppose que vous voulez renvoyer la valeur de ser.Serialize(query.ToArray())
au client (un tableau). Mais vous le retournez sous forme de chaîne. WCF échappera ainsi ce code JSON à une chaîne. Ce que vous allez retrouver n'est pas un tableau, mais une chaîne.
Comme vous utilisez des types anonymes, qui ne sont pas pris en charge de manière native par WCF, vous devez utiliser la variable JavaScriptSerializer
. Par conséquent, pour éviter le double encodage du JSON (dans la chaîne), vous devez plutôt renvoyer les données sous la forme Stream
, afin que WCF ne touche pas vos données (voir l'exemple de code ci-dessous).
Une dernière chose: je vois que votre réponse a un wrapper {"d":...}
, ce qui suggère que vous utilisez le <enableWebScript/>
/WebScriptEnablingBehavior
/WebScriptServiceHostFactory
lors de la définition de votre service/point de terminaison. Puisque vous n'utilisez pas la bibliothèque ASP.NET AJAX, vous n'avez pas besoin de ce retour à la ligne. Vous pouvez donc utiliser le "plus simple" <webHttp/>
/WebHttpBehavior
/WebServiceHostFactory
à la place, et votre réponse ne sera pas enveloppée dans cette "d" objet.
[OperationContract]
[WebGet(ResponseFormat = WebMessageFormat.Json)]
public System.IO.Stream 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
};
string json = ser.Serialize(query.ToArray());
using (MemoryStream ms = new MemoryStream(Encoding.UTF8.GetBytes(json)))
{
WebOperationContext.Current.OutgoingResponse.ContentType = "application/json; charset=utf-8";
return ms;
}
}
J'ai trouvé une solution de contournement:
Le premier problème était l'exception de référence circulaire sur le modèle d'entité. Pour surmonter cela, j'utilise le code suivant pour Détacher mes entités du contexte, puis les sérialiser en chaînes. Je les sérialise ensuite sur le client en utilisant le code ci-dessous.
Un service
[WebGet(ResponseFormat = WebMessageFormat.Json)]
[OperationContract]
public string[] GetPeople(Guid groupId)
{
using (SchedulerContext context = new SchedulerContext())
{
var people = (from p in context.People
where p.Group_ID == groupId
select p).ToList();
JavaScriptSerializer ser = new JavaScriptSerializer();
string[] result = new string[people.Count];
for (int i = 0; i<people.Count; i++)
{
context.Detach(people[i]);
string json = ser.Serialize(people[i]);
result[i] = json;
}
return result;
}
}
Client
$.ajax(
{
type: "GET",
//dataType: "application/json",
//dataType: "text/plain",
contentType: "json",
data: { groupId: 'ae09a080-5d7c-4e92-9a87-591574b7c4b8' },
//data: { groupId: 'test' },
//data: { groupId: '739526F1-7C58-4E3B-97D8-4870948BFE32' },
url: "WebAPI.svc/GetPeople",
error: function (jqXHR, textStatus, errorThrown) {
alert(jqXHR.resultText);
},
success: function (people) {
//the returned param "people" is of type string[], so each string needs parsed
$(people).each(function (index, value) {
var person = $.parseJSON(value);
//now I can use the Person object
});
}
}
);