(X) Hide this
    • Login
    • Join
      • Generate New Image
        By clicking 'Register' you accept the terms of use .

Connecting Windows 8 applications with services: Part 2: Working with REST, oData and RSS from Windows 8 applications

(4 votes)
Gill Cleeren
>
Gill Cleeren
Joined Apr 02, 2010
Articles:   63
Comments:   6
More Articles
0 comments   /   posted on Aug 22, 2012
Tags:   windows-8 , rest , odata , gill-cleeren
Categories:   Windows 8 , General
Tweet

In the first article of this series, we looked at how Windows 8 applications can work in general with services. We saw that the way that Windows 8 apps communicate with a service layer, is similar to how we performed the communication in Silverlight. Without a local database, Windows 8 apps need to talk to a service layer for all their relational data needs. Service communication is asynchronous, but instead of having to write a callback, in Windows 8, we can work with the async/await pattern. Once the data is available locally, we can use it in data binding scenarios.

We’ve seen how communication with ASMX and WCF services is done. Let’s know look at some other common types of services: REST, oData and RSS.

The code for this article can be downloaded here.

Talking to REST services

A REST (REpresentational State Transfer) service is based on some basic concepts of the web such as the HTTP protocol and the HTTP verbs (GET, POST…). When using a REST service, we need to send a request to a particular URL and a response will be returned. This response is unique, based on the URL: never should a specific URL return a different schema of the response. The best example of a REST implementation is the web itself: when we send a request to a particular URL, we’ll get back a response. Such a response is generally known as a resource in the REST terminology. The response is plain text, XML or JSON. The schema for this response can be seen as a contract: the service promises that the response will always be of the specified format. This way, we can write parsing code for the schema.

Over the last couple of years, REST has gained a lot of traction, mainly because of its simplicity. People are moving their services to REST in favor of SOAP-based services such as WCF. For many scenarios, REST is more than enough: simply sending a request and receiving a clear-text response makes thing simple. And isn’t that what we want?!

Many big sites including Facebook, Twitter, Flickr and many more offer a REST API. Application developers can therefore easily connect with available services by sending a request to a URL dictated by the site (including some parameters such as a search term). The response is XML or JSON and the response format is specified by the API as well.

