2012-05-04 6 views
18

Я использую jquery для вызова метода wcf ajax, который возвращает список объектов как строку JSON. Строка JSON выглядит так, осматривая его в Fiddler2 (в TextView):jquery ajax call return JSON parsing error

{"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\"}]"} 

Когда я проверить результат в Фиддлерз JSON View, он показывает следующий 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"}] 

Так стельку можно разобрать она успешно, но на клиенте, функция ошибки обратного вызова JQuery Ajax отображает следующее сообщение об ошибке:

Error: No conversion from text to application/json 

метод ФОС определяется следующим образом:

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

И, наконец, вызывающий JQuery является:

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

Заранее спасибо!

ОБНОВЛЕНИЕ: Благодаря @ user1370958, на один шаг ближе к решению.

При изменении функции ошибки обратного вызова к следующему его успешно возвращает результат ...

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

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

ответ

48

Здесь "применение/JSON" не является допустимым значением для свойства типа данных. Я изменил его на «json» в моем проекте, и эта же проблема была решена.

Пожалуйста, проверьте детали здесь (комментарий 7 #): http://bugs.jquery.com/ticket/8216

+0

application/json используется в заголовках http не в jquery ajax. просто подтверждено. –

3

Попробуйте добавить тип MIME в ваш серверный код:

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

да у меня есть без успеха, благодаря хотя – hofnarwillie

0

Я предполагаю, что вы хотите чтобы вернуть значение ser.Serialize(query.ToArray()) клиенту (массив). Но вы возвращаете его как строку, поэтому WCF выйдет из этого JSON в строку, а то, что вы закончите, - это не массив, а строка.

Поскольку вы используете анонимные типы, которые не поддерживаются со стороны WCF, вам необходимо использовать JavaScriptSerializer. Поэтому, чтобы предотвратить двойное кодирование JSON (в строку), вы должны вернуть данные как Stream, чтобы WCF не касался ваших данных (см. Пример кода ниже). более

одно: я вижу ваш ответ имеет {"d":...} оболочку, которая предполагает, что вы используете <enableWebScript/>/WebScriptEnablingBehavior/WebScriptServiceHostFactory при определении вашей службы/конечной точки. Поскольку вы не используете библиотеку AJAX ASP.NET, вам не нужна эта упаковка, поэтому вместо этого вы можете использовать «более простой» <webHttp/>/WebHttpBehavior/WebServiceHostFactory, и ваш ответ не будет завернут в этот объект «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

спасибо, но не повезло. Я скопировал ваш код, но теперь обратный вызов ошибки javascript не имеет информации об ошибке, просто пустые строки и говорит, что ошибка является «ошибкой». Кроме того, больше не возвращалось resultText. – hofnarwillie

+0

Попробуйте включить трассировку на сервере, чтобы узнать, есть ли что-то странное. Или посмотрите на фактический сетевой ответ (используя Fiddler или инструменты разработчика браузера), чтобы узнать, есть ли какая-либо дополнительная информация. – carlosfigueira

+0

«Ошибка [Fiddler] ReadResponse(): сервер не ответил на этот запрос». – hofnarwillie

1

WCF 4.0 С, можно добавить атрибут automaticFormatSelectionEnabled, который позволяет сервис смотреть на Accept заголовок в запросе HTTP, чтобы определить, какой формат для возврата. Пока возвращаемое вами сериализуемое значение, WCF будет обрабатывать правильную сериализацию для вас. В вашем jQuery ajax-вызове заголовок Accept добавляется, включая accepts: {json: "application/json"}.

+0

Я попробую это, где я могу добавить autoFormatSelectionEnabled? – hofnarwillie

+0

Ссылка в ответе показывает, как добавить его в конфигурацию или программно. –

+0

Я попытался добавить материал, который вы сказали. Он вызывает сервер успешно, и я могу пройти через WebGET. Затем, похоже, возвращается, но отчеты о скрипачах: [Fiddler] ReadResponse() не удалось: сервер не ответил на этот запрос. И обратный вызов ошибки снова запускается без возвращаемых данных. – hofnarwillie

0

Я нашел обходной путь:

Первая проблема была циклическая ссылка исключение на модели объекта. Чтобы преодолеть это, я использую следующий код, чтобы отделить мои объекты от контекста, а затем сериализовать их в строки. Затем я сериализую их на клиенте, используя следующий код.

Сервис

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

Client

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

        } 
       } 

     );