4

The environment

As part of an integration project, I need a PHP website to be able to both read from and write to Microsoft Dynamics NAV 2016's Odata services.

Microsoft Dynamics NAV 2016 uses the Odata v3 standard.


The context

Now, let's take my customer service as an example.

Fetching a collection of entities

Fetching an overview of my collection of customer entities works fine, using a link with the following format :

https://<Server>:<WebServicePort>/<ServerInstance>/OData/Company(\'<CompanyName>\')/customer

Fetching a single entity

Fetching a single customer entity based on id works fine, using a link with the following format :

https://<Server>:<WebServicePort>/<ServerInstance>/OData/Company(\'<CompanyName>\')/customer(\'<Id>\')

Fetching the global metadata

Getting an overview of the $metadata for all of my services works fine (although it's lacking Json support), using a link with the following format :

https://<Server>:<WebServicePort>/<ServerInstance>/OData/$metadata

Fetching collection-specific metadata

Now, based on both the Odata v3 specs and the value of the odata.metadata property of my customer overview service, I would expect to be able to get an overview of the $metadata of the customer entity, using a link with the following format :

https://<Server>:<WebServicePort>/<ServerInstance>/OData/$metadata#customer

This doesn't work as expected. See sub-section The issue below.

Fetching entity-specific metadata

Similarly, based on both the Odata v3 specs and the value of the odata.metadata property of my dataset when retrieving a single customer, I would expect to be able to get an overview of the $metadata of a single field of the customer entity, using a link with this format :

https://<Server>:<WebServicePort>/<ServerInstance>/OData/$metadata#customer/@<FieldName>

This doesn't work as expected. See sub-section The issue below.

The issue

For some reason, everything following $metadata appears to be ignored. This means that the last three URLs give me the exact same output, which is not what I expected.


The actual question(s)

  • Is it possible to fetch the metadata of just one collection or entity, as I'm trying in sub-sections Fetching collection-specific metadata and Fetching entity-specific metadata of my The context section hereabove?
  • If yes, what I doing wrong here? What am I missing?
John Slegers
  • 45,213
  • 22
  • 199
  • 169
  • 1
    It seems that you're looking for the metadata as a service. It doesn't support now in ODL, neither in Dynamics CRM. See [issue](https://github.com/OData/odata.net/issues/181) – Sam Xu Feb 22 '16 at 01:37
  • @SamXu : So, does this mean that the metadata is really nothing but a static file?! That would explain a lot, actually! – John Slegers Feb 22 '16 at 01:55
  • 1
    So far, I think so. However, metadata is useful and necessary for client. For example, OData client or similar clients can read the metadata content to generate the codes used to access the service. – Sam Xu Feb 22 '16 at 01:59

2 Answers2

2

As @xuzhg suggested in the comments and as is indicated by Github issues like Support Metadata as a service (#181), it appears that the Odata $metadata are not really a dynamic service. Instead, it's just a single XML file.

This explains not only why anything after $metadata is ignored in links of format https://<Server>:<WebServicePort>/<ServerInstance>/OData/$metadata#..., but also why it only supports XML, and not Json (unlike actual Odata services).

John Slegers
  • 45,213
  • 22
  • 199
  • 169
  • Per [RFC 3986](https://tools.ietf.org/html/rfc3986#section-3.5), the HTTP client is stripping the `#` and everything after it (i.e., the fragment) prior to sending the request. – lencharest Feb 22 '16 at 07:20
  • 1
    Also, there is no JSON representation of the metadata because there is no JSON-based articulation of the schema for metadata ([CSDL](http://docs.oasis-open.org/odata/odata/v4.0/odata-v4.0-part3-csdl.html)). – lencharest Feb 22 '16 at 07:25
  • @lencharest : The `#` was kind of a give-away, I guess. I just didn't expect the metadata to be completely static. Much the same way, I just didn't expect the metadata of a Json service to be defined in XML. Maybe it's naive to expect more from a company like Microsoft, but having metadata for a Json service as an XML-only static file comes off as kinda rushed / sloppy to me, especially considering this is already v3 of their Odata web service standard. – John Slegers Feb 22 '16 at 13:39
  • 1
    At the time OData was created, XML was still king. Atom (XML) was the primary OData serialization format. The use of CSDL in OData follows from Microsoft's investment in EF and EDM, and OData's dependency on the latter. Now that JSON is ascendant, there is [interest in adopting Swagger/OpenAPI](https://issues.oasis-open.org/browse/ODATA-907) for representing metadata. – lencharest Feb 23 '16 at 05:26
1

Since the specific metadata you want is identified by a fragment appended to the metadata URI, you must fetch the entire $metadata document and then dereference the fragment on the client.

The good news is that the fragment dereferencing is pretty straightforward. A fragment like #customer specifies an EntityType element whose Name attribute has the value customer. Similarly, #customer/@someprop maps to a Property element whose Name attribute is someprop.

lencharest
  • 2,825
  • 2
  • 15
  • 22