Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Proper way to call nested Expand() from .NET OData 4 Client

Problem

In an OData 4 service on Web API, what is the proper way to call nested $expand from a .NET client? We are using the OData Client Generator. Back in the prior WCF Data Services with OData 3 service we could call .Expand("Customers/Orders"). In Web API with OData 4 we can no longer do so and receive the following should you attempt .Expand("Customers/Orders"):

The query specified in the URI is not valid. Found a path traversing multiple navigation >properties. Please rephrase the query such that each expand path contains only type >segments and navigation properties.

Workaround

We are able to work around this by calling expand like so: .Expand("Customers($expand=Orders)"). In non-nested $expand scenarios, I like the lambda support like so .Expand(d => d.Customers). Is there a proper way in .NET OData 4 client to call nested expands without the unfortunate magic string of .Expand("Customers($expand=Orders)")? If not, is there a cleaner string pattern like "Customers/Orders" that would work? Thanks.

like image 975
Adam Caviness Avatar asked Aug 11 '14 15:08

Adam Caviness


People also ask

What is $value in OData?

The $value option is used to get individual properties of an Entity. There are two ways to get individual properties from an entity. We can get the response in either OData format or get the raw value of the property. We need to add method to the controller named GetProperty here property is a name of the property.

What is $select in OData?

The $select option specifies a subset of properties to include in the response body. For example, to get only the name and price of each product, use the following query: Console Copy. GET http://localhost/odata/Products?$select=Price,Name.

How do I query OData service?

You can find details on filter specification in the OData spec filter options section. Examples: All products with a Name equal to 'Milk': http://host/service/Products?$filter=Name eq 'Milk' All products with a Name not equal to 'Milk' : http://host/service/Products?$filter=Name ne 'Milk'


1 Answers

The request that you want to send is:

GET http://host/service/Customers/Orders

right?

According to the OData protocol:

To request related entities according to a particular relationship, the client issues a GET request to the source entity’s request URL, followed by a forward slash and the name of the navigation property representing the relationship.

So such request is not supported as the "Customers" before "/Orders" is the name of an entity set instead of a single entity. You can only write nested expanding like:

GET http://host/service/Customers(1)/Orders

Which corresponds to the following code snippets using OData V4 Code Generator:

var orders = context.Customers.ByKey(new Dictionary<string, object>() { { "ID", 1 } }).Orders.Execute();

And you need to iterate through all the customers to get all their orders.

like image 151
Yi Ding - MSFT Avatar answered Oct 21 '22 17:10

Yi Ding - MSFT