Creating solutions that leverage AJAX data retrieval are relatively easy with the tools available today. However, creating solutions that depend on AJAX updates to server-side data stores remain time-consuming at best. Luckily, we have a few tools in our repertoire to make the job significantly easier: jQuery in the browser and OData (via WCF Data Services) on the server side. These frameworks not only help make developers’ lives easier, they do so in a web-friendly manner. In this article, I'll demonstrate how these technologies can help create robust, data-driven AJAX applications with very little hassle.
Microsoft created the OData protocol to easily expose and work with data in a web-friendly manner. OData achieves this level of web-friendliness by embracing ubiquitous web protocols such as HTTP, ATOM, and (most relevant to this article) JSON to expose Collections of Entries. At the core of these concepts is the referencing of data via Links (along with a new and intuitive querying and filtering language) to provide a very REST-ful, discoverable, and navigable way to present data over the web. In this way, OData is able to further enhance the value of its underlying protocols. OData leverages many of its underlying protocols’ features by heavily leveraging standard HTTP methods and response codes as meaningful and semantic communication features.
The easiest way to express OData’s power and simplicity is showing it in action. The code snippet in Figure 1 includes what should be relatively familiar jQuery code calling the root (feed) of an OData service to retrieve the various Collections it’s exposing.
$.getJSON( 'http://odata.netflix.com/Catalog?$format=json&$callback=?', function (data) { alert(data.d.EntitySets.join(', ')); } );
The jQuery call is pretty simple: the $.getJSON() utility method makes it easy to provide jQuery with a URL to execute a JSON request against, as well as a JavaScript method to execute once the response returns with data. The request URL in this example is straightforward: it’s the base URL to the NetFlix OData catalog with the special OData $format keyword instructing the service to return JSON data back to the browser, as well as the WCF Data Service keyword $callback that instructs the service to trigger our callback method.
Figure 2 shows the raw data that would be returned from this request. Because the request executed against the root feed URL, the OData protocol dictates that the NetFlix service respond with a list of the Catalogs available in this feed.

OData’s inherent discoverability is immediately apparent because—even though the service’s root URL is the only thing the client knows at this point—it has all the information it needs to navigate all the service’s exposed data.
Once the client retrieves a list of the Catalogs that the service exposes, it's able to append any one of those Catalog names to the root service URL to retrieve the contents (Entries) of that Catalog. The snippet in Figure 3 provides an example of this concatenation, effectively copying the original request, then adding /Titles to the end of the root service URL.
$.getJSON( netflixServiceUrl + '/Titles' + '?$format=json&$callback=?', function (data) { /* Do something with the data */ } );
Things really start to get interesting in Figure 4, which shows that the response containing the Catalog’s Entries provides much more than just its Entries’ basic information.

