WP7 Getting started (4) – Displaying data from webservice

This is the fourth in a series of blog posts describing how to get started with Windows Phone 7 development. It is written based on my own experience getting started with Windows Phone 7 development.

The previous entry, where I demonstrated how to store and retrieve view states between application deactivation and activation is available here.

In this blog post I will demonstrate how to fetch data from a simple REST based web service and use it in an application, that many, many people have been waiting for.

Background

In Copenhagen there is a famous neon billboard from 1953 showing a hen laying eggs.

It just so happens that there is a REST api available, where one can query the status of the egglaying.

If you load

http://sevengoslings.net/~fangel/hvormangeaeg/eggs_laid/json

You will get the status in json format

{"eggs":105300654,"on":902667014,"currently_laying_eggs":false}

When I made the request,  the hen had been working for 902667014 seconds, it had layd 105.300.654 eggs and was not currently laying any eggs (it was not dark outsite).

The status is also available in xml, php-serialized and LOL (don’t ask). The complete developers api is documented at http://sevengoslings.net/~fangel/hvormangeaeg/developers.

 The application

In the following, I’m assuming that you have either read the previous posts or have sufficient knowledge of how to create a new Windows Phone 7 based application.

I have created a new Windows Phone project using the simple “Windows Phone Application” template.

In the grid called ContentPanel, I’ve added a few TextBlocks to display the status and Rectangles to serve as dividers between the TextBlocks.

<!--ContentPanel - place additional content here-->
<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
    <Grid.RowDefinitions>
        <RowDefinition Height="Auto"></RowDefinition>
        <RowDefinition Height="20"></RowDefinition>
        <RowDefinition Height="Auto"></RowDefinition>
        <RowDefinition Height="20"></RowDefinition>
        <RowDefinition Height="Auto"></RowDefinition>
    </Grid.RowDefinitions>
    <TextBlock Grid.Row="0" x:Name="txbHenAge" TextWrapping="Wrap"></TextBlock>
    <Rectangle Grid.Row="1" Width="300" Height="2" Stroke="White" Fill="White"></Rectangle>
    <TextBlock Grid.Row="2" x:Name="txbEggCount" TextWrapping="Wrap"></TextBlock>
    <Rectangle Grid.Row="3" Width="300" Height="2" Stroke="White" Fill="White"></Rectangle>
    <TextBlock Grid.Row="4" x:Name="txbEggLayingStatus" TextWrapping="Wrap"></TextBlock>
</Grid>

To retrieve the egg-laying status, I’ll use the WebClient class, which uses a simple event -based system to make requests and receive responses. For more details on how to use the WebClient class, you might check out Accessing a REST web service quick start on create.msdn.com.

Sending the request

In my page constructor I’ll add:

_webClient = new WebClient();
_webClient.DownloadStringCompleted += _webClient_DownloadStringCompleted;
_webClient.DownloadStringAsync(new Uri("http://sevengoslings.net/~fangel/hvormangeaeg/eggs_laid/json"));

First I create a new instance of WebClient. Then I provide a method to handle the DownloadStringCompleted event, and finally I call DownloadStringAsync with the URI that I want to load.

Handling the response

In the method handling the DownloadStringCompleted event I have to parse the received Json. For that purpose I’m using Json.NET.

First I create class to model the data I expect to receive:

public class IrmaHenStatus
{
    public int eggs { get; set; }
    public long on { get; set; }
    public bool currently_laying_eggs { get; set; }
}

Then I apply JsonConvert.DeserializeObject to the received Json:

void _webClient_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e)
{
    IrmaHenStatus result = JsonConvert.DeserializeObject<IrmaHenStatus>(e.Result);
    ...

Add a bit of error handling:

if (e.Error != null)
{
    // Do something meaningfull if the response was not OK

Add strings and a helper method to turn the number of seconds into human readable format:

string HenAgeText= "The hen has been laying eggs for {0}.";
string EggCountText = "During that time, the hen has layed {0} eggs.";
string NetworkErrorText = "A network error occured!";
string EggLayingOngoing = "The hen is currently laying eggs";
string EggLayingPaused = "The hen is currently not laying any eggs";
private string FormatEggLayingTime(long time)
{
    var seconds = time;
    var elapsedDays = (int) (seconds/(60*60*24));
    seconds = seconds % (60*60*24);

    var elapsedHours = (int) (seconds/(60*60));
    seconds = seconds%(60*60);

    var elapsedMinutes = (int) (seconds/60);
    var elapsedSeconds = seconds%60;

    string returnValue = string.Format("{0} days, {1} hours, {2} minutes and {3} seconds", elapsedDays, elapsedHours, elapsedMinutes, elapsedSeconds);
    return returnValue;
}

And we are now ready to update the UI

txbEggCount.Text = string.Format(EggCountText, result.eggs.ToString("N"));
txbHenAge.Text = string.Format(HenAgeText, FormatEggLayingTime(result.on));
txbEggLayingStatus.Text = result.currently_laying_eggs ? EggLayingOngoing : EggLayingPaused;

The final result may not be very impressive, but it does illustrate quite nicely how an app can display data retrieved from a REST based webservice.

This Post Has One Comment

Leave a Reply