我可以更改用于ODataController请求的ODataQueryOptions吗?

时间:2014-05-07 08:00:27

标签: c# asp.net-web-api odata asp.net-web-api2 asp.net-web-api-odata

更新

投票here on User Voice以解决歧义问题。


我已经从ODataController编写了一个OData WebAPI控制器。

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;
    }
}

此代码会运行,并且会向传递给方法的OrderByNodeOrderBy属性添加额外的ODataQueryOptions

问题

此更改对控制器生成的语句没有影响。 处理继续,好像我什么都没改变任何OrderBy 已应用于ManyColumns实体的内容将替换为原始请求的OrderBy参数中指定的原始$orderby

在进一步检查时,似乎ODataQueryOptions可能是不可改变的。它的大多数属性只有get个访问者。

问题

我是否只是误用了OrderByQueryOption的实施失败?

有没有办法修改将在管道中稍后应用于请求的ODataQueryOptions

3 个答案:

答案 0 :(得分:3)

您应该删除[可查询]属性。

根据http://www.asp.net/web-api/overview/odata-support-in-aspnet-web-api/supporting-odata-query-options#ODataQueryOptions,您应该使用Queryable或手动操作ODataQueryOptions。 Web API从URI查询字符串填充ODataQueryOptions,之后您可以(可能)更改这些选项。

在页面的下方,他们实现的东西看起来非常接近您的问题的解决方案。它们实现了一个自定义的MyQueryable属性,该属性强制执行自定义的order-by验证器。您可能无法在验证期间更改查询,但您可以覆盖属性的ApplyQuery实现以注入所需的order-by子句。

答案 1 :(得分:2)

如果您将ODataQueryOptions作为方法参数,则表示您希望自己处理这些选项。所以试试这个:

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

答案 2 :(得分:1)

默认情况下,如果未指定$ orderby,则所有查询都由表的PrimaryKey进行订购

此代码不起作用,总是按主键排序

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

对于覆盖该行为,在Queyable属性中使用此参数

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

以前的代码工作正常,返回值是Marca的orderer,或者是$ orderby参数中的值(如果指定的话)