I am using Microsoft ASP.NET Web API 2.2 for OData v4. Because of circular references in edmx I can't use ODataConventionModelBuilder, so I use ODataModelBuilder.
One of my entity types has optional NavigationProperty, which is added like this
var item = builder.EntityType<API.Item>();
...
item.HasOptional(a => a.Customer);
This results in following $metadata
<EntityType Name="Item">
...
<NavigationProperty Name="Customer" Type="XXX.API.Customer" />
...
Browser, of course, has no problems in obtaining $expand results for odata/Items?$expand=Customer like this
{"@odata.context":"http://localhost:5404/odata/$metadata#Items","value":
[
{"ItemId":15, ... "Customer":{"CustomerId":5,...}}
...
]
However, when it comes to client C# application which uses
Microsoft.OData.Client.DataServiceQuery<Item> _items;
...
_items.Expand(i => i.Customer)
It fails with the following exception:
When writing a JSON response, a user model must be specified and the entity set and entity type must be passed to the ODataMessageWriter.CreateODataEntryWriter method or the ODataFeedAndEntrySerializationInfo must be set on the ODataEntry or ODataFeed that is being written.
However, if I change the server model to
var item = builder.EntityType<API.Item>();
...
item.ContainsOptional(a => a.Customer);
Which results in following $metadata
<EntityType Name="Item">
...
<NavigationProperty Name="Customer" Type="XXX.API.Customer" ContainsTarget="true"/>
...
And the following response (note second @odata.context)
{"@odata.context":"http://localhost:5404/odata/$metadata#Items","value":
[
{
"ItemId":15, ...
"[email protected]": "http://localhost:5404/odata/$metadata#Items(15)/Customer/$entity",
"Customer":{"CustomerId":5,...}}
...
]
The client code is just fine. Expand works like a charm.
So, as I suppose, this is because second @odata.context describes nested object. Of course I could use ContainsOptional as workaround, but this does not seem like proper thing to do, since "item" does not contain "customer" - they are independing in business logic.
Is it a bug in OData core library? Or, is there any way to force Web API to include @odata.context for HasOptional property?
Edit: I've checked on most recent version 7.4.0, and now it gives slightly different error: "The Id cannot be computed, since the navigation source 'Customer' cannot be resolved to a known entity set from model." But essentially, it is the same.