OData and Windows Phone 7

Last week at the Tech Days Online Conference, I did a quick WP7 demo that showed a simple app connecting to the Twitpic OData feed and pulling back a set of images for a particular user. I’m a newbie to OData and I must admit I found the process of figuring out how to achieve this relatively simple task to be quite frustrating, primarily because there’s so much “stale” content out there. The WP7 OData story has evolved rapidly in a relatively short time and what worked 6 months simply doesn’t work today. I thought it might be worth a walk-through post so others new to OData can at least get something simple working…

Get the libraries

image

First up, you’ll want the OData client library for WP7 (also linked from the Developers page on the OData site along with many other client libraries). You can build this solution and grab the generated WP7 binaries. Or, perhaps easier (as you’re going to need it anyway), you can just grab the binaries themselves (check the Other Available Downloads section). I say you’ll need this anyway as you’re going to want the code gen tool – more of this in a mo.

So, in summary, get the ODataClient_BinariesAndCodeGenToolForWinPhone (direct download link) and optionally the ODataNetFx4_SL4_WinPhone7_Client (which contains the source). There’s also a sample app you can download ODataClient_WinPhone7SampleApp if you’re so inclined. Unblock and unzip to a suitable location.

Generate a proxy

Now you’ve got the libraries etc, we can move on to creating a proxy for the OData service. I’m going to use the Twitpic service – its OData feed is at https://odata.twitpic.com. You can hit this in a browser to get an idea of the “shape” of the feed (turn off feed reading view in IE: Internet Options –> Content –> Feeds and Web Slices).

My first mistake was assuming that I could use the standard .NET 4.0 DataSvcUtil tool (which you’ll find in \Windows\Microsoft.NET\Framework\v4.0.30319) to build the OData proxy. Instead you have to use the tool that comes as part of the ODataClient_BinariesAndCodeGenToolForWinPhone download.

Open a command prompt in the folder where you unzipped the file – you’ll find a WP7 specific version of DataSvcUtil in there. In order the generate the proxy classes, run the following command:

DataSvcUtil /out:"twitpic.cs" /uri:"https://odata.twitpic.com" /Version:2.0 /DataServiceCollection

This will generate a file called twitpic.cs containing the necessary data service proxy classes which we’ll include in our WP7 app.

Create a Windows Phone application

In Visual Studio, create a new Windows Phone Application.

WindowsPhoneApp

Add a reference to the OData client library assembly you downloaded earlier.

AddReference

Add the twitpic.cs file we created earlier to the project (in Visual Studio – Add Existing Item – Shift+Alt+A)

AddExisting

Add some simple UI

Let’s start with something super-simple to check things are working. We’ll need some UI. In MainPage.xaml, modify the ContentPanel Grid XAML to be as follows:

 <Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
  <Grid.ColumnDefinitions>
    <ColumnDefinition Width="*" />
    <ColumnDefinition Width="Auto" />
  </Grid.ColumnDefinitions>
  <Grid.RowDefinitions>
    <RowDefinition Height="*" />
    <RowDefinition Height="Auto" />
  </Grid.RowDefinitions>
  <ListBox Grid.ColumnSpan="2" 
            ItemsSource="{Binding}">
    <ListBox.ItemTemplate>
      <DataTemplate>
        <TextBlock Text="{Binding ShortId}" />
      </DataTemplate>
    </ListBox.ItemTemplate>
  </ListBox>
  <TextBox Name="textBox1" Text="ZDNet" Grid.Row="1" />
  <Button Content="Go" 
          Grid.Column="1" Grid.Row="1" 
          Name="button1" 
          Click="button1_Click" />
</Grid>

This adds a ListBox with a simple ItemTemplate that displays the ShortId of each item retrieved by our query. We can inspect the structure of the response either by looking through the twitpic.cs proxy code or by exploring the OData feed itself. For the query we’ll use the contents of the TextBox (initially set to a known Twitpic username) as the sole parameter. The query will be initiated by pressing the Button.

[Sorry, I haven’t renamed anything and I’ve embedded templates in controls – I am a bad, bad person]

And a few lines of code

In the code-behind (MainPage.xaml.cs) we can query the feed and bind it to the Listbox in just a few lines of code (if you cut and paste this you’ll have to resolve a couple of namespaces):

 private void button1_Click(object sender, System.Windows.RoutedEventArgs e)
{
  DataServiceCollection<TwitpicOData.Model.Entities.Image> images;

  TwitpicData ctx =
    new TwitpicData(new Uri("https://odata.twitpic.com"));
  string uriString =
    string.Format("/Users('{0}')/Images?$top=20", textBox1.Text);
  Uri queryUri =
    new Uri(uriString, UriKind.Relative);
  images =
    new DataServiceCollection<TwitpicOData.Model.Entities.Image>(ctx);
  images.LoadAsync(queryUri);
  this.DataContext = images;
}

The DataServiceCollection is an ObervableCollection with some additional functionality specifically for OData. TwitpicData is a DataServiceContext from the generated proxy we can use to query against our OData feed.

Unfortunately the LINQ query syntax isn’t available to you in the WP7 client libraries at this time so you need to generate the query URL yourself. Not too difficult in our case, we create a relative URI that points to

https://odata.twitpic.com/Users('zdnet')/Images?$top=20 

In other words (working from the far right), get the first 20 images for the user ‘zdnet’.

Then we create our DataServiceCollection (passing our DataServiceContext) and request it to do asynchronous load with a call to LoadAsync() passing the query URI we want to execute. LoadAsync() will automagically populate our collection when the query completes (and there’s a LoadCompleted event you can hook into as well in case you need to take action).

Finally, set the DataContext on the page to our collection and the binding in the ListBox ItemTemplate will pick up on the Image’s ShortId property.

OdataQuery1Tada!

This gives us something that at least executes a query against the OData feed and binds the results to the ListBox. Run it, and you should see something like this (click the button to execute the query).

Not very exciting but it works. In the next post we’ll actually get some images to display (which isn’t quite as straightforward as it could be…)