This recipe demonstrates how to access OData using a simple URI. For this recipe, we will use the DataSvcUtil
to generate the proxy classes instead of adding a reference.
For this sample, we will be using an OData API exposed by Netflix, an online movie rental company. At the time of writing the book, this service was in preview mode; please refer to the online documentation for the latest changes:
$filter
to get the lowest rated titles available to watch instantly or the highest rated titles. filter, format, top/skip, orderby, expand, inlinecount
, and select
. ge
(greater than or equal to), gt
(greater than), le
(less than or equal to), lt
(less than), eq
(equal to), and ne
(not equal to). Date
(year, month, day, hour, minute, second
), String
(indexOf, replace, toLower, toUpper, trim, substring, concat
, and length
), and Math
(Round
, Ceiling
, and Floor
).In this recipe we first generate the proxy class and then we add this file to the project. We then call the Netflix API to get the results, which are displayed in the listbox control.
Recipe1_Netflix
under the solution folder Ch4_Recipes
. DataSvcUtil
, which is a part of the Windows Phone 7.1 SDK. Use the following command line to generate the proxy class NetflixModel:
datasvcutil /uri:http://odata.netflix.com/v1/Catalog/ /out:.NetflixModel.cs /Version:2.0 /DataServiceCollection
NetflixModel.cs
, which we generated into the project by right-clicking and choosing Add Existing Item. Alternatively, from Windows Explorer you can just copy and paste to the project. System.Data.Services.Client
assembly, which comes with the SDK for the project. MainPage.xaml
file, add a TextBlock
control inside the ListBox
and bind the control to Name
. The title of the movie is the property Name returned from the Netflix Service.<!--LayoutRoot is the root grid where all page content is placed--> <Grid x:Name="LayoutRoot" Background="Transparent" DataContext="{Binding}"> <Grid.RowDefinitions> <RowDefinition Height="Auto"/> <RowDefinition Height="*"/> </Grid.RowDefinitions> <!--TitlePanel contains the name of the application and page title--> <StackPanel x:Name="TitlePanel" Grid.Row="0" Margin="12,17,0,28"> <TextBlock x:Name="ApplicationTitle" Text= "Ch4 Recipes" Style="{StaticResource PhoneTextNormalStyle}"/> <TextBlock x:Name="PageTitle" Text="Movie Titles" Margin="9,-7,0,0" Style="{StaticResource PhoneTextTitle1Style}"/> </StackPanel> <!--ContentPanel - place additional content here--> <Grid x:Name="ContentPanel" Margin="12,0,12,-13" Grid.Row="1"> <ListBox x:Name ="lstTasks" Grid.Row="3" Grid.Column ="1"> <ListBox.ItemTemplate> <DataTemplate> <Grid> <Grid.RowDefinitions> <RowDefinition Height="*" /> <RowDefinition Height="*" /> </Grid.RowDefinitions> <Grid.ColumnDefinitions> <ColumnDefinition Width="*" /> </Grid.ColumnDefinitions> <TextBlock Grid.Row="0" TextWrapping="Wrap" Text="{Binding Name}" FontWeight="Bold" FontStretch="Expanded" Foreground="OrangeRed"/> </Grid> </DataTemplate> </ListBox.ItemTemplate> </ListBox> </Grid> </Grid>
MainPage.xaml.cs
file and include the following two references:using NetflixCatalog.Model; using System.Data.Services.Client;
MainPage.xaml
file and click on<New Eventhandler>
. Give it the name MainPage_Loaded
. Check the last line in the following code:<phone:PhoneApplicationPage x:Class="Recipe1_Netflix.MainPage" xmlns="http://schemas.microsoft.com/winfx/2006/ xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:phone="clr-namespace:Microsoft.Phone.Controls; assembly=Microsoft.Phone" xmlns:shell="clr-namespace:Microsoft.Phone.Shell; assembly=Microsoft.Phone" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/ markup-compatibility/2006" mc:Ignorable="d" d:DesignWidth="480" d:DesignHeight="768" FontFamily="{StaticResource PhoneFontFamilyNormal}" FontSize="{StaticResource PhoneFontSizeNormal}" Foreground="{StaticResource PhoneForegroundBrush}" SupportedOrientations="Portrait" Orientation="Portrait" shell:SystemTray.IsVisible="True" Loaded="MainPage_Loaded">
MainPage_Loaded
. MainPage_Loaded
method, we will add the code to navigate to the service URI. Here we create an instance of Uri
with the Netflix service URI. Then, we will use the generic DataServiceCollection
to get the Titles from the model. Then we will call the LoadAsync
method with the query "Titles":public MainPage_Loaded(object sender,RoutedEventArgs e) { Uri svcUri = new Uri(@"http://odata.netflix.com/v1/Catalog/"); var query = "Titles"; // create context NetflixCatalog.Model.NetflixCatalog ctx = new NetflixCatalog.Model.NetflixCatalog(svcUri); DataServiceCollection<NetflixCatalog.Model.Title> rslts = new DataServiceCollection<NetflixCatalog.Model.Title>(ctx); rslts.LoadAsync(new Uri(query,UriKind.Relative)); lstTasks.ItemsSource = rslts; }
In the first step, we created a Uri
object with the OData provider URI. We used two arguments, /Version
and /DataServiceCollection. The version is 2.0, which is the latest. DataServiceCollection
supports a read/write model that tracks changes automatically. In the MainPage_Loaded
event method, we created instances of the DataServiceCollection
and the Context
objects. Then, we sent the request using the LoadAsync
method by passing the query string Titles
. Finally, we loaded the results to the ListBox
.
The Netflix API reference provides us with many different options to consume the data for customizing the client. You can add more features to your own app or to one of the recipes discussed in this chapter.
In the last recipe, we learned how to consume the OData service by generating proxy classes using DataSvcUtil
. Now with Phone 7.1 SDK, adding the reference to the project creates the proxy classes automatically. Let's repeat the same sample in the following steps:
Ch4_Recipes
, and create a new Phone 7 project and name it Recipe1_MyFlicks1
. Pick the SDK version 7.1 in the dialog box. NetflixReference
. All the available entities exposed by the Netflix service are displayed in the left listbox. This is shown in the following screenshot: References
and Service References
folders updated as shown in the following screenshot: MainPage.xaml
file and copy the XAML
shown in the following code snippet, which will add a listbox control with a text block control:<!--LayoutRoot is the root grid where all page content is placed--> <Grid x:Name="LayoutRoot" Background="Transparent" DataContext="{Binding}"> <Grid.RowDefinitions> <RowDefinition Height="Auto"/> <RowDefinition Height="*"/> </Grid.RowDefinitions> <!--TitlePanel contains the name of the application and page title--> <StackPanel x:Name="TitlePanel" Grid.Row="0" Margin="12,17,0,28"> <TextBlock x:Name="ApplicationTitle" Text= "Ch4 Recipes" Style="{StaticResource PhoneTextNormalStyle}"/> <TextBlock x:Name="PageTitle" Text="Movie Titles" Margin="9,-7,0,0" Style="{StaticResource PhoneTextTitle1Style}"/> </StackPanel> <!--ContentPanel - place additional content here--> <Grid x:Name="ContentPanel" Margin="12,0,12,-13" Grid.Row="1"> <ListBox x:Name ="lstTasks" Grid.Row="3" Grid.Column ="1"> <ListBox.ItemTemplate> <DataTemplate> <Grid> <Grid.RowDefinitions> <RowDefinition Height="*" /> <RowDefinition Height="*" /> </Grid.RowDefinitions> <Grid.ColumnDefinitions> <ColumnDefinition Width="*" /> </Grid.ColumnDefinitions> <TextBlock Grid.Row="0" TextWrapping="Wrap" Text="{Binding Name}" FontWeight="Bold" FontStretch="Expanded" Foreground="OrangeRed"/> </Grid> </DataTemplate> </ListBox.ItemTemplate> </ListBox> </Grid> </Grid>
MainPage.xaml.cs
file and add using
references at the top of the page to the System.Data.Services.Client
and Recipe2_Netflix.NetflixReferece:
using System.Data.Services.Client; using Recipe2_Netflix.NetflixReference;
MainPage.xaml
file, add the loaded event by right-clicking the<New EventHandler>
. Navigate to the event handler PhoneApplicationPage_Loaded
.private void PhoneApplicationPage_Loaded(object sender, RoutedEventArgs e) { }
NetflixCatalog
using the service Uri
. Then, using the DataServiceCollection
, we get the genre as a list and call the LoadCompleted
event. Using LINQ to Objects, we query all the genres and pass the query to the LoadAsync
method.private void PhoneApplicationPage_Loaded(object sender, RoutedEventArgs e) { Uri svcUri = new Uri(@"http://odata.netflix.com/Catalog/"); ctx= new NetflixCatalog(svcUri); lstGenres = new DataServiceCollection<Genre>(); lstGenres.LoadCompleted += new EventHandler <LoadCompletedEventArgs>(lstGenres_LoadCompleted); var query = from g in ctx.Genres select g; lstGenres.LoadAsync(query); }
lstGenres_LoadCompleted
. In this method, we assign the genre list lstGenres
to lstBoxItems.ItemsSource:
void lstGenres_LoadCompleted(object sender, LoadCompletedEventArgs e) { if (lstGenres.Continuation != null) { lstGenres.LoadNextPartialSetAsync(); } else { this.lstBoxItems.ItemsSource = lstGenres; } }
Check the next recipe for more on how to search the Netflix catalog. Also, check the following online resources to understand more on OData support in Phone 7.1 SDK: http://msdn.microsoft.com/en-us/library/gg521146(v=vs.92).aspx.