Передача данных из запроса jquery ajax в службу wcf не выполняет десериализацию?

Я использую следующий код для вызова службы wcf. Если я вызываю (тестовый) метод, который не принимает параметров, но возвращает строку, он работает нормально. Если я добавлю параметр в свой метод, я получу странную ошибку:

{"ExceptionDetail": {"HelpLink": null, "InnerException": null, "Message": "Токен '\"' ожидался, но был найден '' '. "," StackTrace ":" в System.Xml.XmlExceptionHelper .ThrowXmlException (средство чтения XmlDictionaryReader, String res, String arg1, String arg2, String arg3) \ u000d \ u000a в System.Xml.XmlExceptionHelper.ThrowTokenExpected (XmlDictionaryReader reader, String ожидается, Char найден) \ u000d \ u000a в System.Runtime.Serialization .Json.XmlJsonReader.ParseStartElement () \ u000d \ u000a в System.Runtime.Serialization.Json.XmlJsonReader.Read () \ u000d \ u000a в System.ServiceModel.Dispatcher.DataContractJsonSerializerOperationFormatter.DeserializeBodyCharder (параметры объекта BoostoReader, ReaderDeserializeBodyCodemlCreaderDeserializeBodyModelCreaderDeserializeBodyCreaderDeserializeBodyCreader isRequest) в System.ServiceModel.Dispatcher.DataContractJsonSerializerOperationFormatter.DeserializeBody (средство чтения XmlDictionaryReader, версия MessageVersion, действие String, MessageDescription messageDescription, параметры Object [], логическое значение isRequest) \ u000d \ u000a в System.ServiceModel.Dispatcher.OperationFormatter.DeserializeBodyContents (параметры сообщения) в System.ServiceModel.Dispatcher.OperationFormatter.DeserializeRequest (Сообщение сообщения, параметры Object []) в System.ServiceModel.Dispatcher.DemultiplexingDispatchMessageFormatter.DeserializeRequest (Сообщение сообщения, параметры Objectd []) \ u000 в System.ServiceModel.Dispatcher.UriTemplateDispatchFormatter.DeserializeRequest (сообщение сообщения, параметры объекта []) \ u000d \ u000a в System.ServiceModel.Dispatcher.CompositeDispatchFormatter.DeserializeRequest (сообщение сообщения,Параметры объекта []) в System.ServiceModel.Dispatcher.DispatchOperationRuntime.DeserializeInputs (MessageRpc & rpc) \ u000d \ u000a в System.ServiceModel.Dispatcher.DispatchOperationRuntime.InvokeBegin (MessageRpc \ udc) в System.ServiceModel. Dispatcher.ImmutableDispatchRuntime.ProcessMessage5 (MessageRpc & rpc) \ u000d \ u000a в System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage4 (MessageRpc & rpc) \ u000d \ u000cI в System.DessageDispatch \ u000d \ u000aMessageModel \ u000a \ u000a в System.DessageDispatcher.Model \ u000aMessageModel \ u000a в System.ServiceDisp; System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage2 (MessageRpc & rpc) \ u000d \ u000a в System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage1 (MessageRpc & rpcModel.Process (Boolean isOperationContextSet) "," Тип ":" System.Xml.XmlException "}," ExceptionType ":" System.Xml.XmlException "," Message ":" Токен '\ "' ожидался, но был найден '' ' . "," StackTrace ":" в System.Xml.XmlExceptionHelper.ThrowXmlException (средство чтения XmlDictionaryReader, String res, String arg1, String arg2, String arg3) \ u000d \ u000a в System.Xml.XmlExceptionHelper.ThrowTokenExpected (средство чтения StringDictionaryReader, средство чтения XmlDictionaryReader , Char найдено) в System.Runtime.Serialization.Json.XmlJsonReader.ParseStartElement () в System.Runtime.Serialization.Json.XmlJsonReader.Read () в System.ServiceModel.Dispatcher .DataContractJsonSerializerOperationFormatter.DeserializeBodyCore (средство чтения XmlDictionaryReader, параметры Object [],Логическое значение isRequest) \ u000d \ u000a в System.ServiceModel.Dispatcher.DataContractJsonSerializerOperationFormatter.DeserializeBody (средство чтения XmlDictionaryReader, версия MessageVersion, строковое действие, MessageDescription messageDescription, параметры Object [], логическое значение isRequest.Model. .DeserializeBodyContents (сообщение сообщения, параметры объекта [], логическое значение isRequest) в System.ServiceModel.Dispatcher.OperationFormatter.DeserializeRequest (сообщение сообщения, параметры объекта []) в System.ServiceModel.Dispatcher.DematchMplexingDispatcher. DeserializeRequest (Сообщение сообщения, параметры Object []) в System.ServiceModel.Dispatcher.UriTemplateDispatchFormatter.DeserializeRequest (Сообщение сообщения, параметры Object []) в System.ServiceModel.Dispatcher.CompositeDispatchFormatter.DeserializeRequest (Сообщение сообщения, параметры объекта []) \ u000d \ u000a в System.ServiceModel.Dispatcher.DispatchOperationRuntime.DeserializeInputs (MessageRpc & rpc) \ u000d \ u000a в System.ServiceModel.Dispatcher. \ u000d \ u000a в System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage5 (MessageRpc & rpc) \ u000a в System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage4 (MessageRpcMessageMessage4 (MessageRpc) (MessageRpc & rpc) в System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage2 (MessageRpc & rpc) \ u000d \ u000a в System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMesspatchRuntime.ProcessMessagerpc) в System.ServiceModel.Dispatcher.MessageRpc.Process (Boolean isOperationContextSet) "}

Мой jquery выглядит так, но я попытался изменить фактические данные, которые я отправляю в виде строки, сериализованной json (как вы можете видеть), на чистый объект json с тем же печальным результатом.

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

Сервис wcf выглядит так:

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

Он помещен в класс со следующими атрибутами:

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

Я не буду перечислять конфигурацию в web.config, чтобы это длинное сообщение было «коротким», но я могу опубликовать его, если кто-то думает, что он может его использовать - я просто хочу подчеркнуть, что я МОГУ вызвать метод и получить результат - строка или даже объект json, из которого я могу читать, если я НЕ передаю какие-либо данные службе wcf.

Ответов (4)

Решение

Используйте двойные кавычки вместо одинарных кавычек в JSON, который вы отправляете службе. То есть изменить:

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

к

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

Я тестировал это локально, и это решает проблему.

Между прочим, я отлаживал это, используя метод, который часто использовал при вызове служб ASMX и WCF с использованием библиотек, отличных от встроенных инструментов ASP.NET. Я вызвал службу, используя клиентский прокси, созданный asp: ScriptReference, а затем проверил запрос, отправляемый на сервер с помощью сниффера HTTP (например, HttpFox для FireFox), и сравнил запрос с тем, который отправляется jQuery . Тогда вы обычно можете быстро увидеть, что отличается (и, вероятно, неправильно) в запросе. В этом случае было ясно, что существует разница в отправляемых данных POST.

Я только когда-либо думал, что публикация важна для функциональности входа в систему с помощью имени пользователя и пароля, поэтому именно так я кодирую параметры JSon, которые я отправляю в веб-службу ...

Вот контракт на веб-сервис ..

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

Вот JQuery (обратите внимание, что использование "и" важно!)

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

Я думаю, что для вашей работы вам понадобится этот атрибут:

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

Для получения дополнительной информации см. Вызовы jQuery AJAX к службе WCF REST .

Я выполнил функцию в jscript, которая решила проблему отправки данных через POST в службу WCF ... следуйте коду ...

функция 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;

}