Im building a WebAPI OData solution that handles untyped entity objects, as described in this excellent post. Like that post, I define my EdmModel upfront, and use the MapODataRoute method and pass in the model to use:
config.Routes.MapODataRoute("odata", "odata", ModelBuilder.GetEdmModel());
However, this does not seem to work with ODataQueryOptions parameter in my methods:
Get(ODataQueryOptions query)
{
}
It gives the following error: The given model does not contain the type 'System.Web.Http.OData.IEdmEntityObject'. Parameter name: elementClrType
Is there any way to get ODataQueryOptions to work with MapODataRoute?
You should build the ODataQueryOptions manually in your controller action in untyped mode. Sample code follows,
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);
Ive managed to do it as follows:
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;
}
This works for most query options, but crashes with $select and $expand: The type 'Collection([Org.Microsoft.Product Nullable=False])' is not an entity type. Only entity types support $select and $expand. Is there a way to avoid this exception gracefully when a client tries to filter with $select and $expand, or should i just write something like
if (Request.RequestUri.Query.Contains("select")) { return errormessage }
Also, and more importantly, how would one apply these query options to an EdmEntityObjectCollection which gets returned in the first method?
queryOptions.ApplyTo(collectionProduct.AsQueryable()); // wont work...
(perhaps it is better practice to dynamically build your collection in regards to the query options anyway)