简体   繁体   English

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

[英]ASP.NET Core API only returning first result of list

I have created a teams web api controller and trying to call the GET method to get the json result of all the teams in the database.我创建了一个团队 web api 控制器并尝试调用 GET 方法来获取数据库中所有团队的 json 结果。 But when I make the call I am only getting the first team back in the json but when I set a breakpoint on the return statement it has all 254 teams along with all of the games.但是当我拨打电话时,我只让第一个团队回到 json 中,但是当我在 return 语句上设置断点时,它包含所有 254 个团队以及所有游戏。

These are the two models that I am dealing with:这是我正在处理的两个模型:

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

When I do this:当我这样做时:

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

    return teams;
}

I get all 254 teams but Game property is null because EF Core does not support lazy loading.我得到了所有 254 个团队,但 Game 属性为空,因为 EF Core 不支持延迟加载。 So what I really want to do is add the .Include() like this:所以我真正想做的是像这样添加 .Include() :

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

    return teams;
}

This returns the first team with the first game but nothing else.这将返回第一场比赛的第一支球队,但没有别的。 Here is the json:这是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"
      }
    ]
  }
]

When I set a break point on the return statement it shows that there are 254 teams and every team has their games populated correctly...but the json result does not reflect.当我在 return 语句上设置断点时,它显示有 254 个团队,每个团队都正确填充了他们的游戏......但 json 结果没有反映。 Here is an image:这是一张图片:

在此处输入图片说明

I have tried doing this both synchronously and asynchronously but getting the same result.我尝试同步和异步执行此操作,但得到相同的结果。 Do you know why I am only getting one result back in the json but at the breakpoint it has all of the results?你知道为什么我在 json 中只得到一个结果,但在断点处它有所有结果吗?

Add this to Startup.cs inside the public void ConfigureServices(IServiceCollection services) method:将此添加到Startup.cspublic void ConfigureServices(IServiceCollection services)方法:

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

The issue was discussed https://github.com/aspnet/Mvc/issues/4160 and https://github.com/aspnet/EntityFramework/issues/4646 also see circular reference讨论了这个问题https://github.com/aspnet/Mvc/issues/4160https://github.com/aspnet/EntityFramework/issues/4646也见循环参考

It is worth noting that if you do control the json output like with inline JsonSerializerSettings option,值得注意的是,如果您像使用内联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
    });
}

Simply putting the suggested solution from @adeam-caglin, which is not wrong in approach, will not work.简单地提出@adeam-caglin 的建议解决方案,这在方法上没有错,是行不通的。 You must also set the setting in your return.您还必须在退货中设置该设置。 For example.例如。

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

It basically nulls out, not adds to the settings you set on the Startup.cs .它基本上是空的,而不是添加到您在Startup.cs上设置的设置。 This also gives you a road map to not globally alter your output but do it case by case.这也为您提供了一个路线图,不要全局更改您的输出,而是逐案进行。

EDIT编辑

I would also like to take a moment and clarify what happens when you use ReferenceLoopHandling.Ignore , you are asking to drink from the fire hose but hoping it will be a controlled flow.我还想花点时间澄清一下当您使用ReferenceLoopHandling.Ignore时会发生什么,您要求从消防软管中喝水,但希望它是受控的流量。 If you have a highly developed modeling, you will more then likely have a set where you think you going to get your intended entity and it's child list, but if those list items also have children, or other parents then you will load those.如果您有一个高度发达的建模,那么您可能会有一个集合,您认为您将在其中获得预期的实体及其子列表,但是如果这些列表项也有子项或其他父项,那么您将加载它们。 Lets say you have让我们说你有

Teams>Players>Contacts
Games>Teams

This would produce a heck of a json nested return.这会产生大量的 json 嵌套返回。 I would have been wanting a flat Game>Teams but would end up with Games>Teams>Players .我本来想要一个扁平的Game>Teams但最终会得到Games>Teams>Players This is a simple example but it is easy to see how you could go from a couple KB of data to never ending loop that chokes out the client consuming the results.这是一个简单的示例,但很容易看出如何从几 KB 的数据转到永无止境的循环,从而扼杀了使用结果的客户端。

This is means you will need to control that flow your self.这意味着你需要控制自己的流动。 To get that flatter json return expected you will also need to incorporate .AsNoTracking() on the .Include(x => x.Games)要获得预期的更平坦的 json 返回,您还需要在.Include(x => x.Games)上合并.AsNoTracking() .Include(x => x.Games)

As a very simple example, you would need to do something like:作为一个非常简单的示例,您需要执行以下操作:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM