score:12

Accepted answer

To override default sort order, you need to set property EnsureStableOrdering of EnableQueryAttribute to false, like describe here:

A true value indicates the original query should be modified when necessary to guarantee a stable sort order. A false value indicates the sort order can be considered stable without modifying the query. Query providers that ensure a stable sort order should set this value to false. The default value is true.

So in your code, changes the action attribute like this:

// GET api/documents
[EnableQuery(EnsureStableOrdering = false)]
public IQueryable<Item> Get()
{
    return ctx.Items.OrderBy(o => o.Order).AsQueryable();
}

score:3

You can manually invoke the odata in your controller. This should create the proper sorted IQueryable and then apply the $top and any other odata like $filter and $skip. Now you don't have to return an IQueryable which was causing the problem because the actual query was being executed later in the pipeline.

public class ItemsController : ApiController
{
    protected DbContext ctx = // ...

    public IEnumerable<Item> Get(ODataQueryOptions<Item> odata)
    {
        var collection = ctx.Items.OrderBy(o => o.Order);

        if (odata == null)
        {
            //return a default max size of 100
            return collection.Take(100).ToList();
        }

        var results = odata.ApplyTo(collection.AsQueryable()) as List<Item>;

        //still provide a max incase the $top wasn't specified.
        //you could check the odata to see if $top is there or not.
        return results.Take(100);
    }
}

More information can be found in the WebApi documentation.


Related Articles