2012-05-04 18 views
18

jqueryを使用してオブジェクトのリストをJSON文字列として返すajax wcfメソッドを呼び出しています。 (TextViewの中)Fiddler2をして、それを検査する際にJSON文字列は次のようになります。jquery ajax呼び出しが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\"}]"} 

私はフィドラーズJSONビューで結果を検査する場合、それは以下の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 

次のようにWCFメソッドが定義されています。

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

わからない結果を返しますが、私は結果を解析し、その内側にネストされたオブジェクトを解析する必要があります。私はあなたがしたいと仮定し

Response.ContentType = "application/json"; 

答えて

48

、 "アプリケーション/ JSONは、" データ型プロパティの有効な値ではありません。 プロジェクトで「json」に変更しました。同じ問題が解決されました。

ここ(コメント#7)の詳細を確認してください:http://bugs.jquery.com/ticket/8216

+0

jquery ajaxではなく、httpヘッダーでapplication/jsonが使用されています。ただ確認した。 –

3

てみてくださいと仮定していますser.Serialize(query.ToArray())の値をクライアント(配列)に返します。しかし、それを文字列として返すので、WCFはそのJSONを文字列にエスケープし、最終的には配列ではなく文字列になります。

WCFでネイティブにサポートされていない匿名型を使用しているため、JavaScriptSerializerを使用する必要があります。だからJSONのダブルエンコーディング(文字列への)を防ぐために、代わりにStreamとしてデータを返す必要があります。これによりWCFはデータに触れません(下記のサンプルコードを参照)。

もう一つ:私はあなたの応答はあなたのサービス/エンドポイントを定義するときに<enableWebScript/>/WebScriptEnablingBehavior/WebScriptServiceHostFactoryを使用していることを示唆している{"d":...}ラッパーを、持っている参照してください。 ASP.NET AJAXライブラリを使用していないので、ラップする必要はないので、代わりに "より簡単な" <webHttp/>//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

をはい私は、成功しません – hofnarwillie

0

:私返さ種類のいずれかが、それはまた別の解析を必要としていた複雑なオブジェクトが含まれている場合、私は...あなたのサーバー側のコードでMIMEタイプを追加

+0

おかげで、ない運けれども感謝を持っています。あなたのコードをコピーしましたが、javascriptエラーコールバックにはエラー情報がなく、ただ空の文字列で、エラーは "エラー"と表示されます。また、それ以上のresultTextは返されません。 – hofnarwillie

+0

サーバー上でトレースを有効にして、異常が発生しているかどうかを確認してください。あるいは、実際のネットワークレスポンス(Fiddlerやブラウザ開発ツールを使用して)を見て、追加情報があるかどうか確認してください。 – carlosfigueira

+0

"[Fiddler] ReadResponse()に失敗しました:サーバーはこの要求に対して応答を返しませんでした。 – hofnarwillie

1

WCF 4.0を使用すると、サービスが返すためにどのような形式を決定するためにHTTPリクエストでAcceptヘッダを見ることができautomaticFormatSelectionEnabledと呼ばれる属性を追加することができます。返すものがシリアル化可能である限り、WCFは正しいシリアル化を処理します。 jQueryのajax呼び出しでは、accepts: {json: "application/json"}を含めることでAcceptヘッダーが追加されます。

+0

私はこれを試してみます、どこにautomaticFormatSelectionEnabledを追加しますか? – hofnarwillie

+0

答えの中のリンクは、設定でそれをプログラムに追加する方法を示しています。 –

+0

あなたが言ったものを追加しようとしました。サーバーを正常に呼び出すと、WebGETを実行できます。それから、それは戻っているようだが、フィドラー報告:[Fiddler] ReadResponse()failed:サーバーはこの要求に対して応答を返しませんでした。そして、エラーコールバックは返されたデータなしで再び実行されます。 – 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; 
     } 
    } 

クライアント

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

        } 
       } 

     );