odata.net
odata.net copied to clipboard
OData lib duplicates type cast segment in editLink URI
When derived entity is accessed through parent type entityset and no editLink is provided the default etitLink is generated based on entity ID
Assemblies affected
OData .Net lib 7.x
Reproduce steps
Create entities like this
<EntityType Name="Entity6" Abstract="true">
<Key>
<PropertyRef Name="Id"/>
</Key>
<Property Name="Id" Type="Edm.String" Nullable="false"/>
</EntityType>
<EntityType Name="Entity7" BaseType="referencedomain.Entity6">
<Property Name="Extended_attr" Type="Edm.String"/>
</EntityType>
<EntitySet Name="Entity6s" EntityType="Entity6" />
Expected result
"@odata.type": "#referencedomain.Entity7", "@odata.id": "http://localhost.fiddler:1981/ReferenceDomain.svc/Entity6s('0')/referencedomain.Entity7", "@odata.editLink": "Entity6s('0')/referencedomain.Entity7", "Id": "0",
Actual result
"@odata.type": "#referencedomain.Entity7", "@odata.id": "http://localhost.fiddler:1981/ReferenceDomain.svc/Entity6s('0')/referencedomain.Entity7", "@odata.editLink": "Entity6s('0')/referencedomain.Entity7/referencedomain.Entity7", "Id": "0",
Additional detail
By the default ID URI has typecast segment and ODataConventionalEntityMetadataBuilder.ComputeEditLink() adds another one.
Kindly share a sample repro project
I saw this exact problem when using the AspNetCoreOData library.
While debugging, I saw that when the ResourceBase.NonComputedEditLink
contains the type cast, the ODataConventionalEntityMetadataBuilder.ComputeEditLink
will add an extra type cast.
https://github.com/OData/odata.net/blob/a08accf645ac75875a1801677bf83e09436255fe/src/Microsoft.OData.Core/Evaluation/ODataConventionalEntityMetadataBuilder.cs#L404-L415
If still needed, I could create a public sample application to showcase this.
I was looking a bit more into this issue and now know how this happens, at least in our case. The AspNetCoreOData library sets the ID on a resource explicitly, and when a derived type contains navigation properties that are not declared on the base type, the cast is added to the IDLink.
The following tests show how things go wrong in the ODataConventionalEntityMetadataBuilderTests for both the edit link and the readlink:
[Fact]
public void GetEditLinkShoulReturnNonComputedIdUriWithoutDoubleTypeCastForDerivedEntityWhenNonComputedIdIsSet()
{
var id = new Uri($"http://anotherodata.org/serviceBase/SomeType('xyz')/{DerivedMleEntityTypeName}");
this.derivedMultiKeyMultiEtagMleEntry.Id = id;
Assert.Equal(this.derivedMultiKeyMultiEtagMleConventionalEntityMetadataBuilder.GetEditLink(), id);
}
[Fact]
public void GetReadLinkShoulReturnNonComputedIdUriWithoutDoubleTypeCastForDerivedEntityWhenNonComputedIdIsSet()
{
var id = new Uri($"http://anotherodata.org/serviceBase/SomeType('xyz')/{DerivedMleEntityTypeName}");
this.derivedMultiKeyMultiEtagMleEntry.Id = id;
Assert.Equal(this.derivedMultiKeyMultiEtagMleConventionalEntityMetadataBuilder.GetReadLink(), id);
}
Although I am not sure if this is intended like this (I don't think so), I will add a PR with a proposed fix.
Fixed by https://github.com/OData/AspNetCoreOData/pull/831