OData / odata.net

ODataLib: Open Data Protocol - .NET Libraries and Frameworks
https://docs.microsoft.com/odata
Other
687 stars 349 forks source link

Fix contextUrl for $ref #1434

Open mikepizzo opened 5 years ago

mikepizzo commented 5 years ago

According to OASIS spec, the contextUrl for a reference should be /$metadata#$ref <- for a single reference /$metadata#collection($ref) <- for a collection of references

however, we currently write: /$metadata#entityset/$entity <- for a single reference /$metadata#entityset <- for a collection of references

Assemblies affected

OData .NET Lib 7.6 beta

Reproduce steps

var settings = new ODataMessageWriterSettings
{
     Version = ODataVersion.V401,
     ODataUri = new ODataUri
     {
           ServiceRoot = new Uri("http://testService"),
           RequestUri = new Uri(@"customers/1/$ref", UriKind.Relative)
     },
     Validations = ValidationKinds.All
};

ODataResponseMessage responseMessage = new InMemoryResponseMessage();
var customers = model.FindDeclaredEntitySet("customers");
var messageWriter = new ODataMessageWriter(responseMessage, settings, model);
ODataWriter writer = messageWriter.CreateODataResourceWriter(customers, customers.EntityType());

writer.WriteStart(new ODataResource { Id = new Uri("http://testService/customers/1") });
writer.WriteEnd(); // resource

Expected result

{
  "@context": "http://testservice/$metadata#$ref",
  "@id": "http://testservice/customers/1"
}

Actual result

{
  "@context": "http://testservice/$metadata#customers/$entity",
  "@id": "http://testservice/customers/1"
}

Additional info

Note that, in src\Microsoft.OData.Core\UriParser\Visitors\PathSegmentToContextUrlPathTranslator.cs, ln201 there is a comment for not knowing how to translate key segment (and leaving to implementation).

Also, in ODataContextUriBuilder.BuildContextUrl, ln 107-110, we check to see if the payload type is EntityReferenceLink or EntityReferenceLinks, but this is only set by WriteEntityReferenceLink, which is only supported for writing a URL in a request (and explicitly disallowed in responses, which is good, because it's the wrong format for OData V4).

Problem is that we don't really seem to have a way to write an entity reference, versus an entity with only an id property.

mikepizzo commented 5 years ago

Related to #1292, Reference segment in the ContextUrl.