Notice that each Entry has a __metadata property that includes a uri property indicating that particular Entry’s URI. It's this URI that uniquely identifies this Entry, providing clients with a direct reference to the Entry. Thus, retrieving the details for a particular Entry is as easy as making another GET request to its URI (as shown in Figure 5).
function loadEntry(entryUri) { $.getJSON( entryUri + '?$format=json&$callback=?', function (data) { var renderedEntry = $('#entry-info-template').render(data.d); $('#entry-info').html(renderedEntry); } ); }
What’s more, if that Entry contains references to yet more Entries, they too will be exposed using this same method. Thus, the entire model is navigable using only GET requests.
Introducing jQuery Templating
In addition to the jQuery AJAX request to retrieve a specific Entry, Figure 5 also introduces the new jQuery templating extension. Upon successful completion of the AJAX request, the framework calls the templating plugin’s .render() method, executing token replacement and some simple evaluation functions against a given jQuery template object (for example, the template markup shown in Figure 6). The render method produces a jQuery object containing the rendered and transformed template, ready to be displayed in the browser.
One nice feature of the templating extension is that it inherently supports arrays of objects. Thus, the snippet $(‘#template’).render(\\[ entry1, entry2, entry 3 \\]) will return a collection of rendered markup objects, one for each of the Entry objects in the source array. Similar to the previous example, these two can be collectively appended to the DOM, making list population and other common operations against arrays incredibly painless.
Token Replacement
A templating engine’s primary purpose is replacing tokens in a template with data from a given source. As such, the jQuery templating engine provides straightforward syntax, making this replacement as easy as possible: $\\{\\[Property\\]\\}. For example, given the template in Figure 6, the $\\{Name\\}, $\\{Rating\\}, $\\{Runtime\\}, and $\\{Synopsis\\} placeholders would all be replaced with their correspondingly named properties (Name, Rating, Runtime, and Synopsis) on the model provided to the templating engine. The result of this transform would produce the markup shown in Figure 7.

Expression Evaluation
For those times when simple token replacement just won’t cut it, the jQuery templating engine provides a concise syntax to execute arbitrary JavaScript expressions: \\{\\{= \\[expression\\] \\}\\}. For example, the following snippet—placed anywhere in the template markup—would produce a very familiar JavaScript alert box:
\\{\\{= alert('I love jQuery!') \\}\\}
Additionally, the template engine natively supports the each and if/else constructs to help make template markup more readable and easier to maintain. Figure 8 shows examples of the three constructs.
{{if (Rating == 'G' || Rating == 'PG')}}Child friendly{{else}}Keep your children away!{{/if}}Cast
-
{{each(i,actor) Cast.results}}
- Name: ${actor.Name} {{/each}}
The OData querying examples shown so far have been relatively straightforward, mostly requesting arbitrary sets of data. Once an application achieves anything but the most basic complexity, the application developer must be able to leverage more advanced querying technique to effectively work with the application’s data. Luckily, OData shines in this area as well.
Paging
You may have noticed that the response object returned in Figure 4 included a __next property. This is one of the ways that OData supports paging and—as with everything else in OData—this functionality is provided in a very web-friendly manner (via yet another URI). To get the next page of information, simply make the same $.getJSON() call displayed in Figure 3, replacing the fabricated URI with the URI value held in the __next property. This will return the next result set in exactly the same format (including yet another __next property to continue to the following result set, and so on).
You might also have noticed that there is no __prev property representing the previous result set. This omission is quite understandable considering that the web is a stateless medium, so each server request is isolated from any preceding it. The absence of state leaves the previous request tracking to the application developer.
In addition to the __next property paging method through which the server controls the page size, OData also supports two more query options providing clients control over which Entries to retrieve: $skip and $top. Much like their T-SQL counterparts, $skip and $take each accept a numeric parameter indicating how many Entries in the entire Collection to skip and then how many to retrieve (respectively). For example, the query ?$skip=20&$take=10 would retrieve Entries 21-30 in a Collection containing at least 30 Entries.
Sorting
Yet one more query option that should be familiar to anyone who’s written T-SQL is $orderby, which (surprisingly enough) allows ordering Entities based on a sorting expression. By leveraging this query option, a set of query parameters including $orderby=Rating asc would order the items in the Collection by the Rating property in ascending order prior to executing any other filters. Alternatively, $orderby=Rating desc would order the Entries on the same Rating property in reverse (descending) order.
Filtering
OData’s powerful querying syntax includes one last category of query options used for filtering. This set of query options provide full control over what the OData service will deliver in a response, allowing applications to retrieve exactly what they need in order to get the job done. OData supports a slew of filtering options; too many to list in this article. The OData protocol documentation (www.odata.org/developers/protocols) contains an extensive list of filtering options.
What are WCF Data Services? Built on the WCF platform’s solid foundations, the WCF Data Services (formerly ADO.NET Data Services) framework is Microsoft’s OData protocol implementation that enables developers to expose their existing data to the web in the highly consumable and web-friendly manner that is OData. The WCF Data Services framework is the perfect complement to currently deployed technologies such as Entity Framework, LINQ-to-SQL, Azure data storage solutions, and many others. In fact, in many situations exposing these existing data sources requires no changes to existing implementations and minimal configuration.
Creating a WCF Data Service to easily expose OData feeds. Up to this point, the examples in this article have focused on the client-side consumption of OData feeds. If we shift our focus to the server side, we see that WCF Data Services and Visual Studio 2010 make exposing these feeds a breeze.
As an example, let’s create an online task-tracking website we’ll call “Forget the Milk,” an application with an Entity Framework data model exposed via a WCF Data Service. Starting from scratch, create a new ASP.NET Empty Web Application. In the root of this new application, add a new ADO.NET Entity Data model entitled ForgetTheMilk.edmx (as shown in Figure 9), and choose Empty Model from the wizard.

Next, add an Entity to the data model named Task that has a Name string property and an IsComplete boolean property (as shown in Figure 10).

Finally, from the Entity Data Model designer’s context menu, select Generate Database from Model and follow the wizard to generate a database to hold our data. The data model is now created and available for exposure as an OData feed.
Now comes the interesting part: exposing the new data model via OData. Luckily, this is very simple: right-click on the project, select Add > New Item…, and choose the WCF Data Service item type (shown in Figure 11), naming it ForgetTheMilkService.svc.

This should provide a code-behind file like the one shown in Figure 12; note the highlighted areas.
using System.Data.Services; using System.Data.Services.Common; namespace ForgetTheMilk { public class ForgetTheMilk : DataService< /* TODO: put your data source class name here */ > { // This method is called only once to initialize service-wide policies. public static void InitializeService(DataServiceConfiguration config) { // TODO: set rules to indicate which entity sets and service operations // are visible, updatable, etc. // Examples: // config.SetEntitySetAccessRule("MyEntityset", EntitySetRights.AllRead); // config.SetServiceOperationAccessRule("MyServiceOperation", ServiceOperationRights.All); config.DataServiceBehavior.MaxProtocolVersion = DataServiceProtocolVersion.V2; } } }
To expose the Entity Model, edit these two highlighted areas, setting the DataService
using System.Data.Services; namespace ForgetTheMilk { public class ForgetTheMilk : DataService{ public static void InitializeService(DataServiceConfiguration config) { config.SetEntitySetAccessRule("Tasks", EntitySetRights.All); } } }
At this point, right-clicking on the ForgetTheMilkService.svc service and choosing View in Browser should display something similar to what's shown in Figure 14. That’s all there is to creating OData feeds using WCF Data Services.

For simplicity’s sake, the example in this article exposes the Tasks database with All rights exposed. This means that any client accessing this feed has full rights to insert, update, and delete all the feed’s data. Although that is exactly what this example desires, you probably don't want to expose your data in this manner. Please choose the EntitySetRights value appropriate to your scenarios.
Using jQuery to Modify OData Collections. Now that we have created a feed with write permissions, it'is time to really put OData through its paces by modifying data on a server. Once again, true to form, OData does this in a responsible, web-friendly manner via standard POST, PUT, and DELETE HTTP calls.
Adding New Entries
Most web developers have at some point provided users a way to submit data to a web server through the use of the HTML