2
votes

I'm implementing an generic base controller for my applications OData Controllers. This controller had a method like:

[EnableQuery(AllowedQueryOptions = AllowedQueryOptions.All)]
public virtual async Task<IHttpActionResult> Get(ODataQueryOptions<TEntity> options)
{
    var source = db.Set<TEntity>().Where(e => !e.IsDeleted);
    var queryable = (IQueryable<TEntity>)options.ApplyTo(source);

    var entities = await queryable.ToListAsync();
    return Ok(entities);
}

This controller action works perfectly fine until you try to use something like $expand or $select, which actually modifies the entity itself. This is because after applying the ODataQueryOptions, we can't be sure that we still have an IQueryable anymore.

To fix this issue, I removed my cast to IQueryable:

[EnableQuery(AllowedQueryOptions = AllowedQueryOptions.All)]
public virtual async Task<IHttpActionResult> Get(ODataQueryOptions<TEntity> options)
{
    var source = db.Set<TEntity>().Where(e => !e.IsDeleted);
    var queryable = options.ApplyTo(source);

    var entities = await queryable.ToListAsync();
    return Ok(entities);
}

Now, every call to this controller actions returns a HTTP status code of 406 (not acceptable), regardless if I use $expand/$select or not.

Entities is a List at the moment it gets passed to Ok(), could this be the problem? Does the ODataContentFormatter have problems with List? How are you supposed to return this kind of result, then?

2
Did you solve this in the end?gorillapower

2 Answers

0
votes

for enabling $select and $expand you should return queryables so you need to keep returning the IQueryable.

your action should looks like this

[Queryable]
[EnableQuery(AllowedQueryOptions = AllowedQueryOptions.All)]
public virtual async Task<IHttpActionResult> Get(ODataQueryOptions<TEntity> options)
{
    var source = db.Set<TEntity>().Where(e => !e.IsDeleted);
    var queryable = options.ApplyTo(source);

    var entities = await queryable.ToListAsync();
    return Ok(entities);
}

To enable OData query options globally, call EnableQuerySupport on the HttpConfiguration class at startup:

public static void Register(HttpConfiguration config)
{
    // ...

    config.EnableQuerySupport();

    // ...
}
0
votes

Make sure the following is in your startup:

ODataConventionModelBuilder builder = new ODataConventionModelBuilder();
// configure your entities here
var model = builder.GetEdmModel();
config.Select().Expand().Filter().OrderBy().MaxTop(null).Count();
config.Routes.MapODataServiceRoute("ODataRoute", "data", model);