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

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.


A little extension for that :

        public static DataServiceQuery<TSource> Expand<TSource,TNavigation,TExpand>(this DataServiceQuery<TSource> dataServiceQuery, Expression<Func<TSource, DataServiceCollection<TNavigation>>> expression,  Expression<Func<TNavigation,TExpand>> navigation)
    {
        var expressionName = (expression.Body as System.Linq.Expressions.MemberExpression).Member.Name;
        var navigationName = (navigation.Body as System.Linq.Expressions.MemberExpression).Member.Name;


        return dataServiceQuery.Expand($"{expressionName}($expand={navigationName})");
    }

Now you have intellisense and type checking

Example :

db.Container.Expand(c=> c.Customers, customer => customer.Orders)


In OData v4, it is not valid to expand multi levels, such as what you mentioned in the question: .Expand("Customers/Orders"). I dont think the client will support such API. Here is what in the ABNF http://docs.oasis-open.org/odata/odata/v4.0/os/abnf/odata-abnf-construction-rules.txt:

expand            = '$expand' EQ expandItem *( COMMA expandItem )
expandItem        = STAR [ ref / OPEN levels CLOSE ]
                  / expandPath
                    [ ref   [ OPEN expandRefOption   *( SEMI expandRefOption   ) CLOSE ]
                    / count [ OPEN expandCountOption *( SEMI expandCountOption ) CLOSE ]
                    /         OPEN expandOption      *( SEMI expandOption      ) CLOSE 
                    ]
expandPath        = [ qualifiedEntityTypeName "/" ] 
                    *( ( complexProperty / complexColProperty ) "/" [ qualifiedComplexTypeName "/" ] )
                    navigationProperty 
                    [ "/" qualifiedEntityTypeName ]