Saturday, August 9, 2014

Expose OData endpoint in Web API/ MVC

In today's IT industry OData is one of the common buzzwords. People are talking about OData and OData services. What can OData do? And in which scenario it fit best? We will discuss them a little and then we will see how to expose the OData endpoints in our Web API application.

So, let's discuss what OData is. OData stands for Open Data protocol that was introduced by Microsoft in an open release context then it was widely adapted by the industry. It provides an idea of uniform data access.

We know that today's IT world is on top of data, data may come from various sources and multiple ways and data will be valuable only if we can categorize it easily. Hence the idea of a uniform data access mechanism was created. The industry thought that data might come from multiple locations and multiple protocols but it would be great if we can access data uniformly from all platforms.

For example, an analyst wanted to get data from a Windows data marketplace and SQL Azure using the same mechanism, hence the concept of OData was created.

Another example of an OData endpoint is something like that. Let's think of an e-commerce organization sharing their data with a vendor and one vendor wants to get a report based on region by providing a region code where another wants to get a sales report by country by providing a country key. But surprisingly all the data is stored in a single place or in technical terms, in a single table. 

The problem is that if tomorrow another vendor demands another type of report by supplying another key then it needs to add another function to serve the needs. This is the exact situation where OData can rescue us.

Ok, so we have learned the fundamental idea behind OData, now we will implement an OData endpoint in our Web API application. In this example we have used Web API 2.0 to implement an OData service, so please ensure that you have installed the OData package in your application before executing this code.




To implement OData service in Web API, we have to inherit our controller from OData Controller or we can inherit our controller from EntitySetController<TEntity,TKey> too. The reason is, EntitySetController is inherited from ODataController. Here is the inheritance hierarchy.


Now, in this example we have used Entity Framework to fetch data from Database and here is the data model for this example.

The data model is very simple, just we have only one Model called “UserMaster” . Now, we will implement OData endpoint in application.


Create OData endpoint using OData controller
As we discuss , we can inherit our controller from ODataController . In this example OdataController is our OData controller and it has inherited from ODataController.

    public class OdataController : ODataController

    {
        ConnectionStrign _db = new ConnectionStrign();

        [EnableQuery]
        public IQueryable<UserMaster> Get()
        {
            return _db.UserMaster.AsQueryable<UserMaster>();
        }
    }

The implementation is very simple, just we are returning IQuerable of the model , so that client can able to fire farther query into the returned data. The Get()action is decorated with [EnableQuery] attribute.

Register OData endpoint
This is the process where we will register the OData endpoint .Just open WebApiConfig.cs file of the application and modify accordingly.

public static class WebApiConfig
    {
        private static IEdmModel GenerateEdmModel()
        {
            var builder = new ODataConventionModelBuilder();
            builder.EntitySet<UserMaster>("Odata");
            return builder.GetEdmModel();
        }

        public static void Register(HttpConfiguration config)
        {
            config.MapHttpAttributeRoutes();
     //Expose Odata route
            config.Routes.MapODataRoute("odata", "odata", GenerateEdmModel());

            config.Routes.MapHttpRoute(
                name: "DefaultApi",
                routeTemplate: "api/{controller}/{id}",
                defaults: new { id = RouteParameter.Optional }
            );
        }
    }

The GenerateEdmModel() function is to generate Edm matadata for OData service.

private static IEdmModel GenerateEdmModel()
 {
            var builder = new ODataConventionModelBuilder();
            builder.EntitySet<UserMaster>("Odata");
            return builder.GetEdmModel();
        }

We have used EntitySet function which will register an entity set as a part of the model and returns an object that can be uses to configure the entity set.

Fine, we have completed our OData setup, now we can consume the OData endpoint from client. In this example I am using Fiddler as client. But one typical OData client could be anything like web browser, Other .NET application or JavaScript application etc.

In fiddler I am trying to access the below url and we are seeing that the data has come from endpoint.


As we discussed EntitySetController class is derived from ODataController and so that we can use EntitySetController too to expose OData  endpoint . Let’s see the implementation.

Expose OData endpoint using EntitySetControler<TEntity,TKey>
The implementation is very similar with the ODataController class just we are passing the parameters to EntitySetController generic class. The first parameter is the actual Model and the second parameter is the key of the model. In this example, the key property of the UserMaster model is integer type so that  

public class UserEntityController : EntitySetController<UserMaster,int>
    {
        ConnectionStrign _db = new ConnectionStrign();
        public override IQueryable<UserMaster> Get()
        {
            return _db.UserMaster.AsQueryable();
        }
    }

We are passing “int” as second argument. It could be any data type depending on model. The all other setting will remain same.

Conclusion:-
In this article we have learned to expose Odata endpoint in Web API. OData is helpful when application don’t know the query of end client.  

1 comment: