diff --git a/src/Microsoft.AspNet.OData.Shared/Formatter/Serialization/ODataResourceSerializer.cs b/src/Microsoft.AspNet.OData.Shared/Formatter/Serialization/ODataResourceSerializer.cs index d44c6de1b..2da3ff131 100644 --- a/src/Microsoft.AspNet.OData.Shared/Formatter/Serialization/ODataResourceSerializer.cs +++ b/src/Microsoft.AspNet.OData.Shared/Formatter/Serialization/ODataResourceSerializer.cs @@ -1808,7 +1808,7 @@ private IEnumerable> GetNavigationPro if (navigationProperties == null) { - yield break; + navigationProperties = resourceContext.StructuredType.DeclaredNavigationProperties(); } if (resourceContext.EdmObject is IDelta changedObject) diff --git a/test/E2ETest/Microsoft.Test.E2E.AspNet.OData/BulkOperation/BulkOperationTest.cs b/test/E2ETest/Microsoft.Test.E2E.AspNet.OData/BulkOperation/BulkOperationTest.cs index f6ce22008..1a1809f83 100644 --- a/test/E2ETest/Microsoft.Test.E2E.AspNet.OData/BulkOperation/BulkOperationTest.cs +++ b/test/E2ETest/Microsoft.Test.E2E.AspNet.OData/BulkOperation/BulkOperationTest.cs @@ -42,7 +42,69 @@ protected override void UpdateConfiguration(WebRouteConfiguration configuration) } #region Update - + + [Fact] + public async Task PatchEmployee_WithNestedFriends_WithNestedOrders_IsSerializedSuccessfully() + { + //Arrange + string requestUri = this.BaseAddress + "/convention/Employees"; + var content = @"{ + '@odata.context':'http://host/service/$metadata#Employees/$delta', + 'value':[ + {'ID':1,'Name':'Employee1','Friends@odata.delta':[{'Id':1,'Name':'Friend1','Orders@odata.delta':[{'Id':1,'Price': 10},{'Id':2,'Price':20} ]},{'Id':2,'Name':'Friend2'}]}, + {'ID':2,'Name':'Employee2','Friends@odata.delta':[{'Id':3,'Name':'Friend3','Orders@odata.delta' :[{'Id':3,'Price': 30}, {'Id':4,'Price': 40} ]},{'Id':4,'Name':'Friend4'}]} + ]}"; + + var requestForPatch = new HttpRequestMessage(new HttpMethod("PATCH"), requestUri); + + string expectedResponse = "{" + + "\"@context\":\"" + this.BaseAddress + "/convention/$metadata#Employees/$delta\"," + + "\"value\":[" + + "{\"ID\":1,\"Name\":\"Employee1\",\"SkillSet\":[],\"Gender\":\"0\",\"AccessLevel\":\"0\",\"FavoriteSports\":null,\"Friends@delta\":[{\"Id\":1,\"Name\":\"Friend1\",\"Age\":0,\"Orders@delta\":[{\"Id\":1,\"Price\":10},{\"Id\":2,\"Price\":20}]},{\"Id\":2,\"Name\":\"Friend2\",\"Age\":0}]}," + + "{\"ID\":2,\"Name\":\"Employee2\",\"SkillSet\":[],\"Gender\":\"0\",\"AccessLevel\":\"0\",\"FavoriteSports\":null,\"Friends@delta\":[{\"Id\":3,\"Name\":\"Friend3\",\"Age\":0,\"Orders@delta\":[{\"Id\":3,\"Price\":30},{\"Id\":4,\"Price\":40}]},{\"Id\":4,\"Name\":\"Friend4\",\"Age\":0}]}]}"; + StringContent stringContent = new StringContent(content: content, encoding: Encoding.UTF8, mediaType: "application/json"); + requestForPatch.Content = stringContent; + + // Act & Assert + using (HttpResponseMessage response = await this.Client.SendAsync(requestForPatch)) + { + Assert.Equal(HttpStatusCode.OK, response.StatusCode); + var json = response.Content.ReadAsStringAsync().Result; + Assert.Equal(expectedResponse.ToString().ToLower(), json.ToString().ToLower()); + Assert.Contains("Employee1", json); + Assert.Contains("Employee2", json); + } + } + + [Fact] + public async Task PatchEmployee_WithDeletedAndODataId_IsSerializedSuccessfully() + { + //Arrange + string requestUri = this.BaseAddress + "/convention/Employees"; + + var content = @"{ + '@odata.context':'http://host/service/$metadata#Employees/$delta', + 'value':[ + {'ID':1,'Name':'Employee1','Friends@odata.delta':[{'@odata.removed':{'reason':'changed'},'Id':1}]}, + {'ID':2,'Name':'Employee2','Friends@odata.delta':[{'@odata.id':'Friends(1)'}]} + ]}"; + + string expectedResponse = "{\"@context\":\"" + this.BaseAddress + "/convention/$metadata#Employees/$delta\",\"value\":[{\"ID\":1,\"Name\":\"Employee1\",\"SkillSet\":[],\"Gender\":\"0\",\"AccessLevel\":\"0\",\"FavoriteSports\":null,\"Friends@delta\":[{\"@removed\":{\"reason\":\"changed\"},\"@id\":\"http://host/service/Friends(1)\",\"Id\":1,\"Name\":null,\"Age\":0}]},{\"ID\":2,\"Name\":\"Employee2\",\"SkillSet\":[],\"Gender\":\"0\",\"AccessLevel\":\"0\",\"FavoriteSports\":null,\"Friends@delta\":[{\"Id\":0,\"Name\":null,\"Age\":0}]}]}"; + + var requestForUpdate = new HttpRequestMessage(new HttpMethod("PATCH"), requestUri); + + StringContent stringContent = new StringContent(content: content, encoding: Encoding.UTF8, mediaType: "application/json"); + requestForUpdate.Content = stringContent; + + //Act & Assert + using (HttpResponseMessage response = await this.Client.SendAsync(requestForUpdate)) + { + Assert.Equal(HttpStatusCode.OK, response.StatusCode); + var json = response.Content.ReadAsStringAsync().Result; + Assert.Equal(expectedResponse.ToString().ToLower(), json.ToString().ToLower()); + } + } + [Fact] public async Task PatchEmployee_WithUpdates() {