una tipo serialize serializar referencia objeto newtonsoft net jsonconvert example detectó c# json entity-framework asp.net-mvc-4 serialization

c# - tipo - newtonsoft json serialize vb net



Referencia circular detectó una excepción al serializar el objeto a JSON (9)

Cualesquiera que sean las clases que tengan la referencia de otra clase, solo agregue un atributo como este

[Newtonsoft.Json.JsonIgnoreAttribute] public virtual ICollection<PurchaseOrderLine> Lines { get; set; }

Ahora todo funciona sin problemas

Tal como se menciona en this publicación, recibo un error de serialización de Json al serializar un proxy de Entity Framework:

Se detectó una referencia circular al serializar un objeto de tipo ''System.Data.Entity.DynamicProxies.PurchaseOrder_446B939192F161CDBC740067F174F7A6059B0F9C0EEE68CD3EBBD63CF9AF5BD0''.

Pero la diferencia es que no tengo una referencia circular en mis entidades, y solo ocurre en nuestro entorno de producción. Localmente todo funciona bien ...

Mis entidades:

public interface IEntity { Guid UniqueId { get; } int Id { get; } } public class Entity : IEntity { public int Id { get; set; } public Guid UniqueId { get; set; } } public class PurchaseOrder : Entity { public string Username { get; set; } public string Company { get; set; } public string SupplierId { get; set; } public string SupplierName { get; set; } public virtual ICollection<PurchaseOrderLine> Lines { get; set; } } public class PurchaseOrderLine : Entity { public string Code { get; set; } public string Name { get; set; } public decimal Quantity { get; set; } }

La acción GetCurrent en mi PurchaseOrderController arroja la excepción:

public class PurchaseOrderController : Controller { private readonly IUnitOfWork _unitOfWork; public PurchaseOrderController(IUnitOfWork unitOfWork) { _unitOfWork = unitOfWork; } public JsonResult GetCurrent() { return Json(EnsurePurchaseOrder(), JsonRequestBehavior.AllowGet); } private PurchaseOrder EnsurePurchaseOrder() { var company = RouteData.GetRequiredString("company"); var repository = _unitOfWork.GetRepository<PurchaseOrder>(); var purchaseOrder = repository .Include(p => p.Lines) .FirstOrDefault ( p => p.Company == company && p.Username == User.Identity.Name ); if (purchaseOrder == null) { purchaseOrder = repository.Create(); purchaseOrder.UniqueId = Guid.NewGuid(); purchaseOrder.Company = company; purchaseOrder.Username = User.Identity.Name; _unitOfWork.SaveChanges(); } return purchaseOrder; } }


En su clase DbContext , agregue esta línea de código:

this.Configuration.ProxyCreationEnabled = false;

Por ejemplo:

public partial class EmpDBEntities : DbContext { public EmpDBEntities() : base("name=EmpDBEntities") { this.Configuration.ProxyCreationEnabled = false; } protected override void OnModelCreating(DbModelBuilder modelBuilder) { throw new UnintentionalCodeFirstException(); } public virtual DbSet<Department> Departments { get; set; } public virtual DbSet<Employee> Employees { get; set; } }


Estaba teniendo el mismo problema, lo que hice fue pasar la columna que solo necesitaba ver, en mi caso. solo 2.

List<SubCategory> lstSubCategory = GetSubCateroy() // list from repo var subCategoryToReturn = lstSubCategory.Select(S => new { Id = S.Id, Name = S.Name }); return this.Json(subCategoryToReturn , JsonRequestBehavior.AllowGet);


La referencia circular ocurre porque usa carga ansiosa en el objeto.

Tienes 3 métodos:

  • Desactive la carga ansiosa al cargar su consulta (linq o lambda) DbContext.Configuration.ProxyCreationEnabled = false;
  • Separar los objetos (= sin funcionalidad de carga ansiosa y sin proxy)
    • Repository.Detach (entityObject)
    • DbContext.Entry (entityObject) .EntityState = EntityState.Detached
  • Clona las propiedades
    • Puede usar algo como AutoMapper para clonar el objeto, no use la interfaz ICloneable, ya que también clona ProxyProperties en el objeto, por lo que no funcionará.
  • En caso de que esté creando una API, intente utilizar un proyecto separte con una configuración diferente (que no arroje proxies)

PD. Proxies es el objeto creado por EF cuando lo carga desde Entity Framework. En resumen: Significa que contiene los valores originales y los valores actualizados para que puedan actualizarse más tarde. Maneja otras cosas para ;-)


Opción 1 (recomendado)

Intente desactivar la creación de objetos Proxy en su DbContext .

DbContext.Configuration.ProxyCreationEnabled = false;

Normalmente, este escenario se debe a que la aplicación utiliza objetos POCO (ya sea T4 generado o código primero). El problema surge cuando Entity Framework desea rastrear los cambios en su objeto que no están integrados en los objetos POCO. Para resolver esto, EF crea objetos proxy que carecen de los atributos en los objetos POCO, y no son serializables.

