2010-12-01 52 views
3

最近我已經建立了一個WCF與EF4的寧靜服務。 當返回XML格式的響應時,這一切都奏效了。但是當談到JSON時,我得到了504錯誤。 unable to return json data, WCF Resful Service .NET 4.0WCF restful使用實體框架複合返回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序列化實體對象的服務方法之一上。對於我所有其他的方法,我返回了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

這是使用實體元數據而不是反射更清晰得多。 元數據相當廣泛。

0

另一種方法是使用LINQ創建一個匿名類型,其中包含實體需要的字段子集,然後使用JSON.NET序列化您在LINQ語句中創建的匿名類型集合。然後通過序列化將該集合保存爲字符串。