在WebApi ApiController上启用OData v4查询

时间:2015-01-20 11:50:03

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

我正努力将OData v4查询支持添加到继承自ApiController而非ODataController的控制器上的方法。虽然我在解决方案中有一个工作的OData模型,但有一些端点并不真正属于模型,但查询的强大功能会很有用。

我已经看到一些文章建议我可以返回IQueryable并使用EnableQuery。

以下是我的示例代码:

public class TestController : ApiController
{
    [HttpGet]    
    [EnableQuery]
    public IQueryable<TestObject> Events()
    {
        var result = new[] { new TestObject { Id = "1" } }.AsQueryable();
        return result;
    }
}

public class TestObject
{
    public string Id { get; set; }
}

当一个电话/测试/事件是406不可接受的时候我回来了,我经常遇到很多关于OData的事情,这通常意味着我已经返回了OData框架所没有的东西。喜欢。我从来没有能够从框架中获得更多信息(我认为是一个重大的失败),为什么它不喜欢它,并且过去只是通过反复试验来解决它们。

有没有人有这个设置工作,如果有的话?

或者有关调试406响应的任何建议?

编辑:

好的,所以事实证明,罪魁祸首是启动时的代码注册了自定义的ODataMediaTypeFormatter,并且在此过程中正在清除所有其他格式化程序。

删除有问题的代码后,它有效。

真的希望WebApi能够在某个地方记录导致406错误的原因。

1 个答案:

答案 0 :(得分:0)

您可以手动应用“查询”魔法,而无需[EnableQuery]。

  1. 创建一个ODataQueryContext,传入你的模型(你需要 将其保存在全局并使其可用),以及您的实体类型 查询。
  2. 使用Get和当前网址创建HttpRequestMessage (Request.RequestUri.AbsoluteUri)。
  3. 创建一个新的ODataQueryOptions&lt; yourEntity&gt;,传入上下文和 请求您创建的消息。
  4. 使用您的实体调用该对象的ApplyTo .AsQueryable(),强制转换 结果为IQueryable&lt; yourEntity&gt;。
  5. 进一步操纵所需和返回。请注意,返回类型不需要是IQueryable&lt; yourEntity&gt;,甚至不需要基于“yourEntity”。

    这是一个类似的实现,它为ODataController方法执行此操作(作为基本ODataQueryOptions免费提供):

            public IEnumerable<Aggregate> GetOrders(ODataQueryOptions<ReportingOrder> opts, [FromUri(Name="$groupby")]string groupby, [FromUri(Name="$aggregates")]string aggregates = null)
            {
                var url = opts.Request.RequestUri.AbsoluteUri;
    
    
                int? top = null;
    
                if (opts.Top != null)
                {
                    top = int.Parse(opts.Top.RawValue);
    
                    var topStr = string.Format("$top={0}", top.Value);
                    url = url.Replace(topStr, "");
                    var req = new HttpRequestMessage(HttpMethod.Get, url);
    
                    opts = new ODataQueryOptions<ReportingOrder>(opts.Context, req);
    
                }
    
                var query = opts.ApplyTo(db.ReportingOrders.AsQueryable()) as IQueryable<ReportingOrder>;
    
                var results = query.GroupBy(groupby, aggregates, top);
    
                return results;
            }