Skip to content

Commit

Permalink
Fix the issue when read nested resource untyped in the request (#2179)
Browse files Browse the repository at this point in the history
* Fix the issue when read nested resource untyped in the request

* Resolve the comments
  • Loading branch information
xuzhg authored Sep 14, 2021
1 parent 7a68828 commit 0c446be
Show file tree
Hide file tree
Showing 6 changed files with 100 additions and 9 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -425,15 +425,12 @@ protected ODataJsonLightReaderNestedResourceInfo InnerReadUndeclaredProperty(IOD
ValidateExpandedNestedResourceInfoPropertyValue(this.JsonReader, isCollection, propertyName, payloadTypeReference);
if (isCollection)
{
readerNestedResourceInfo = this.ReadingResponse
? ReadExpandedResourceSetNestedResourceInfo(resourceState, null, payloadTypeReference.ToStructuredType(), propertyName, /*isDeltaResourceSet*/ false)
: ReadEntityReferenceLinksForCollectionNavigationLinkInRequest(resourceState, null, propertyName, /*isExpanded*/ true);
readerNestedResourceInfo =
ReadExpandedResourceSetNestedResourceInfo(resourceState, null, payloadTypeReference.ToStructuredType(), propertyName, /*isDeltaResourceSet*/ false);
}
else
{
readerNestedResourceInfo = this.ReadingResponse
? ReadExpandedResourceNestedResourceInfo(resourceState, null, propertyName, payloadTypeReference.ToStructuredType(), this.MessageReaderSettings)
: ReadEntityReferenceLinkForSingletonNavigationLinkInRequest(resourceState, null, propertyName, /*isExpanded*/ true);
readerNestedResourceInfo = ReadExpandedResourceNestedResourceInfo(resourceState, null, propertyName, payloadTypeReference.ToStructuredType(), this.MessageReaderSettings);
}

resourceState.PropertyAndAnnotationCollector.ValidatePropertyUniquenessOnNestedResourceInfoStart(readerNestedResourceInfo.NestedResourceInfo);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,12 +80,15 @@ public ODataJsonLightEntryAndFeedDeserializerUndeclaredTests()
}
// ----------- end of edm for entry reader -----------

private void ReadEntryPayload(string payload, EdmEntitySet entitySet, EdmEntityType entityType, Action<ODataReader> action, bool readUntypedAsValue = false)
private void ReadEntryPayload(string payload, EdmEntitySet entitySet, EdmEntityType entityType, Action<ODataReader> action, bool readUntypedAsValue = false, bool readRequest = false)
{
ODataMessageReaderSettings readerSettings = readUntypedAsValue ? UntypedAsValueReaderSettings : UntypedAsStringReaderSettings;
var message = new InMemoryMessage() { Stream = new MemoryStream(Encoding.UTF8.GetBytes(payload)) };
message.SetHeader("Content-Type", "application/json");
using (var msgReader = new ODataMessageReader((IODataResponseMessage)message, readerSettings, this.serverModel))

using (var msgReader = readRequest ?
new ODataMessageReader((IODataRequestMessage)message, readerSettings, this.serverModel) :
new ODataMessageReader((IODataResponseMessage)message, readerSettings, this.serverModel))
{
var reader = msgReader.CreateODataResourceReader(entitySet, entityType);
while (reader.Read())
Expand Down Expand Up @@ -624,6 +627,37 @@ public void ReadNonOpenUnknownTypeInvalidComplexAsValueTest()
Assert.Equal("No.10000000999,Zixing Rd Minhang", undeclaredAddress1.Properties.First(s => string.Equals("UndeclaredStreet", s.Name, StringComparison.Ordinal)).Value);
}

[Fact]
public void ReadNonOpenWithoutTypeComplexAsValueTest_InRequest()
{
// non-open entity's unknown property type including string & numeric values
const string payload = @"{""@odata.context"":""http://www.sampletest.com/$metadata#serverEntitySet/$entity"",""Id"":61880128,""UndeclaredAddress1"":"
+ @"{'Street':""No.999,Zixing Rd Minhang"",""UndeclaredStreet"":'No.10000000999,Zixing Rd Minhang'}}";
ODataResource entry = null;
ODataResource undeclaredAddress1 = null;
this.ReadEntryPayload(payload, this.serverEntitySet, this.serverEntityType, reader =>
{
if (reader.State == ODataReaderState.ResourceStart)
{
if (entry == null)
{
entry = (reader.Item as ODataResource);
}
else if (undeclaredAddress1 == null)
{
undeclaredAddress1 = (reader.Item as ODataResource);
}
}
},
/*readUntypedAsValue*/ true,
/*readRequest*/ true);

Assert.Single(entry.Properties);
Assert.Equal("Edm.Untyped", undeclaredAddress1.TypeName);
Assert.Equal(2, undeclaredAddress1.Properties.Count());
Assert.Equal("No.10000000999,Zixing Rd Minhang", undeclaredAddress1.Properties.First(s => string.Equals("UndeclaredStreet", s.Name, StringComparison.Ordinal)).Value);
}

[Fact]
public void ReadNonOpenUnknownTypeInvalidComplexNestedAsValueTest()
{
Expand Down Expand Up @@ -768,6 +802,63 @@ public void ReadNonOpenUnknownComplexTypeCollectionWithInvalidTypeAsValueTest()
Assert.Equal("No.999,Zixing Rd Minhang", address.Properties.First(s => string.Equals("Street", s.Name, StringComparison.Ordinal)).Value);
Assert.Equal("No.10000000999,Zixing Rd Minhang", address.Properties.First(s => string.Equals("UndeclaredStreet", s.Name, StringComparison.Ordinal)).Value);
}

[Fact]
public void ReadNonOpenUnknownComplexTypeCollectionWithInvalidTypeAsValueTest_InRequest()
{
const string payload = @"{""@odata.context"":""http://www.sampletest.com/$metadata#serverEntitySet/$entity"",""Id"":61880128,""UndeclaredFloatId"":12.3,
""[email protected]"":""Collection(Server.NS.UnknownCollectionType)"",""UndeclaredCollection1"":[{""email"":""[email protected]""},{""email"":""[email protected]""},{""email"":""[email protected]""}],""Address"":{""Street"":""No.999,Zixing Rd Minhang"",""UndeclaredStreet"":""No.10000000999,Zixing Rd Minhang""}}";
ODataResource entry = null;
ODataResource address = null;
ODataNestedResourceInfo undeclaredCollection1 = null;
List<ODataResource> untypedCollection = new List<ODataResource>();
bool insideCollection = false;
this.ReadEntryPayload(payload, this.serverEntitySet, this.serverEntityType, reader =>
{
if (reader.State == ODataReaderState.ResourceStart)
{
if (insideCollection)
{
untypedCollection.Add(reader.Item as ODataResource);
}
else if (entry == null)
{
entry = (reader.Item as ODataResource);
}
else if (address == null)
{
address = (reader.Item as ODataResource);
}
}
else if (reader.State == ODataReaderState.NestedResourceInfoStart)
{
ODataNestedResourceInfo nestedInfo = (reader.Item as ODataNestedResourceInfo);
if (insideCollection = nestedInfo.IsCollection == true)
{
undeclaredCollection1 = nestedInfo;
}
}
else if (reader.State == ODataReaderState.NestedResourceInfoEnd)
{
ODataNestedResourceInfo nestedInfo = (reader.Item as ODataNestedResourceInfo);
insideCollection = !(nestedInfo.IsCollection == true);
}
else if (reader.State == ODataReaderState.ResourceSetStart)
{
undeclaredCollection1.TypeAnnotation = new ODataTypeAnnotation((reader.Item as ODataResourceSet).TypeName);
}
},
/*readUntypedAsValue*/ true,
/*readRequest*/ true);

Assert.Equal(2, entry.Properties.Count());
Assert.Equal("Collection(Server.NS.UnknownCollectionType)", undeclaredCollection1.TypeAnnotation.TypeName);
Assert.Equal(3, untypedCollection.Count());
Assert.Equal("[email protected]@[email protected]", String.Concat(untypedCollection.Select(c => ((ODataResource)c).Properties.Single(p => string.Equals(p.Name, "email", StringComparison.Ordinal)).Value)));
Assert.Equal(2, address.Properties.Count());
Assert.Equal("No.999,Zixing Rd Minhang", address.Properties.First(s => string.Equals("Street", s.Name, StringComparison.Ordinal)).Value);
Assert.Equal("No.10000000999,Zixing Rd Minhang", address.Properties.First(s => string.Equals("UndeclaredStreet", s.Name, StringComparison.Ordinal)).Value);
}
#endregion

#region open entity's property unknown name + known value type
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
<GenerateAssemblyConfigurationAttribute>false</GenerateAssemblyConfigurationAttribute>
<RestorePackages>true</RestorePackages>
<GenerateTargetFrameworkAttribute>false</GenerateTargetFrameworkAttribute>
</PropertyGroup>

<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
<RestorePackages>true</RestorePackages>
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
<GenerateAssemblyConfigurationAttribute>false</GenerateAssemblyConfigurationAttribute> <!--check this in attributes-->
<GenerateTargetFrameworkAttribute>false</GenerateTargetFrameworkAttribute>
</PropertyGroup>

<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
Expand All @@ -33,7 +34,6 @@

<ItemGroup>
<ProjectReference Include="..\..\..\src\Microsoft.OData.Edm\Microsoft.OData.Edm.csproj" />
<ProjectReference Include="..\Microsoft.OData.TestCommon\Microsoft.OData.TestCommon.csproj" />
</ItemGroup>

<ItemGroup Condition="'$(TargetFramework)' == 'netcoreapp2.1' or '$(TargetFramework)' == 'netcoreapp3.1'">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
<TargetFrameworks>net45;netcoreapp1.1;netcoreapp2.1;netcoreapp3.1</TargetFrameworks>
<RestorePackages>true</RestorePackages>
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
<GenerateTargetFrameworkAttribute>false</GenerateTargetFrameworkAttribute>
<SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\..\..\..\sln\</SolutionDir>
</PropertyGroup>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
<RestorePackages>true</RestorePackages>
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
<GenerateAssemblyConfigurationAttribute>false</GenerateAssemblyConfigurationAttribute>
<GenerateTargetFrameworkAttribute>false</GenerateTargetFrameworkAttribute>
</PropertyGroup>

<PropertyGroup>
Expand Down

0 comments on commit 0c446be

Please sign in to comment.