If you look at the following sample oData feed you'll see included navigation properties for 'child' items to tell you which URL to follow:
http://services.odata.org/OData/OData.svc/Suppliers?$format=json
For example supplier 0 has a navigation property to products. This links to a list of products for that supplier.
http://services.odata.org/OData/OData.svc/Suppliers(0)/Products?$format=json
I'm trying to do the same with ODataConventionModelBuilder
and EntitySetController<Product>
so that when I request oData/Product(0)
it will show me the 'features' for the product:
I create my model like this (based on GetImplicitEdmModel sample)
// odata
ODataModelBuilder modelBuilder = new ODataConventionModelBuilder();
modelBuilder.EntitySet<RRStoreDB.Models.Product>("Product");
modelBuilder.EntitySet<RRStoreDB.Models.ProductFeature>("ProductFeature");
Microsoft.Data.Edm.IEdmModel model = modelBuilder.GetEdmModel();
config.Routes.MapODataRoute("ODataRoute", "odata", model);
I create a controller for WebAPI :
public class ProductController : EntitySetController<Product, int>
{
RRStoreDBContext _db = new RRStoreDBContext();
[Queryable]
public override IQueryable<DProduct> Get()
{
return _db.Products.AsQueryable();
}
public ICollection<ProductFeature> GetProductFeatures(int key)
{
Product product = _db.Products.FirstOrDefault(p => p.ProductId == key);
if (product == null)
{
throw new HttpResponseException(HttpStatusCode.NotFound);
}
return product.ProductFeatures;
}
}
When I actually call the URL for my child property it works and gives me the correct list of features :
/oData/Products(18)/ProductFeatures
However I would have expected a navigation property in /oData/Products(18)
pointing to this.
What do I need to do to get this to appear. This article says it's automatic but I'm not seeing them:
The ODataConventionModelBuilder, which is generally recommended over the ODataModelBuilder, will automatically infer inheritance hierarchies in the absence of explicit configuration. Then once the hierarchy is inferred, it will also infer properties and navigation properties too. This allows you to write less code, focusing on where you deviate from our conventions.
I think the problem is that you are asking for application/json
. application/json
in web API OData points to json light which is the latest OData json representation aimed at reducing response payload sizes and trimming the un-necessary/redundant metadata from the response. For comparison, try getting the url ~/oData/Products(18)
with accept header application/json;odata=verbose
.
Now, the idea behind json light is that if a link can be calculated because the link follows conventions, it will not be put in the response. The navigation link /oData/Products(18)/ProductFeatures
is a perfect example of that. It follows OData uri conventions.
OData json light has 3 modes, minimalmetadata (the default), fullmetadata and nometadata. The names are themselves explanatory. If you want the link to be on the wire, send the request with accept header application/json;odata=fullmetadata
.
Refer to this document to understand more about json light.