2009-02-26 20 views
22

Io uso il seguente codice per chiamare un servizio wcf. Se chiamo un metodo (test) che non accetta parametri, ma restituisce una stringa, funziona correttamente. Se posso aggiungere un parametro al mio metodo ottengo un errore strano:Il passaggio di dati da una richiesta jquery ajax a un servizio wcf fallisce la deserializzazione?

{"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)"}

mio jquery assomiglia a questo, ma ho provato a cambiare i dati reali che ho mando come stringa JSON serializzato (come potete vedere) ad un puro oggetto json con lo stesso triste risultato.

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

il servizio WCF si presenta così:

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

E 'situato in aa classe con i seguenti attributi:

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

Non voglio elencare la configurazione nel web.config per mantenere questo breve messaggio "breve" ma posso postarlo se qualcuno pensa di poterlo usare - voglio solo sottolineare che POSSO chiamare un metodo e ottenere un risultato - stringa o anche un oggetto json che posso leggere finchè lo voglio NON passare alcun dato al servizio wcf.

risposta

32

Utilizzare le virgolette anziché le virgolette singole nel JSON che si sta inviando al servizio. Cioè, il cambiamento:

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

a

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

Ho provato questo a livello locale e questo risolve il problema.

Per inciso, ho eseguito il debug di questo utilizzando un metodo che ho spesso utilizzato quando si chiamano servizi ASMX e WCF utilizzando librerie diverse dagli strumenti ASP.NET incorporati. Ho chiamato il servizio utilizzando il proxy client creato da un asp:ScriptReference e poi ispezionato la richiesta inviata al server utilizzando uno sniffer HTTP (come HttpFox per FireFox) e confrontata la richiesta con quella inviata da jQuery. Quindi di solito puoi vedere rapidamente cosa è diverso (e quindi probabilmente sbagliato) con la richiesta. In questo caso, era chiaro che c'era una differenza nei dati POST inviati.

+1

Questo è selvaggio - l'ho fatto prima di leggere il tuo post, ma non ha funzionato. Quindi ho pensato che forse se ho rimosso l'attributo WebInvoke davogones pubblicato (e ho aggiunto) potrebbe funzionare e basta! –

+1

Dopo un po 'di riflessione (sul mio errore) mi rendo conto che ho appena finito di serializzare json: P I miei dati non erano formattati correttamente JSON - questa non è magia, JSON ha bisogno di virgolette doppie e non singole. Javascript potrebbe non interessarsene, ma JSON lo fa, quindi ovviamente dovrebbe assomigliare a questo. –

+0

Grazie Daniel .................... PHEW. Assolutamente giusto quando dici che JavaScript potrebbe non interessare, ma JSON lo fa. Grazie. – user96403

0

penso sul funzionamento avete bisogno di questo attributo:

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

Vedi jQuery AJAX calls to a WCF REST Service per maggiori informazioni.

+0

Ho aggiunto l'attributo ma ottengo ancora un errore - sfortunatamente l'errore che ora ottengo è vuoto, quindi non riesco a vedere quale sia il nuovo problema. Ho anche provato ad aggiungere "RequestFormat = WebMessageFormat.Json" –

1

Ho fatto una funzione in JScript che ha risolto il problema per l'invio di dati tramite POST a un servizio WCF ... seguire il codice ...

funzione 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

ho sempre e solo pensato che distacco è essenziale per l'username e la password di log sulla funzionalità quindi questo è il mio modo di codificare i parametri JSON che invio al servizio web ...

Ecco il contratto Webservice ..

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

Ecco la JQuery (Si noti l'uso di "e 'è 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) {  
    } 
}); 
Problemi correlati