WebApi OData: $filter 'any' or 'all' query not working

Chris Pietschmann picture Chris Pietschmann · Mar 18, 2013 · Viewed 16.2k times · Source

First, using the ASP.NET WebApi tutorials I've created a basic ApiController that exposes an Entity Framework model through OData. The service works to return json for OData $filter queries.

When I perform OData $filter queries that include "any" or "all" queryies on a multi-value property it throws an ODataException

Here's the OData query I'm trying to use

~/api/Blogs?$filter=any(Tags,Name+eq+'csharp')

My ApiController looks like this:

public class BlogController : ApiController
{
    public BlogsController()
    {
        this.Entities = new BlogEntities();
    }

    public ContactEntities Entities { get; set; }

    [Queryable(PageSize = 25, AllowedQueryOptions = AllowedQueryOptions.All)]
    public IQueryable<Blog> Get()
    {
        return this.Entities.Blogs;
    }
}

The Blog entity has this contract

public Blog {
    public Guid ID { get; set; }
    public string Title { get; set; }
    public Tag Tags { get; set; }
}

public Tag {
    public Guid ID { get; set; }
    public string Name { get; set; }
}

The exception thrown

ODataException: Type 'Blog' does not have a property 'Name'

As you can see, I have nothing out of the ordinary in my code and everything should work fine. Is it possible that "any" and "all" queryies aren't supported yet in Microsoft ASP.NET Web API OData?

Answer

Youssef Moussaoui picture Youssef Moussaoui · Mar 18, 2013

Your any needs to be changed a bit. Try something like this:

~/api/Blogs?$filter=Tags/any(tag: tag/Name eq 'csharp')

This is assuming Tags actually returns a collection of Tags, not just a single Tag like you have above.

$inlinecount is only supported out of the box for the OData format. I wrote extensively about it here:

Web API OData Inlinecount not working

The short answer is that you can get it working for other formats with code that looks like this:

public PageResult<Customer> Get(ODataQueryOptions<Customer> queryOptions)
{
    IQueryable results = queryOptions.ApplyTo(_customers.AsQueryable());
    return new PageResult<Customer>(results as IEnumerable<Customer>, Request.GetNextPageLink(), Request.GetInlineCount());
}