35 votes

API ASP.NET Core ne renvoyant que le premier résultat de la liste

J'ai créé une des équipes de l'api web de contrôleur et d'essayer d'appeler la méthode GET pour obtenir le résultat json de toutes les équipes dans la base de données. Mais quand je fais l'appel, je ne suis que de l'obtention de la première équipe est de retour dans le json mais quand j'ai mis un point d'arrêt sur l'instruction return on a tous 254 des équipes avec tous les jeux.

Ce sont les deux modèles que j'ai affaire à:

public class Team
{
    public string Id { get; set; }
    public string Name { get; set; }
    public string Icon { get; set; }
    public string Mascot { get; set; }
    public string Conference { get; set; }
    public int NationalRank { get; set; }

    public List<Game> Games { get; set; }
}

public class Game
{
    public string Id { get; set; }
    public string Opponent { get; set; }
    public string OpponentLogo { get; set; }
    public string GameDate { get; set; }
    public string GameTime { get; set; }
    public string TvNetwork { get; set; }
    public string TeamId { get; set; }

    public Team Team { get; set; }
}

Lorsque je fais ceci:

[HttpGet]
public async Task<List<Team>> Get()
{
    var teams = await _context.Teams.ToListAsync();

    return teams;
}

Je reçois tous les 254 équipes, mais propriété de Jeu est nul car EF de Base ne prend pas en charge le chargement paresseux. Donc, ce que je veux vraiment faire est d'ajouter le .Include() comme ceci:

[HttpGet]
public async Task<List<Team>> Get()
{
    var teams = await _context.Teams.Include(t => t.Games).ToListAsync();

    return teams;
}

Cela renvoie à la première équipe, le premier jeu, mais rien d'autre. Voici le json:

[
  {
    "id": "007b4f09-d4da-4040-be3a-8e45fc0a572b",
    "name": "New Mexico",
    "icon": "lobos.jpg",
    "mascot": "New Mexico Lobos",
    "conference": "MW - Mountain",
    "nationalRank": null,
    "games": [
      {
        "id": "1198e6b1-e8ab-48ab-a63f-e86421126361",
        "opponent": "vs Air Force*",
        "opponentLogo": "falcons.jpg",
        "gameDate": "Sat, Oct 15",
        "gameTime": "TBD ",
        "tvNetwork": null,
        "teamId": "007b4f09-d4da-4040-be3a-8e45fc0a572b"
      }
    ]
  }
]

Lorsque j'ai mis un point d'arrêt sur l'instruction return, il montre qu'il y a 254 équipes et chaque équipe a ses jeux remplie correctement...mais le résultat json ne reflète pas. Voici une image:

enter image description here

J'ai essayé de faire cela en mode synchrone et asynchrone, mais obtenir le même résultat. Savez-vous pourquoi je suis seulement d'obtenir un résultat en arrière dans le json, mais au point d'arrêt, il a tous les résultats?

54voto

adem caglin Points 9337

Essaye ça:

 services.AddMvc().AddJsonOptions(options => {
            options.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
        });
 

La question a été discutée https://github.com/aspnet/Mvc/issues/4160 et https://github.com/aspnet/EntityFramework/issues/4646 voir également la référence circulaire

1voto

jeremy.bass Points 378

Il est intéressant de noter que si vous ne le contrôle de la sortie json comme avec inline JsonSerializerSettings option,

[HttpGet]
public async Task<IActionResult> Get([FromForm]bool strip_nulls = true)
{
    var teams = await _context.Teams.Include(t => t.Games).ToListAsync();

    return Json(teams, new JsonSerializerSettings() { 
         NullValueHandling = strip_nulls ? NullValueHandling.Ignore : NullValueHandling.Include
    });
}

Tout simplement en mettant la solution proposée par @adeam-caglin, ce qui n'est pas mauvaise en approche, ne fonctionnera pas. Vous devez également définir le paramètre de votre retour. Par exemple.

[HttpGet]
public async Task<IActionResult> Get([FromForm]bool strip_nulls = true)
{
    var teams = await _context.Teams.Include(t => t.Games).ToListAsync();

    return Json(teams, new JsonSerializerSettings() { 
         NullValueHandling = strip_nulls ? NullValueHandling.Ignore : NullValueHandling.Include,
         ReferenceLoopHandling = ReferenceLoopHandling.Ignore
    });
}

Il fondamentalement, les valeurs null, pas ajoute des paramètres que vous définissez sur l' Startup.cs. Cela vous donne également une feuille de route afin de ne pas modifier globalement votre sortie, mais le faire au cas par cas.

MODIFIER

J'aimerais aussi prendre un moment et de clarifier ce qui se passe lorsque vous utilisez ReferenceLoopHandling.Ignore, vous demander à boire au tuyau d'incendie, mais en espérant qu'il sera un débit contrôlé. Si vous avez une très développé de la modélisation, vous aurez plus de chances d'avoir un jeu où vous pensez que vous allez obtenir votre entité et c'est l'enfant de la liste, mais si ces éléments de la liste ont aussi des enfants, ou d'autres parents, alors vous aurez la charge de ceux-ci. Disons que vous avez

Teams>Players>Contacts
Games>Teams

Ce serait de produire un diable d'un json imbriquée retour. J'aurais eu envie d'un plat, Game>Teams mais serait Games>Teams>Players. C'est un exemple simple, mais il est facile de voir comment vous pouvez aller de quelques KO de données pour ne jamais se terminant boucle qui étouffe le client consommer les résultats.

Cela signifie que vous aurez besoin de contrôle de débit de votre auto. Pour obtenir que flatter json retour prévu, vous aurez également besoin d'incorporer .AsNoTracking() sur le .Include(x => x.Games)

Comme un exemple très simple, vous devez faire quelque chose comme:

[HttpGet]
public async Task<IActionResult> Get([FromForm]bool strip_nulls = true)
{
    var teams = _context.Teams.AsQueryable();
    teams = teams.Include(t => t.Games).AsNoTracking();
    Teams _return = await teams.ToListAsync();
    return Json(_return, new JsonSerializerSettings() { 
         NullValueHandling = strip_nulls ? NullValueHandling.Ignore : NullValueHandling.Include,
         ReferenceLoopHandling = ReferenceLoopHandling.Ignore
    });
}

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