Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fixes #923 Enable using ODataValue to write Untyped property directly #924

Merged
merged 1 commit into from
May 16, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 28 additions & 7 deletions sample/ODataRoutingSample/Controllers/PeopleController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -157,12 +157,13 @@ public IActionResult Post([FromBody] Person person)
{
null,
"A string Value",
// The following resources can't work: https://github.com/OData/odata.net/issues/2661
// new Address { City = "Issaquah", Street = "Klahanie Way" },
//new Person
//{
// FirstName = "Kerry", LastName = "Xu"
//}
new Address { City = "Issaquah", Street = "Klahanie Way" },
new Person
{
FirstName = "Kerry", LastName = "Xu",
Infos = new List<object> { 1, 2, 3 }, // Collection should have a value.
Sources = new List<object> { } // Collection should have a value.
}
}
};

Expand Down Expand Up @@ -217,7 +218,27 @@ public IActionResult Post([FromBody] Person person)
},
[
null,
"A string Value"
"A string Value",
{
"City": "Issaquah",
"Street": "Klahanie Way"
},
{
"@odata.type": "#ODataRoutingSample.Models.Person",
"@odata.id": "http://localhost:5000/People(FirstName='Kerry',LastName='Xu')",
"@odata.editLink": "People(FirstName='Kerry',LastName='Xu')",
"FirstName": "Kerry",
"LastName": "Xu",
"Data": null,
"Other": null,
"Infos": [
1,
2,
3
],
"Sources": [],
"CustomProperties": null
}
]
],
"CustomProperties": {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1332,23 +1332,7 @@ public virtual object CreateUntypedPropertyValue(IEdmStructuralProperty structur
Error.Format(SRResources.TypeCannotBeSerialized, structuralProperty.Type.FullName()));
}

ODataProperty odataProperty =
serializer.CreateProperty(propertyValue, actualType, structuralProperty.Name, writeContext);

// The following codes are not-needed but ODL has the problem to write ODataPrimitiveValue for 'Edm.Untyped' declared property
// This's the workaround and when ODL fixes the issue at https://github.com/OData/odata.net/pull/2664,
// Let's update the dependency and remove these codes.
string untypedValue = ODataUriUtils.ConvertToUriLiteral(odataProperty.Value, ODataVersion.V4, resourceContext.EdmModel);

return new ODataProperty
{
Name = odataProperty.Name,
Value = new ODataUntypedValue
{
RawValue = untypedValue,
TypeAnnotation = new ODataTypeAnnotation(actualType.FullName())
}
};
return serializer.CreateProperty(propertyValue, actualType, structuralProperty.Name, writeContext);
}

/// <summary>
Expand Down
14 changes: 14 additions & 0 deletions src/Microsoft.AspNetCore.OData/Microsoft.AspNetCore.OData.xml
Original file line number Diff line number Diff line change
Expand Up @@ -1102,6 +1102,20 @@
<param name="clrType">The type to test.</param>
<returns>True if the type is a DateTime; false otherwise.</returns>
</member>
<member name="M:Microsoft.AspNetCore.OData.Common.TypeHelper.IsDateOnly(System.Type)">
<summary>
Determine if a type is a <see cref="T:System.DateOnly"/>.
</summary>
<param name="clrType">The type to test.</param>
<returns>True if the type is a DateOnly; false otherwise.</returns>
</member>
<member name="M:Microsoft.AspNetCore.OData.Common.TypeHelper.IsTimeOnly(System.Type)">
<summary>
Determine if a type is a <see cref="T:System.TimeOnly"/>.
</summary>
<param name="clrType">The type to test.</param>
<returns>True if the type is a TimeOnly; false otherwise.</returns>
</member>
<member name="M:Microsoft.AspNetCore.OData.Common.TypeHelper.IsTimeSpan(System.Type)">
<summary>
Determine if a type is a TimeSpan.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,43 @@ public static IList<InModelPerson> GetAllPeople()
}
},
};

// Collection in collection
InModelPerson p = new InModelPerson
{
Id = 99, // special Id to test collection in collection
Name = "Chuan",
Data = new object[]
{
null,
new object[] { 42, new InModelAddress { City = "Redmond", Street = "134TH AVE" } }
},
Infos = new object[]
{
new EdmUntypedCollection
{
new NotInModelAddress { ZipCode = "NoAValidZip", Location = "OnEarth" },
null,
new EdmUntypedCollection
{
new EdmUntypedCollection
{
new object[]
{
new InModelAddress { City = "Issaquah", Street = "80TH ST" }
}
}
}
},
42
},
Containers = new Dictionary<string, object>
{
{ "Dp", new object[] { new InModelAddress{ City = "BlackCastle", Street = "To Castle Rd" } } }
}
};

_people.Add(p);
}

return _people;
Expand Down
58 changes: 58 additions & 0 deletions test/Microsoft.AspNetCore.OData.E2E.Tests/Untyped/UntypedTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -324,6 +324,64 @@ public async Task QuerySinglePeople_OnDeclaredUntypedProperty(string request, st
Assert.Equal(expected, payloadBody);
}

[Fact]
public async Task QuerySinglePeople_WithCollectionInCollection_OnDeclaredUntypedProperty()
{
// Arrange
HttpClient client = CreateClient();

// Act
HttpResponseMessage response = await client.GetAsync("odata/people/99");

// Assert
Assert.NotNull(response);
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
Assert.NotNull(response.Content);

string payloadBody = await response.Content.ReadAsStringAsync();

Assert.Equal("{\"@odata.context\":\"http://localhost/odata/$metadata#People/$entity\"," +
"\"Id\":99," +
"\"Name\":\"Chuan\"," +
"\"Data\":[" +
"null," +
"[" +
"42," +
"{" +
"\"@odata.type\":\"#Microsoft.AspNetCore.OData.E2E.Tests.Untyped.InModelAddress\"," +
"\"City\":\"Redmond\"," +
"\"Street\":\"134TH AVE\"" +
"}" +
"]" +
"]," +
"\"Infos\":[" +
"[" +
"{\"ZipCode\":\"NoAValidZip\",\"Location\":\"OnEarth\"}," + // a resource whose type is not defined in the Edm model, so there's no @odata.type
"null," +
"[" +
"[" +
"[" +
"{" +
"\"@odata.type\":\"#Microsoft.AspNetCore.OData.E2E.Tests.Untyped.InModelAddress\"," +
"\"City\":\"Issaquah\"," +
"\"Street\":\"80TH ST\"" +
"}" +
"]" +
"]" +
"]" +
"]," +
"42" +
"]," +
"\"Dp\":[" +
"{" +
"\"@odata.type\":\"#Microsoft.AspNetCore.OData.E2E.Tests.Untyped.InModelAddress\"," +
"\"City\":\"BlackCastle\"," +
"\"Street\":\"To Castle Rd\"" +
"}" +
"]" +
"}", payloadBody);
}

[Fact]
public async Task CreatePerson_Works_RoundTrip()
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1388,8 +1388,7 @@ public void CreateUntypedPropertyValue_Calls_CreateODataValueOnInnerSerializer()
innerSerializer.Verify();
ODataProperty odataProperty = Assert.IsType<ODataProperty>(createdProperty);
Assert.Equal("PropertyName", odataProperty.Name);
ODataUntypedValue untypedValue = Assert.IsType<ODataUntypedValue>(odataProperty.Value);
Assert.Equal("42", untypedValue.RawValue);
Assert.Equal(42, odataProperty.Value);
}

[Fact]
Expand Down