2012-05-04 31 views
18

Używam jquery do wywołania metody ajax wcf, która zwraca listę obiektów jako ciąg JSON. Ciąg JSON wygląda to podczas sprawdzania go w fiddler2 (w TextView):jquery ajax call return JSON parsujący błąd

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

Kiedy sprawdzić wynik w Skrzypek za JSON View, pokazuje następujący 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"}] 

Więc Skrzypek można analizować to z powodzeniem, ale na kliencie, funkcja zwrotna jquery ajax błąd wyświetla się następujący błąd:

Error: No conversion from text to application/json 

metoda WCF jest zdefiniowany następująco:

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

I wreszcie, jquery powołaniem jest:

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

Z góry dzięki!

AKTUALIZACJA: Dzięki @ user1370958, o krok bliżej rozwiązania.

Przy zmianie funkcji błędu oddzwonienia do następujących go pomyślnie zwraca wynik ...

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

Nie wiem dlaczego, ale mam do analizowania wyników, a następnie analizować zagnieżdżonych obiektów wewnątrz tego. Zakładam, że jeśli któryś z moich typów zwracanych zawarte skomplikowanych obiektów byłoby również potrzebne kolejne parse ...

Odpowiedz

48

Tutaj "application/json" nie jest prawidłową wartością dla właściwości dataType. Zmieniłem go na "json" w moim projekcie i ten sam problem został rozwiązany.

Proszę tutaj sprawdzić szczegóły (komentarz 7 #): http://bugs.jquery.com/ticket/8216

+0

Aplikacja/json jest używana w nagłówkach HTTP nie w jquery ajax. właśnie potwierdzone. –

3

spróbuj dodać typ MIME w kodzie strony serwera:

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

tak mam bez powodzenia, dzięki chociaż – hofnarwillie

0

Zakładam, że chcesz zwrócić wartość klienta ser.Serialize(query.ToArray()) (tablica). Ale zwracasz go jako ciąg znaków, więc WCF ucieknie z tego JSON-a do łańcucha, a to, co skończysz, nie jest tablicą, ale łańcuchem.

Ponieważ używasz typów anonimowych, które nie są natywnie obsługiwane przez WCF, musisz użyć JavaScriptSerializer. Aby zapobiec podwójnemu kodowaniu JSON (w łańcuchu), powinieneś zwrócić dane jako Stream, aby WCF nie dotknął twoich danych (patrz przykładowy kod poniżej).

jeszcze jedno: widzę twoja odpowiedź ma {"d":...} owijkę, co sugeruje, że używasz <enableWebScript/>/WebScriptEnablingBehavior/WebScriptServiceHostFactory podczas definiowania usług/końcowy. Ponieważ nie używasz biblioteki ASP.NET AJAX, nie potrzebujesz tego owijania, więc zamiast tego możesz użyć "prostszego", a twoja odpowiedź nie zostanie zapakowana w obiekt "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

Dzięki, ale bez powodzenia. Skopiowałem twój kod, ale teraz wywołanie zwrotne błędu javascript nie zawiera informacji o błędzie, tylko puste ciągi i mówi, że błąd to "błąd". Również nie zwracano wyniku resultText. – hofnarwillie

+0

Spróbuj włączyć śledzenie na serwerze, aby sprawdzić, czy dzieje się coś dziwnego. Lub spójrz na rzeczywistą reakcję sieci (używając Fiddlera lub narzędzi programistycznych przeglądarki), aby sprawdzić, czy są jakieś dodatkowe informacje. – carlosfigueira

+0

"[Fiddler] ReadResponse() nie powiodło się: serwer nie zwrócił odpowiedzi na to żądanie." – hofnarwillie

1

Z WCF 4.0 można dodać atrybut o nazwie automaticFormatSelectionEnabled który umożliwia usługa patrzeć w nagłówku żądania HTTP Accept aby określić jaki format wrócić. Tak długo, jak to, co wracasz jest serializowalne, WCF obsłuży poprawną serializację dla ciebie. W wywołaniu ajax jQuery nagłówek Accept jest dodawany przez dodanie accepts: {json: "application/json"}.

+0

Spróbuję tego, gdzie mogę dodać automaticFormatSelectionEnabled? – hofnarwillie

+0

Łącze w odpowiedzi pokazuje, jak dodać go w konfiguracji lub programowo. –

+0

Próbowałem dodać rzeczy, które powiedziałeś. Łączy serwer z powodzeniem i mogę przejść przez WebGET. Wtedy wydaje się, że powraca, ale fiddler zgłasza: [Fiddler] ReadResponse() nie powiodło się: Serwer nie zwrócił odpowiedzi na to żądanie. Odwołanie błędu działa ponownie bez zwracanych danych. – hofnarwillie

0

Znalazłem obejście:

Pierwszym problemem był okrągły wyjątek odniesienia na modelu jednostki. Aby temu zaradzić, używam następującego kodu, aby odłączyć moje jednostki od kontekstu, a następnie serializować je do łańcuchów. Następnie serializuję je na kliencie za pomocą poniższego kodu.

usługi

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

        } 
       } 

     );