2010-12-01 4 views
3

Недавно я создал службу поддержки WCF с EF4. Все это сработало при возврате ответа формата XML. однако, когда дело доходит до JSON, я получил 504 Error. unable to return json data, WCF Resful Service .NET 4.0WCF restful возвращающий JSON с использованием Entity Framework Complex

По углубиться с помощью Service трассировки просмотра: Я нашел эту ошибку:

'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 из процедуры магазина. Я потратил довольно много времени на google, как отключить 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. Для всех моих других методов я возвращал сериализованные объекты передачи данных 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 Entity модели. Я не нашел прямого решения этой проблемы, но, как работа, я сериализую ответ как 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

Это гораздо яснее использовать метаданные Entity вместо Reflection. Метаданные довольно обширны.

0

Другой способ сделать это - использовать LINQ для создания анонимного типа с подмножеством полей, которые вам нужны из вашей сущности, а затем использовать JSON.NET для сериализации коллекции типов анонов, созданных в операторе LINQ. затем сохраняйте эту сборку как строку путем сериализации.

Смежные вопросы