Skip to content

Commit e300bef

Browse files
authored
Merge pull request #149 from Research-Institute/hotfix/#148
fix(DocumentBuilder): do not include entities twice
2 parents 4a9968a + bf5f4f6 commit e300bef

File tree

3 files changed

+48
-12
lines changed

3 files changed

+48
-12
lines changed

src/JsonApiDotNetCore/Builders/DocumentBuilder.cs

+12-11
Original file line numberDiff line numberDiff line change
@@ -95,12 +95,10 @@ private Dictionary<string, object> GetMeta(IIdentifiable entity)
9595

9696
private List<DocumentData> AppendIncludedObject(List<DocumentData> includedObject, ContextEntity contextEntity, IIdentifiable entity)
9797
{
98-
var includedEntities = GetIncludedEntities(contextEntity, entity);
99-
if (includedEntities.Count > 0)
98+
var includedEntities = GetIncludedEntities(includedObject, contextEntity, entity);
99+
if (includedEntities?.Count > 0)
100100
{
101-
if (includedObject == null)
102-
includedObject = new List<DocumentData>();
103-
includedObject.AddRange(includedEntities);
101+
includedObject = includedEntities;
104102
}
105103

106104
return includedObject;
@@ -174,10 +172,8 @@ private void AddRelationships(DocumentData data, ContextEntity contextEntity, II
174172
});
175173
}
176174

177-
private List<DocumentData> GetIncludedEntities(ContextEntity contextEntity, IIdentifiable entity)
175+
private List<DocumentData> GetIncludedEntities(List<DocumentData> included, ContextEntity contextEntity, IIdentifiable entity)
178176
{
179-
var included = new List<DocumentData>();
180-
181177
contextEntity.Relationships.ForEach(r =>
182178
{
183179
if (!RelationshipIsIncluded(r.PublicRelationshipName)) return;
@@ -186,20 +182,25 @@ private List<DocumentData> GetIncludedEntities(ContextEntity contextEntity, IIde
186182

187183
if (navigationEntity is IEnumerable hasManyNavigationEntity)
188184
foreach (IIdentifiable includedEntity in hasManyNavigationEntity)
189-
AddIncludedEntity(included, includedEntity);
185+
included = AddIncludedEntity(included, includedEntity);
190186
else
191-
AddIncludedEntity(included, (IIdentifiable)navigationEntity);
187+
included = AddIncludedEntity(included, (IIdentifiable)navigationEntity);
192188
});
193189

194190
return included;
195191
}
196192

197-
private void AddIncludedEntity(List<DocumentData> entities, IIdentifiable entity)
193+
private List<DocumentData> AddIncludedEntity(List<DocumentData> entities, IIdentifiable entity)
198194
{
199195
var includedEntity = GetIncludedEntity(entity);
200196

197+
if(entities == null)
198+
entities = new List<DocumentData>();
199+
201200
if(includedEntity != null && !entities.Any(doc => doc.Id == includedEntity.Id && doc.Type == includedEntity.Type))
202201
entities.Add(includedEntity);
202+
203+
return entities;
203204
}
204205

205206
private DocumentData GetIncludedEntity(IIdentifiable entity)

src/JsonApiDotNetCore/JsonApiDotNetCore.csproj

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<Project Sdk="Microsoft.NET.Sdk">
22
<PropertyGroup>
3-
<VersionPrefix>2.1.1</VersionPrefix>
3+
<VersionPrefix>2.1.2</VersionPrefix>
44
<TargetFrameworks>netstandard1.6</TargetFrameworks>
55
<AssemblyName>JsonApiDotNetCore</AssemblyName>
66
<PackageId>JsonApiDotNetCore</PackageId>

test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/DocumentTests/Included.cs

+35
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,41 @@ public async Task GET_Included_DoesNot_Duplicate_Records_ForMultipleRelationship
169169
Assert.Equal(1, documents.Included.Count);
170170
}
171171

172+
[Fact]
173+
public async Task GET_Included_DoesNot_Duplicate_Records_If_HasOne_Exists_Twice()
174+
{
175+
// arrange
176+
_context.People.RemoveRange(_context.People); // ensure all people have todo-items
177+
_context.TodoItems.RemoveRange(_context.TodoItems);
178+
var person = _personFaker.Generate();
179+
var todoItem1 = _todoItemFaker.Generate();
180+
var todoItem2 = _todoItemFaker.Generate();
181+
todoItem1.Owner = person;
182+
todoItem2.Owner = person;
183+
_context.TodoItems.AddRange(new[] { todoItem1, todoItem2 });
184+
_context.SaveChanges();
185+
186+
var builder = new WebHostBuilder()
187+
.UseStartup<Startup>();
188+
189+
var httpMethod = new HttpMethod("GET");
190+
var route = $"/api/v1/todo-items?include=owner";
191+
192+
var server = new TestServer(builder);
193+
var client = server.CreateClient();
194+
var request = new HttpRequestMessage(httpMethod, route);
195+
196+
// act
197+
var response = await client.SendAsync(request);
198+
var documents = JsonConvert.DeserializeObject<Documents>(await response.Content.ReadAsStringAsync());
199+
var data = documents.Data;
200+
201+
// assert
202+
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
203+
Assert.NotEmpty(documents.Included);
204+
Assert.Equal(1, documents.Included.Count);
205+
}
206+
172207
[Fact]
173208
public async Task GET_ById_Included_Contains_SideloadedData_ForOneToMany()
174209
{

0 commit comments

Comments
 (0)