Las razones por las que recomiendo este enfoque; El uso de un sitio web significa que probablemente no necesite seguimiento de cambios (con estado) en objetos de Entity Framework, memoria libre y CPU porque el seguimiento de cambios está deshabilitado y funcionará de manera consistente en todos sus objetos de la misma manera.

opcion 2

Use un serializador (como JSON.Net que ya está incluido en ASP.Net 4) que permite la personalización para serializar los objetos.

Las razones por las que no recomiendo este enfoque es que, eventualmente, la lógica de serialización de objetos personalizados será necesaria para los objetos proxy en serie como otros tipos de objetos. Esto significa que tiene una dependencia de la lógica para entregar un resultado en sentido descendente. Cambiar el objeto significa cambiar la lógica, y en un proyecto ASP.Net MVC (cualquier versión) en lugar de solo cambiar una Vista, tiene algo más que cambiar que no se conoce fácilmente fuera de quien escribió la lógica primero.

Opción 3 (Entity Framework 5.x +)

Utilice .AsNoTracking() que deshabilitará los objetos proxy en la consulta específica. Si necesita usar el seguimiento de cambios, esto permite una buena solución intermedia para la solución n. ° 1.


Pasé innumerables horas intentando todas las diversas soluciones que encontré diseminadas por la web, que incluyen:

  • [JsonIgnore]
  • Getters internos
  • Deshabilitar LazyLoadingEnabled y ProxyCreationEnabled
  • Configuración de ReferenceLoopHandling para "ignorar"
  • Usar cuidadosamente carga explícita cuando sea necesario

Todo lo cual finalmente resultó infructuoso para mí. Ignorar una propiedad ayudó a una consulta, pero dañó otras 3. Se sentía como la programación equivalente a whack-a-mole.

El contexto de mi problema fue que la información que entraba fuera de mi aplicación tenía que ser JSON. No hay forma de evitarlo Las inserciones y actualizaciones obviamente plantean un problema mucho menor. Pero seleccionar los datos que se almacenan en una base de datos normalizada (y en mi caso incluyendo un historial de versiones) para ser serializados es una pesadilla.

La solución:

Devuelve los datos (propiedades) que necesitas como objetos anónimos.

Un ejemplo de código:

En este caso, necesitaba las 3 últimas entradas, basadas en "Fecha programada". Pero también necesitaba varias propiedades almacenadas en entidades relacionadas.

var tickets = context.TicketDetails .Where(t => t.DateScheduled >= DateTime.Now) .OrderBy(t => t.DateScheduled) .Take(3) .Include(t => t.Ticket) .Include(t => t.Ticket.Feature) .Include(t => t.Ticket.Feature.Property) .AsEnumerable() .Select( t => new { ID = t.Ticket.ID, Address = t.Ticket.Feature.Property.Address, Subject = t.Ticket.Subject, DateScheduled = String.Format("{0:MMMM dd, yyyy}", t.DateScheduled) } );

Y voila, no hay bucles de auto referencia.

Me doy cuenta de que esta situación puede no ser adecuada en todos los casos dado que las entidades y los objetos pueden cambiar. Pero ciertamente vale la pena considerarlo si todo lo demás falla.


Sus entidades POCO son perfectamente serializables. Su problema es que los proxies dinámicos que crea el tiempo de ejecución de EF para usted generalmente no lo son. Puede configurar el context.Configuration.ProxyCreationEnabled en false pero luego pierde la carga diferida. Mi gran recomendación para usted es usar Json.NET que admita la serialización para entidades EF:

El soporte de ADO.NET Entity Framework se agregó accidentalmente a Json.NET

Marco JSON popular de alto rendimiento para .NET


Tuve el mismo error, sin embargo lo vi tanto en el servidor de producción como a nivel local. Cambiar la configuración de DbContext no resolvió completamente mi problema. Se me presentó una solución diferente con el

[IgnoreDataMember]

atributo en referencias de entidades DB. Vea la publicación aquí si esto le parece más pertinente a su problema.

ASP.NET Web API Serialized JSON Error: "bucle de autoreferencia"


Tuve el mismo problema y lo resolví al desmarcar Json.NET en las extensiones del proyecto en el Administrador de referencias.

(ver la imagen http://i.stack.imgur.com/RqbXZ.png )

También tuve que cambiar el archivo project.csproj para mapear la ruta correcta para la nueva versión:

<Reference Include="Newtonsoft.Json"> <HintPath>../packages/Newtonsoft.Json.6.0.5/lib/net45/Newtonsoft.Json.dll</HintPath> </Reference>

y todavía tenía que configurar el web.config

<dependentAssembly> <assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" /> <bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" /> </dependentAssembly>

Tenga en cuenta que en el archivo web.config me vi obligado a referirme a la versión OLDER (6.0.0.0) aunque la versión instalada era 6.0.5.

¡Espero eso ayude!