diff --git a/src/JsonApiDotNetCore/Internal/ResourceGraph.cs b/src/JsonApiDotNetCore/Internal/ResourceGraph.cs index 9c1d421437..a7afe98398 100644 --- a/src/JsonApiDotNetCore/Internal/ResourceGraph.cs +++ b/src/JsonApiDotNetCore/Internal/ResourceGraph.cs @@ -144,11 +144,18 @@ private IEnumerable GetHasManyThrough(IIdentifiable parent, HasMa var throughProperty = GetRelationship(parent, hasManyThrough.InternalThroughName); if (throughProperty is IEnumerable hasManyNavigationEntity) { - foreach (var includedEntity in hasManyNavigationEntity) - { - var targetValue = hasManyThrough.RightProperty.GetValue(includedEntity) as IIdentifiable; - yield return targetValue; - } + // wrap "yield return" in a sub-function so we can correctly return null if the property is null. + return GetHasManyThroughIter(hasManyThrough, hasManyNavigationEntity); + } + return null; + } + + private IEnumerable GetHasManyThroughIter(HasManyThroughAttribute hasManyThrough, IEnumerable hasManyNavigationEntity) + { + foreach (var includedEntity in hasManyNavigationEntity) + { + var targetValue = hasManyThrough.RightProperty.GetValue(includedEntity) as IIdentifiable; + yield return targetValue; } } diff --git a/test/JsonApiDotNetCoreExampleTests/Acceptance/ManyToManyTests.cs b/test/JsonApiDotNetCoreExampleTests/Acceptance/ManyToManyTests.cs index b5d80cdee8..948ea442c9 100644 --- a/test/JsonApiDotNetCoreExampleTests/Acceptance/ManyToManyTests.cs +++ b/test/JsonApiDotNetCoreExampleTests/Acceptance/ManyToManyTests.cs @@ -110,6 +110,34 @@ public async Task Can_Fetch_Many_To_Many_Through_GetById() Assert.Equal(tag.Name, tagResponse.Name); } + [Fact] + public async Task Can_Fetch_Many_To_Many_Without_Include() + { + // arrange + var context = _fixture.GetService(); + var article = _articleFaker.Generate(); + var tag = _tagFaker.Generate(); + var articleTag = new ArticleTag + { + Article = article, + Tag = tag + }; + context.ArticleTags.Add(articleTag); + await context.SaveChangesAsync(); + + var route = $"/api/v1/articles/{article.Id}"; + + // act + var response = await _fixture.Client.GetAsync(route); + + // assert + var body = await response.Content.ReadAsStringAsync(); + Assert.True(HttpStatusCode.OK == response.StatusCode, $"{route} returned {response.StatusCode} status code with payload: {body}"); + + var document = JsonConvert.DeserializeObject(body); + Assert.Null(document.Data.Relationships["tags"].ManyData); + } + [Fact] public async Task Can_Create_Many_To_Many() { @@ -269,4 +297,4 @@ public async Task Can_Update_Many_To_Many_Through_Relationship_Link() Assert.Equal(tag.Id, persistedArticleTag.TagId); } } -} \ No newline at end of file +}