Asp.net web api MapODataRoute和ODataQueryOptions

Asp.net web api MapODataRoute和ODataQueryOptions,asp.net-web-api,odata,Asp.net Web Api,Odata,我正在构建一个WebAPI OData解决方案,用于处理非类型化实体对象,如中所述。像那篇文章一样,我预先定义了我的EdmModel,并使用MapODataRoute方法并传入要使用的模型: config.Routes.MapODataRoute("odata", "odata", ModelBuilder.GetEdmModel()); 但是,在我的方法中,这似乎不适用于ODataQueryOptions参数: Get(ODataQueryOptions query) { } 它给出以下错

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

config.Routes.MapODataRoute("odata", "odata", ModelBuilder.GetEdmModel());
但是,在我的方法中,这似乎不适用于ODataQueryOptions参数:

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


有没有办法让ODataQueryOptions与MapODataRoute一起使用?

您应该在非类型化模式下的控制器操作中手动构建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);

我做到了以下几点:

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...

(也许最好是根据查询选项动态构建集合)

Hi Raghuram,谢谢你的回答,这正是我一直在做的,请参阅我回答中的代码。但是,它会抛出$select和$EXPLAND的错误…作为一个补充说明,如果执行此操作,则似乎不需要将返回的集合定义为
IQueryable
。在返回到
IEnumerable
之前,我一直被串行化错误绊倒。请注意,对于更高版本,此方法被标记为过时。使用
System.Web.Http.OData.Extensions.HttpRequestMessageExtensions.ODataProperties(请求).Path
。传递给
ODataQueryContext
的edmType是元素类型。因此,如果
ODataPath.EdmType
是一个集合,那么应该取出元素类型并使用它。我会更新我的答案来解决这个问题。另外,关于ApplyTo。我们不支持非类型化ODataQueryOptions上的ApplyTo,因为不涉及CLR类型,并且IQueryable需要CLR类型。因此,您应该自己在后端应用ODataQueryOptions,然后将结果转换为
EdmEntityObjectCollection
。这篇博文可以给你一些指导——嗨,RaghuRam,有没有一种方法可以用非类型的集合实现$select$过滤器工作正常,但当我们循环处理数据并仅TrySetPropertyValue$select子句中的属性时,将返回完整的EdmentyObject(包含所有属性),而不是仅包含选定属性的EdmentyObject。有解决方法吗?在另一个SO问题中找到了答案: