WCF restful возвращает JSON с помощью Entity Framework Complex - PullRequest
3 голосов
/ 01 декабря 2010

недавно я установил WCF-службу отдыха с EF4. Все сработало при возврате ответа в формате XML. Однако, когда дело доходит до JSON, я получил 504 Ошибка. невозможно вернуть данные json, WCF Resful Service .NET 4.0

Копая глубже с помощью Service Trace Viewer: Я нашел эту ошибку:

'Тип' xxx.DataEntity.AppView ' не может быть сериализовано в JSON, потому что для параметра IsReference установлено значение «True». JSON формат не поддерживает ссылки потому что нет стандартизированный формат для представления Рекомендации. Чтобы включить сериализацию, отключить настройку IsReference на введите или соответствующий родительский класс тип. '

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

Ответы [ 4 ]

1 голос
/ 26 апреля 2011

Намного понятнее использовать метаданные сущности вместо отражения. Метаданные довольно обширны.

1 голос
/ 29 января 2012

Я столкнулся с точно такой же проблемой. Это произошло только в одном из моих методов обслуживания, когда я пытался вернуть сериализованные объекты JSON Entity. Для всех других моих методов я возвращал сериализованные объекты передачи данных (DTO) JSON, которые являются автономными и не связаны с платформой Entity. Я использую DTO для данных, размещенных в методах. Часто отправляемым данным не нужны все данные, которые вы храните в модели или в базе данных, например, Значения идентификаторов, обновленные даты и т. Д. Сопоставление выполняется в классе модели, например:

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 голос
/ 20 января 2011

Я столкнулся с той же проблемой, что и вызванная использованием автоматически созданных ADO Entity Models.Я не нашел прямого решения этой проблемы, но в качестве обходного пути я сериализовал ответ как 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());

}}
0 голосов
/ 04 января 2013

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

...