OData Web API v5.5 supports nested $filter in $expand, e.g.: .../Customers?$expand=Orders($filter=Id eq 10)

POCO classes:

public class Customer
{
    public int Id { get; set; }
    public string Name { get; set; }
    public IEnumerable<Order> Orders { get; set; }
}

public class Order
{
    public int Id { get; set; }
    public string Name { get; set; }
}

With Edm model built as follows:

var builder = new ODataConventionModelBuilder(config);
builder.EntitySet<Customer>("Customers");
var model = builder.GetEdmModel();

To Map route,

  • For Microsoft.AspNet.OData, e.g., in WebApiConfig.cs:
config.MapODataServiceRoute("orest", "orest", model);
  • For Microsoft.AsnNetCore.OData, e.g., in Startup.Configure((IApplicationBuilder app, IHostingEnvironment env) method:
app.UseMvc(routeBuilder => 
    {
        routeBuilder.Select().Expand().Filter().OrderBy().MaxTop(null).Count();
        routeBuilder.MapODataServiceRoute("orest", "orest", model);
    });

Controller:

public class CustomersController : ODataController
{
    private Customer[] _customers =
    {
        new Customer
        {
            Id = 0,
            Name = "abc",
            Orders = new[]
            {
                new Order { Id = 10, Name = "xyz" },
                new Order { Id = 11, Name = "def" },
            }
        }
    };

    [EnableQuery]
    public IHttpActionResult Get()
    {
        return Ok(_customers.AsQueryable());
    }
}

Request: http://localhost:port_number/orest/Customers?$expand=Orders($filter=Id eq 10)

Response:

{
    "@odata.context": "http://localhost:52953/orest/$metadata#Customers",
    "value": [
        {
            "Id": 0,
            "Name": "abc",
            "Orders": [
                {
                    "Id": 10,
                    "Name": "xyz"
                }
            ]
        }
    ]
}