Pergunta

Estou tendo problemas com uma referência circular quando tento e serializando um objeto retornado via EF4 CTP5. Estou usando a primeira abordagem do código e o simples poco para o meu modelo.

Eu adicionei atributos [ScriptIgnore] a quaisquer propriedades que forneçam referências de volta a um objeto e, irritantemente, todos parecem funcionar bem se eu instanciar manualmente os POCOs, ou seja, eles seriam serializados a JSON Fine, e o atributo scriptignore é reconhecido. No entanto, quando tento e serializou um objeto devolvido do dal, recebo a exceção de referência circular "Uma referência circular foi detectada ao serializar um objeto do tipo 'System.data.entity.dynamicproxies.xxxx'"

Eu tentei várias maneiras de recuar os dados, mas todos ficam presos com este erro:

    public JsonResult GetTimeSlot(int id) {
        TimeSlotDao tsDao = new TimeSlotDao();
        TimeSlot ts = tsDao.GetById(id);
        return Json(ts);
    }

O método abaixo funciona um pouco melhor, pois, em vez do objeto proxado dinâmico do time -slot, causando a referença circular é o objeto de nomeação.

    public JsonResult GetTimeSlot(int id) {
        TimeSlotDao tsDao = new TimeSlotDao();
            var ts = from t in tsDao.GetQueryable()
                 where t.Id == id
                 select new {t.Id, t.StartTime, t.Available, t.Appointment};
        return Json(ts);
    }

Alguma ideia ou soluções para esse problema?

Atualizar Eu preferiria usar o serializador fora da caixa, se possível, embora o JSON.NET via Nuget seja bom como uma alternativa, espero que seja possível usá -lo como pretendia também ...

Foi útil?

Solução

Eu tive um problema semelhante com um serviço WCF hospedado no IIS e tentando serializar objetos POCO com a classe DataCOrtractJSonserializer. O serializador de JSON embutido não parece lidar com referências circulares. Consegui contorná -lo lidando com a serialização usando o Json.net Serializer, e apenas retornando as cordas JSON dos meus métodos. O serializador do JSON.NET tem a opção de ignorar referências circulares, pois o próprio JSON não as suporta.

Outras dicas

Não importa o que eu fiz, os proxies dinâmicos continuavam sendo um ponto de discórdia, cheguei a remover todas as referências circulares do meu modelo! Mas ainda assim o problema persistiu.

Eu tentei JSON.NET, mas o mesmo problema ocorreu.

No final, tropecei em um post sobre o uso de um JavaScriptConverter personalizado

http://hellowebapps.com/2010-09-26/producing-json-from-entity-framework-4-0-generated-classes/

Implementou o código e os bobs seu tio tudo funcionou

Eu resolvi isso sem ter que recorrer a um serializador de JSON externo. Em poucas palavras, desativei a proxycreation no construtor do contexto do meu objeto.

Não sei por que isso funciona, mas publiquei uma pergunta de acompanhamento aqui.

Eu usei o seguinte Contractresolver. Observe que eu herdei do CamelCASECONTROTROPROPERTYRESOLVER para obter esse recurso também, mas você também pode herdar diretamente do DefaultContractResolver.

using System;
using System.Collections.Generic;
using System.Reflection;
using Newtonsoft.Json.Serialization;

namespace MyNamespace
{
    /// <summary>
    /// This class enables EntityFramework POCO objects to be serialized. In some cases POCO
    /// objects are subclassed by a proxy which has an additional member _entityWrapper. This
    /// object prevents serialization (circular references and references to non-serializable types).
    /// This removes the _entityWrapper from the list of members to be serialized.
    /// </summary>
    public class ContractResolver : CamelCasePropertyNamesContractResolver
    {
        protected override List<MemberInfo> GetSerializableMembers(Type objectType)
        {
            if (objectType.FullName.StartsWith("System.Data.Entity.DynamicProxies."))
            {
                var members = base.GetSerializableMembers(objectType);
                members.RemoveAll(memberInfo => memberInfo.Name == "_entityWrapper");
                return members;
            }
            return base.GetSerializableMembers(objectType);
        }
    }
}

Para usá -lo, crie seu serializador e defina a propriedade Contractresolver como uma nova instância desta classe:

var ser = JsonSerializer.Create(sJsonSerializerSettings);            
ser.ContractResolver = new ContractResolver(); 

Eu também conheci esse problema. As respostas a este tópico contêm soluções numéricas. Mas as melhores soluções diferentes para casos diferentes com explicação e, além disso, sem serializar serializados que encontrei no artigo por Hongye Sun. - Manuseio de referência em loop na API da Web.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top