2

I have an ASP.NET Web API project, and I want to use oData filters in the project, with the ASP.NET oData preview package. This means I need to use IQueryable as the response type.

Unfortunately, the consumer requires the response wrapped like so:

{
   "total": 2,
   "success": true,
   "data": [ 
           { object1 },
           { object2 } ]
}

I created a wrapper object which assigns the IQueryable response from my original version to the "data" property, and sets the values for the "total" and "success" properties as well. This creates the JSON response the consumer is looking for. But it's no longer IQueryable, which means I can't implement oData filters.

I was hoping to take my wrapper object and make it implement IQueryable by setting its enumerators, etc. However, I don't think this will work because I have to assign the Provider and Expression properties to implement the interface, and I don't know what I should put there. I'm using a Repository pattern with IoC, and the EntityFramework Code First data access is in a separate project, with concrete objects assigned to the interface placeholders using Ninject. Perhaps I can abstract out the interfaces all the way from the data access layer so that the the Repository objects carry a reference to an IQueryProvider. Do you think this would work, and allow it to support the automated oData integration?

phuzi
  • 12,078
  • 3
  • 26
  • 50
devlord
  • 4,054
  • 4
  • 37
  • 55

1 Answers1

3

Here's how you do it. Behind the scenes, [Queryable] just creates an instance of ODataQueryOptions and then applies it to the queryable you return. The good news is that you can parameter bind ODataQueryOptions and have code that looks like this:

public Wrapper<MyObject> Get(ODataQueryOptions<MyObject> queryOptions)
{
    IQueryable<MyObject> queryResults = queryOptions.ApplyTo(dbSet);
    return Wrap(queryResults);
}

You don't even need [Queryable] anymore because you're doing what it would have done for you. Hope that helps.

devlord
  • 4,054
  • 4
  • 37
  • 55
Youssef Moussaoui
  • 12,187
  • 2
  • 41
  • 37
  • Wow, thanks. That's a lot easier than what I was going to try: http://stackoverflow.com/questions/1839901/how-to-wrap-entity-framework-to-intercept-the-linq-expression-just-before-execut – devlord Feb 06 '13 at 06:17
  • The setup seems to work for this, however, when a filter is applied via `queryOptions.ApplyTo(repoResult)`, it doesn't actually change the result. Do I have to persist the options all the way to the entity framework dbSet? Or can't I apply it to any IQueryable result returned from my Repository class? – devlord Feb 07 '13 at 04:17
  • ApplyTo doesn't change the IQueryable you pass in. It just returns an IQueryable with the results of the query. Can you clarify what you mean? – Youssef Moussaoui Feb 07 '13 at 07:04
  • I know this is an old post, but I'm trying to do this and I still get the EntitySet json response. I need to get "success" property in the response. I'm using OData v4 – Piyey Apr 24 '15 at 16:42