2010-12-01 9 views
3

最近、私はEF4でWCFの快適なサービスをセットアップしました。 XMLフォーマットのレスポンスを返すときは、すべてうまくいっています。しかし、それはJSONになると、私は504エラーがあります。サービストレースビューアを使用して、深く掘ってunable to return json data, WCF Resful Service .NET 4.0Entity Framework Complexを使用してWCF JSONを快適に返す

: 私はこのエラーを検出しました:

'The type 'xxx.DataEntity.AppView' cannot be serialized to JSON because its IsReference setting is 'True'. The JSON format does not support references because there is no standardized format for representing references. To enable serialization, disable the IsReference setting on the type or an appropriate parent class of the type.'

「APPVIEWは、」ストア手順からEF4によって生成された複雑なオブジェクトクラスです。 私はIsReferenceを無効にする方法をかなり時間を費やして、これまでのところほとんど結果を得ていません。

誰ですか?どんなソリューションでも?事前に

おかげ

コード:

[OperationContract] 
     [WebInvoke(Method = "GET", 
      BodyStyle = WebMessageBodyStyle.Wrapped, 
      UriTemplate = "App/{id}/{format}")] 
     AppView FuncDetail(string id, string format); 



public AppView FuncDetail(string id, string format) 
     { 
      SetResponseFormat(format); 
      return AppSvcs.GetById(id); 
     } 


private void SetResponseFormat(string format) 
      { 
       if (format.ToLower() == "json") 
       { 
        ResponseContext.Format = WebMessageFormat.Json; 
       } 
       else 
       { 
        ResponseContext.Format = WebMessageFormat.Xml; 
       } 
      } 

答えて

1

私はまったく同じ問題に遭遇しました。 JSONシリアル化されたEntityオブジェクトを返そうとしていたサービスメソッドの1つでのみ発生しました。他のすべてのメソッドについては、JSON直列化データ転送オブジェクト(DTO)を返していました。これはスタンドアロンであり、Entityフレームワークには接続されていません。メソッドに投稿されたデータにDTOを使用しています。多くの場合、送信するデータには、モデルまたはデータベースに保存するすべてのデータは必要ありません。 ID値、更新日時などのマッピングはモデルクラスで行われているが、そのよう:

public partial class Location 
{ 

    public static LocationDto CreateLocationDto(Location location) 
    { 
     LocationDto dto = new LocationDto 
     { 
      Accuracy = location.Accuracy, 
      Altitude = location.Altitude, 
      Bearing = location.Bearing     
     }; 
     return dto; 
    } 

それは少し不格好に見えるかもしれませんが、それは動作し、それはあなただけあなたが送信するために意図されたデータフィールドを送信することを保証しますバック。私は5,6人のエンティティしか持っていないので、私にとってはうまくいきますが、たくさんのクラスがあればちょっと面倒なことがあります。

1

自動生成ADOエンティティモデルを使用することによって引き起こされるような私は、同じ問題に実行していました。私はこの問題の直接的な修正を見つけられませんでしたが、回避策としてjsonとして応答を明示的にシリアライズします。

だからあなたの例では、APPVIEW FuncDetailは次のようになります。

ここ
public object FuncDetail(string id, string format) 
    { 
     SetResponseFormat(format); 

     // where AppSvc is the object type and the enumerable list of this type is returned by the GetById method, cast it to a json string 
     return JSONSerializer.ToJson<AppSvc>(AppSvcs.GetById(id)); 
    } 

は、私が使用しているシリアライザです:

public static class GenericSerializer 
{ 
public static DataTable ToDataTable<T>(IEnumerable<T> varlist) 
{ 
    DataTable dtReturn = new DataTable(); 

    // column names 
    PropertyInfo[] oProps = null; 

    if (varlist == null) return dtReturn; 

    foreach (T rec in varlist) 
    { 
     // Use reflection to get property names, to create table, Only first time, others will follow 
     if (oProps == null) 
     { 
      oProps = ((Type)rec.GetType()).GetProperties(); 
      foreach (PropertyInfo pi in oProps) 
      { 
       Type colType = pi.PropertyType; 

       if ((colType.IsGenericType) && (colType.GetGenericTypeDefinition() 
       == typeof(Nullable<>))) 
       { 
        colType = colType.GetGenericArguments()[0]; 
       } 

       dtReturn.Columns.Add(new DataColumn(pi.Name, colType)); 
      } 
     } 

     DataRow dr = dtReturn.NewRow(); 

     foreach (PropertyInfo pi in oProps) 
     { 
      dr[pi.Name] = pi.GetValue(rec, null) == null ? DBNull.Value : pi.GetValue 
      (rec, null); 
     } 

     dtReturn.Rows.Add(dr); 
    } 
    return dtReturn; 
} 

}

public static class JSONSerializer 
{ 
public static string ToJson<T>(IEnumerable<T> varlist) 
{ 
    DataTable dtReturn = GenericSerializer.ToDataTable(varlist); 
    return GetJSONString(dtReturn); 
} 

    static object RowsToDictionary(this DataTable table) 
{ 

    var columns = table.Columns.Cast<DataColumn>().ToArray(); 

    return table.Rows.Cast<DataRow>().Select(r => columns.ToDictionary(c => c.ColumnName, c => r[c])); 

} 

static Dictionary<string, object> ToDictionary(this DataTable table) 
{ 

    return new Dictionary<string, object> 
    { 
     { table.TableName, table.RowsToDictionary() } 
    }; 

} 

static Dictionary<string, object> ToDictionary(this DataSet data) 
{ 

    return data.Tables.Cast<DataTable>().ToDictionary(t => "Table", t => t.RowsToDictionary()); 

} 

public static string GetJSONString(DataTable table) 
{ 

    JavaScriptSerializer serializer = new JavaScriptSerializer(); 

    return serializer.Serialize(table.ToDictionary()); 

} 

public static string GetJSONString(DataSet data) 
{ 

    JavaScriptSerializer serializer = new JavaScriptSerializer(); 

    return serializer.Serialize(data.ToDictionary()); 

}} 
1

ことがありますReflectionではなくEntity Metadataを使用する方がはるかに明確です。 メタデータはかなり広範囲です。

0

これを行う別の方法は、LINQを使用してエンティティから必要なフィールドのサブセットを持つ匿名型を作成し、JSON.NETを使用してLINQ文で作成したanon型のコレクションをシリアル化することです。そのコレクションをシリアル化して文字列として保持します。

関連する問題