Quantcast
Channel: ASPNETWebStack Issue Tracker Rss Feed
Viewing all articles
Browse latest Browse all 7215

Commented Unassigned: OData Controller Async HttpWebResponse HTTP 406 [1436]

$
0
0
I am trying to implement an odata query with async and support for $select and $expand. I can get everything working when I create a regular sync method returning HttpResponseMessage, but as soon as I make it async and return Task<HttpResponseMessage> I start getting 406 error responses. Is this a bug with the OData MediaType Formatters or am I doing something wrong?

I followed Sample #4 [here](https://aspnetwebstack.codeplex.com/wikipage?title=%24select%20and%20%24expand%20support&referringTitle=Specs) and I got it working just fine.

```C#
public class EntriesController : ODataController
{
public HttpResponseMessage Get(ODataQueryOptions<CatalogEntry> opts)
{
var db = new IntegrationCatalog();
var query = opts.ApplyTo(db.Entries.AsNoTracking());
var result = query;
//var result = (await query.ToListAsync()).AsQueryable();
return CreateQueryableResponse(Request, result);
}

private static HttpResponseMessage CreateQueryableResponse(HttpRequestMessage request, IQueryable queryable)
{
MethodInfo mi = typeof(EntriesController).GetMethod("CreateQueryableResponseImpl", BindingFlags.Static | BindingFlags.NonPublic);
mi = mi.MakeGenericMethod(queryable.ElementType);
return mi.Invoke(null, new object[] { request, queryable }) as HttpResponseMessage;
}

private static HttpResponseMessage CreateQueryableResponseImpl<T>(HttpRequestMessage request, IQueryable<T> response)
{
return request.CreateResponse(response as IQueryable<T>);
}
}
```

However, as soon as I change the method to async it starts returning an http 406 on me.

```C#
public async Task<HttpResponseMessage> Get(ODataQueryOptions<CatalogEntry> opts)
{
var db = new IntegrationCatalog();
var query = opts.ApplyTo(db.Entries.AsNoTracking());
//var result = query;
var result = (await query.ToListAsync()).AsQueryable();
return CreateQueryableResponse(Request, result);
}
```
Comments: So this was my misuse and not a bug. When calling the EF ToListAsync() method it returns an List<object> so calling Queryable.ElementType returned type object which is incorrect. I had to modify the reflection code to also perform a Enumerable.Cast<T> on the returned list and all is working now. The real bug to me is returning a 406 in this situation. I do understand that no media type formatter was able to format the IEnumerable<object> but this is clearly a server side error and had nothing to do with the Request or the Accept headers. Below is my code which is not optimized but at least demonstrates a true async queryable with $select and $expand support. ```C# public class EntriesController : ODataController { public async Task<HttpResponseMessage> Get(ODataQueryOptions<CatalogEntry> opts) { using (var db = new MyContext()) { var query = opts.ApplyTo(db.Entries.AsNoTracking()); var queryableType = query.ElementType; var result = (await query.ToListAsync()); return CreateEnumerableResponse(Request, result, queryableType); } } static HttpResponseMessage CreateEnumerableResponse(HttpRequestMessage request, IEnumerable enumerable, Type queryableType) { MethodInfo castOfT = typeof(Enumerable).GetMethod( "Cast", BindingFlags.Static | BindingFlags.Public, null, new[] { typeof(IEnumerable<>).MakeGenericType(queryableType) }, null); castOfT = castOfT.MakeGenericMethod(queryableType); var castedEnumerable = castOfT.Invoke(null, new object[] { enumerable }); MethodInfo mi = typeof(EntriesController).GetMethod("CreateEnumerableResponseImpl", BindingFlags.Static | BindingFlags.NonPublic); mi = mi.MakeGenericMethod(queryableType); return mi.Invoke(null, new object[] { request, castedEnumerable }) as HttpResponseMessage; } static HttpResponseMessage CreateEnumerableResponseImpl<T>(HttpRequestMessage request, IEnumerable<T> response) { return request.CreateResponse(response as IEnumerable<T>); } } ```

Viewing all articles
Browse latest Browse all 7215

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>