Estoy tratando de hacer una simple devolución JSON pero tengo problemas, tengo lo siguiente a continuación.
public JsonResult GetEventData()
{
var data = Event.Find(x => x.ID != 0);
return Json(data);
}
Recibo un HTTP 500 con la excepción que se muestra en el título de esta pregunta. También intenté
var data = Event.All().ToList()
Eso dio el mismo problema.
¿Es esto un error o mi implementación?
ScriptIgnore
atributo. stackoverflow.com/questions/1193857/subsonic-3-0-0-2-structs-ttScriptIgnore
atributo en la propiedad Torneo.Juego y funcionó bien :)Respuestas:
Parece que hay referencias circulares en su jerarquía de objetos que no es compatible con el serializador JSON. ¿Necesitas todas las columnas? Puede seleccionar solo las propiedades que necesita en la vista:
Esto hará que su objeto JSON sea más ligero y fácil de entender. Si tiene muchas propiedades, AutoMapper podría usarse para asignar automáticamente entre objetos DTO y objetos de vista.
fuente
Tuve el mismo problema y resuelto por
using Newtonsoft.Json;
fuente
Esto realmente sucede porque los objetos complejos son los que hacen que el objeto json resultante falle. Y falla porque cuando el objeto está mapeado, mapea a los niños, que mapea a sus padres, haciendo que ocurra una referencia circular. Json tomaría un tiempo infinito para serializarlo, por lo que evita el problema con la excepción.
El mapeo de Entity Framework también produce el mismo comportamiento, y la solución es descartar todas las propiedades no deseadas.
Simplemente explicitando la respuesta final, todo el código sería:
También podría ser el siguiente en caso de que no desee los objetos dentro de una
Result
propiedad:fuente
Para resumir, hay 4 soluciones para esto:
Solución 1: apague ProxyCreation para DBContext y restaúrelo al final.
Solución 2: Uso de JsonConvert configurando ReferenceLoopHandling para ignorar la configuración del serializador.
Seguir dos soluciones es lo mismo, pero usar un modelo es mejor porque tiene un tipo fuerte.
Solución 3: devuelva un modelo que incluya solo las propiedades necesarias.
Solución 4: devuelve un nuevo objeto dinámico que incluye solo las propiedades necesarias.
fuente
JSON, como xml y varios otros formatos, es un formato de serialización basado en árbol. No te amará si tienes referencias circulares en tus objetos, ya que el "árbol" sería:
A menudo hay formas de desactivar la navegación a lo largo de un determinado camino; por ejemplo, con
XmlSerializer
usted puede marcar la propiedad principal comoXmlIgnore
. No sé si esto es posible con el serializador json en cuestión, ni siDatabaseColumn
tiene marcadores adecuados ( muy poco probable, ya que necesitaría hacer referencia a cada API de serialización)fuente
Esto se debe a la nueva plantilla DbContext T4 que se utiliza para generar las entidades EntityFramework. Para poder realizar el seguimiento de cambios, estas plantillas utilizan el patrón Proxy, envolviendo sus bonitas POCO con ellas. Esto provoca problemas al serializar con JavaScriptSerializer.
Entonces las 2 soluciones son:
Puede desactivar la generación automática de proxies configurándola en la configuración del contexto
context.Configuration.ProxyCreationEnabled = false;
Muy bien explicado en el siguiente artículo.
http://juristr.com/blog/2011/08/javascriptserializer-circular-reference/
fuente
Usando Newtonsoft.Json: en su método Global.asax Application_Start agregue esta línea:
fuente
agregar
[JsonIgnore]
a las propiedades virtuales en su modelo.fuente
Evite convertir el objeto de tabla directamente. Si se establecen relaciones entre otras tablas, podría arrojar este error. En cambio, puede crear una clase de modelo, asignar valores al objeto de clase y luego serializarlo.
fuente
Las respuestas proporcionadas son buenas, pero creo que pueden mejorarse agregando una perspectiva "arquitectónica".
Investigación
MVC's Controller.Json
La función está haciendo el trabajo, pero es muy pobre para proporcionar un error relevante en este caso. Al usarNewtonsoft.Json.JsonConvert.SerializeObject
, el error especifica exactamente cuál es la propiedad que está activando la referencia circular. Esto es particularmente útil cuando se serializan jerarquías de objetos más complejas.Arquitectura adecuada
Nunca se debe tratar de serializar modelos de datos (por ejemplo, modelos EF), ya que las propiedades de navegación de ORM son el camino a la perdición cuando se trata de serialización. El flujo de datos debe ser el siguiente:
Los modelos de servicio se pueden obtener a partir de modelos de datos utilizando mapeadores automáticos (por ejemplo, Automapper ). Si bien esto no garantiza la falta de referencias circulares, el diseño adecuado debería hacerlo: los modelos de servicio deben contener exactamente lo que requiere el consumidor del servicio (es decir, las propiedades).
En esos casos raros, cuando el cliente solicita una jerarquía que involucra el mismo tipo de objeto en diferentes niveles, el servicio puede crear una estructura lineal con relación padre-> hijo (usando solo identificadores, no referencias).
Las aplicaciones modernas tienden a evitar cargar estructuras de datos complejas a la vez y los modelos de servicio deben ser delgados. P.ej:
fuente
Estoy usando la solución, porque uso Knockout en vistas MVC5.
En acción
función
fuente
Puede notar las propiedades que causan la referencia circular. Entonces puedes hacer algo como:
fuente
fuente
Una alternativa más fácil para resolver este problema es devolver una cadena y formatear esa cadena a json con JavaScriptSerializer.
Es importante la parte "Seleccionar", que elige las propiedades que desea en su vista. Algún objeto tiene una referencia para el padre. Si no elige los atributos, puede aparecer la referencia circular, si solo toma las tablas como un todo.
No hagas esto:
Haga esto en su lugar si no desea toda la tabla:
Esto ayuda a representar una vista con menos datos, solo con los atributos que necesita, y hace que su web funcione más rápido.
fuente