Let’s take a look at Flickr for example (http://www.flickr.com/services/api/). A long list of methods is offered. Quite a few require authentication before they can be called (quite logical since they are based on a user account).

For our sample, we’ll use one that doesn’t need authenticating: the regular Search method: flickr.photos.search (http://www.flickr.com/services/api/flickr.photos.search.html). A long list of arguments is listed, most of them are optional though. The first one, the api_key is required. Such a key is an identifier for your application with Flickr. Obtaining one is free via http://www.flickr.com/services/api/misc.api_keys.html.

Flickr thus lists out all we need to know: the URL we need to send our request to as well as a sample response in XML format. As mentioned before, this XML is like a contract. The people at Flickr won’t be changing this (at least, not very often).

Let’s create a basic Flickr search application.

Create a new Windows 8 application and name it FlickrSearch. In the MainPage.xaml, add the following XAML code.

<Page.Resources>
    <DataTemplate x:Key="ImageItemTemplate">
        <Grid>
            <Image Width="200" Height="200" Source="{Binding ImageUrl}"></Image>
        </Grid>
    </DataTemplate>
</Page.Resources>
 
<Grid Background="{StaticResource ApplicationPageBackgroundThemeBrush}">
    <Grid Margin="10">
        <Grid.RowDefinitions>
            <RowDefinition Height="100"></RowDefinition>
            <RowDefinition Height="800"></RowDefinition>
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition></ColumnDefinition>
        </Grid.ColumnDefinitions>
        <StackPanel Orientation="Horizontal">
            <TextBox Name="SearchTextBox" Width="200" HorizontalAlignment="Center" VerticalAlignment="Center" Margin="10"></TextBox>
            <Button Content="Search Flickr" Name="SearchButton" Click="SearchButton_Click"></Button>
            <TextBlock Name="ResultTextBlock"></TextBlock>
        </StackPanel>
        <GridView Name="FlickrGridView" ItemTemplate="{StaticResource ImageItemTemplate}" Grid.Row="1" SelectionMode="None" IsItemClickEnabled="True"></GridView>
    </Grid>
</Grid>

Now in the code-behind, we are going to connect with Flickr’s REST API. For REST communication, we have to use the HttpClient (in Silverlight, we would have used the WebClient). We also need the API key and of course the address to send a request to.

private HttpClient httpClient;
private string api_key = "cd0d5bb6367eeb7afed15d2a09f89be6";//TODO: replace with your own key
private string searchUrl = "http://api.flickr.com/services/rest/?method=flickr.photos.search&api_key={0}&text={1}";

In the click event handler, we instantiate the HttpClient and use the GetAsync method to perform a GET to the specified address. The result of this asynchronous call is of type HttpResponseMessage. This instance contains the response coming back from the server.

private async void SearchButton_Click(object sender, RoutedEventArgs e)
{
 
    httpClient = new HttpClient();
 
    try
    {
        HttpResponseMessage response = await httpClient.GetAsync(String.Format(searchUrl, api_key, SearchTextBox.Text));
        ParseFlickrResponse(response);
    }
    catch (HttpRequestException hre)
    {
        ResultTextBlock.Text = hre.Message;
    }   
}

We can now parse the response using some basic LINQ-To-XML code:

private async void ParseFlickrResponse(HttpResponseMessage response)
{
    XDocument xml = XDocument.Parse(await response.Content.ReadAsStringAsync());
    var photos = from results in xml.Descendants("photo")
                 select new FlickrImage
                 {
                     ImageId = results.Attribute("id").Value.ToString(),
                     FarmId = results.Attribute("farm").Value.ToString(),
                     ServerId = results.Attribute("server").Value.ToString(),
                     Secret = results.Attribute("secret").Value.ToString(),
                     Title = results.Attribute("title").Value.ToString()
                 };
 
    FlickrGridView.ItemsSource = photos;
}

The resulting UI is shown below.

We’ll revisit REST services later in this series when we look at how we can secure communication and use credentials.

oData services and Windows 8

oData stands for the Open Data Protocol (www.odata.org). oData itself is based on REST: the communication also consists out of sending a request to a URL and receiving a response in XML or JSON format. While not tied to just a Microsoft technology, WCF Data Services is Microsoft’s way of building oData services.

The idea behind oData is that in many scenarios where we work with services, we end up writing a whole lot of service methods (think of GetAllCustomers, GetCustomerById, GetCustomerByName, GetAllCustomersDescending…). Most of these are just basic CRUD operations. Using a WCF Data Service, we can choose to expose the data model and allow clients to send queries using a URL format. This way, we just expose one endpoint and allow clients to query using parameters on a URL. Take a look at the following samples where we are querying the oData endpoint of Netflix, available via http://odata.netflix.com/Catalog/.

  • http://odata.netflix.com/Catalog/Genres: retrieves all genres. Note that the response itself is formatted according to ATOMpub standard.

  • http://odata.netflix.com/Catalog/Genres('Adventures'): queries the data source so that only movies that are in the Adventures genre are returned
  • http://odata.netflix.com/Catalog/Genres('Adventures')/Titles: navigates to the Titles within the Adventures genre
  • http://odata.netflix.com/Catalog/Titles?$filter=AverageRating gt 4: retrieves only those titles that have a rating greater than 4

As you can see, without having to write any methods, we can quite easily query the data model by using nothing more that URL.

One might think: we are just moving the problem. oData requires that we build up the URL and parse the XML response into objects. For this very reason, an oData client library exists for most .NET technologies. This library allows us to write some LINQ queries, which will be translated by the client library into a URL. The response will be materialized into objects, so we don’t need to do the XML parsing ourselves.

An oData client library exists for Windows 8. The RC version can be downloaded here: http://www.microsoft.com/en-us/download/confirmation.aspx?id=30714. The RTM version wasn’t available at the time of writing.

Let’s create together an application that consumes an oData endpoint (note that this application requires a local SQL Server database). Create a new Windows 8 application and name it MyMiniCrmApp. Execute the database script you find with the downloads of this article. Now add an empty web site to the solution. In this web site, add an ADO.NET entity model and link it to the database you created when running the script. Add the Users table to the model.

Now add a WCF Data Service to the website. Make the following changes in the code of the service:

 

public static void InitializeService(DataServiceConfiguration config)
{
    // TODO: set rules to indicate which entity sets and service operations are visible, updatable, etc.
    // Examples:
    config.SetEntitySetAccessRule("Users", EntitySetRights.All);
    // config.SetServiceOperationAccessRule("MyServiceOperation", ServiceOperationRights.All);
    config.DataServiceBehavior.MaxProtocolVersion = DataServiceProtocolVersion.V2;
}

You can test the service by navigating to the *.svc endpoint. We’re now going to connect to this service from the Windows 8 application. In the latter, add a service reference to the *.svc endpoint. Visual Studio will create the proxy class. This proxy is different from the one generated for a regular WCF service. The main class here inherits from DataServiceContext: it’s a client-side context used for communication with the online service.

/// <summary>
/// There are no comments for MyCRMEntities in the schema.
/// </summary>
public partial class MyCRMEntities : global::System.Data.Services.Client.DataServiceContext
{
 
}

In the MainPage.xaml, add the following code:

<StackPanel>
    <TextBlock Text="oData sample" FontSize="42"></TextBlock>
    <StackPanel>
        <TextBlock Text="Load all users" Margin="10" FontSize="25"></TextBlock>
        <Button Content="Load" VerticalAlignment="Center" Name="LoadButton" Click="LoadButton_Click_1"></Button>
    </StackPanel>
    <ListBox Name="UserListBox" Width="200" Margin="10" Height="200">
        <ListBox.ItemTemplate>
            <DataTemplate>
                <TextBlock Text="{Binding UserName}"></TextBlock>    
            </DataTemplate>    
        </ListBox.ItemTemplate>
    </ListBox>
</StackPanel>

In the click event, we are going to talk with the client-side context. Using a simple LINQ syntax, we are asking to retrieve all users from the model, ordered by FirstName. The oData client library will take care that this query is translated into a URL. The DataServiceQuery is executed asynchronously using the await pattern. At this point, the actual communication is taking place: we are awaiting the response from the service, which will be XML. However, nowhere in this code snippet is there any XML parsing code to be found. This is handled by the client library once again: the result is loaded in a collection of User instances. This User class was generated in the proxy upon service referencing.

public MainPage()
{
    this.InitializeComponent();
 
    this.Context = new MyMiniCRMEntities(new Uri("http://localhost:10365/MyCRMDataService.svc/"));
}
 
public MyMiniCRMEntities Context { get; set; }
        
private async void LoadButton_Click_1(object sender, RoutedEventArgs e)
{
    var query = (DataServiceQuery<User>)Context.Users.OrderBy(user => user.FirstName);
 
    var data = await query.ExecuteAsync();
    var result = new DataServiceCollection<User>(Context);
    result.Load(data);
 
    UserListBox.ItemsSource = result;
}

The screenshot below shows the URL that was generated:

Consuming RSS feeds in Windows 8

The last type of communication we’ll look at in this article is RSS. With RSS, we’re basically still in the same type of content: the result of reading out an RSS or ATOMPub feed is always XML. This XML however, is always in the same format. If this wouldn’t be the case, RSS reader applications wouldn’t know how to parse a site’s RSS content.

When building Windows 8 applications that read out RSS content, we could parse the result manually. Since we know the format of the XML, we could write LINQ-To-XML code that parses the feed content. However, since .NET 3.5, some classes were added that wrap RSS content. These classes are available in WinRT as well in the Windows.Web.Syndication namespace. The SyndicationFeed and SyndicationClient are the two most important ones to work with. Just like other service types, the communication to an RSS feed needs to happen asynchronously.

Let’s build a basic RSS reader in Windows 8. Create a new application and name it MyRSSReader. To save some space, take a look at the sample code for the XAML markup.

In the code-behind, we’ll make the call to the RSS endpoint as follows.

private SyndicationFeed currentFeed = null;
 
private async void DownloadFeedButton_Click_1(object sender, RoutedEventArgs e)
{
    SyndicationClient client = new SyndicationClient();
    client.BypassCacheOnRetrieve = true;
 
    client.SetRequestHeader("User-Agent", "Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.2; WOW64; Trident/6.0)");
 
    try
    {
        Uri uri = new Uri(AddressTextBox.Text.Trim());
 
        currentFeed = await client.RetrieveFeedAsync(uri);
 
        EntryListBox.ItemsSource = currentFeed.Items;
    }
    catch (Exception ex)
    {
        //Handle errors
        string a = ex.Message;
    }
}

As can be seen, a SyndicationClient instance is created first. We specify that we don’t want to use the cached response by setting the BypassCacheOnRetrieve to true. Using the RetrieveFeedAsync method on the SyndicationClient returns a SyndicationFeed instance. This contains an Items property, which is an IList<SyndicationItem>. This is then used as the ItemsSource property for a ListBox. The content of the screen is then created by data binding on these values:

 

<TextBlock Name="FeedTitleTextBlock" Text="{Binding Title.Text}" FontSize="30"></TextBlock>
<HyperlinkButton Name="linkField" Content="{Binding Links[0].Uri.AbsoluteUri}" 
    FontSize="15"></HyperlinkButton>
<TextBlock x:Name="ContentTextBlock" Text="{Binding Summary.Text}" FontSize="24" 
    TextWrapping="Wrap" Margin="10,10,0,10" Width="600" Height="400"></TextBlock>
 

Summary

In this article, we’ve looked at several services that return an XML response. We started with a regular REST service where we parsed the response ourselves. When using the oData, the querying is done by sending a request to a URL and parsing the response. The client library however relieves us from this work and abstracts this away from us. When using RSS feeds, the Syndication classes also remove the requirement of having to parse XML manually and instead add an object model around an RSS response.

 

About the author

Gill Cleeren is Microsoft Regional Director (www.theregion.com), Silverlight MVP (former ASP.NET MVP) and Telerik MVP. He lives in Belgium where he works as .NET architect at Ordina (http://www.ordina.be/). Passionate about .NET, he’s always playing with the newest bits. In his role as Regional Director, Gill has given many sessions, webcasts and trainings on new as well as existing technologies, such as Silverlight, ASP.NET and WPF at conferences including TechEd Berlin 2010, TechDays Belgium – Switzerland - Sweden, DevDays NL, NDC Oslo Norway, SQL Server Saturday Switzerland, Spring Conference UK, Silverlight Roadshow in Sweden, Telerik RoadShow UK… He’s also the author of many articles in various developer magazines and for SilverlightShow.net and he organizes the yearly Community Day event in Belgium. He also leads Visug (www.visug.be), the largest .NET user group in Belgium. Gill is the author of “Silverlight 4 Data and Services Cookbook”. In 2012, the second edition, “Silverlight 5 Data and Services Cookbook” was released.

You can find his blog at www.snowball.be.

Twitter: @gillcleeren


Subscribe

Comments

No comments

Add Comment

Login to comment:
  *      *       

From this series