ASP.NET Core API只返回列表的第一个结果

我创build了一个团队的Web 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属性为空,因为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" } ] } ] 

当我在返回语句中设置一个断点时,它显示有254个团队,每个团队都有他们的游戏填充正确…但json结果并不反映。 这是一个图像:

在这里输入图像描述

我试图同步和asynchronous,但得到相同的结果。 你知道为什么我只在json中得到一个结果,但在断点处它有所有的结果?

尝试这个:

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

讨论了这个问题https://github.com/aspnet/Mvc/issues/4160和https://github.com/aspnet/EntityFramework/issues/4646也可以看到循环引用;

值得注意的是,如果你像使用内联JsonSerializerSettings选项一样控制json输出,

 [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推荐的解决scheme,这是没有办法错误,将无法正常工作。 您还必须在您的回报中设置设置。 例如。

 [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会发生什么情况,您是要求从消防水pipe中喝水,但希望能够控制stream量。 如果你有一个高度发展的模型,你可能会有一个集合,你认为你会得到你想要的实体,这是孩子列表,但如果这些列表项目也有孩子,或其他父母,那么你会加载这些。 可以说你有

 Teams>Players>Contacts Games>Teams 

这将产生一个json嵌套返回。 我本来想要一个平板Game>Teams但最终会与Games>Teams>Players 。 这是一个简单的例子,但是很容易看到如何从几KB的数据到永不结束的循环,扼杀客户端消费结果。

这意味着你将需要控制stream动你的自我。 为了得到那个更平坦的json返回值,你还需要在.Include(x => x.Games)上join.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 }); }