diff --git a/src/Microsoft.OData.Core/JsonLight/ODataJsonLightResourceDeserializer.cs b/src/Microsoft.OData.Core/JsonLight/ODataJsonLightResourceDeserializer.cs index 3a1d6e9a8e..7163febbcf 100644 --- a/src/Microsoft.OData.Core/JsonLight/ODataJsonLightResourceDeserializer.cs +++ b/src/Microsoft.OData.Core/JsonLight/ODataJsonLightResourceDeserializer.cs @@ -861,6 +861,7 @@ internal void ApplyEntryInstanceAnnotation(IODataJsonLightReaderResourceState re else { resource.Id = (Uri)annotationValue; + resource.HasExplicitODataId = true; } break; diff --git a/src/Microsoft.OData.Core/ODataResource.cs b/src/Microsoft.OData.Core/ODataResource.cs index 57033b60ed..689c5f1d06 100644 --- a/src/Microsoft.OData.Core/ODataResource.cs +++ b/src/Microsoft.OData.Core/ODataResource.cs @@ -213,6 +213,14 @@ public ICollection InstanceAnnotations set { this.SetInstanceAnnotations(value); } } + /// Gets or sets the value that shows if the resource has @odata.id or @id. + /// true if the resource has @odata.id or @id, false otherwise. + public bool HasExplicitODataId + { + get; + internal set; + } + /// /// The metadata builder for this OData resource. /// diff --git a/src/Microsoft.OData.Core/PublicAPI/net45/PublicAPI.Unshipped.txt b/src/Microsoft.OData.Core/PublicAPI/net45/PublicAPI.Unshipped.txt index e69de29bb2..1cecf89ab3 100644 --- a/src/Microsoft.OData.Core/PublicAPI/net45/PublicAPI.Unshipped.txt +++ b/src/Microsoft.OData.Core/PublicAPI/net45/PublicAPI.Unshipped.txt @@ -0,0 +1 @@ +Microsoft.OData.ODataResourceBase.HasExplicitODataId.get -> bool \ No newline at end of file diff --git a/src/Microsoft.OData.Core/PublicAPI/netcoreapp3.1/PublicAPI.Unshipped.txt b/src/Microsoft.OData.Core/PublicAPI/netcoreapp3.1/PublicAPI.Unshipped.txt index e69de29bb2..1cecf89ab3 100644 --- a/src/Microsoft.OData.Core/PublicAPI/netcoreapp3.1/PublicAPI.Unshipped.txt +++ b/src/Microsoft.OData.Core/PublicAPI/netcoreapp3.1/PublicAPI.Unshipped.txt @@ -0,0 +1 @@ +Microsoft.OData.ODataResourceBase.HasExplicitODataId.get -> bool \ No newline at end of file diff --git a/src/Microsoft.OData.Core/PublicAPI/netstandard1.1/PublicAPI.Unshipped.txt b/src/Microsoft.OData.Core/PublicAPI/netstandard1.1/PublicAPI.Unshipped.txt index e69de29bb2..1cecf89ab3 100644 --- a/src/Microsoft.OData.Core/PublicAPI/netstandard1.1/PublicAPI.Unshipped.txt +++ b/src/Microsoft.OData.Core/PublicAPI/netstandard1.1/PublicAPI.Unshipped.txt @@ -0,0 +1 @@ +Microsoft.OData.ODataResourceBase.HasExplicitODataId.get -> bool \ No newline at end of file diff --git a/src/Microsoft.OData.Core/PublicAPI/netstandard2.0/PublicAPI.Unshipped.txt b/src/Microsoft.OData.Core/PublicAPI/netstandard2.0/PublicAPI.Unshipped.txt index e69de29bb2..1cecf89ab3 100644 --- a/src/Microsoft.OData.Core/PublicAPI/netstandard2.0/PublicAPI.Unshipped.txt +++ b/src/Microsoft.OData.Core/PublicAPI/netstandard2.0/PublicAPI.Unshipped.txt @@ -0,0 +1 @@ +Microsoft.OData.ODataResourceBase.HasExplicitODataId.get -> bool \ No newline at end of file diff --git a/test/FunctionalTests/Microsoft.OData.Core.Tests/JsonLight/ODataJsonLightResourceDeserializerTests.cs b/test/FunctionalTests/Microsoft.OData.Core.Tests/JsonLight/ODataJsonLightResourceDeserializerTests.cs index 2fd6456bd4..2ba3472f28 100644 --- a/test/FunctionalTests/Microsoft.OData.Core.Tests/JsonLight/ODataJsonLightResourceDeserializerTests.cs +++ b/test/FunctionalTests/Microsoft.OData.Core.Tests/JsonLight/ODataJsonLightResourceDeserializerTests.cs @@ -205,6 +205,44 @@ await SetupJsonLightResourceSerializerAndRunReadResourceContextTestAsync( }); } + [Fact] + public async Task ReadResourceContentWithODataId() + { + var payload = "{\"@odata.context\":\"http://tempuri.org/$metadata#Categories/$entity\"," + + "\"@odata.id\":\"http://tempuri.org/Categories(1)\"," + + "\"Name\":\"Food\"}"; + + await SetupJsonLightResourceSerializerAndRunReadResourceContextTestAsync( + payload, + this.categoriesEntitySet, + this.categoryEntityType, + (resourceState) => + { + var resource = resourceState.Resource; + Assert.Equal(new Uri("http://tempuri.org/Categories(1)"), resource.Id); + Assert.True(resource.HasExplicitODataId); + }); + } + + [Fact] + public async Task ReadResourceContentWithIdProperty() + { + var payload = "{\"@odata.context\":\"http://tempuri.org/$metadata#Categories/$entity\"," + + "\"Id\":1," + + "\"Name\":\"Food\"}"; + + await SetupJsonLightResourceSerializerAndRunReadResourceContextTestAsync( + payload, + this.categoriesEntitySet, + this.categoryEntityType, + (resourceState) => + { + var resource = resourceState.Resource; + Assert.Null(resource.Id); // Null since Id is computed at ODataReaderState.ResourceEnd + Assert.False(resource.HasExplicitODataId); + }); + } + [Fact] public async Task ReadResourceContentWithODataAnnotationsAsync() { diff --git a/test/FunctionalTests/Microsoft.OData.Core.Tests/ScenarioTests/Reader/JsonLight/ODataJsonLightSingletonReaderTests.cs b/test/FunctionalTests/Microsoft.OData.Core.Tests/ScenarioTests/Reader/JsonLight/ODataJsonLightSingletonReaderTests.cs index fa3df531c1..698c5aedcc 100644 --- a/test/FunctionalTests/Microsoft.OData.Core.Tests/ScenarioTests/Reader/JsonLight/ODataJsonLightSingletonReaderTests.cs +++ b/test/FunctionalTests/Microsoft.OData.Core.Tests/ScenarioTests/Reader/JsonLight/ODataJsonLightSingletonReaderTests.cs @@ -70,10 +70,11 @@ public void ReadBasicSingletonTest() Assert.Equal(2, entry.Properties.Count()); Assert.Equal(10, entry.Properties.Single(p => p.Name == "WebId").Value); Assert.Equal("SingletonWeb", entry.Properties.Single(p => p.Name == "Name").Value); + Assert.False(entry.HasExplicitODataId); } [Fact] - public void ReadSingletonWithIdSpecifiedTest() + public void ReadSingletonWithODataIdSpecifiedTest() { const string payload = "{" + "\"@odata.context\":\"http://odata.org/test/$metadata#MySingleton\"," + @@ -86,6 +87,7 @@ public void ReadSingletonWithIdSpecifiedTest() Assert.Equal(new Uri("http://odata.org/test/Bla"), entry.Id); Assert.Equal(new Uri("http://odata.org/test/BlaBla"), entry.EditLink); Assert.Equal(new Uri("http://odata.org/test/BlaBlaBla"), entry.ReadLink); + Assert.True(entry.HasExplicitODataId); } [Fact] diff --git a/test/PublicApiTests/BaseLine/Microsoft.OData.PublicApi.net45.bsl b/test/PublicApiTests/BaseLine/Microsoft.OData.PublicApi.net45.bsl index f07121f141..be0e51f36b 100644 --- a/test/PublicApiTests/BaseLine/Microsoft.OData.PublicApi.net45.bsl +++ b/test/PublicApiTests/BaseLine/Microsoft.OData.PublicApi.net45.bsl @@ -4810,6 +4810,7 @@ public abstract class Microsoft.OData.ODataResourceBase : Microsoft.OData.ODataI System.Uri EditLink { public get; public set; } string ETag { public get; public set; } System.Collections.Generic.IEnumerable`1[[Microsoft.OData.ODataFunction]] Functions { public get; } + bool HasExplicitODataId { public get; } System.Uri Id { public get; public set; } System.Collections.Generic.ICollection`1[[Microsoft.OData.ODataInstanceAnnotation]] InstanceAnnotations { public get; public set; } bool IsTransient { public get; public set; } diff --git a/test/PublicApiTests/BaseLine/Microsoft.OData.PublicApi.netstandard1.1.bsl b/test/PublicApiTests/BaseLine/Microsoft.OData.PublicApi.netstandard1.1.bsl index c30f3b01e8..a2efcdda82 100644 --- a/test/PublicApiTests/BaseLine/Microsoft.OData.PublicApi.netstandard1.1.bsl +++ b/test/PublicApiTests/BaseLine/Microsoft.OData.PublicApi.netstandard1.1.bsl @@ -4810,6 +4810,7 @@ public abstract class Microsoft.OData.ODataResourceBase : Microsoft.OData.ODataI System.Uri EditLink { public get; public set; } string ETag { public get; public set; } System.Collections.Generic.IEnumerable`1[[Microsoft.OData.ODataFunction]] Functions { public get; } + bool HasExplicitODataId { public get; } System.Uri Id { public get; public set; } System.Collections.Generic.ICollection`1[[Microsoft.OData.ODataInstanceAnnotation]] InstanceAnnotations { public get; public set; } bool IsTransient { public get; public set; } diff --git a/test/PublicApiTests/BaseLine/Microsoft.OData.PublicApi.netstandard2.0.bsl b/test/PublicApiTests/BaseLine/Microsoft.OData.PublicApi.netstandard2.0.bsl index f07121f141..be0e51f36b 100644 --- a/test/PublicApiTests/BaseLine/Microsoft.OData.PublicApi.netstandard2.0.bsl +++ b/test/PublicApiTests/BaseLine/Microsoft.OData.PublicApi.netstandard2.0.bsl @@ -4810,6 +4810,7 @@ public abstract class Microsoft.OData.ODataResourceBase : Microsoft.OData.ODataI System.Uri EditLink { public get; public set; } string ETag { public get; public set; } System.Collections.Generic.IEnumerable`1[[Microsoft.OData.ODataFunction]] Functions { public get; } + bool HasExplicitODataId { public get; } System.Uri Id { public get; public set; } System.Collections.Generic.ICollection`1[[Microsoft.OData.ODataInstanceAnnotation]] InstanceAnnotations { public get; public set; } bool IsTransient { public get; public set; }