Table of Contents
- Introduction
- Roadmap
- OData
- Query Options
- Setup Solution
- OData Endpoints
- $top
- $filter
- $orderby
- $orderby with $top
- $skip
- Standard filter operators
- Standard query functions
- Paging
- QueryOptions Constraints
- AllowedQueryOptions
- AllowedOrderByProperties
- AllowedLogicalOperators
- AllowedArithmeticOperators
- Conclusion
- References
Introduction
This is the last article of the RESTful series in which I’ll explain how you can leverage OData capabilities in ASP.NET WebAPI. I’ll explain what OData is and we’ll create OData enabled RESTful services. I’ll try to keep the article very concise with less theory and more practical implementations.
Roadmap
The following is the roadmap I have setup to learn WebAPI step by step,
- RESTful Day #1: Enterprise-level application architecture with Web APIs using Entity Framework, Generic Repository pattern and Unit of Work.
- RESTful Day #2: Inversion of control using dependency injection in Web APIs using Unity Container and Bootstrapper
- RESTful Day #3: Resolve dependency of dependencies using Inversion of Control and dependency injection in ASP.Net Web APIs with Unity Container and Managed Extensibility Framework (MEF)
- RESTful Day #4: Custom URL Re-Writing/Routing using Attribute Routes in MVC 4 Web APIs
- RESTful Day #5: Basic Authentication and Token-based custom Authorization in Web APIs using Action Filters
- RESTful Day #6: Request logging and Exception handing/logging in Web APIs using Action Filters, Exception Filters and NLog
- RESTful Day #7: Unit Testing and Integration Testing in WebAPI using NUnit and Moq framework (Part1)
- RESTful Day #8: Unit Testing and Integration Testing in WebAPI using NUnit and Moq framework (Part 2)
- RESTful Day #9: Extending OData support in ASP.NET Web APIs
I’ll purposely use Visual Studio 2010 and .net Framework 4.0 because there are a few implementations that are very hard to find in .Net Framework 4.0, but I’ll make it easy by showing how we can do it.
OData
OData is a protocol that provides a flexibility of creating queryable REST services. It provides certain query options through which the on demand data can be fetched from the server by the client over HTTP.
The following is the definition from ASP.NET,
“The Open Data Protocol (OData) is a data access protocol for the web. OData provides a uniform way to query and manipulate data sets through CRUD operations (create, read, update, and delete).”
More elaborated from,
“OData defines parameters that can be used to modify an OData query. The client sends these parameters in the query string of the request URI. For example, to sort the results, a client uses the $orderby parameter:
http://localhost/Products?$orderby=Name
The OData specification calls these parameters query options. You can enable OData query options for any Web API controller in your project — the controller does not need to be an OData endpoint. This gives you a convenient way to add features such as filtering and sorting to any Web API application.”
Suppose our product table in the database contains more than 50000 products and we want to fetch only the top 50 products based on certain conditions like product id or price or name, then as per our current implementation of the service, I’ll have to fetch all the products from the server database and filter them on client or another option could be that I fetch the data at server only and filter the same and send the filtered data to client. In both the cases I am bearing a cost of writing an extra code of filtering the data. Here comes OData in picture. OData allows you to create services that are queryable. If the endpoints of the exposed services are OData enabled or supports OData query options then the service implementation would be in such a way that it considers the OData request and process it accordingly. So had that request for 50 records been an OData request, the service would have fetched only 50 records from the server. Not only filtering, but OData provides features like searching, sorting, skipping the data, selecting the data too. I’ll explain the concept with practical implementation. We’ll use our already created service and modify them to be enabled for OData query options.

Query Options
The following are the OData query options that ASP.NET WebAPI supports,
- $orderby: Sorts the fetched record in particular order like ascending or descending.
- $select: Selects the columns or properties in the result set. Specifies which all attributes or properties to include in the fetched result.
- $skip: Used to skip the number of records or results. For e.g. I want to skip first 100 records from the database while fetching complete table data, then I can make use of $skip.
- $top: Fetches only top n records. For e.g. I want to fetch top 10 records from the database, then my particular service should be OData enabled to support $top query option.
- $expand: Expands the related domain entities of the fetched entities.
- $filter: Filters the result set based on certain conditions, it is like where clause of LINQ. For e.g. I want to fetch the records of 50 students who have scored more than 90% marks, and then I can make use of this query option.
- $inlinecount: This query option is mostly used for pagination at client side. It tells the count of total entities fetched from the server to the client.
Setup Solution
When you take the code base from my last article and open it in visual studio, you’ll see the project structure something like as shown in below image,
The solution contains the WebAPI application and related projects.
Step 1: Click on Tools, Library Package manager, then click Package Manager Console.

Step 2: In Package manager console, select default project as WebApi and run the command:
Install-Package Microsoft.AspNet.WebApi.OData -Version 4.0.0
Note that, since we are using VS 2010 and .Net framework 4.0, we need to install OData libraries compatible to it.

The command will download a few dependent packages and reference the dll in your project references. You’ll get the OData reference dll in your project references,

Our project is set to make OData endpoints. You can create new services. I’ll modify my existing services to demonstrate the OData working.
OData Endpoints
Open the ProductController class in WebAPI project and got to Get() method. This method fetches all the product records from the database. The following is the code,
- [GET("allproducts")]
- [GET("all")]
- public HttpResponseMessage Get()
- {
- var products = _productServices.GetAllProducts();
- var productEntities = products as List < ProductEntity > ? ? products.ToList();
- if (productEntities.Any())
- return Request.CreateResponse(HttpStatusCode.OK, productEntities);
- throw new ApiDataException(1000, "Products not found", HttpStatusCode.NotFound);
- }
Just run the application, we get,

