83 votes

Détection d'une boucle d'auto-référencement - Récupération des données de la WebApi vers le navigateur

J'utilise Entity Framework et j'ai un problème avec l'envoi des données parent et enfant au navigateur. Voici mes classes :

 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; }
}

J'utilise le code suivant pour renvoyer les données de la question et de la réponse :

    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; 
    }

Du côté C#, cela semble fonctionner, mais je remarque que les objets de réponse ont des références à la question. Lorsque j'utilise l'interface WebAPI pour obtenir les données dans le navigateur, j'obtiens le message suivant :

Le type 'ObjectContent`1' n'a pas réussi à sérialiser le corps de la réponse pour le type de contenu 'application/json ; charset=utf-8'.

Une boucle d'auto-référencement a été détectée pour la propriété 'question' de type 'Models.Core.Question'.

Est-ce parce que la question comporte des réponses et que les réponses renvoient à la question ? Tous les sites que j'ai consultés suggèrent d'avoir une référence au parent dans l'enfant, donc je ne sais pas trop quoi faire. Quelqu'un peut-il me donner des conseils à ce sujet ?

4voto

Stewart Hou Points 153

Si l'on utilise DNX / MVC 6 / ASP.NET vNext blah blah, même HttpConfiguration est manquante. Vous devez configurer les formateurs en utilisant les codes suivants dans votre Startup.cs fichier.

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);
        });
    }

3voto

it dũng Points 29

Dans le cadre d'ASP.NET Core 3.0, l'équipe a renoncé à inclure Json.NET par défaut. Vous pouvez en savoir plus à ce sujet en général dans le document [Including Json.Net to netcore 3.x][1] https://github.com/aspnet/Announcements/issues/325

Une erreur peut être causée par l'utilisation de lazyloading : services.AddDbContext(options => options.UseLazyLoadingProxies().... ou db.Configuration.LazyLoadingEnabled = true ;

fixer : ajout au fichier startup.cs

 services.AddControllers().AddNewtonsoftJson(options =>
        {
            options.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore;
        });

2voto

Mike Points 135

En utilisant ceci :

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

n'a pas fonctionné pour moi. Au lieu de cela, j'ai créé une nouvelle version simplifiée de ma classe de modèle juste pour tester, et cela a fonctionné. Cet article aborde certains des problèmes que je rencontrais dans mon modèle qui fonctionnait parfaitement pour EF, mais qui n'était pas sérialisable :

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

1voto

Rob Sedgwick Points 469

ReferenceLoopHandling.Ignore n'a pas fonctionné pour moi. La seule façon de contourner le problème a été de supprimer par le code les liens vers le parent que je ne voulais pas et de conserver ceux que je voulais.

parent.Child.Parent = null;

1voto

Ogglas Points 1

Pour une nouvelle application Web Asp.Net utilisant .Net Framework 4.5 :

Web Api : Goto App_Start -> WebApiConfig.cs :

Il devrait ressembler à ceci :

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 }
        );
    }
}

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X