Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ASP .NET MVC 4 WebApi: Manually handle OData queries

I have a Web Service made using the WebAPI provided by ASP .NET MVC 4. I know that the layer on top of which WebAPI works automatically handles OData Queries (such as $filter, $top, $skip), but what if I want to handle the filtering by myself?

I don't simply return data from my database, but I have another layer which adds some properties, makes some conversions etc. So querying ALL of my data, converting them and returning them to the WebAPI class for OData filtering isn't just good enough. It's of course terribly slow, and generally a crappy idea.

So is there a way to propagate the OData query parameters from my WebAPI entry point to the functions I call to get and convert the data?

For example, a GET to /api/people?$skip=10&$top=10 would call on the server:

public IQueryable<Person> get() {     return PersonService.get(SomethingAboutCurrentRequest.CurrentOData); } 

And in PersonService:

public IQueryable<Person> getPeople(var ODataQueries) {     IQueryable<ServerSidePerson> serverPeople = from p in dbContext.ServerSidePerson select p;     // Make the OData queries     // Skip     serverPeople = serverPeople.Skip(ODataQueries.Skip);     // Take     serverPeople = serverPeople.Take(ODataQueries.Take);     // And so on     // ...      // Then, convert them     IQueryable<Person> people = Converter.convertPersonList(serverPeople);     return people; } 
like image 220
frapontillo Avatar asked May 28 '12 08:05

frapontillo


1 Answers

I just stumbled across this old post and I'm adding this answer as it's now very easy to handle the OData queries yourself. Here's an example:

[HttpGet] [ActionName("Example")] public IEnumerable<Poco> GetExample(ODataQueryOptions<Poco> queryOptions) {     var data = new Poco[] {          new Poco() { id = 1, name = "one", type = "a" },         new Poco() { id = 2, name = "two", type = "b" },         new Poco() { id = 3, name = "three", type = "c" }     };      var t = new ODataValidationSettings() { MaxTop = 2 };     queryOptions.Validate(t);      //this is the method to filter using the OData framework     //var s = new ODataQuerySettings() { PageSize = 1 };     //var results = queryOptions.ApplyTo(data.AsQueryable(), s) as IEnumerable<Poco>;      //or DIY     var results = data;     if (queryOptions.Skip != null)          results = results.Skip(queryOptions.Skip.Value);     if (queryOptions.Top != null)         results = results.Take(queryOptions.Top.Value);      return results; }  public class Poco {     public int id { get; set; }     public string name { get; set; }     public string type { get; set; } } 
like image 177
qujck Avatar answered Sep 17 '22 19:09

qujck