After working with Jerther in chat, we narrowed the problem down to the expanded properties not being marked as contained navigations. As a result, the OData framework was removing them since they did not have corresponding entity sets defined. Updating the model to specifically declare the containment appears to have solved the problem.
Containment can be specified in a couple of ways, depending on what model builder is being used. In the case of the ODataConventionModelBuilder
you can add the System.Web.OData.Builder.ContainedAttribute
to the property in question, while for the ODataModelBuilder
you can use the ContainsMany<T>
method on the EntityTypeConfiguration
instance for the containing class.
Also, at the moment, a cascaded expand will stop where a complex type contains an Entity type.
UPDATE:
Defining all types in the chain as EntitySet works.
builder.EntitySet<Item>("Items");
builder.EntitySet<Product>("Products");
builder.EntitySet<Model>("Models");
builder.EntitySet<Type>("Types");
It seems defining them as EntityType
isn't sufficient.
see here: https://github.com/OData/WebApi/issues/226
Original Answer
I tried reproing your situation and couldn't. Is it possible that "Types" isn't being set in your action? Here was my little repro
public class ItemsController : ODataController
{
[HttpGet]
[EnableQuery(MaxExpansionDepth = 10)]
[ODataRoute("/Items")]
public IHttpActionResult GetItems()
{
return this.Ok(CreateItem());
}
private Item CreateItem()
{
return new Item
{
Id = 1,
Products = new Product[]
{
new Product
{
Id = 2,
Models = new Model[]
{
new Model
{
Id = 3,
Types = new MyType[]
{
new MyType
{
Id = 4,
},
},
},
},
},
},
};
}
}
Which when called with /Items?$expand=Products($expand=Models($expand=Types)) resulted in the following:
{
"@odata.context": "http://localhost:9001/$metadata#Items/$entity",
"Id": 1,
"Products@odata.context": "http://localhost:9001/$metadata#Items(1)/Products",
"Products": [{
"Id": 2,
"Models@odata.context": "http://localhost:9001/$metadata#Items(1)/Products(2)/Models",
"Models": [{
"Id": 3,
"Types@odata.context": "http://localhost:9001/$metadata#Items(1)/Products(2)/Models(3)/Types",
"Types": [{
"Id": 4
}]
}]
}]
}