Estou tentando fazer um retorno JSON simples, mas estou tendo problemas com os seguintes itens abaixo.
public JsonResult GetEventData()
{
var data = Event.Find(x => x.ID != 0);
return Json(data);
}
Eu recebo um HTTP 500 com a exceção, como mostrado no título desta pergunta. Eu também tentei
var data = Event.All().ToList()
Isso deu o mesmo problema.
Isso é um bug ou minha implementação?
ScriptIgnore
atributo stackoverflow.com/questions/1193857/subsonic-3-0-0-2-structs-ttScriptIgnore
atributo na propriedade Tournament.Game e funcionou muito bem :)Respostas:
Parece que há referências circulares na hierarquia de objetos que não são suportadas pelo serializador JSON. Você precisa de todas as colunas? Você pode escolher apenas as propriedades necessárias na exibição:
Isso tornará seu objeto JSON mais leve e fácil de entender. Se você tiver muitas propriedades, o AutoMapper poderá ser usado para mapear automaticamente entre objetos DTO e Exibir objetos.
fonte
Eu tive o mesmo problema e resolvi por
using Newtonsoft.Json;
fonte
Na verdade, isso acontece porque os objetos complexos são o que faz com que o objeto json resultante falhe. E falha porque, quando o objeto é mapeado, ele mapeia os filhos, que mapeiam seus pais, fazendo com que uma referência circular ocorra. O Json levaria um tempo infinito para serializá-lo, impedindo o problema com a exceção.
O mapeamento do Entity Framework também produz o mesmo comportamento, e a solução é descartar todas as propriedades indesejadas.
Apenas explicando a resposta final, todo o código seria:
Também pode ser o seguinte, caso você não queira os objetos dentro de uma
Result
propriedade:fonte
Para resumir, existem 4 soluções para isso:
Solução 1: desative o ProxyCreation para o DBContext e restaure-o no final.
Solução 2: Usando JsonConvert, definindo ReferenceLoopHandling para ignorar nas configurações do serializador.
As duas soluções a seguir são as mesmas, mas o uso de um modelo é melhor porque é tipado com bastante força.
Solução 3: retorne um modelo que inclua apenas as propriedades necessárias.
Solução 4: retorne um novo objeto dinâmico que inclua apenas as propriedades necessárias.
fonte
JSON, como xml e vários outros formatos, é um formato de serialização baseado em árvore. Não vai te amar se você tiver referências circulares em seus objetos, como seria a "árvore":
Muitas vezes, existem maneiras de desativar a navegação ao longo de um determinado caminho; por exemplo,
XmlSerializer
você pode marcar a propriedade pai comoXmlIgnore
. Não sei se isso é possível com o serializador json em questão, nem seDatabaseColumn
possui marcadores adequados ( muito improvável, pois seria necessário fazer referência a todas as APIs de serialização)fonte
Isso se deve ao novo modelo DbContext T4 usado para gerar as entidades EntityFramework. Para poder executar o rastreamento de alterações, esses modelos usam o padrão Proxy, envolvendo seus POCOs legais com eles. Isso causa os problemas ao serializar com o JavaScriptSerializer.
Então, as 2 soluções são:
Você pode desativar a geração automática de proxies configurando-a na configuração do contexto
context.Configuration.ProxyCreationEnabled = false;
Muito bem explicado no artigo abaixo.
http://juristr.com/blog/2011/08/javascriptserializer-circular-reference/
fonte
Usando Newtonsoft.Json: No seu método Global.asax Application_Start, adicione esta linha:
fonte
adicione
[JsonIgnore]
às propriedades virtuais no seu modelo.fonte
Evite converter o objeto de tabela diretamente. Se as relações forem definidas entre outras tabelas, isso poderá gerar esse erro. Em vez disso, você pode criar uma classe de modelo, atribuir valores ao objeto de classe e depois serializá-lo.
fonte
As respostas fornecidas são boas, mas acho que elas podem ser melhoradas adicionando uma perspectiva "arquitetônica".
Investigação
MVC's Controller.Json
A função está fazendo o trabalho, mas é muito ruim em fornecer um erro relevante nesse caso. Ao usarNewtonsoft.Json.JsonConvert.SerializeObject
, o erro especifica exatamente qual é a propriedade que está acionando a referência circular. Isso é particularmente útil ao serializar hierarquias de objetos mais complexas.Arquitetura adequada
Nunca se deve tentar serializar modelos de dados (por exemplo, modelos EF), pois as propriedades de navegação do ORM são o caminho para a perdição no que diz respeito à serialização. O fluxo de dados deve ser o seguinte:
Modelos de serviço podem ser obtidos em modelos de dados usando mapeadores automáticos (por exemplo, Automapper ). Embora isso não garanta a falta de referências circulares, o design adequado deve fazê-lo: os modelos de serviço devem conter exatamente o que o consumidor de serviços exige (ou seja, as propriedades).
Nesses casos raros, quando o cliente solicita uma hierarquia envolvendo o mesmo tipo de objeto em diferentes níveis, o serviço pode criar uma estrutura linear com o relacionamento pai-> filho (usando apenas identificadores, não referências).
Os aplicativos modernos tendem a evitar o carregamento de estruturas de dados complexas de uma só vez e os modelos de serviço devem ser escassos. Por exemplo:
fonte
Estou usando a correção, porque usando Knockout nos modos de exibição MVC5.
Em ação
função
fonte
Você pode observar as propriedades que causam a referência circular. Então você pode fazer algo como:
fonte
fonte
Uma alternativa mais fácil para resolver esse problema é retornar uma sequência e formatar essa sequência para json com JavaScriptSerializer.
É importante a parte "Selecionar", que escolhe as propriedades que você deseja na sua exibição. Algum objeto tem uma referência para o pai. Se você não escolher os atributos, a referência circular poderá aparecer, se você apenas tomar as tabelas como um todo.
Não faça isso:
Faça isso se não quiser a tabela inteira:
Isso ajuda a renderizar uma exibição com menos dados, apenas com os atributos que você precisa, e torna a sua Web mais rápida.
fonte