diff --git a/src/Examples/JsonApiDotNetCoreExample/Models/Tag.cs b/src/Examples/JsonApiDotNetCoreExample/Models/Tag.cs index 296fd559df..dbee65a188 100644 --- a/src/Examples/JsonApiDotNetCoreExample/Models/Tag.cs +++ b/src/Examples/JsonApiDotNetCoreExample/Models/Tag.cs @@ -1,3 +1,5 @@ +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations.Schema; using JsonApiDotNetCore.Resources; using JsonApiDotNetCore.Resources.Annotations; @@ -10,6 +12,11 @@ public class Tag : Identifiable [Attr] public TagColor Color { get; set; } + + [NotMapped] + [HasManyThrough(nameof(ArticleTags))] + public ISet
Articles { get; set; } + public ISet ArticleTags { get; set; } } public enum TagColor diff --git a/src/JsonApiDotNetCore/Queries/Internal/QueryableBuilding/SelectClauseBuilder.cs b/src/JsonApiDotNetCore/Queries/Internal/QueryableBuilding/SelectClauseBuilder.cs index e9a51c4092..eb8f37e117 100644 --- a/src/JsonApiDotNetCore/Queries/Internal/QueryableBuilding/SelectClauseBuilder.cs +++ b/src/JsonApiDotNetCore/Queries/Internal/QueryableBuilding/SelectClauseBuilder.cs @@ -61,7 +61,7 @@ public Expression ApplySelect(IDictionary se private Expression CreateLambdaBodyInitializer(IDictionary selectors, ResourceContext resourceContext, LambdaScope lambdaScope, bool lambdaAccessorRequiresTestForNull) { - var propertySelectors = ToPropertySelectors(selectors, resourceContext, lambdaScope.Parameter.Type); + var propertySelectors = ToPropertySelectors(selectors, resourceContext, lambdaScope.Accessor.Type); MemberBinding[] propertyAssignments = propertySelectors.Select(selector => CreatePropertyAssignment(selector, lambdaScope)).Cast().ToArray(); NewExpression newExpression = _resourceFactory.CreateNewExpression(lambdaScope.Accessor.Type); diff --git a/test/JsonApiDotNetCoreExampleTests/IntegrationTests/Includes/IncludeTests.cs b/test/JsonApiDotNetCoreExampleTests/IntegrationTests/Includes/IncludeTests.cs index 97f7c15dd9..768b98ae16 100644 --- a/test/JsonApiDotNetCoreExampleTests/IntegrationTests/Includes/IncludeTests.cs +++ b/test/JsonApiDotNetCoreExampleTests/IntegrationTests/Includes/IncludeTests.cs @@ -329,6 +329,51 @@ await _testContext.RunOnDatabaseAsync(async dbContext => responseDocument.Included[0].Attributes["name"].Should().Be(article.ArticleTags.Single().Tag.Name); } + [Fact] + public async Task Can_include_HasManyThrough_relationship_in_secondary_resource() + { + // Arrange + var article = new Article + { + Caption = "One", + ArticleTags = new HashSet + { + new ArticleTag + { + Tag = new Tag + { + Name = "Hot" + } + } + } + }; + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + dbContext.Articles.Add(article); + + await dbContext.SaveChangesAsync(); + }); + + var route = $"/api/v1/articles/{article.StringId}/tags?include=articles"; + + // Act + var (httpResponse, responseDocument) = await _testContext.ExecuteGetAsync(route); + + // Assert + httpResponse.Should().HaveStatusCode(HttpStatusCode.OK); + + responseDocument.ManyData.Should().HaveCount(1); + responseDocument.ManyData[0].Type.Should().Be("tags"); + responseDocument.ManyData[0].Id.Should().Be(article.ArticleTags.ElementAt(0).Tag.StringId); + responseDocument.ManyData[0].Attributes["name"].Should().Be(article.ArticleTags.Single().Tag.Name); + + responseDocument.Included.Should().HaveCount(1); + responseDocument.Included[0].Type.Should().Be("articles"); + responseDocument.Included[0].Id.Should().Be(article.StringId); + responseDocument.Included[0].Attributes["caption"].Should().Be(article.Caption); + } + [Fact] public async Task Can_include_chain_of_HasOne_relationships() {