【问题标题】:Enable OData v4 query on WebApi ApiController在 WebApi ApiController 上启用 OData v4 查询
【发布时间】:2015-03-18 15:21:12
【问题描述】:

我正在努力将 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; }
}

当调用 /Test/Events 是 406 Not Acceptable 时,我得到的只是 406 Not Acceptable,这是我在处理 OData 时遇到的很多问题,这通常意味着我返回了 OData 框架不喜欢的东西。我再也无法从框架中获得更多信息(我认为这是一个重大失败),说明它为什么不喜欢它,并且过去只能通过反复试验来解决它们。

有没有人让这个设置工作,如果有,怎么做?

或者对调试 406 响应有什么建议?

编辑:

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

删除有问题的代码后,它起作用了。

真的很希望 WebApi 会在某处记录导致 406 错误的原因。

【问题讨论】:

  • 你是如何声明路由的?
  • 我没有,我只是使用了Controller/Action的约定。当我删除 EnableQuery 时它工作正常。
  • 将动作名称 Events() 更改为 Get() 是否有效?
  • 不,EnableQuery 是我的老朋友 406,当我使用 GET 重命名为 /Test 时没有它可以工作

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


【解决方案1】:

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

  1. 创建一个 ODataQueryContext,传入您的模型(您需要 将其保存在全局中并使其可用),以及您的实体类型 查询。
  2. 使用 Get 和当前 url 创建一个 HttpRequestMessage (Request.RequestUri.AbsoluteUri)。
  3. 创建一个新的 ODataQueryOptions,传入上下文并 请求您创建的消息。
  4. 使用您的 entity.AsQueryable() 调用该对象的 ApplyTo,进行强制转换 结果为 IQueryable

需要进一步操作并返回。请记住,返回类型不需要是 IQueryable,甚至不需要基于“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;
        }

【讨论】:

    猜你喜欢
    • 2016-06-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-07-24
    • 2016-02-27
    • 2014-02-15
    • 2015-11-06
    • 2014-07-26
    相关资源
    最近更新 更多