Overview of Open Data Protocol (ODP)

In this article you will learn about Open Data Protocol (ODP).

The Open Data Protocol (OData) is a protocol to request data through a query string.

The Open Data Protocol (OData) is a protocol to access data on the web. It provides a uniform way to query and manipulate data sets through CRUD operations.

This article shows how to create an OData v4 endpoint that supports Get operations.

This article has two sections:

  • Creating OData serviceGet methods.
  • Consuming OData service Get methods using AngularJS.

Why we need an OData Service?

Advantages

  1. OData is based on RESTful architecture, so we can retrieve data based on an URL query string.

  2. OData supports HTTP, Atom Pub as well as JSON format.

  3. It is very lightweight to use. Since it is lightweight, the performance is very good while interacting between client and service.

  4. It supports for any type of data source. Even you can use your own custom class as a data source.

  5. You can create your own custom methods and expose it.

  6. It supports different HTTP methods:

    1. GET: Gets one or many entries.
    2. POST: Create a new entry.
    3. PUT: Update an existing entry.
    4. DELETE: Remove an entry.

Limitations

  1. It is much less secure as it is purely URL based.
  2. As per my understanding, OData does not support every query operator in LINQ like Filter, Skip, Take etc.

Create the Visual Studio Project

In Visual Studio, from the File menu, select New > Project.

Expand Installed > Templates > Visual C# > Web, and select the ASP.NET Web Application template. Name the project "ODataServiceApp".

Web Application template

In the New Project dialog, select the Empty template. Click Web APIcheckbox. Click OK.

Application template

Install the OData Packages


OData Packages

From the Tools menu, select NuGet Package Manager > Package Manager Console. Run the following command in the Package Manager Console.

PM> Install-Package Microsoft.AspNet.OData

This command installs the latest OData NuGet packages.

Note: You can install OData either from Package Manager Console or Package Manager Console for Solution.

Add Model Classes

A model is a class that contains data entity in the application.

In Solution Explorer, Right-click the Model folder. From the context menu, select Add > Class.

Model

Add two model class Course.cs and Subject.cs under Model folder.

  1. using System;  
  2. using System.Collections.Generic;  
  3. using System.Linq;  
  4. using System.Web;  
  5. using System.ComponentModel.DataAnnotations;  
  6. namespace ODataServiceApp.Models  
  7. {  
  8.     publicclassCourse  
  9.     {  
  10.         [Key]  
  11.         publicString ID  
  12.         {  
  13.             get;  
  14.             set;  
  15.         }  
  16.         [Required]  
  17.         publicString Name  
  18.         {  
  19.             get;  
  20.             set;  
  21.         }  
  22.         publicString Description  
  23.         {  
  24.             get;  
  25.             set;  
  26.         }  
  27.         publicList < Subject > Subjects  
  28.         {  
  29.             get;  
  30.             set;  
  31.         }  
  32.     }  
  33. }  
  1. using System;  
  2. using System.Collections.Generic;  
  3. using System.ComponentModel.DataAnnotations;  
  4. using System.Linq;  
  5. using System.Web;  
  6. namespace ODataServiceApp.Models  
  7. {  
  8.     publicclassSubject  
  9.     {  
  10.         [Key]  
  11.         publicString ID  
  12.         {  
  13.             get;  
  14.             set;  
  15.         }  
  16.         [Required]  
  17.         publicString Name  
  18.         {  
  19.             get;  
  20.             set;  
  21.         }  
  22.     }  
  23. }  
The attributes [Key] and [Required] are all from. System.ComponentModel.DataAnnotations.

Inline data source

This example uses inline data sources. The below steps describe how to to create the inline data source.

