Tengo un extraño error. Estoy experimentando con una .NET 4.5 Web API, Entity Framework y MS SQL Server. Ya he creado la base de datos y establecer la correcta claves principales y externas y las relaciones.

He creado un .modelo de edmx y importó dos tablas: Empleado y Departamento. Un departamento puede tener muchos empleados, y esta relación existe. He creado un nuevo controlador llamado EmployeeController el uso de los andamios opciones para crear una API controlador de lectura/escritura de acciones usando Entity Framework. En el asistente, Empleado seleccionado como el modelo y la entidad correcto para el contexto de datos.

El método que se crea se parece a esto:

public IEnumerable<Employee> GetEmployees()
{
    var employees = db.Employees.Include(e => e.Department);
    return employees.AsEnumerable();
}

Cuando llamo a mi API a través de /api/Empleado, me sale este error:

El ‘ObjectContent`1’ tipo de error para serializar el cuerpo de la respuesta para el tipo de contenido ‘application/json; …Sistema.InvalidOperationException»,»StackTrace»:null,»InnerException»:{«Message»:»se ha producido Un error.»,»ExceptionMessage»:»Auto-referencia de bucle detectado con el tipo ‘System.Data.Entity.DynamicProxies.Employee_5D80AD978BC68A1D8BD675852f94e8b550f4cb150adb8649e8998b7f95422552’. Camino ‘[0].Department.Employees’.»,»ExceptionType»:»Newtonsoft.Json.JsonSerializationException»,»StackTrace»:» …

¿Por qué es la auto referencia [0].Departamento.Los empleados? Que no hacer un montón de sentido. Me sería de esperar que esto suceda si yo tuviera la circular de referencia en mi base de datos, pero este es un ejemplo muy simple. ¿Qué podría ir mal?

InformationsquelleAutor Lydon | 2013-10-19

12 Comentarios

  1. 150

    Bien la respuesta correcta para el valor predeterminado de Json formater basado en Json.net es el conjunto de ReferenceLoopHandling a Ignore.

    Añadir a la Application_Start en el Mundial.asax:

    HttpConfiguration config = GlobalConfiguration.Configuration;
    
    config.Formatters.JsonFormatter
                .SerializerSettings
                .ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore;

    Esta es la manera correcta. Omitir la referencia apunta hacia el objeto.

    Otras respuestas se centró en el cambio de la lista que se devuelve mediante la exclusión de los datos o por la realización de una fachada de objeto y, a veces, que no es una opción.

    El uso de la JsonIgnore atributo para limitar las referencias puede ser desperdiciador de tiempo y si usted desea serializar el árbol a partir de otro punto que va a ser un problema.

    • Estoy de acuerdo en que esta es la respuesta correcta y se fija el mismo problema que tenía después de 2.5 años.
    • var config = GlobalConfiguration.De configuración.Formatters.JsonFormatter?
    • HttpConfiguration config = GlobalConfiguration.Configuración; //System.Web.Http
    • Ningún Efecto, a excepción persiste
    • Doug Barba, me Puede dar la información relativa a sus clases?
    • los tanques de Pedro Figueiredo, pero ¿qué de la aplicación de cliente de windows? ¿cómo puedo solucionar este error en ella?
    • o en la biblioteca de clases ??
    • ¿Dónde ir en un asp.net núcleo de la aplicación mvc?
    • Puedo obtener una referencia a sí misma bucle de error, aunque tengo el código de arriba en Application_Start y han [JsonIgnore] en las propiedades relevantes…también tengo [IgnoreDataMember] en estas propiedades, y han puesto a ProxyCreationEnabled a false para entity framework…
    • Cada vez que hago esto, tengo la siguiente excepción: el Intento de leer o escribir en la memoria protegida. Esto es a menudo una indicación de que otra memoria está dañada
    • El uso de clases DTO. stackoverflow.com/questions/45329513/…
    • Esta solución funcionó para mí! gracias por tu ayuda.

  2. 52

    Esto sucede porque usted está tratando de serializar el EF colección de objetos directamente. Desde el departamento cuenta con una asociación de los empleados y de los empleados del departamento, el JSON serializador bucle infinetly lectura d.Empleado.Departamentos.Empleado.Los departamentos etc…

    Para solucionar este derecho antes de la serialización de crear un tipo anónimo con los accesorios que desea

    ejemplo (pseudo)código:

    departments.select(dep => new { 
        dep.Id, 
        Employee = new { 
            dep.Employee.Id, dep.Employee.Name 
        }
    });
    • Esta es la respuesta correcta. Usted necesita saber el EF lo que usted necesita.
    • puede alguien por favor decirme cual es una mejor práctica. Es el aceptado respuesta es mejor o el más votado como uno?
    • En este caso me gustaría utilizar una clase del modelo, tales como los departamentos.seleccione(dep => nuevo { dep.Id de Empleado = new ModelClass { Id = dep.Empleado.Id, Name = dep.Empleado.Nombre } });
    • depende de lo que usted desea. Si usted simplemente desea utilizar el servicio a través de AJAX a partir de un SPA, entonces esto es suficiente, y yo diría que mejor si usted está haciendo MVVM, porque permite especificar el ViewModel en el servidor. si desea utilizar este servicio como parte de un N-Tier API, consumidos por otros .los servicios de la red, entonces la otra respuesta es la más apropiada, ya que mantiene la base de datos de contrato intacta (como en, usted todavía será el envío de un calificado EF entidad).
  3. 32

    Yo tenía el mismo problema y se encontró que sólo se puede aplicar el [JsonIgnore] atributo de la propiedad de navegación usted no quiere ser serializado. Todavía serialise ambos el padre y el hijo entidades, sino que sólo evita la auto referencia bucle.

  4. 16

    Soy consciente de que la pregunta es bastante antiguo, pero todavía es popular y yo no puedo ver ninguna solución para ASP.net Núcleo.

    Me caso de ASP.net Núcleo, usted necesita agregar nuevos JsonOutputFormatter en Startup.cs de archivo:

        public void ConfigureServices(IServiceCollection services)
        {
    
            services.AddMvc(options =>
            {
                options.OutputFormatters.Clear();
                options.OutputFormatters.Add(new JsonOutputFormatter(new JsonSerializerSettings()
                {
                    ReferenceLoopHandling = ReferenceLoopHandling.Ignore,
                }, ArrayPool<char>.Shared));
            });
    
            //...
        }

    Después de su aplicación, JSON serializador simplemente ignorar bucle de referencias. Lo que significa es: devolverá null en lugar de infinitamente carga de objetos de referencia a cada uno de los otros.

    Sin solución anterior mediante:

    var employees = db.Employees.ToList();

    Carga Employees y relacionados con ellos Departments.

    Después de establecer ReferenceLoopHandling a Ignore, Departments se establece en null a menos que usted incluya en su consulta:

    var employees = db.Employees.Include(e => e.Department);

    También, tenga en cuenta que se borrarán todos los OutputFormatters, si usted no quiere que usted puede tratar de quitar esta línea:

    options.OutputFormatters.Clear();

    Pero quitando causas nuevo self referencing loop excepción en mi caso, por alguna razón.

  5. 8

    El principal problema es que serializar un modelo de entidad que tiene relación con otra entidad(modelo de relación de clave externa). Esta relación causa la referencia a este va a lanzar la excepción, mientras que la serialización json o xml.
    Hay un montón de opciones. Sin serializar entidad modelos mediante el uso de modelos personalizados.Los valores o datos de entidad del modelo de datos asignados a modelos personalizados(asignación de objeto) el uso de Automapper o Valueinjector luego de solicitud de devolución y se va a serializar sin ningún otro tipo de cuestiones.
    O usted puede serializar modelo de entidad por lo que primero deshabilitar el proxy
    en el modelo de entidad

    public class LabEntities : DbContext
    {
       public LabEntities()
       {
          Configuration.ProxyCreationEnabled = false;
       }

    Para preservar las referencias a objetos en XML, usted tiene dos opciones. La opción más simple es agregar [DataContract(IsReference=true)] para el modelo de clase. El IsReference parámetro permite oibject referencias. Recuerde que DataContract hace que la serialización de opt-in, por lo que también tendrá que agregar atributos de DataMember a las propiedades:

    [DataContract(IsReference=true)]
    public partial class Employee
    {
       [DataMember]
       string dfsd{get;set;}
       [DataMember]
       string dfsd{get;set;}
       //exclude  the relation without giving datamember tag
       List<Department> Departments{get;set;}
    }

    En formato Json
    en global.asax

    var json = GlobalConfiguration.Configuration.Formatters.JsonFormatter;
    json.SerializerSettings.PreserveReferencesHandling = 
        Newtonsoft.Json.PreserveReferencesHandling.All;

    en formato xml

    var xml = GlobalConfiguration.Configuration.Formatters.XmlFormatter;
    var dcs = new DataContractSerializer(typeof(Employee), null, int.MaxValue, 
        false, /* preserveObjectReferences: */ true, null);
    xml.SetSerializer<Employee>(dcs);
    • Opción 1 funcionaba bien el uso de los atributos DataContract y DataMember sin embargo, al final el resultado me sale «Empleados»:[{«$ref»:»1″}]}}]. Se ha eliminado el síntoma, pero el problema sigue ahí. Seguramente todos los demás tendrían exactamente el mismo problema. Me estoy acercando a esta solución de forma incorrecta?
    • Me puse ProxyCreationEnabled = false y el jason cosita en el mundial.archivo asax. Y workes como un f**rey encanto. Gracias
  6. 8

    El mensaje de error significa que usted tiene un auto de referencia del bucle.

    El json que producen es como en este ejemplo (con una lista de uno de los empleados) :

    [
    employee1 : {
        name: "name",
        department : {
            name: "departmentName",
            employees : [
                employee1 : {
                    name: "name",
                    department : {
                        name: "departmentName",
                        employees : [
                            employee1 : {
                                name: "name",
                                department : {
                                    and again and again....
                                }
                        ]
                    }
                }
            ]
        }
    }

    ]

    Usted tiene que decirle a la db contexto que usted no desea conseguir todas las entidades vinculadas cuando se solicita algo.
    La opción de DbContext es Configuration.LazyLoadingEnabled

    La mejor manera que he encontrado es crear un contexto para la serialización :

    public class SerializerContext : LabEntities 
    {
        public SerializerContext()
        {
            this.Configuration.LazyLoadingEnabled = false;
        }
    }
  7. 7

    Agregar una línea Configuration.ProxyCreationEnabled = false; en el constructor de su modelo de contexto de definición de clase parcial.

        public partial class YourDbContextModelName : DbContext
    {
        public YourDbContextModelName()
            : base("name=YourDbContextConn_StringName")
        {
            Configuration.ProxyCreationEnabled = false;//this is line to be added
        }
    
        public virtual DbSet<Employee> Employees{ get; set; }
    
        protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
        }
    }
    • Este trabajo para mí en 2017, las demás soluciones no funcionan
    • Funciona, otras soluciones que no funcionan.
  8. 3

    Sólo había un modelo que yo quería usar, así que terminé con el siguiente código:

    var JsonImageModel = Newtonsoft.Json.JsonConvert.SerializeObject(Images, new JsonSerializerSettings { ReferenceLoopHandling = ReferenceLoopHandling.Ignore });
  9. 1

    Yo sólo tenía el mismo problema en mi .net core sitio.
    El aceptó respuesta no trabajo para mí, pero he encontrado que una combinación de ReferenceLoopHandling.Ignorar y PreserveReferencesHandling.Los objetos se corrigió.

    //serialize item
    var serializedItem = JsonConvert.SerializeObject(data, Formatting.Indented, 
    new JsonSerializerSettings
    {
         PreserveReferencesHandling = PreserveReferencesHandling.Objects,
         ReferenceLoopHandling = ReferenceLoopHandling.Ignore
    });
  10. 0

    hace referencia a sí misma como ejemplo

    =============================================================

    public class Employee
    {
        public int Id { get; set; }
        public string FirstName { get; set; }
        public string LastName { get; set; }
        public string Email { get; set; }
        public int ManagerId { get; set; }
        public virtual Employee Manager { get; set; }
    
        public virtual ICollection<Employee> Employees { get; set; }
    
        public Employee()
        {
            Employees = new HashSet<Employee>();
        }
    }

    =============================================================

            HasMany(e => e.Employees)
                .WithRequired(e => e.Manager)
                .HasForeignKey(e => e.ManagerId)
                .WillCascadeOnDelete(false);
  11. 0

    Si usted está tratando de cambiar esta configuración en el Blazor (ASP.NET Núcleo Hosted) de la plantilla, que deberá pasar el siguiente a la AddNewtonsoftJson llamada en Startup.cs en el Server proyecto:

    services.AddMvc().AddNewtonsoftJson(options => 
        options.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore
    );

Dejar respuesta

Please enter your comment!
Please enter your name here