Question

Update

vote here on User Voice to get the ambiguity addressed.


I've written a OData WebAPI controller inherting from ODataController.

public class ManyColumnsController : ODataController
{
    [Queryable(
        AllowedOrderByProperties = "Aa,Bb,Cc,Dd",
        EnsureStableOrdering = false,
        MaxOrderByNodeCount = 2)]
    public IQueryable<ManyColumn> GetManyColumns(
            ODataQueryOptions<ManyColumn> options)
    {
        // Because I've disabled EnsureStableOrdering,
        // I need to check column "Dd" is always included
        // in the OrderBy option. This will ensure stable ordering.
        if (!options.OrderBy.RawValue.Contains("Dd")
        {
             var entityType = options.Context.ElementType as IEdmEntityType;
             var ddProperty = entityType.DeclaredStructuralProperties()
                 .Single(p => p.Name == "Dd");
             options.OrderBy.OrderByNodes.Add(new OrderByPropertyNode(
                 ddProperty,
                 OrderByDirection.Descending));
        }

        return this.context.ManyColumns;
    }
}

This code runs and an extra OrderByNode is added to the OrderBy property of the ODataQueryOptions passed into the method.

The Problem

This alteration has no effect on the statement that is generated by the contoller. Processing continues as if I had changed nothing and any OrderBy applied to the ManyColumns entity is replaced with the orignal OrderBy specified in the $orderby parameter of the original request.

On further examination it seems that ODataQueryOptions is probably intended to be immutable. Most of its properties have only get accessors.

The Question

Have I just misused a failing in the implementation of OrderByQueryOption?

Is there a way to amend the ODataQueryOptions that will be applied to the request, later in the pipeline?

Was it helpful?

Solution

You should remove the [Queryable] attribute.

According to http://www.asp.net/web-api/overview/odata-support-in-aspnet-web-api/supporting-odata-query-options#ODataQueryOptions, you should use either Queryable or manually manipulate the ODataQueryOptions. The web API populates the ODataQueryOptions from the URI query string, after which you could (presumably) alter those options.

Further down the page, they implement something that looks really close to a solution for your problem. They implement a custom MyQueryable attribute which enforces a custom order-by validator. You may not be able to alter the query during validation, but you may be able to override the attribute's implementation of ApplyQuery to inject your required order-by clause.

OTHER TIPS

If you have ODataQueryOptions as the method parameter, it means that you want to handle the options yourself. So try this:

return options.ApplyTo(this.context.ManyColumns.AsQueryable());

By default all the querys are orderer by the table's PrimaryKey if no $orderby is specified

This code dont work, allways order by the primary key

[Queryable]
public IQueryable<Coches> GetCoches()
{
return db.Coches.OrderByDescending(c => c.Marca);
}

For override that behavior use this parameter in the Queyable attribute

[Queryable(EnsureStableOrdering=false)]
public IQueryable<Coches> GetCoches()
{
return db.Coches.OrderByDescending(c=>c.Marca);
}

The previous code work fine, the return values are orderer by Marca, or by the value in the $orderby parameter if specified

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top