2009-02-26 24 views
22

Uso el siguiente código para llamar a un servicio wcf. Si llamo a un método (de prueba) que no toma parámetros, pero devuelve una cadena, funciona bien. Si puedo añadir un parámetro a mi método me sale un error extraño:Pasar datos de una solicitud jquery ajax a un servicio wcf ¿falla la deserialización?

{"ExceptionDetail":{"HelpLink":null,"InnerException":null,"Message":"The token '\"' was expected but found '''.","StackTrace":" at System.Xml.XmlExceptionHelper.ThrowXmlException(XmlDictionaryReader reader, String res, String arg1, String arg2, String arg3)\u000d\u000a at System.Xml.XmlExceptionHelper.ThrowTokenExpected(XmlDictionaryReader reader, String expected, Char found)\u000d\u000a at System.Runtime.Serialization.Json.XmlJsonReader.ParseStartElement()\u000d\u000a at System.Runtime.Serialization.Json.XmlJsonReader.Read()\u000d\u000a at System.ServiceModel.Dispatcher.DataContractJsonSerializerOperationFormatter.DeserializeBodyCore(XmlDictionaryReader reader, Object[] parameters, Boolean isRequest)\u000d\u000a at System.ServiceModel.Dispatcher.DataContractJsonSerializerOperationFormatter.DeserializeBody(XmlDictionaryReader reader, MessageVersion version, String action, MessageDescription messageDescription, Object[] parameters, Boolean isRequest)\u000d\u000a at System.ServiceModel.Dispatcher.OperationFormatter.DeserializeBodyContents(Message message, Object[] parameters, Boolean isRequest)\u000d\u000a at System.ServiceModel.Dispatcher.OperationFormatter.DeserializeRequest(Message message, Object[] parameters)\u000d\u000a at System.ServiceModel.Dispatcher.DemultiplexingDispatchMessageFormatter.DeserializeRequest(Message message, Object[] parameters)\u000d\u000a at System.ServiceModel.Dispatcher.UriTemplateDispatchFormatter.DeserializeRequest(Message message, Object[] parameters)\u000d\u000a at System.ServiceModel.Dispatcher.CompositeDispatchFormatter.DeserializeRequest(Message message, Object[] parameters)\u000d\u000a at System.ServiceModel.Dispatcher.DispatchOperationRuntime.DeserializeInputs(MessageRpc& rpc)\u000d\u000a at System.ServiceModel.Dispatcher.DispatchOperationRuntime.InvokeBegin(MessageRpc& rpc)\u000d\u000a at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage5(MessageRpc& rpc)\u000d\u000a at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage4(MessageRpc& rpc)\u000d\u000a at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage3(MessageRpc& rpc)\u000d\u000a at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage2(MessageRpc& rpc)\u000d\u000a at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage1(MessageRpc& rpc)\u000d\u000a at System.ServiceModel.Dispatcher.MessageRpc.Process(Boolean isOperationContextSet)","Type":"System.Xml.XmlException"},"ExceptionType":"System.Xml.XmlException","Message":"The token '\"' was expected but found '''.","StackTrace":" at System.Xml.XmlExceptionHelper.ThrowXmlException(XmlDictionaryReader reader, String res, String arg1, String arg2, String arg3)\u000d\u000a at System.Xml.XmlExceptionHelper.ThrowTokenExpected(XmlDictionaryReader reader, String expected, Char found)\u000d\u000a at System.Runtime.Serialization.Json.XmlJsonReader.ParseStartElement()\u000d\u000a at System.Runtime.Serialization.Json.XmlJsonReader.Read()\u000d\u000a at System.ServiceModel.Dispatcher.DataContractJsonSerializerOperationFormatter.DeserializeBodyCore(XmlDictionaryReader reader, Object[] parameters, Boolean isRequest)\u000d\u000a at System.ServiceModel.Dispatcher.DataContractJsonSerializerOperationFormatter.DeserializeBody(XmlDictionaryReader reader, MessageVersion version, String action, MessageDescription messageDescription, Object[] parameters, Boolean isRequest)\u000d\u000a at System.ServiceModel.Dispatcher.OperationFormatter.DeserializeBodyContents(Message message, Object[] parameters, Boolean isRequest)\u000d\u000a at System.ServiceModel.Dispatcher.OperationFormatter.DeserializeRequest(Message message, Object[] parameters)\u000d\u000a at System.ServiceModel.Dispatcher.DemultiplexingDispatchMessageFormatter.DeserializeRequest(Message message, Object[] parameters)\u000d\u000a at System.ServiceModel.Dispatcher.UriTemplateDispatchFormatter.DeserializeRequest(Message message, Object[] parameters)\u000d\u000a at System.ServiceModel.Dispatcher.CompositeDispatchFormatter.DeserializeRequest(Message message, Object[] parameters)\u000d\u000a at System.ServiceModel.Dispatcher.DispatchOperationRuntime.DeserializeInputs(MessageRpc& rpc)\u000d\u000a at System.ServiceModel.Dispatcher.DispatchOperationRuntime.InvokeBegin(MessageRpc& rpc)\u000d\u000a at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage5(MessageRpc& rpc)\u000d\u000a at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage4(MessageRpc& rpc)\u000d\u000a at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage3(MessageRpc& rpc)\u000d\u000a at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage2(MessageRpc& rpc)\u000d\u000a at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage1(MessageRpc& rpc)\u000d\u000a at System.ServiceModel.Dispatcher.MessageRpc.Process(Boolean isOperationContextSet)"}

