【问题标题】:MapODataRoute and ODataQueryOptionsMapODataRoute 和 ODataQueryOptions
【发布时间】:2013-11-25 21:43:59
【问题描述】:

我正在构建一个处理无类型实体对象的 WebAPI OData 解决方案,如 this excellent post 中所述。像那篇文章一样,我预先定义了我的 EdmModel,并使用 MapODataRoute 方法并传入要使用的模型:

config.Routes.MapODataRoute("odata", "odata", ModelBuilder.GetEdmModel());

但是,这似乎不适用于我的方法中的 ODataQueryOptions 参数:

Get(ODataQueryOptions query)
{
}

它给出以下错误:给定模型不包含类型“System.Web.Http.OData.IEdmEntityObject”。参数名称:elementClrType

有没有办法让 ODataQueryOptions 与 MapODataRoute 一起工作?

【问题讨论】:

    标签: asp.net-web-api odata


    【解决方案1】:

    您应该以非类型化模式在控制器操作中手动构建 ODataQueryOptions。示例代码如下,

    ODataPath path = Request.GetODataPath();
    IEdmType edmType = path.EdmType;
    
    IEdmType elementType = edmType.TypeKind == EdmTypeKind.Collection 
        ? (edmType as IEdmCollectionType).ElementType.Definition 
        : edmType;
    
    // build the typeless query options using the element type.
    ODataQueryContext queryContext = new ODataQueryContext(Request.GetEdmModel(), elementType);
    ODataQueryOptions queryOptions = new ODataQueryOptions(queryContext, Request);
    

    【讨论】:

    • 嗨 Raghuram,感谢您的回答,这正是我一直在做的事情,请参阅我回答中的代码。虽然 $select 和 $expand 会引发错误...
    • 附带说明,如果您这样做,您似乎也不需要将返回的集合定义为IQueryable。在我回到IEnumerable 之前,我被序列化错误绊倒了。
    • 请注意,对于以后的版本,此方法被标记为已过时。使用System.Web.Http.OData.Extensions.HttpRequestMessageExtensions.ODataProperties(request).Path
    【解决方案2】:

    我设法做到了如下:

    ODataPath path = Request.GetODataPath();
    IEdmType edmType = path.EdmType;   
    
    private ODataQueryOptions GetODataQueryOptions(IEdmType edmType)
        {
            IEdmModel model = Models.ModelBuilder.GetEdmModel();
            ODataQueryContext queryContext = new ODataQueryContext(model, edmType);
            ODataQueryOptions queryOptions = new ODataQueryOptions(queryContext, this.Request);
    
            return queryOptions;
        }
    

    这适用于大多数查询选项,但使用 $select 和 $expand 会崩溃:类型“Collection([Org.Microsoft.Product Nullable=False])”不是实体类型。只有实体类型支持 $select 和 $expand。 当客户端尝试使用 $select 和 $expand 进行过滤时,是否有办法优雅地避免此异常,或者我应该只写类似的东西

    if (Request.RequestUri.Query.Contains("select")) { return errormessage }
    

    另外,更重要的是,如何将这些查询选项应用于在第一种方法中返回的 EdmEntityObjectCollection

    queryOptions.ApplyTo(collectionProduct.AsQueryable()); // wont work...
    

    (也许最好还是动态地构建关于查询选项的集合)

    【讨论】:

    • 您传递给ODataQueryContext 的edmType 是元素类型。所以,如果ODataPath.EdmType 是一个集合,你应该取出元素类型并使用它。我会更新我的答案来解决这个问题。
    • 另外,关于 ApplyTo。我们不支持无类型 ODataQueryOptions 上的 ApplyTo,因为不涉及 CLR 类型并且 IQueryable 需要 CLR 类型。因此,您应该自己在后端应用 ODataQueryOptions,然后将结果转换为 EdmEntityObjectCollection。这篇博文可以为您提供一些指导 - blogs.msdn.com/b/webdev/archive/2013/02/25/…
    • 嗨 RaghuRam,有没有办法使用无类型集合实现 $select? $filter 工作正常,但是当我们遍历我们的数据并且仅 TrySetPropertyValue 中的属性 $select 子句时,将返回完整的 EdmEntityObject(具有所有属性),而不是仅具有选定属性的 EdmEntityObject。有解决办法吗?
    • 在另一个 SO 问题中找到了您的答案:stackoverflow.com/a/18603494/1197130
    猜你喜欢
    • 1970-01-01
    • 2013-09-05
    • 1970-01-01
    • 2013-08-14
    • 2013-09-23
    • 1970-01-01
    • 2013-04-20
    • 1970-01-01
    • 2016-02-07
    相关资源
    最近更新 更多