チームWeb APIコントローラーを作成し、GETメソッドを呼び出してデータベース内のすべてのチームのJSON結果を取得しようとしています。しかし、電話をかけると、最初のチームがjsonに戻るだけですが、returnステートメントにブレークポイントを設定すると、254チームすべてとすべてのゲームが含まれます。
これらは私が扱っている2つのモデルです。
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チームすべてを取得していますが、EF Coreは遅延読み込みをサポートしていないため、Gameプロパティはnullです。したがって、私が本当にやりたいことは、次のように.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に1つの結果しか返されないのに、ブレークポイントですべての結果が得られる理由を知っていますか?
これを試して:
services.AddMvc().AddJsonOptions(options => {
options.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
});
問題は議論されました https://github.com/aspnet/Mvc/issues/416 および 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から提案された解決策を単に置くだけで、アプローチは間違っていませんが、機能しません。また、返品時に設定を行う必要があります。例えば。
_[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
});
}
_
基本的にnullになり、_Startup.cs
_で設定した設定に追加されません。また、出力をグローバルに変更するのではなく、ケースバイケースで変更するためのロードマップも提供します。
また、_ReferenceLoopHandling.Ignore
_を使用したときに何が起こるかを少し時間をかけて明確にしたいと思います。消防ホースから飲むように求めていますが、制御されたフローになることを期待しています。高度に開発されたモデリングを使用している場合、目的のエンティティとその子リストを取得する予定のセットが存在する可能性が高くなりますが、それらのリストアイテムにも子または他の親がある場合は、それらをロードします。あなたが持っているとしましょう
_Teams>Players>Contacts
Games>Teams
_
これにより、jsonネストされた戻り値が生成されます。フラットな_Game>Teams
_が必要でしたが、最終的には_Games>Teams>Players
_になります。これは簡単な例ですが、数KBのデータから、結果を消費しているクライアントを止めるループを終わらせないようにする方法は簡単にわかります。
これは、自分の流れを制御する必要があることを意味します。期待どおりのフラットな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
});
}
_