I'm building an OData application and I'm struggling on how to retrieve results and only include certain (child properties).
First, let me show you the registration in my builder:
builder.EntitySet<AggregatedArticlesSearchModel>("Search").EntityType.HasKey(x => x.Name);
Now, on to the model that I'm returning from my Query:
<EntityType Name="AggregatedArticlesSearchModel">
<Key>
<PropertyRef Name="Name"/>
</Key>
<Property Name="Name" Nullable="false" Type="Edm.String"/>
<Property Name="Values" Type="Collection(Zevij_Necomij.Mobile.App.Api.Models.OccurenceViewModel)"/>
</EntityType>
<ComplexType Name="OccurenceViewModel">
<Property Name="Value" Type="Edm.String"/>
<Property Name="Count" Nullable="false" Type="Edm.Double"/>
<Property Name="Articles" Type="Collection(Zevij_Necomij.Mobile.App.Api.Models.AggregatedArticleDescriptionViewModel)"/>
</ComplexType>
<ComplexType Name="AggregatedArticleDescriptionViewModel">
<Property Name="Name" Type="Edm.String"/>
<Property Name="Specification" Type="Edm.String"/>
<Property Name="Brand" Type="Edm.String"/>
</ComplexType>
When I'm executing a request to get the data, I'm not doing anything fancy but just returning the results from the database:
public async Task<IHttpActionResult> Get()
{
// Create all the managers for the platform context that are required by the application.
var classificationManager = Context.CreateManager(typeof(AggregatedArticleManager<>)) as AggregatedArticleManager<IAggregatedArticleStore<AggregatedArticle>>;
var classifications = await classificationManager.GetAllAsync();
var returnList = classifications.OrderBy(x => x.Name).Select(AggregatedArticlesSearchModel.MapFromDbModel).ToList();
return Ok(returnList.AsQueryable());
}
Since I'm working with child objects, the list can get quite huge:
{
"@odata.context": "http://api.mobileapp.appserver.dev.dsoft.be/OData/$metadata#Search",
"value": [
{
"Name": "(Veiligheids)slipkoppeling",
"Values": [
{
"Value": "ja",
"Count": 118,
"Articles": [
{
"Name": "230 V Sleuvenzaag",
"Specification": "Compacte machine",
"Brand": "Makita"
},
{
"Name": "230V Cirkelzaag SJS",
"Specification": "Softstart voor
},
}
}
I can have a thousand articles in a single set, thus, way to much to return over the Web Api.
Since I don't need all those properties in a single request, I was thinking to let the cliënt only retrieve child properties by using the ?$select
parameter, thus the cliënts can say for example:
OData/Search?$select=Values
The problem here is that I for example, only want to return the Count, thus, I tought that a request like this was possible:
OData/Search?$select=Values/Count
However, this leads to an OData error: "The query specified in the URI is not valid. Found a path with multiple navigation properties or a bad complex property path in a select clause. Please reword your query such that each level of select or expand only contains either TypeSegments or Properties."
Anyone who has an idea on how to solve this one?
@Complexity
As I know, to select a sub property in a property is not supported.
However, if you build the OccurenceViewModel
as entity type, then you can use the nested $select in $expand to meet your requirement.
For example:
1) build the entity type
builder.EntitySet<OccurenceViewModel>("ViewModels").EntityType.HasKey(x => x.Value);
then, Values
in AggregatedArticlesSearchModel
should be a navigation property.
2) Now, you can issue a GET request as follows to only return the Count property:
GET ~/odata/Search?$select=Values&$expand=Values($select=Count)
Then, the payload should look like the below:
{
"@odata.context":"http://localhost/odata/$metadata#Search(Values,Values(Count))","value":[
{
"Values":[
{
"Count":101.0
},{
"Count":102.0
}
]
},{
"Values":[
{
"Count":101.0
},{
"Count":102.0
}
]
}
]
}
Hope it can help you. Thanks.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With