From fc60d8b91b32fe50050be79251f0095ec7248273 Mon Sep 17 00:00:00 2001 From: Derrick Butoyi Date: Mon, 7 Oct 2024 11:42:13 +0300 Subject: [PATCH 1/6] Add DependsOnId on Add Related Object API --- .../DataServiceContext.cs | 3 +- ...ceContextHttpClientHandlerProviderTests.cs | 216 ++++++++++++++++-- 2 files changed, 205 insertions(+), 14 deletions(-) diff --git a/src/Microsoft.OData.Client/DataServiceContext.cs b/src/Microsoft.OData.Client/DataServiceContext.cs index e614d0bb46..1ece0ba678 100644 --- a/src/Microsoft.OData.Client/DataServiceContext.cs +++ b/src/Microsoft.OData.Client/DataServiceContext.cs @@ -2634,7 +2634,8 @@ public virtual void AddRelatedObject(object source, string sourceProperty, objec var targetResource = new EntityDescriptor(this.model) { Entity = target, - State = EntityStates.Added + State = EntityStates.Added, + DependsOnIds = new List { sourceResource.ChangeOrder.ToString(CultureInfo.InvariantCulture) } }; targetResource.SetParentForInsert(sourceResource, sourceProperty); diff --git a/test/FunctionalTests/Microsoft.OData.Client.Tests/DataServiceContextHttpClientHandlerProviderTests.cs b/test/FunctionalTests/Microsoft.OData.Client.Tests/DataServiceContextHttpClientHandlerProviderTests.cs index 15b43f18e3..ce0196d3f6 100644 --- a/test/FunctionalTests/Microsoft.OData.Client.Tests/DataServiceContextHttpClientHandlerProviderTests.cs +++ b/test/FunctionalTests/Microsoft.OData.Client.Tests/DataServiceContextHttpClientHandlerProviderTests.cs @@ -4,7 +4,9 @@ // //--------------------------------------------------------------------- +using Microsoft.Extensions.Logging.Abstractions; using Microsoft.OData.Client.Tests.Serialization; +using Microsoft.OData.Edm.Csdl; using Microsoft.WindowsAzure.ActiveDirectory; using System; using System.Collections.Generic; @@ -13,7 +15,9 @@ using System.Net; using System.Net.Http; using System.Text; +using System.Text.RegularExpressions; using System.Threading.Tasks; +using System.Xml; using Xunit; namespace Microsoft.OData.Client.Tests @@ -22,19 +26,61 @@ public class DataServiceContextHttpClientHandlerProviderTests { private const string BaseUri = "http://service.org"; private const string Edmx = @" - - - - - - - - - - - - -"; + + + + + + + + + + + + + "; + + private const string ExpectedRequestPayloadUsingJson1 = @"{ + ""requests"": [ + { + ""id"": ""1"", + ""atomicityGroup"": ""93dd314c-48e2-442c-a016-d17be61cc7f0"", + ""method"": ""POST"", + ""url"": ""http://service.org/Banks"", + ""headers"": { + ""odata-version"": ""4.0"", + ""odata-maxversion"": ""4.0"", + ""content-type"": ""application/json;odata.metadata=minimal"", + ""accept"": ""application/json;odata.metadata=minimal"", + ""accept-charset"": ""UTF-8"", + ""user-agent"": ""Microsoft.OData.Client/8.0.1"" + }, + ""body"": { + ""Id"": 45, + ""Name"": ""Test Bank"" + } + }, + { + ""id"": ""2"", + ""atomicityGroup"": ""93dd314c-48e2-442c-a016-d17be61cc7f0"", + ""dependsOn"": [""1""], + ""method"": ""POST"", + ""url"": ""http://service.org/$1/BankAccounts"", + ""headers"": { + ""odata-version"": ""4.0"", + ""odata-maxversion"": ""4.0"", + ""content-type"": ""application/json;odata.metadata=minimal"", + ""accept"": ""application/json;odata.metadata=minimal"", + ""accept-charset"": ""UTF-8"", + ""user-agent"": ""Microsoft.OData.Client/8.0.1"" + }, + ""body"": { + ""Id"": 890 + } + } + ] + } + "; private const string PersonNameValue = "John Doe"; @@ -160,6 +206,85 @@ private HttpResponseMessage HandleRequest(HttpRequestMessage request) return response; } + + + + [Fact] + public void TestDependsOnIDJsonBatchSingleChangeSetSupportAddObjectAPITest() + { + using (var handler = new MockHttpClientHandler((httpRequest) => + { + var contents = httpRequest.Content.ReadAsStringAsync().Result; + var stringContent = new StringContent(contents, Encoding.UTF8, "application/json"); + + Assert.Contains("\"dependsOn\":[\"1\"]", contents); + + var normalizedRequestPayload = GetNormalizedJsonMessage(contents); + var normalizedExpectedPayload = GetNormalizedJsonMessage(ExpectedRequestPayloadUsingJson1); + + Assert.Equal(normalizedExpectedPayload, normalizedRequestPayload); + + var response = new HttpResponseMessage(HttpStatusCode.OK); + + response.Content.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("application/json"); + response.Content.Headers.ContentType.Parameters.Add(new System.Net.Http.Headers.NameValueHeaderValue("odata.metadata", "minimal")); + response.Headers.Add("OData-Version", "4.0"); + response.Headers.Add("OData-MaxVersion", "4.0"); + return response; + } )) + { + var provider = new MockHttpClientFactory(handler); + + var context = new Container(new Uri(BaseUri)); + context.HttpClientFactory = provider; + + // Create new Bank object + var bank = new Bank + { + Id = 45, + Name = "Test Bank", + BankAccounts = new List() + }; + + // Create new BankAccount object + var bankAccount = new BankAccount + { + Id = 890 + }; + + // Establish the relationship between Bank and BankAccount + bank.BankAccounts.Add(bankAccount); + + // Add the Bank entity to the context + context.AddObject("Banks", bank); + + // Add the related BankAccount entity + context.AddRelatedObject(bank, "BankAccounts", bankAccount); + + context.BeginSaveChanges( + SaveChangesOptions.BatchWithSingleChangeset | SaveChangesOptions.UseJsonBatch, + (ar) => + { + var response = context.EndSaveChanges(ar); + }, + null); + } + } + + private string GetNormalizedJsonMessage(string jsonMessage) + { + const string myIdProperty = @"""id"":""my_id_guid"""; + const string myAtomicGroupProperty = @"""atomicityGroup"":""my_groupid_guid"""; + const string myDependsOnProperty = @"""dependsOn"":""[my_ids]"""; + const string myODataVersionProperty = @"""odata-version"":""myODataVer"""; + + string result = Regex.Replace(jsonMessage, @"\s*", "", RegexOptions.Multiline); + result = Regex.Replace(result, "\"id\":\"[^\"]*\"", myIdProperty, RegexOptions.Multiline); + result = Regex.Replace(result, "\"atomicityGroup\":\"[^\"]*\"", myAtomicGroupProperty, RegexOptions.Multiline); + result = Regex.Replace(result, "\"dependsOn\":\\[\"[^\\]]*\\]", myDependsOnProperty, RegexOptions.Multiline); + result = Regex.Replace(result, "\"odata-version\":\"[^\"]*\"", myODataVersionProperty, RegexOptions.Multiline); + return result; + } } [Key("Id")] @@ -168,4 +293,69 @@ public class TestPerson : BaseEntityType public int Id { get; set; } public string Name { get; set; } } + + [Key("Id")] + public class Bank : BaseEntityType + { + public int Id { get; set; } + + public string Name { get; set; } + + public List BankAccounts { get; set; } + } + + [Key("Id")] + public class BankAccount + { + public int Id { get; set; } + } + + class Container : DataServiceContext + { + public Container(Uri serviceRoot) : + base(serviceRoot, ODataProtocolVersion.V4) + { + Format.LoadServiceModel = () => CsdlReader.Parse(XmlReader.Create(new StringReader(@" + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + "))); + Format.UseJson(); + Banks = base.CreateQuery("Banks"); + BankAccounts = base.CreateQuery("BankAccounts"); + } + + public DataServiceQuery Banks { get; private set; } + public DataServiceQuery BankAccounts { get; private set; } + } } From af5facd6cc4baf86d3e0035da65fe25dd0e8a854 Mon Sep 17 00:00:00 2001 From: Derrick Butoyi Date: Thu, 24 Oct 2024 07:55:42 +0300 Subject: [PATCH 2/6] refactor jsonbatch sequencing tests --- .../Batch/AsyncMethodTests.cs | 132 ++++++++++++++++++ .../Batch/Server/BanksController.cs | 54 +++++++ .../Common/Server/Default/DefaultDataModel.cs | 18 +++ .../Common/Server/Default/DefaultEdmModel.cs | 2 + .../EndToEnd/CommonEndToEndDataModel.cs | 18 +++ .../EndToEnd/CommonEndToEndDataSource.cs | 43 ++++++ .../Server/EndToEnd/CommonEndToEndEdmModel.cs | 2 + 7 files changed, 269 insertions(+) create mode 100644 test/EndToEndTests/Tests/Client/Microsoft.OData.Client.E2E.Tests/Batch/AsyncMethodTests.cs create mode 100644 test/EndToEndTests/Tests/Client/Microsoft.OData.Client.E2E.Tests/Batch/Server/BanksController.cs diff --git a/test/EndToEndTests/Tests/Client/Microsoft.OData.Client.E2E.Tests/Batch/AsyncMethodTests.cs b/test/EndToEndTests/Tests/Client/Microsoft.OData.Client.E2E.Tests/Batch/AsyncMethodTests.cs new file mode 100644 index 0000000000..451b6dcd66 --- /dev/null +++ b/test/EndToEndTests/Tests/Client/Microsoft.OData.Client.E2E.Tests/Batch/AsyncMethodTests.cs @@ -0,0 +1,132 @@ +//----------------------------------------------------------------------------- +// +// Copyright (c) .NET Foundation and Contributors. All rights reserved. +// See License.txt in the project root for license information. +// +//------------------------------------------------------------------------------ + +using Microsoft.AspNetCore.OData; +using Microsoft.AspNetCore.OData.Batch; +using Microsoft.AspNetCore.OData.Routing.Controllers; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.OData.Client.E2E.TestCommon; +using Microsoft.OData.Client.E2E.Tests.Batch.Server; +using Microsoft.OData.Client.E2E.Tests.Common.Server.EndToEnd; +using Microsoft.OData.Edm.Csdl; +using System.Xml; +using Xunit; + +namespace Microsoft.OData.Client.E2E.Tests.Batch +{ + public class AsyncMethodTests : EndToEndTestBase + { + private readonly Uri _baseUri; + private readonly Container _context; + + public class TestsStartup : TestStartupBase + { + public override void ConfigureServices(IServiceCollection services) + { + services.ConfigureControllers(typeof(BanksController), typeof(MetadataController)); + services.AddControllers().AddOData(opt => opt.Count().Filter().Expand().Select().OrderBy().SetMaxTop(null) + .AddRouteComponents("odata", CommonEndToEndEdmModel.GetEdmModel(), new DefaultODataBatchHandler())); + } + } + + public AsyncMethodTests(TestWebApplicationFactory fixture) + : base(fixture) + { + _baseUri = new Uri(Client.BaseAddress, "odata/"); + _context = new Container(_baseUri) + { + HttpClientFactory = HttpClientFactory + }; + } + + [Fact] + public async Task JsonBatchSequencingSingeChangeSetTest() + { + // Create new BankAccounts object + var bank = new Bank + { + Id = 45, + Name = "Test Bank", + Location = "KE", + BankAccounts = new List() + }; + + // Create new BankAccount object + var bankAccount = new BankAccount + { + Id = 890, + AccountNumber = "4567890", + BankId = bank.Id, + Bank = bank + }; + + // Establish the relationship between BankAccounts and BankAccount + bank.BankAccounts.Add(bankAccount); + + // Add the BankAccounts entity to the context + _context.AddObject("Banks", bank); + + // Add the related BankAccount entity + _context.AddRelatedObject(bank, "BankAccounts", bankAccount); + + // Save both entities in a single batch request using JSON + var response = await _context.SaveChangesAsync(SaveChangesOptions.BatchWithSingleChangeset | SaveChangesOptions.UseJsonBatch); + Assert.Equal(201, (response.First() as ChangeOperationResponse).StatusCode); + Assert.Equal(201, (response.First() as ChangeOperationResponse).StatusCode); + } + } + + class Container : DataServiceContext + { + public Container(Uri serviceRoot) : + base(serviceRoot, ODataProtocolVersion.V4) + { + Format.LoadServiceModel = () => CsdlReader.Parse(XmlReader.Create(new StringReader(@" + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + "))); + Format.UseJson(); + Banks = base.CreateQuery("Banks"); + BankAccounts = base.CreateQuery("BankAccounts"); + } + + public DataServiceQuery Banks { get; private set; } + public DataServiceQuery BankAccounts { get; private set; } + } +} + diff --git a/test/EndToEndTests/Tests/Client/Microsoft.OData.Client.E2E.Tests/Batch/Server/BanksController.cs b/test/EndToEndTests/Tests/Client/Microsoft.OData.Client.E2E.Tests/Batch/Server/BanksController.cs new file mode 100644 index 0000000000..5f0b782975 --- /dev/null +++ b/test/EndToEndTests/Tests/Client/Microsoft.OData.Client.E2E.Tests/Batch/Server/BanksController.cs @@ -0,0 +1,54 @@ +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.OData.Formatter; +using Microsoft.AspNetCore.OData.Query; +using Microsoft.AspNetCore.OData.Routing.Controllers; +using Microsoft.OData.Client.E2E.Tests.Common.Server.EndToEnd; + +namespace Microsoft.OData.Client.E2E.Tests.Batch.Server +{ + public class BanksController : ODataController + { + private static CommonEndToEndDataSource _dataSource = CommonEndToEndDataSource.CreateInstance(); + + [EnableQuery] + [HttpGet("odata/Banks")] + public IActionResult Get() + { + var banks = _dataSource.Banks; + return Ok(banks); + } + + // POST: odata/Banks + [EnableQuery] + [HttpPost("odata/Banks")] + public IActionResult Post([FromBody] Bank bankd) + { + if (bankd == null) + { + return BadRequest(); + } + _dataSource.Banks.Add(bankd); + return Created(bankd); + } + + // POST: /odata/$1/BankAccounts + [HttpPost] + [Route("odata/Banks({id})/BankAccounts")] + public IActionResult PostBankAccount([FromODataUri] int id , [FromBody] BankAccount bankAccount) + { + if (bankAccount == null) + { + return BadRequest(); + } + + var bank = _dataSource.Banks.FirstOrDefault(b => b.Id == id); + if (bank == null) + { + return NotFound(); + } + + bankAccount.Bank = bank; + return Created(bankAccount); + } + } +} diff --git a/test/EndToEndTests/Tests/Client/Microsoft.OData.Client.E2E.Tests/Common/Server/Default/DefaultDataModel.cs b/test/EndToEndTests/Tests/Client/Microsoft.OData.Client.E2E.Tests/Common/Server/Default/DefaultDataModel.cs index edfb704b79..1004f9e5ba 100644 --- a/test/EndToEndTests/Tests/Client/Microsoft.OData.Client.E2E.Tests/Common/Server/Default/DefaultDataModel.cs +++ b/test/EndToEndTests/Tests/Client/Microsoft.OData.Client.E2E.Tests/Common/Server/Default/DefaultDataModel.cs @@ -340,4 +340,22 @@ public class AccountInfo public DateTimeOffset UpdatedTime { get; set; } public Dictionary? DynamicProperties { get; set; } = new Dictionary(); } + + [global::Microsoft.OData.Client.Key("Id")] + public class Bank + { + public int Id { get; set; } + public string Name { get; set; } + public string Location { get; set; } + public ICollection BankAccounts { get; set; } = new List(); + } + + [global::Microsoft.OData.Client.Key("Id")] + public class BankAccount + { + public int Id { get; set; } + public string AccountNumber { get; set; } + + public Bank Bank { get; set; } + } } diff --git a/test/EndToEndTests/Tests/Client/Microsoft.OData.Client.E2E.Tests/Common/Server/Default/DefaultEdmModel.cs b/test/EndToEndTests/Tests/Client/Microsoft.OData.Client.E2E.Tests/Common/Server/Default/DefaultEdmModel.cs index aea5cd3642..6e229949bf 100644 --- a/test/EndToEndTests/Tests/Client/Microsoft.OData.Client.E2E.Tests/Common/Server/Default/DefaultEdmModel.cs +++ b/test/EndToEndTests/Tests/Client/Microsoft.OData.Client.E2E.Tests/Common/Server/Default/DefaultEdmModel.cs @@ -37,6 +37,8 @@ public static IEdmModel GetEdmModel() builder.EntitySet("StoredPIs"); builder.EntitySet("SubscriptionTemplates"); builder.Singleton("DefaultStoredPI"); + builder.EntitySet("Banks"); + builder.EntitySet("BankAccounts"); builder.EntityType() .Action("AddAccessRight") diff --git a/test/EndToEndTests/Tests/Client/Microsoft.OData.Client.E2E.Tests/Common/Server/EndToEnd/CommonEndToEndDataModel.cs b/test/EndToEndTests/Tests/Client/Microsoft.OData.Client.E2E.Tests/Common/Server/EndToEnd/CommonEndToEndDataModel.cs index f75e78dcb3..3b6a6c66e1 100644 --- a/test/EndToEndTests/Tests/Client/Microsoft.OData.Client.E2E.Tests/Common/Server/EndToEnd/CommonEndToEndDataModel.cs +++ b/test/EndToEndTests/Tests/Client/Microsoft.OData.Client.E2E.Tests/Common/Server/EndToEnd/CommonEndToEndDataModel.cs @@ -396,4 +396,22 @@ public class ComplexWithAllPrimitiveTypes public GeographyPoint? GeographyPoint { get; set; } public GeometryPoint? GeometryPoint { get; set; } } + + [Key("Id")] + public class Bank + { + public int Id { get; set; } + public string Name { get; set; } + public string Location { get; set; } + public ICollection BankAccounts { get; set; } + } + + [Key("Id")] + public class BankAccount + { + public int Id { get; set; } + public string AccountNumber { get; set; } + public int BankId { get; set; } + public Bank Bank { get; set; } + } } diff --git a/test/EndToEndTests/Tests/Client/Microsoft.OData.Client.E2E.Tests/Common/Server/EndToEnd/CommonEndToEndDataSource.cs b/test/EndToEndTests/Tests/Client/Microsoft.OData.Client.E2E.Tests/Common/Server/EndToEnd/CommonEndToEndDataSource.cs index 3e741bc64e..2a69e04706 100644 --- a/test/EndToEndTests/Tests/Client/Microsoft.OData.Client.E2E.Tests/Common/Server/EndToEnd/CommonEndToEndDataSource.cs +++ b/test/EndToEndTests/Tests/Client/Microsoft.OData.Client.E2E.Tests/Common/Server/EndToEnd/CommonEndToEndDataSource.cs @@ -70,6 +70,7 @@ private void InitializeData() PopulatePerson_PersonMetadata(); PopulateEmployee_Manager(); PopulateSpecialEmployee_Car(); + PopulateBank(); } private void ResetData() @@ -124,6 +125,31 @@ private void ResetData() public IList? Drivers { get; private set; } public IList? Licenses { get; private set; } public IList? PersonMetadata { get; private set; } + public IList? Banks { get; private set; } + public IList? BankAccounts { get; private set; } + + private void PopulateBank() + { + this.Banks = + [ + new (){ + Id = 300, + Name = "ICM", + Location = "KE", + BankAccounts = new List() + } + ]; + + } + + private void PopulateBankAccount() + { + this.AddBankAccountToBank(300, new BankAccount() + { + AccountNumber = "2002", + BankId = 300 + }); + } private void PopulateAllTypesSet() { @@ -8413,6 +8439,23 @@ private void AddLoginOrderReference(string username, params int[] orderIds) } } + private void AddBankAccountToBank(int bankId, params BankAccount[] bankAccounts) + { + var bank = this.Banks.FirstOrDefault(b => b.Id == bankId); + + if (bank != null) + { + foreach (var bankAccount in bankAccounts) + { + if (bankAccount != null) + { + bankAccount.Bank = bank; + bank.BankAccounts.Add(bankAccount); + } + } + } + } + private void AddMessageAttachmentReference(int messageId, params Guid[] attachmentIds) { var message = this.Messages.FirstOrDefault(m => m.MessageId == messageId); diff --git a/test/EndToEndTests/Tests/Client/Microsoft.OData.Client.E2E.Tests/Common/Server/EndToEnd/CommonEndToEndEdmModel.cs b/test/EndToEndTests/Tests/Client/Microsoft.OData.Client.E2E.Tests/Common/Server/EndToEnd/CommonEndToEndEdmModel.cs index 659dfb9b37..f17b813c59 100644 --- a/test/EndToEndTests/Tests/Client/Microsoft.OData.Client.E2E.Tests/Common/Server/EndToEnd/CommonEndToEndEdmModel.cs +++ b/test/EndToEndTests/Tests/Client/Microsoft.OData.Client.E2E.Tests/Common/Server/EndToEnd/CommonEndToEndEdmModel.cs @@ -39,6 +39,8 @@ public static IEdmModel GetEdmModel() builder.EntitySet("Licenses"); builder.EntitySet("MappedEntityTypes"); builder.EntitySet("Cars"); + builder.EntitySet("Banks"); + builder.EntitySet("BankAccounts"); builder.Action("RetrieveProduct") .Returns(); From 95f79b353c36f7246ccce47e9eaf84df61695e34 Mon Sep 17 00:00:00 2001 From: Derrick Butoyi Date: Thu, 24 Oct 2024 08:05:46 +0300 Subject: [PATCH 3/6] restore DataServiceContextHttpClientHandlerProviderTests tests --- ...ceContextHttpClientHandlerProviderTests.cs | 216 ++---------------- 1 file changed, 13 insertions(+), 203 deletions(-) diff --git a/test/FunctionalTests/Microsoft.OData.Client.Tests/DataServiceContextHttpClientHandlerProviderTests.cs b/test/FunctionalTests/Microsoft.OData.Client.Tests/DataServiceContextHttpClientHandlerProviderTests.cs index ce0196d3f6..15b43f18e3 100644 --- a/test/FunctionalTests/Microsoft.OData.Client.Tests/DataServiceContextHttpClientHandlerProviderTests.cs +++ b/test/FunctionalTests/Microsoft.OData.Client.Tests/DataServiceContextHttpClientHandlerProviderTests.cs @@ -4,9 +4,7 @@ // //--------------------------------------------------------------------- -using Microsoft.Extensions.Logging.Abstractions; using Microsoft.OData.Client.Tests.Serialization; -using Microsoft.OData.Edm.Csdl; using Microsoft.WindowsAzure.ActiveDirectory; using System; using System.Collections.Generic; @@ -15,9 +13,7 @@ using System.Net; using System.Net.Http; using System.Text; -using System.Text.RegularExpressions; using System.Threading.Tasks; -using System.Xml; using Xunit; namespace Microsoft.OData.Client.Tests @@ -26,61 +22,19 @@ public class DataServiceContextHttpClientHandlerProviderTests { private const string BaseUri = "http://service.org"; private const string Edmx = @" - - - - - - - - - - - - - "; - - private const string ExpectedRequestPayloadUsingJson1 = @"{ - ""requests"": [ - { - ""id"": ""1"", - ""atomicityGroup"": ""93dd314c-48e2-442c-a016-d17be61cc7f0"", - ""method"": ""POST"", - ""url"": ""http://service.org/Banks"", - ""headers"": { - ""odata-version"": ""4.0"", - ""odata-maxversion"": ""4.0"", - ""content-type"": ""application/json;odata.metadata=minimal"", - ""accept"": ""application/json;odata.metadata=minimal"", - ""accept-charset"": ""UTF-8"", - ""user-agent"": ""Microsoft.OData.Client/8.0.1"" - }, - ""body"": { - ""Id"": 45, - ""Name"": ""Test Bank"" - } - }, - { - ""id"": ""2"", - ""atomicityGroup"": ""93dd314c-48e2-442c-a016-d17be61cc7f0"", - ""dependsOn"": [""1""], - ""method"": ""POST"", - ""url"": ""http://service.org/$1/BankAccounts"", - ""headers"": { - ""odata-version"": ""4.0"", - ""odata-maxversion"": ""4.0"", - ""content-type"": ""application/json;odata.metadata=minimal"", - ""accept"": ""application/json;odata.metadata=minimal"", - ""accept-charset"": ""UTF-8"", - ""user-agent"": ""Microsoft.OData.Client/8.0.1"" - }, - ""body"": { - ""Id"": 890 - } - } - ] - } - "; + + + + + + + + + + + + +"; private const string PersonNameValue = "John Doe"; @@ -206,85 +160,6 @@ private HttpResponseMessage HandleRequest(HttpRequestMessage request) return response; } - - - - [Fact] - public void TestDependsOnIDJsonBatchSingleChangeSetSupportAddObjectAPITest() - { - using (var handler = new MockHttpClientHandler((httpRequest) => - { - var contents = httpRequest.Content.ReadAsStringAsync().Result; - var stringContent = new StringContent(contents, Encoding.UTF8, "application/json"); - - Assert.Contains("\"dependsOn\":[\"1\"]", contents); - - var normalizedRequestPayload = GetNormalizedJsonMessage(contents); - var normalizedExpectedPayload = GetNormalizedJsonMessage(ExpectedRequestPayloadUsingJson1); - - Assert.Equal(normalizedExpectedPayload, normalizedRequestPayload); - - var response = new HttpResponseMessage(HttpStatusCode.OK); - - response.Content.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("application/json"); - response.Content.Headers.ContentType.Parameters.Add(new System.Net.Http.Headers.NameValueHeaderValue("odata.metadata", "minimal")); - response.Headers.Add("OData-Version", "4.0"); - response.Headers.Add("OData-MaxVersion", "4.0"); - return response; - } )) - { - var provider = new MockHttpClientFactory(handler); - - var context = new Container(new Uri(BaseUri)); - context.HttpClientFactory = provider; - - // Create new Bank object - var bank = new Bank - { - Id = 45, - Name = "Test Bank", - BankAccounts = new List() - }; - - // Create new BankAccount object - var bankAccount = new BankAccount - { - Id = 890 - }; - - // Establish the relationship between Bank and BankAccount - bank.BankAccounts.Add(bankAccount); - - // Add the Bank entity to the context - context.AddObject("Banks", bank); - - // Add the related BankAccount entity - context.AddRelatedObject(bank, "BankAccounts", bankAccount); - - context.BeginSaveChanges( - SaveChangesOptions.BatchWithSingleChangeset | SaveChangesOptions.UseJsonBatch, - (ar) => - { - var response = context.EndSaveChanges(ar); - }, - null); - } - } - - private string GetNormalizedJsonMessage(string jsonMessage) - { - const string myIdProperty = @"""id"":""my_id_guid"""; - const string myAtomicGroupProperty = @"""atomicityGroup"":""my_groupid_guid"""; - const string myDependsOnProperty = @"""dependsOn"":""[my_ids]"""; - const string myODataVersionProperty = @"""odata-version"":""myODataVer"""; - - string result = Regex.Replace(jsonMessage, @"\s*", "", RegexOptions.Multiline); - result = Regex.Replace(result, "\"id\":\"[^\"]*\"", myIdProperty, RegexOptions.Multiline); - result = Regex.Replace(result, "\"atomicityGroup\":\"[^\"]*\"", myAtomicGroupProperty, RegexOptions.Multiline); - result = Regex.Replace(result, "\"dependsOn\":\\[\"[^\\]]*\\]", myDependsOnProperty, RegexOptions.Multiline); - result = Regex.Replace(result, "\"odata-version\":\"[^\"]*\"", myODataVersionProperty, RegexOptions.Multiline); - return result; - } } [Key("Id")] @@ -293,69 +168,4 @@ public class TestPerson : BaseEntityType public int Id { get; set; } public string Name { get; set; } } - - [Key("Id")] - public class Bank : BaseEntityType - { - public int Id { get; set; } - - public string Name { get; set; } - - public List BankAccounts { get; set; } - } - - [Key("Id")] - public class BankAccount - { - public int Id { get; set; } - } - - class Container : DataServiceContext - { - public Container(Uri serviceRoot) : - base(serviceRoot, ODataProtocolVersion.V4) - { - Format.LoadServiceModel = () => CsdlReader.Parse(XmlReader.Create(new StringReader(@" - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - "))); - Format.UseJson(); - Banks = base.CreateQuery("Banks"); - BankAccounts = base.CreateQuery("BankAccounts"); - } - - public DataServiceQuery Banks { get; private set; } - public DataServiceQuery BankAccounts { get; private set; } - } } From c4b94487f9e447a9705f84ed0469e8f0944edbde Mon Sep 17 00:00:00 2001 From: Derrick Butoyi Date: Thu, 24 Oct 2024 11:50:05 +0300 Subject: [PATCH 4/6] fix test assertion --- .../Microsoft.OData.Client.E2E.Tests/Batch/AsyncMethodTests.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/EndToEndTests/Tests/Client/Microsoft.OData.Client.E2E.Tests/Batch/AsyncMethodTests.cs b/test/EndToEndTests/Tests/Client/Microsoft.OData.Client.E2E.Tests/Batch/AsyncMethodTests.cs index 451b6dcd66..ac7585284a 100644 --- a/test/EndToEndTests/Tests/Client/Microsoft.OData.Client.E2E.Tests/Batch/AsyncMethodTests.cs +++ b/test/EndToEndTests/Tests/Client/Microsoft.OData.Client.E2E.Tests/Batch/AsyncMethodTests.cs @@ -76,7 +76,7 @@ public async Task JsonBatchSequencingSingeChangeSetTest() // Save both entities in a single batch request using JSON var response = await _context.SaveChangesAsync(SaveChangesOptions.BatchWithSingleChangeset | SaveChangesOptions.UseJsonBatch); Assert.Equal(201, (response.First() as ChangeOperationResponse).StatusCode); - Assert.Equal(201, (response.First() as ChangeOperationResponse).StatusCode); + Assert.Equal(201, (response.Last() as ChangeOperationResponse).StatusCode); } } From 2161e87445417f5e885123428fb87bc232d449bd Mon Sep 17 00:00:00 2001 From: Derrick Butoyi Date: Mon, 11 Nov 2024 16:29:29 +0300 Subject: [PATCH 5/6] Address PR feedback --- .../Batch/AsyncMethodTests.cs | 12 ++++++++++-- .../Batch/Server/BanksController.cs | 8 ++++---- .../Common/Server/Default/DefaultDataModel.cs | 18 ------------------ .../Common/Server/Default/DefaultEdmModel.cs | 1 + 4 files changed, 15 insertions(+), 24 deletions(-) diff --git a/test/EndToEndTests/Tests/Client/Microsoft.OData.Client.E2E.Tests/Batch/AsyncMethodTests.cs b/test/EndToEndTests/Tests/Client/Microsoft.OData.Client.E2E.Tests/Batch/AsyncMethodTests.cs index ac7585284a..44fc20b433 100644 --- a/test/EndToEndTests/Tests/Client/Microsoft.OData.Client.E2E.Tests/Batch/AsyncMethodTests.cs +++ b/test/EndToEndTests/Tests/Client/Microsoft.OData.Client.E2E.Tests/Batch/AsyncMethodTests.cs @@ -75,8 +75,16 @@ public async Task JsonBatchSequencingSingeChangeSetTest() // Save both entities in a single batch request using JSON var response = await _context.SaveChangesAsync(SaveChangesOptions.BatchWithSingleChangeset | SaveChangesOptions.UseJsonBatch); - Assert.Equal(201, (response.First() as ChangeOperationResponse).StatusCode); - Assert.Equal(201, (response.Last() as ChangeOperationResponse).StatusCode); + Assert.Equal(2, response.Count()); + + var firstBankResponse = response.First() as ChangeOperationResponse; + var secondBankAccountResponse = response.Last() as ChangeOperationResponse; + + Assert.NotNull(firstBankResponse); + Assert.NotNull(secondBankAccountResponse); + + Assert.Equal(201, firstBankResponse.StatusCode); + Assert.Equal(201, secondBankAccountResponse.StatusCode); } } diff --git a/test/EndToEndTests/Tests/Client/Microsoft.OData.Client.E2E.Tests/Batch/Server/BanksController.cs b/test/EndToEndTests/Tests/Client/Microsoft.OData.Client.E2E.Tests/Batch/Server/BanksController.cs index 5f0b782975..62ef0350e2 100644 --- a/test/EndToEndTests/Tests/Client/Microsoft.OData.Client.E2E.Tests/Batch/Server/BanksController.cs +++ b/test/EndToEndTests/Tests/Client/Microsoft.OData.Client.E2E.Tests/Batch/Server/BanksController.cs @@ -21,14 +21,14 @@ public IActionResult Get() // POST: odata/Banks [EnableQuery] [HttpPost("odata/Banks")] - public IActionResult Post([FromBody] Bank bankd) + public IActionResult Post([FromBody] Bank bank) { - if (bankd == null) + if (bank == null) { return BadRequest(); } - _dataSource.Banks.Add(bankd); - return Created(bankd); + _dataSource.Banks.Add(bank); + return Created(bank); } // POST: /odata/$1/BankAccounts diff --git a/test/EndToEndTests/Tests/Client/Microsoft.OData.Client.E2E.Tests/Common/Server/Default/DefaultDataModel.cs b/test/EndToEndTests/Tests/Client/Microsoft.OData.Client.E2E.Tests/Common/Server/Default/DefaultDataModel.cs index 1004f9e5ba..edfb704b79 100644 --- a/test/EndToEndTests/Tests/Client/Microsoft.OData.Client.E2E.Tests/Common/Server/Default/DefaultDataModel.cs +++ b/test/EndToEndTests/Tests/Client/Microsoft.OData.Client.E2E.Tests/Common/Server/Default/DefaultDataModel.cs @@ -340,22 +340,4 @@ public class AccountInfo public DateTimeOffset UpdatedTime { get; set; } public Dictionary? DynamicProperties { get; set; } = new Dictionary(); } - - [global::Microsoft.OData.Client.Key("Id")] - public class Bank - { - public int Id { get; set; } - public string Name { get; set; } - public string Location { get; set; } - public ICollection BankAccounts { get; set; } = new List(); - } - - [global::Microsoft.OData.Client.Key("Id")] - public class BankAccount - { - public int Id { get; set; } - public string AccountNumber { get; set; } - - public Bank Bank { get; set; } - } } diff --git a/test/EndToEndTests/Tests/Client/Microsoft.OData.Client.E2E.Tests/Common/Server/Default/DefaultEdmModel.cs b/test/EndToEndTests/Tests/Client/Microsoft.OData.Client.E2E.Tests/Common/Server/Default/DefaultEdmModel.cs index 6e229949bf..87a6e805f2 100644 --- a/test/EndToEndTests/Tests/Client/Microsoft.OData.Client.E2E.Tests/Common/Server/Default/DefaultEdmModel.cs +++ b/test/EndToEndTests/Tests/Client/Microsoft.OData.Client.E2E.Tests/Common/Server/Default/DefaultEdmModel.cs @@ -5,6 +5,7 @@ // //------------------------------------------------------------------------------ +using Microsoft.OData.Client.E2E.Tests.Common.Server.EndToEnd; using Microsoft.OData.Edm; using Microsoft.OData.ModelBuilder; From 8e53661e8845acb7c54fbb20899e2290aa7a47c9 Mon Sep 17 00:00:00 2001 From: Derrick Butoyi Date: Mon, 11 Nov 2024 16:32:06 +0300 Subject: [PATCH 6/6] Address PR feedback --- .../Batch/AsyncMethodTests.cs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/test/EndToEndTests/Tests/Client/Microsoft.OData.Client.E2E.Tests/Batch/AsyncMethodTests.cs b/test/EndToEndTests/Tests/Client/Microsoft.OData.Client.E2E.Tests/Batch/AsyncMethodTests.cs index 44fc20b433..ba986869af 100644 --- a/test/EndToEndTests/Tests/Client/Microsoft.OData.Client.E2E.Tests/Batch/AsyncMethodTests.cs +++ b/test/EndToEndTests/Tests/Client/Microsoft.OData.Client.E2E.Tests/Batch/AsyncMethodTests.cs @@ -77,14 +77,14 @@ public async Task JsonBatchSequencingSingeChangeSetTest() var response = await _context.SaveChangesAsync(SaveChangesOptions.BatchWithSingleChangeset | SaveChangesOptions.UseJsonBatch); Assert.Equal(2, response.Count()); - var firstBankResponse = response.First() as ChangeOperationResponse; - var secondBankAccountResponse = response.Last() as ChangeOperationResponse; + var bankResponse = response.First() as ChangeOperationResponse; + var bankAccountResponse = response.Last() as ChangeOperationResponse; - Assert.NotNull(firstBankResponse); - Assert.NotNull(secondBankAccountResponse); + Assert.NotNull(bankResponse); + Assert.NotNull(bankAccountResponse); - Assert.Equal(201, firstBankResponse.StatusCode); - Assert.Equal(201, secondBankAccountResponse.StatusCode); + Assert.Equal(201, bankResponse.StatusCode); + Assert.Equal(201, bankAccountResponse.StatusCode); } }