Introduction
In this article, I want to give an overview of the OData protocol: what it is, how it works, where it make sense to use it.
Background
Open Data Protocol (or OData, http://www.odata.org) is an open protocol for sharing data. It is built upon AtomPub (RFC 5023), itself an extension of Atom Publishing Protocol (RFC 4287). OData is a REST (Representational State Transfer) protocol; therefore a simple web browser can view the data exposed through an OData service. OData specs are under Microsoft Open Specification Promise (OSP).
The basic idea behind OData is to use a well known data format (Atom feed) to expose a list of entities. AtomPub extends the basic Atom Protocol by allowing not only read but the whole set of CRUD operations. OData extends AtomPub by enabling simple queries over feeds. OData also typically exposes a collection of entity sets with a higher-level grouping feed where you see all the feeds available.
Example
To illustrate those concepts, let's look at the OData website (http://www.odata.org). It exposes its data with an OData service: http://services.odata.org/website/odata.svc. You can simply browse that page and it will return you an XML document listing the different entity sets available:
="1.0"="utf-8"="yes"
<service xml:base="http://services.odata.org/Website/odata.svc/"
xmlns:atom="http://www.w3.org/2005/Atom"
xmlns:app="http://www.w3.org/2007/app"
xmlns="http://www.w3.org/2007/app">
<workspace>
<atom:title>Default</atom:title>
<collection href="ODataConsumers">
<atom:title>ODataConsumers</atom:title>
</collection>
<collection href="ODataProducerApplications">
<atom:title>ODataProducerApplications</atom:title>
</collection>
<collection href="ODataProducerLiveServices">
<atom:title>ODataProducerLiveServices</atom:title>
</collection>
</workspace>
</service>
This list of entity sets (or feeds) is called a workspace in OData.
Now, let's look at one of those feeds, for instance, the data consumers (ODataConsumers). The collection has an href
XML attribute indicating how to build the URL to get to it: http://services.odata.org/website/odata.svc/ODataConsumers. This URL also returns an XML document, an Atom feed.
Now, if you look at it in Internet Explorer, you'll view it in a feed reader view. To be able to view the raw XML, you must go to your Internet Options, in the Content tab:
At the bottom, press the Settings button under the Feeds and Web Slices section. In the Settings screen, make sure to turn off feed reading view.
You'll probably need to re-open the browser or at least the tab to view the raw XML.
Now, if we look at the XML, it's a standard Atom feed: it has a title, an ID, a time when it was updated, and a bunch of entries. The entries are the actual data. If we look at an entry:
<entry>
<id>http://services.odata.org/Website/odata.svc/ODataConsumers(2)</id>
<title type="text">OData Explorer</title>
<summary type="text">A Silverlight application that can browse OData Services.
It is available as part of the OData SDK Code Samples, and is available
online at Silverlight.net/ODataExplorer.</summary>
<updated>2010-06-26T17:46:31Z</updated>
<author>
<name />
</author>
<link rel="edit" title="ODataConsumer" href="ODataConsumers(2)" />
<category term="ODataServices.ODataConsumer"
scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme" />
<content type="application/xml">
<m:properties>
<d:Id m:type="Edm.Int32">2</d:Id>
<d:Name>OData Explorer</d:Name>
<d:Description>A Silverlight application
that can browse OData Services. It is available as part
of the OData SDK Code Samples, and is available online
at Silverlight.net/ODataExplorer.</d:Description>
<d:ApplicationUrl>http://silverlight.net/ODataExplorer</d:ApplicationUrl>
</m:properties>
</content>
</entry>
The entry contains an ID and a few other properties, most importantly, content. Now the content contains standard EDM data (Entity Data Model). Typically, the content properties are the same for each entry so you can display the data in a tabular format.
Queries
Now an entity set feed gives you access to the entire entity set. OData allows you to query the entity set through the feed, by manipulating the URL.
For instance, let's say we would just like to retrieve the first three entries of the feed; we would query the following URL: http://services.odata.org/website/odata.svc/ODataConsumers?$top=3. We basically apply a top operator on the data consumers URL. Here is a non-comprehensive list of things we could do to query the feed differently:
|
$skip=<n> | Skips the n first elements of the feed. | Browse... |
$orderby=<property-name> | Orders the results by a given property. | Browse... |
$filter=<filter expression> | Filters the feed given a filter expression. | Browse... |
For a comprehensive list of the different query string options, see http://www.odata.org/developers/protocols/uri-conventions#QueryStringOptions. The OData query system is quite powerful, although not as powerful as SQL.
A good tool to get familiar with the different ways to query an OData service is available at http://www.silverlight.net/content/samples/odataexplorer. It is a free Silverlight application allowing you to query an OData service and showing the results in a tabular format.
Updates
OData isn't only about querying. It enables CRUD operations. Those are performed by using different HTTP verbs (GET for reading, PUT for creating, POST for updating, and DELETE for deleting).
JSON
By default, an OData service returns Atom XML format. It also supports JSON. In order to receive a JSON representation, this must be encoded in the HTTP header. See http://www.odata.org/developers/protocols/ operations#RepresentationFormatsAndContentTypeNegotiation for more details.
When to use OData
Why would you want to use OData instead of your own XML format (e.g., SOAP based)? In general, OData is a standard, it is therefore understood by an increasing number of clients. Specifically, it is understood by the .NET Framework: you can do LINQ queries to an OData service from client code. It is also understood by Microsoft Excel 2010 (for Pivot Table).
OData therefore acts as an ubiquitous data format for lists. It is less ubiquitous than a SQL or ODBC source, but it allows more flexibility in how the data is stored and presented.
An especially useful scenario for me is a replacement of the classic Get<EntityName>By<Criteria> Web Services. We've all seen those GetAllEmployees
, GetEmployeeByID
, GetEmployeesByDepartment
, and so forth. The implementation of those services is boring, and you eventually need to add new web methods for new criteria (this means a lot of code duplication, hence maintenance problems). OData would allow the client to dictate the criteria. You write the service once and many clients can use it differently.