Append/help in the URL and press enter, you’ll see the test client.

Since our product controller is secured, we need to get an authenticated token from the service and use the same to access product Controller methods. To read about WebAPI security, refer this article. Click on POST authenticate API method and get the TestAPI page of test client,

Let’s send the request with credentials now. Just add a header too with the request. Header should be like,
Authorization : Basic YWtoaWw6YWtoaWw=
Here "YWtoaWw6YWtoaWw=" is my Base64 encoded user name and password in database i.e. akhil:akhil
If authorized, you’ll get a Token. Just save that token for making further calls to product controller.
Now open your product controller’s “allproducts” endpoint in test client,

Test the endpoint,

We get response with all the 6 products,

I’ll use this controller method and make it OData endpoint and perform several query options over it.
Add an attribute named [Queryable] above the method and in Request.CreateResponse mark the productEntities to productEntities.AsQueryable().
- [Queryable]
- [GET("allproducts")]
- [GET("all")]
- public HttpResponseMessage Get()
- {
- var products = _productServices.GetAllProducts().AsQueryable();
- var productEntities = products as List < ProductEntity > ? ? products.ToList();
- if (productEntities.Any())
- return Request.CreateResponse(HttpStatusCode.OK, productEntities.AsQueryable());
- throw new ApiDataException(1000, "Products not found", HttpStatusCode.NotFound);
- }
Now test the API with $top query option,

Here in the above endpoint, I have just appended “?$top=2” in the endpoint of the service i.e. like we append query strings. This statement means that I want to fetch only top two products from the service and the result is,
We get only two products. So you can see here that it was very simple to make a service endpoint query able, and we did not have to write a new service to achieve this kind of result. Let us try few more options.
$filter
You can perform all the filtering over the records with this option. Let us try $filter query option. Suppose we need to fetch all the products whose name is “computer”. You can use the same endpoint with filtering as shown below.

I used $filter=ProductName eq 'computer' as a query string, which means fetching product having product name “computer”, as a result we get only one record from products list because there was only one record having product name as “computer”.

You can use filter in many different ways as shown below,
Return all products with name equal to “computer”.
http://localhost:50875/v1/Products/Product/allproducts?$filter=ProductName eq "computer"
Return all products with id less than 3.
http://localhost:50875/v1/Products/Product/allproducts?$filter=ProductId lt 3

Logical operators: Return all products where id >= 3 and id <= 5.
http://localhost:50875/v1/Products/Product/allproducts?$filter=ProductId ge 3 and ProductId le 5
String functions: Return all products with “IPhone” in the name.
http://localhost:50875/v1/Products/Product/allproducts?$filter=substringof('IPhone',ProductName)

Filter option could also be applied on date fields as well.
$orderby
Let us try orderby query with the same endpoint.
Return all products with sorting on product name descending
http://localhost:50875/v1/Products/Product/allproducts?$orderby=ProductName desc
Output:
[
{
"ProductId":6,
"ProductName":"Watch"
},
{
"ProductId":8,
"ProductName":"Titan Watch"
},
{
"ProductId":9,
"ProductName":"Laptop Bag"
},
{
"ProductId":1,
"ProductName":"Laptop"
},
{
"ProductId":11,
"ProductName":"IPhone 6S"
},
{
"ProductId":10,
"ProductName":"IPhone 6"
},
{
"ProductId":4,
"ProductName":"IPhone"
},
{
"ProductId":12,
"ProductName":"HP Laptop"
},
{
"ProductId":2,
"ProductName":"computer"
},
{
"ProductId":5,
"ProductName":"Bag"
}
]





Rajalingam SubramaniamPosted Oct 8, 2018, 9:20 AM
I am new to ASP.NET web api learning, thanks for sharing the code and DB script, even this very useful for complete understanding ASP.NET web api with authentication way....
Hamid KhanPosted Dec 21, 2017, 1:01 PM
Very nice explanation in simple way, Easy to understand..... Thanks Akhil Sir..
Kuppurasu NagarajPosted May 6, 2016, 9:16 AM
Nice Sharing..
Gowtham KPosted Apr 13, 2016, 12:27 PM
Good One, Thanks for sharing:)
Rahul Kumar SaxenaPosted Apr 4, 2016, 7:44 AM
Good Show
K P Singh ChundawatPosted Mar 31, 2016, 3:43 AM
Great work Akhil Mittal
Amatya AgyeyPosted Mar 31, 2016, 1:12 AM
Thats Fantastic.. Keep it up
Debasis SahaPosted Mar 31, 2016, 1:05 AM
Good One..
Vignesh ManiPosted Mar 30, 2016, 5:55 AM
Good one
Shridhar SharmaPosted Mar 30, 2016, 1:01 AM
very nice sir
Jaipal ReddyPosted Mar 30, 2016, 12:23 AM
Great series of article. . Thank you sir. .
Vikas SharmaPosted Mar 29, 2016, 11:31 PM
very nice...
Ankur MistryPosted Mar 29, 2016, 11:17 PM
Great article, nicely explained
Kashif SohailPosted Mar 29, 2016, 1:57 PM
Nice article
Saillesh PawarPosted Mar 29, 2016, 1:10 PM
Hats off.. Akhil sir i have query related to day 1 where you have implemented repository pattern in web api. May i ping you personally. I would be extremely helpful to you.
Asfend YarPosted Mar 29, 2016, 12:43 PM
Good One.
Mohammed IbrahimPosted Mar 29, 2016, 11:07 AM
nice