Подтвердить что ты не робот

API-интерфейс ASP.NET Core возвращает только первый результат списка

Я создал командный веб-api-контроллер и попытался вызвать метод GET, чтобы получить json-результат всех команд в базе данных. Но когда я делаю вызов, я только возвращаю первую команду в json, но когда я устанавливаю точку останова на оператор return, у него есть все 254 команды вместе со всеми играми.

Это две модели, с которыми я имею дело:

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

Когда я это сделаю:

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

    return teams;
}

Я получаю все 254 команды, но свойство Game равно null, потому что EF Core не поддерживает ленивую загрузку. Поэтому я действительно хочу добавить .Include() следующим образом:

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

    return teams;
}

Это возвращает первую команду с первой игрой, но ничего больше. Вот 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"
      }
    ]
  }
]

Когда я устанавливаю точку останова в операторе return, это показывает, что есть 254 команды, и каждая команда имеет свои игры, заполненные правильно... но результат json не отражает. Вот изображение:

введите описание изображения здесь

Я пробовал делать это как синхронно, так и асинхронно, но получая тот же результат. Вы знаете, почему я получаю только один результат в json, но в точке останова он имеет все результаты?

4b9b3361

Ответ 2

Следует отметить, что если вы управляете выходным сигналом json, например, с помощью встроенного параметра JsonSerializerSettings,

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

Проще говоря, предлагаемое решение от @adeam-caglin, которое не является неправильным в подходе, не будет работать. Вы также должны установить настройку в своем возвращении. Например.

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

В основном он отменяет, а не добавляет настройки, установленные на Startup.cs. Это также дает вам дорожную карту, чтобы глобально не изменять ваш результат, но делайте это в каждом случае.

ИЗМЕНИТЬ

Я также хотел бы остановиться и уточнить, что происходит, когда вы используете ReferenceLoopHandling.Ignore, вы просите выпить из пожарного шланга, но надеетесь, что это будет контролируемый поток. Если у вас есть высокоразвитое моделирование, у вас, скорее всего, будет набор, в котором вы думаете, что собираетесь получить свой предполагаемый объект и его дочерний список, но если в этих элементах списка есть дети или другие родители, вы загрузите их. Допустим, у вас есть

Teams>Players>Contacts
Games>Teams

Это создаст черту json inested return. Мне бы хотелось получить квартиру Game>Teams, но в итоге получилось бы Games>Teams>Players. Это простой пример, но легко понять, как вы можете перейти от пары КБ данных к бесконечному циклу, который захлопывает клиента, потребляющего результаты.

Это означает, что вам нужно будет контролировать этот поток. Чтобы получить ожидаемое оживление json, вам также необходимо включить .AsNoTracking() в .Include(x => x.Games)

В качестве очень простого примера вам нужно будет сделать что-то вроде:

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