Estoy usando Entity Framework y tener un problema con la obtención de los padres y el niño de los datos al navegador. Aquí están mis clases:

 public class Question
 {
    public int QuestionId { get; set; }
    public string Title { get; set; }
    public virtual ICollection<Answer> Answers { get; set; }
}

public class Answer
{
    public int AnswerId { get; set; }
    public string Text { get; set; }
    public int QuestionId { get; set; }
    public virtual Question Question { get; set; }
}

Estoy usando el siguiente código para devolver la pregunta y la respuesta de datos:

    public IList<Question> GetQuestions(int subTopicId, int questionStatusId)
    {
        var questions = _questionsRepository.GetAll()
            .Where(a => a.SubTopicId == subTopicId &&
                   (questionStatusId == 99 ||
                    a.QuestionStatusId == questionStatusId))
            .Include(a => a.Answers)
            .ToList();
        return questions; 
    }

Sobre el C# lado de esto parece funcionar, sin embargo me doy cuenta de que la respuesta objetos tienen referencias de vuelta a la pregunta. Cuando yo uso el WebAPI para obtener los datos en el navegador me sale el siguiente mensaje:

El ‘ObjectContent`1’ tipo de error para serializar el cuerpo de la respuesta para el tipo de contenido ‘application/json; charset=utf-8’.

Auto referencia bucle detectado por la propiedad ‘pregunta’ con ‘tipo de Modelos.Núcleo.Pregunta’.

Es esto debido a que la Pregunta tiene Respuestas y las Respuestas tienen una referencia de nuevo a la Pregunta? Todos los lugares que he mirado sugieren tener una referencia al padre, en el hijo, así que no estoy seguro de qué hacer. Alguien puede darme algún consejo sobre esto.

  • El uso de Dto para su web api, evitando el retorno de la Entidad directamente en su reaponse
  • ¿Qué es el Dto? Toda nuestra aplicación utiliza EF, estamos utilizando AngularJS en el cliente, y nosotros no tenemos problemas de otros que para este caso particular.
  • A lo que me refería, se debe definir su Dto para su Web Api, Dto es un poco similar con ViewModel en MVC. Dto es como un contenedor o su modelo de EF para proporcionar los datos de su cliente (angularjs).
  • posibles duplicados de JSON.NET Error de Auto referencia bucle detectado por tipo
  • Puede echar un vistazo a mi respuesta en «Auto Referencia Bucle Detectado», a excepción de JSON.Net de la página.
InformationsquelleAutor | 2013-06-26

14 Comentarios

  1. 70

    Es esto debido a que la Pregunta tiene Respuestas y las Respuestas tienen un
    referencia de nuevo a la Pregunta?

    Sí. No puede ser serializado.

    EDIT: Ver Tallmaris la respuesta de OttO comentario ya que es más sencillo y puede ser establecido a nivel mundial.

    GlobalConfiguration.Configuration.Formatters.JsonFormatter.SerializerSettings.Re‌​ferenceLoopHandling = ReferenceLoopHandling.Ignore;

    Viejo Respuesta:

    Proyecto de la EF objeto Question a su propia intermedio o DataTransferObject. Este Dto puede entonces ser serializado con éxito.

    public class QuestionDto
    {
        public QuestionDto()
        {
            this.Answers = new List<Answer>();
        } 
        public int QuestionId { get; set; }
        ...
        ...
        public string Title { get; set; }
        public List<Answer> Answers { get; set; }
    }

    Algo como:

    public IList<QuestionDto> GetQuestions(int subTopicId, int questionStatusId)
    {
        var questions = _questionsRepository.GetAll()
            .Where(a => a.SubTopicId == subTopicId &&
                   (questionStatusId == 99 ||
                    a.QuestionStatusId == questionStatusId))
            .Include(a => a.Answers)
            .ToList();
    
        var dto = questions.Select(x => new QuestionDto { Title = x.Title ... } );
    
        return dto; 
    }
    • Me gustaría añadir, para mí la configuración de ReferenceLoopHandling.Ignorar no trabajo, si el valor es globaly o en la API de inicio no funciona en absoluto. Me las arreglé para conseguir trabajo en la decoración de la propiedad de navegación de la clase hija con [JsonIgnore] . Todavía se me pone la ParentId pero el Padre de navegación es ignorado mientras serialising.
    • Hola, Ignorando la serialización va a romper la dependencia circular Pregunta>Respuesta>Pregunta. ¿El enfoque DTO conservarla?
    • Tengo este problema en un viejo ASP.NET proyecto de MVC. GlobalConfiguration.La configuración no tiene Formatters. Puede plz sugieren lo que se puede hacer para que?
  2. 54

    También puede intentar esto en su Application_Start():

    GlobalConfiguration.Configuration.Formatters.JsonFormatter.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Serialize;

    Se debería solucionar el problema sin tener que ir a través de muchos aros.


    EDICIÓN: Como por OttO comentario a continuación, utilice: ReferenceLoopHandling.Ignore lugar.

    GlobalConfiguration.Configuration.Formatters.JsonFormatter.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
    • No funciona.
    • Sé que este es un hilo viejo, pero para aquellos que tropiezan con ella en el futuro, tratar de: GlobalConfiguration.De configuración.Formatters.JsonFormatter.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignorar;
    • sus sugerencias trabajó para mí. Muchas gracias.
    • Código entra en bucle infinito y muestra excepción de desbordamiento de pila después de añadir esta línea.
    • GlobalConfiguration.De configuración.Formatters.JsonFormatter.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignorar; funciona mejor
    • ¿Qué pasa si usted lo está haciendo desde una línea de comandos?
    • tienes que crear tu JsonSerializer el uso de la estática Create() método que acepta un valor como parámetro. Docs: newtonsoft.com/json/help/html/…

  3. 21

    Si el uso de OWIN, recuerda, no hay más GlobalSettings para usted! Debe modificar esta misma configuración en un HttpConfiguration objeto que se le pasa al IAppBuilder UseWebApi función (o lo que sea servicio de la plataforma de en)

    Sería algo como esto.

        public void Configuration(IAppBuilder app)
        {      
           //auth config, service registration, etc      
           var config = new HttpConfiguration();
           config.Formatters.JsonFormatter.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
           //other config settings, dependency injection/resolver settings, etc
           app.UseWebApi(config);
    }
    • Usted salvó mi día. Me preguntaba por qué la respuesta anterior no estaba funcionando. Sí, a través de OWIN configuración Global.asax no funcionará.
  4. 21

    En ASP.NET Núcleo de la solución es la siguiente:

    services
    .AddMvc()
    .AddJsonOptions(x => x.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore);
    • esto funcionó para mí
  5. 5

    Si el uso de DNX /MVC 6 /ASP.NET vNext, bla, bla, incluso HttpConfiguration falta. Usted debe config formateadores mediante el uso de códigos siguientes en su Startup.cs archivo.

    public void ConfigureServices(IServiceCollection services)
        {
            services.AddMvc().Configure<MvcOptions>(option => 
            {
                //Clear all existing output formatters
                option.OutputFormatters.Clear();
                var jsonOutputFormatter = new JsonOutputFormatter();
                //Set ReferenceLoopHandling
                jsonOutputFormatter.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore;
                //Insert above jsonOutputFormatter as the first formatter, you can insert other formatters.
                option.OutputFormatters.Insert(0, jsonOutputFormatter);
            });
        }
    • En asp-net rc-1-final creo que es «de los servicios.Configure<MvcOptions>» ahora
    • JsonOutputFormatter es en el espacio de nombres Microsoft.AspNet.Mvc.Los formateadores
    • Para .NET Core 1.0 RTM: nueva JsonOutputFormatter(serializerSettings, ArrayPool<char>.Compartido);
  6. 5

    ASP.NET Núcleo de la Web de la API (.NET Core 2.0):

    //Startup.cs
    public void ConfigureServices(IServiceCollection services)
    {
        services.AddMvc();
        services.Configure<MvcJsonOptions>(config =>
        {
            config.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore;
        });
    }
    • Esto funcionó para mí.
  7. 2

    El uso de este:

    GlobalConfiguration.Configuration.Formatters.JsonFormatter.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore

    no funciona para mí. En su lugar he creado una nueva versión simplificada de mi modelo de clase sólo para la prueba, y que devuelve bien. Este artículo entra en algunos de los problemas que estaba teniendo en mi modelo que funcionó muy bien para la EF, pero no serializable:

    http://www.asp.net/web-api/overview/data/using-web-api-with-entity-framework/part-4

  8. 1

    ReferenceLoopHandling.Ignorar no funciona para mí. La única manera de conseguir alrededor de él, fue eliminar a través del código de los enlaces de vuelta para que el padre no quería y mantener a los que hice.

    parent.Child.Parent = null;
  9. 1

    Para una nueva Asp.Net Aplicación Web utilizando .Net Framework 4.5:

    Web Api: Goto App_Start -> WebApiConfig.cs:

    Debería ser algo como esto:

    public static class WebApiConfig
    {
        public static void Register(HttpConfiguration config)
        {
            //Web API configuration and services
            //Configure Web API to use only bearer token authentication.
            config.SuppressDefaultHostAuthentication();
            config.Filters.Add(new HostAuthenticationFilter(OAuthDefaults.AuthenticationType));
    
            //ReferenceLoopHandling.Ignore will solve the Self referencing loop detected error
            config.Formatters.JsonFormatter.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
    
            //Will serve json as default instead of XML
            config.Formatters.JsonFormatter.SupportedMediaTypes.Add(new MediaTypeHeaderValue("text/html"));
    
            //Web API routes
            config.MapHttpAttributeRoutes();
    
            config.Routes.MapHttpRoute(
                name: "DefaultApi",
                routeTemplate: "api/{controller}/{id}",
                defaults: new { id = RouteParameter.Optional }
            );
        }
    }
  10. 0

    Debido a la carga diferida de que usted está recibiendo este error. Por lo tanto, mi sugerencia es eliminar la tecla virtual de la propiedad. Si usted está trabajando con la API, a continuación, carga diferida no es bueno para la API de salud.

    No hay necesidad de añadir la línea en su fichero de configuración.

    public class Question
     {
        public int QuestionId { get; set; }
        public string Title { get; set; }
        public ICollection<Answer> Answers { get; set; }
    }
    
    public class Answer
    {
        public int AnswerId { get; set; }
        public string Text { get; set; }
        public int QuestionId { get; set; }
        public Question Question { get; set; }
    }
  11. 0

    Me encontré con este error fue causado cuando me generó un edmx (archivo XML que define un modelo conceptual) de una base de datos existente y tenía las propiedades de Navegación para ambos el padre y el hijo tablas. He eliminado todos los enlaces de navegación a los padres de los objetos, ya que solo me quería para desplazarse a los niños, y se solucionó el problema.

  12. 0

    Entidades db = new Entidades()

    db.De configuración.ProxyCreationEnabled = false;

    db.De configuración.LazyLoadingEnabled = false;

  13. 0

    Puede crear dinámicamente una nueva colección infantil para evitar fácilmente este problema.

    public IList<Question> GetQuestions(int subTopicId, int questionStatusId)
        {
            var questions = _questionsRepository.GetAll()
                .Where(a => a.SubTopicId == subTopicId &&
                       (questionStatusId == 99 ||
                        a.QuestionStatusId == questionStatusId))
                .Include(a => a.Answers).Select(b=> new { 
                   b.QuestionId,
                   b.Title
                   Answers = b.Answers.Select(c=> new {
                       c.AnswerId,
                       c.Text,
                       c.QuestionId }))
                .ToList();
            return questions; 
        }
  14. 0

    Ninguna de las configuraciones en las respuestas anteriores trabajó para mí en ASP.NET Core 2.2.

    Tuve la agregue el JsonIgnore atributos en mi virtual propiedades de navegación.

    public class Question
    {
        public int QuestionId { get; set; }
        public string Title { get; set; }
        [JsonIgnore]
        public virtual ICollection<Answer> Answers { get; set; }
    }

Dejar respuesta

Please enter your comment!
Please enter your name here