Passing data from a jquery ajax request to a wcf service fails deserialization?

30,785

Solution 1

Use double quotes instead of single quotes in the JSON you are sending to the service. That is, change:

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

to

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

I've tested this locally and this fixes the problem.

Incidentally, I debugged this using a method I've often used when calling ASMX and WCF services using libraries other than the built-in ASP.NET tools. I called the service using the client proxy created by an asp:ScriptReference and then inspected the request being sent to the server using an HTTP sniffer (such as HttpFox for FireFox) and compared the request to the one being sent by jQuery. Then you can usually quickly see what is different (and so probably wrong) with the request. In this case, it was clear that there was a difference in the POST data being sent.

Solution 2

I have only ever thought that posting is essential for username and password log on functionality so this is the way I encode the JSon parameters I send to the web service...

Here is the Webservice Contract..

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

Here is the JQuery (Note the use of " and ' is important!)

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

Solution 3

I did a function in jscript that solved the problem for sending data via POST to a WCF service ... follow the code ...

function 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;

}

Share:
30,785

Related videos on Youtube

Per Hornshøj-Schierbeck
Author by

Per Hornshøj-Schierbeck

SOreadytohelp

Updated on July 09, 2022

Comments

  • Per Hornshøj-Schierbeck
    Per Hornshøj-Schierbeck almost 2 years

    I use the following code to call a wcf service. If i call a (test) method that takes no parameters, but returns a string it works fine. If i add a parameter to my method i get a wierd error:

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

    My jquery looks like this, but i tried changing the actual data which i send as a string serialized json (as you can see) to a pure json object with the same sad result.

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

    The wcf service looks like this:

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

    It's placed in a a class with the following attributes:

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

    I won't list the configuration in the web.config to keep this long message "short" but i can post it if anybody thinks they can use it - i just want to stress that i CAN call a method and get a result - string or even a json object i can read from as long as i DON'T pass any data to the wcf service.

  • Per Hornshøj-Schierbeck
    Per Hornshøj-Schierbeck about 15 years
    I added the attribute but i still get an error - unfortunately the error i now get is empty so i can't see what the new problem is. I even tried adding "RequestFormat = WebMessageFormat.Json"
  • Per Hornshøj-Schierbeck
    Per Hornshøj-Schierbeck about 15 years
    That's wild - i actually did that before i read your post, but it didn't work. Then i figured perhaps if i removed the WebInvoke attribute davogones posted (and i added) it might just work and it did!
  • Per Hornshøj-Schierbeck
    Per Hornshøj-Schierbeck about 15 years
    After a bit of reflection (on my error) i realize i just suck at serializing json :P My data wasn't correctly formatted json - this is no magic, json needs double quotes and not single. Javascript might not care but json does, so ofcourse it should look like this.
  • user96403
    user96403 over 13 years
    Thanks Daniel....................PHEW. Absolutely right when you say that JavaScript might not care, but JSON does. Thank you.