Mi jQuery se parece a esto, pero he intentado cambiar los datos reales que envío como JSON serializado cadena (como se puede ver) a una objeto json puro con el mismo resultado triste.

$.ajax({ 
    type: "POST", 
    contentType: "application/json; charset=utf-8", 
    url: "ajax/Statistics.svc/Get7DaysStatistics", 
    dataType: "json", 
    data: "{'customerId': '2'}", 
    timeout: 10000, 
    success: function(obj) { updateStatistics(obj.d); }, 
    error: function(xhr) { 
     if (xhr.responseText)   
      $("body").html(xhr.responseText); 
     else 
      alert('unknown error'); 
     return; 
    } 
}); 

El servicio WCF tiene el siguiente aspecto:

[SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic"), OperationContract] 
    public string Get7DaysStatistics(string customerId) 
    { 
     Debug.WriteLine(customerId); 
     return "Test done"; 
    } 

Éste se coloca en aa clase con los siguientes atributos:

[ServiceContract(Namespace = "")] 
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)] 

no voy a enumerar la configuración en el web.config para mantener este largo mensaje "corto", pero puedo publicarlo si alguien piensa que pueden usarlo, solo quiero enfatizar que PUEDO llamar a un método y obtener un resultado, una cadena o incluso un objeto JSON del que puedo leer siempre y cuando hago NO pase ningún dato al servicio wcf.

Respuesta

32

Use comillas dobles en lugar de comillas simples en el JSON que está enviando al servicio. Es decir, el cambio:

data: "{'customerId': '2'}", 

a

data: '{"customerId": "2"}', 

He probado esto localmente y esto soluciona el problema.

Incidentalmente, depuré esto usando un método que solía usar cuando llamaba a servicios ASMX y WCF utilizando bibliotecas que no fueran las herramientas integradas de ASP.NET. Llamé al servicio utilizando el cliente proxy creado por un asp:ScriptReference y luego inspeccioné la solicitud que se enviaba al servidor utilizando un sniffer HTTP (como HttpFox para FireFox) y comparé la solicitud con la que se envía por jQuery. Entonces, por lo general, puede ver rápidamente qué es diferente (y, probablemente, incorrecto) con la solicitud. En este caso, estaba claro que había una diferencia en los datos POST enviados.

+1

Eso es descabellado, de hecho lo hice antes de leer su publicación, pero no funcionó. Entonces pensé que quizás si eliminé el atributo WebInvoke davogones publicado (y agregué) podría funcionar y así fue. –

+1

Después de reflexionar un poco (sobre mi error), me di cuenta de que solo me encantaba serializar json: P Mis datos no estaban formateados correctamente json - esto no es mágico, json necesita comillas dobles y no solo. Puede que a javascript no le importe pero json sí, así que por supuesto debería verse así. –

+0

Gracias Daniel .................... PHEW. Absolutamente correcto cuando dices que JavaScript puede no importar, pero JSON sí. Gracias. – user96403

0

Creo que en su operación que necesita este atributo:

[WebInvoke(Method="POST", 
      BodyStyle=WebMessageBodyStyle.Wrapped, 
      ResponseFormat=WebMessageFormat.Json 
)] 

Ver jQuery AJAX calls to a WCF REST Service para obtener más información.

+0

he añadido el atributo, pero sigo teniendo un error - por desgracia, el error que consigo es ahora vacía, así que no puedo ver lo que es el nuevo problema. Incluso intenté agregar "RequestFormat = WebMessageFormat.Json" –

1

Hice una función de JScript que resolvió el problema para el envío de datos a través de POST a un servicio WCF ... seguir el código ...

función formatJsonDataToWCFPost (d) {

var t = {}; 
var a = '{'; 
for (var j = 0; j < d.length; j++) { 
    var x = d[j]; 
    for (var i in x) { 
     if (x.hasOwnProperty(i)) { 
      var c = j + 1 == d.length ? '}' : ','; 
      a += ('"' + i + '":"' + x[i] + '"' + c); 
     } 
    } 
} 

return a; 

}

2

solamente he pensado que la publicación es esencial para el registro de nombre de usuario y contraseña en la funcionalidad por lo que esta es la forma en que codificar los parámetros JSON que envío al servicio web ...

Aquí está el contrato de servicio web ..

[ServiceContract] 
    public interface ILogonService 
    { 
    [OperationContract] 
    [WebInvoke(
     Method = "POST", 
     BodyStyle = WebMessageBodyStyle.WrappedRequest, 
     ResponseFormat = WebMessageFormat.Json 
    )] 
    string Logon(string un, string pw); 
    } 

Aquí es el jQuery (Observe el uso de "y" es importante!)

$.ajax({ 
    type: 'POST', 
    url: "/LogonService.svc/Logon", 
    data: '{ "un": "' + $('#un').val() + '", "pw": "' + $('#pw').val() + '"}', 
    contentType: "application/json; charset=utf-8", 
    dataType: "json", 
    success: function (data) {  
    } 
}); 
Cuestiones relacionadas