Add a folder DataSource and add a class with name SampleDataSources.cs with the code below:
  1. using System;  
  2. using System.Collections.Generic;  
  3. using System.Linq;  
  4. using System.Web;  
  5. using ODataServiceApp.Models;  
  6. namespace ODataServiceApp.DataSource  
  7. {  
  8.     publicclassDemoDataSources  
  9.     {  
  10.         privatestaticDemoDataSources instance  
  11.             = null;  
  12.         publicstaticDemoDataSources Instance  
  13.         {  
  14.             get  
  15.             {  
  16.                 if (instance == null)  
  17.                 {  
  18.                     instance = newDemoDataSources();  
  19.                 }  
  20.                 return instance;  
  21.             }  
  22.         }  
  23.         publicList < Course > Courses  
  24.         {  
  25.             get;  
  26.             set;  
  27.         }  
  28.         publicList < Subject > Subjects  
  29.         {  
  30.             get;  
  31.             set;  
  32.         }  
  33.         private DemoDataSources()  
  34.         {  
  35.             this.Reset();  
  36.             this.Initialize();  
  37.         }  
  38.         publicvoid Reset()  
  39.         {  
  40.             this.Courses = newList < Course >  
  41.                 ();  
  42.             this.Subjects = newList < Subject >  
  43.                 ();  
  44.         }  
  45.         publicvoid Initialize()  
  46.         {  
  47.             this.Subjects.AddRange(newList <  
  48.             Subject > ()  
  49.             {  
  50.                 newSubject()  
  51.                     {  
  52.                         ID = "0",  
  53.                             Name = "C"  
  54.                     },  
  55.                     newSubject()  
  56.                     {  
  57.                         ID = "1",  
  58.                             Name = "C++"  
  59.                     },  
  60.                     newSubject()  
  61.                     {  
  62.                         ID = "2",  
  63.                             Name = "Data Structure"  
  64.                     },  
  65.                     newSubject()  
  66.                     {  
  67.                         ID = "3",  
  68.                             Name = ".Net"  
  69.                     }  
  70.             });  
  71.             this.Courses.AddRange(newList <  
  72.             Course >  
  73.             {  
  74.                 newCourse()  
  75.                 {  
  76.                     ID = "001",  
  77.                         Name = "MCA",  
  78.                         Subjects = newList < Subject >  
  79.                         {  
  80.                             Subjects[0],  
  81.                             Subjects[1]  
  82.                         },  
  83.                         Description =  
  84.                         "Master of Computer Application"  
  85.                 },  
  86.                 newCourse()  
  87.                 {  
  88.                     ID = "002",  
  89.                         Name = "MBA",  
  90.                         Description =  
  91.                         "Master of Business Application",  
  92.                         Subjects = newList < Subject >  
  93.                         {  
  94.                             Subjects[2],  
  95.                             Subjects[3]  
  96.                         }  
  97.                 },  
  98.                 newCourse()  
  99.                 {  
  100.                     ID = "003",  
  101.                         Name = "CA",  
  102.                         Description =  
  103.                         "Chartered Accountant",  
  104.                 },  
  105.                 newCourse()  
  106.                 {  
  107.                     ID = "004",  
  108.                         Name = "MA"  
  109.                 }  
  110.             });  
  111.         }  
  112.     }  
  113. }  
Add Controllers

Add two controller classes under the folder Controllers

First is controller for Courses,

 

  1. using System;  
  2. using System.Collections.Generic;  
  3. using System.Linq;  
  4. using System.Web;  
  5. using System.Web.Mvc;  
  6. using ODataServiceApp.DataSource;  
  7. using System.Web.Http;  
  8. using System.Web.OData;  
  9. namespace ODataServiceApp.Controllers  
  10. {  
  11.     [EnableQuery]  
  12.     publicclassCourseController:  
  13.         ODataController  
  14.         {  
  15.             publicIHttpActionResult Get()  
  16.             {  
  17.                 return Ok(DemoDataSources.Instance  
  18.                     .Courses.AsQueryable());  
  19.             }  
  20.         }  
  21. }  
2nd controller for Subjects,
  1. using System;  
  2. using System.Collections.Generic;  
  3. using System.Linq;  
  4. using System.Web;  
  5. using System.Web.Mvc;  
  6. using ODataServiceApp.DataSource;  
  7. using System.Web.Http;  
  8. using System.Web.OData;  
  9. namespace ODataServiceApp.Controllers  
  10. {  
  11.     [EnableQuery]  
  12.     publicclassSubjectsController:  
  13.         ODataController  
  14.         {  
  15.             publicIHttpActionResult Get()  
  16.             {  
  17.                 return Ok(DemoDataSources.Instance  
  18.                     .Subjects.AsQueryable());  
  19.             }  
  20.         }  
  21. }  
Configure the Endpoint

Modify the WebApiConfig.cs file under App_Startto configure the Endpoints.
  1. using System;  
  2. using System.Collections.Generic;  
  3. using System.Linq;  
  4. using System.Web.Http;  
  5. using ODataServiceApp.Models;  
  6. using Microsoft.OData.Edm;  
  7. using System.Web.OData.Batch;  
  8. using System.Web.OData.Builder;  
  9. using System.Web.OData.Extensions;  
  10. namespace ODataServiceApp  
  11. {  
  12.     publicstaticclassWebApiConfig  
  13.     {  
  14.         publicstaticvoid Register(  
  15.             HttpConfiguration config)  
  16.         {  
  17.             config.MapODataServiceRoute("odata",  
  18.                 null, GetEdmModel(),  
  19.                 newDefaultODataBatchHandler(  
  20.                     GlobalConfiguration.DefaultServer  
  21.                 ));  
  22.             config.EnsureInitialized();  
  23.         }  
  24.         privatestaticIEdmModel GetEdmModel()  
  25.         {  
  26.             ODataConventionModelBuilder builder  
  27.                 = newODataConventionModelBuilder();  
  28.             builder.Namespace =  
  29.                 "ODataServiceApp";  
  30.             builder.ContainerName =  
  31.                 "DefaultContainer";  
  32.             builder.EntitySet < Course > (  
  33.                 "Courses");  
  34.             builder.EntitySet < Subject > (  
  35.                 "Subjects");  
  36.             var edmModel = builder.GetEdmModel();  
  37.             return edmModel;  
  38.         }  
  39.     }  
  40. }  
