diff --git a/src/JsonApiDotNetCore/Data/DefaultEntityRepository.cs b/src/JsonApiDotNetCore/Data/DefaultEntityRepository.cs index dabf447efe..e23b4a316d 100644 --- a/src/JsonApiDotNetCore/Data/DefaultEntityRepository.cs +++ b/src/JsonApiDotNetCore/Data/DefaultEntityRepository.cs @@ -326,10 +326,14 @@ private IList GetTrackedManyRelationshipValue(IEnumerable relatio { if (relationshipValueList == null) return null; bool _wasAlreadyAttached = false; - Type entityType = null; + /// if we're not using entity resource separation, we can just read off the related type + /// from the RelationshipAttribute. If we DO use separation, RelationshipAttribute.DependentType + /// will point to the Resource, not the Entity, which is not the one we need here. + bool entityResourceSeparation = relationshipAttr.EntityPropertyName != null; + Type entityType = entityResourceSeparation ? null : relationshipAttr.DependentType; var trackedPointerCollection = relationshipValueList.Select(pointer => { - /// todo: we can't just use relationshipAttr.Type because + /// todo: we can't just use relationshipAttr.DependentType because /// this will point to the Resource type in the case of entity resource /// separation. We should consider to store entity type on /// the relationship attribute too. diff --git a/src/JsonApiDotNetCore/Services/EntityResourceService.cs b/src/JsonApiDotNetCore/Services/EntityResourceService.cs index 9a06577386..c889af68b8 100644 --- a/src/JsonApiDotNetCore/Services/EntityResourceService.cs +++ b/src/JsonApiDotNetCore/Services/EntityResourceService.cs @@ -220,7 +220,6 @@ public virtual async Task UpdateAsync(TId id, TResource resource) _hookExecutor.AfterUpdate(AsList(entity), ResourcePipeline.Patch); entity = _hookExecutor.OnReturn(AsList(entity), ResourcePipeline.Patch).SingleOrDefault(); } - return MapOut(entity); } diff --git a/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/UpdatingRelationshipsTests.cs b/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/UpdatingRelationshipsTests.cs index b1197447fd..714b59d0e3 100644 --- a/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/UpdatingRelationshipsTests.cs +++ b/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/UpdatingRelationshipsTests.cs @@ -528,7 +528,7 @@ public async Task Can_Update_ToOne_Relationship_ThroughLink() } [Fact] - public async Task Can_Delete_Relationship_By_Patching_Resource() + public async Task Can_Delete_ToOne_Relationship_By_Patching_Resource() { // arrange var person = _personFaker.Generate(); @@ -580,6 +580,64 @@ public async Task Can_Delete_Relationship_By_Patching_Resource() Assert.Null(todoItemResult.Owner); } + + [Fact] + public async Task Can_Delete_ToMany_Relationship_By_Patching_Resource() + { + // arrange + var person = _personFaker.Generate(); + var todoItem = _todoItemFaker.Generate(); + person.TodoItems = new List() { todoItem }; + _context.People.Add(person); + _context.SaveChanges(); + + var builder = new WebHostBuilder() + .UseStartup(); + + var server = new TestServer(builder); + var client = server.CreateClient(); + + var content = new + { + data = new + { + id = person.Id, + type = "people", + relationships = new Dictionary + { + { "todo-items", new + { + data = new List + { + + } + } + } + } + } + }; + + var httpMethod = new HttpMethod("PATCH"); + var route = $"/api/v1/people/{person.Id}"; + var request = new HttpRequestMessage(httpMethod, route); + + string serializedContent = JsonConvert.SerializeObject(content); + request.Content = new StringContent(serializedContent); + request.Content.Headers.ContentType = new MediaTypeHeaderValue("application/vnd.api+json"); + + // Act + var response = await _fixture.Client.SendAsync(request); + + // Assert + var personResult = _context.People + .AsNoTracking() + .Include(p => p.TodoItems) + .Single(p => p.Id == person.Id); + + Assert.Equal(HttpStatusCode.OK, response.StatusCode); + Assert.Empty(personResult.TodoItems); + } + [Fact] public async Task Can_Delete_Relationship_By_Patching_Relationship() {