2012-05-04 20 views
18

Estoy usando jquery para llamar a un método ajax wcf que devuelve una lista de objetos como una cadena JSON. La cadena JSON tiene este aspecto cuando se inspeccionan en fiddler2 (en la Vista de Texto):jquery ajax call return Error de análisis 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\"}]"} 

Cuando examino el resultado en Fiddler JSON Vista, se muestra el siguiente 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"}] 

Así violinista puede analizar con éxito, pero en el cliente, la función de devolución de llamada de error jquery ajax muestra el error siguiente:

Error: No conversion from text to application/json 

el método WCF se define como sigue:

[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()); 
     } 
    } 

Y, por último, la llamada jQuery es:

$.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); 
      } 
     } 
); 

Gracias de antemano!

ACTUALIZACIÓN: Gracias a @ user1370958, un paso más cerca de la solución.

Al cambiar la función de devolución de llamada de error a la siguiente con éxito devuelve el resultado ...

error: function (jqXHR, textStatus, errorThrown) { 
    var test = $.parseJSON(jqXHR.responseText); 
    var test2 = $.parseJSON(test.d); 
    alert(test2[0].Name); 
}, 

No sé por qué, pero tengo que analizar el resultado y luego analizar los objetos anidados dentro de eso. Asumo que si alguno de mis tipos devueltos contenían objetos complejos que también habría necesitado otro de análisis ...

Respuesta

48

Aquí, "application/json" no es un valor válido para la propiedad tipo de datos. Lo cambié a "json" en mi proyecto y se solucionó el mismo problema.

favor comprobar los detalles aquí (comentario # 7): http://bugs.jquery.com/ticket/8216

+0

application/json se usa en encabezados http no en jquery ajax. solo confirmado –

3

Trate de añadir el tipo MIME en el código del lado del servidor:

Response.ContentType = "application/json"; 
+0

sí lo tienen, sin éxito, aunque gracias – hofnarwillie

0

Asumo que desea para devolver el valor de ser.Serialize(query.ToArray()) al cliente (una matriz). Pero lo estás devolviendo como una cadena, por lo que WCF escapará de ese JSON en una cadena, y lo que terminarás no es una matriz, sino una cadena.

Dado que está utilizando tipos anónimos, que no son compatibles nativamente con WCF, debe utilizar el JavaScriptSerializer. Por lo tanto, para evitar la doble codificación de JSON (en la cadena) debe devolver los datos como Stream en su lugar, para que WCF no toque sus datos (consulte el código de ejemplo a continuación).

Una cosa más: Puedo ver su respuesta tiene un envoltorio {"d":...}, lo que sugiere que usted está utilizando el <enableWebScript/>/WebScriptEnablingBehavior/WebScriptServiceHostFactory la hora de definir su servicio/punto final. Como no está utilizando la biblioteca ASP.NET AJAX, no necesita ese ajuste, por lo que puede usar el "más simple" <webHttp/>/WebHttpBehavior/WebServiceHostFactory y su respuesta no estará envuelta en ese objeto "d" .

[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; 
     } 

} 
+0

gracias, pero sin suerte. Copié tu código, pero ahora la devolución de llamada por error de javascript no tiene información de error, solo cadenas vacías y dice que el error es "error". Además, no hay más resultText devuelto. – hofnarwillie

+0

Intente habilitar el seguimiento en el servidor para ver si sucede algo extraño. O mire la respuesta real de la red (usando Fiddler o las herramientas del desarrollador del navegador) para ver si hay información adicional. – carlosfigueira

+0

"[Fiddler] ReadResponse() failed: El servidor no devolvió una respuesta para esta solicitud". – hofnarwillie

1

Con WCF 4.0, se puede añadir un atributo llamado automaticFormatSelectionEnabled el cual permite que el servicio vistazo a la cabecera Accept en la petición HTTP para determinar qué formato para volver. Mientras que lo que está devolviendo sea serializable, WCF manejará la serialización correcta para usted. En su llamada jQuery ajax, se agrega el encabezado Aceptar al incluir accepts: {json: "application/json"}.

+0

Voy a intentar esto, ¿dónde agrego automaticFormatSelectionEnabled? – hofnarwillie

+0

El enlace en la respuesta muestra cómo agregarlo en la configuración o mediante programación. –

+0

Traté de agregar las cosas que dijiste. Llama al servidor con éxito y puedo pasar por WebGET. Luego parece regresar, pero el violinista informa: [Fiddler] ReadResponse() falló: el servidor no devolvió una respuesta para esta solicitud. Y la devolución de llamada de error se ejecuta nuevamente sin datos devueltos. – hofnarwillie

0

he encontrado una solución:

El primer problema fue la excepción de referencia circular en el modelo de entidad. Para superar esto, uso el siguiente código para separar mis entidades del contexto y luego serializarlas en cadenas. Luego los serializo en el cliente usando el siguiente código.

Servicio

[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; 
     } 
    } 

cliente

 $.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 
         }); 

        } 
       } 

     );