Below URLs to call GET methods. 
  • Service document

    http://localhost:[portNumber]/

  • Service metadata

    http://localhost:[portNumber]/$metadata
  • Get Courses

    http://localhost:[portNumber]/Courses

  • Get Subjects

    http://localhost:[portNumber]/Subjects

  • Queries

    http://localhost:[portNumber]/Courses?$filter=contains(Description,'Computer')
    http://localhost:[portNumber]/Courses?$select=Name
    http://localhost:[portNumber]/Courses?$expand=Subjects
    http://localhost:[portNumber]/Subjects?$filter=contains(Name,'Structure')http://localhost:[portNumber]/Subjects?$select=Name

OData service creation is completed and now it’s time to consume it. It can be consumed in different ways; either using web application or web site etc. Scripting languages or frameworks can be used to consume the OData services. In the below example, websiteandAngularJS framework are used to consume OData service.

Consuming OData service Get methods

Steps to consume OData service Get methods

In Visual Studio, from the File menu, select New > Web Site.

Expand Installed > Templates > Visual C# > Web, and select the ASP.NET Empty Web Site template. Name the project "ODataWebAppClient".

ASP.NET Empty Web

In Solution Explorer, Right-click and select Add > HTML Page and name it as “Index.html”.

HTML Page

Index.htmlwith the code below:

  1. <!DOCTYPEhtml>  
  2. <html>  
  3.   
  4. <head>  
  5.     <title></title>  
  6.     <metacharset="utf-8" />  
  7.     <linkrel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.2/css/bootstrap.min.css">  
  8.         <scriptsrc="//code.jquery.com/jquery-2.1.3.min.js">  
  9.         </script>  
  10.         <scriptsrc="//ajax.googleapis.com/ajax/libs/angularjs/1.3.11/angular.min.js">  
  11.         </script>  
  12.         <scriptsrc="//cdnjs.cloudflare.com/ajax/libs/angular-ui-bootstrap/0.12.0/ui-bootstrap.min.js">  
  13.         </script>  
  14.         <scripttype="text/javascript">  
  15.             'use strict'; var app = angular.module('OData',  
  16.             []); app.controller("ODataController",  
  17.             ['$scope''$http', function ($scope,  
  18.             $http) { $scope.SubjectList = []; $scope.GetSubjectList  
  19.             = function () { $http({ method: 'GET',  
  20.             url: "http://localhost:52766/Subjects?$filter=contains(Name,'Structure')",  
  21.             async: true, cache: true, headers:  
  22.             { 'Content-Type': "application/json;  
  23.             charset=utf-8" } }) .success(function  
  24.             (data) { $scope.SubjectList = data.value;  
  25.             }) .error(function (data, status, headers,  
  26.             config) { alert(data.error.trim());  
  27.             }) }; $scope.GetSubjectList(); }]);  
  28.         </script>  
  29. </head>  
  30. <bodyng-app="OData" class="container">  
  31.     <divng-controller="ODataController" ng-class="row">  
  32.         <tableclass="table table-striped">  
  33.             <thead>  
  34.                 <tr>  
  35.                     <th>ID</th>  
  36.                     <th>Name</th>  
  37.                 </tr>  
  38.             </thead>  
  39.             <tbody>  
  40.                 <trng-repeat="iteminSubjectList">  
  41.                     <td>{{item.ID}}</td>  
  42.                     <td>{{item.Name}}</td>  
  43.                     </tr>  
  44.             </tbody>  
  45.         </table>  
  46.     </div>  
  47. </body>  
  48.   
  49. </html>  
Below CSS and scripts from CDN are used for the above example:
  1. <linkrel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.2/css/bootstrap.min.css">  
  2.     <scriptsrc="//code.jquery.com/jquery-2.1.3.min.js">  
  3.     </script>  
  4.     <scriptsrc="//ajax.googleapis.com/ajax/libs/angularjs/1.3.11/angular.min.js">  
  5.     </script>  
  6.     <scriptsrc="//cdnjs.cloudflare.com/ajax/libs/angular-ui-bootstrap/0.12.0/ui-bootstrap.min.js">  
  7.     </script>  
Output:

Output