Serialization For Fun & Profit (A simple WinRT app for Windows Phone)

Hello geeks, in my previous post I showed you how easily you can scrape xml podcasts feeds with Javascript and JQuery and make a simple windows phone application. In this post I’m going to scrape the same xml feeds but will use dot net (.net) xml serialization. And yes we are going to make a Windows phone app again but this time it is a WinRT app.

What I’m going to show you now, you can achieve the same thing in a hundreds of millions ways. However I choose xml serialization since it requires less code and as you might already know less code is always good!

So according to google "XML serialization is a process in which an object is converted to XML format, which is human-readable text based data". As for the deserialization process, it is just the opposite. So today we are going to scrape down the xml podcast feeds authored by Jesse Liberty which is "YapCast". Let’s begin, shall we?

Quick create a WinRT project for Windows Phone from the Visual C# > Store Apps > Windows Phone Apps node. Don’t choose Windows Phone Silverlight since it’s a different runtime and you may not get the expected results like mine. Name it and hit ok.

First let’s do the coding parts then we will set the UI. So first we would want to initiate an http ‘GET’ to the link where the xml podcast feeds are. For "YapCast", the link is http://feeds.feedburner.com/JesseLibertyYapcast . By doing so we will get the raw xml as a response. Then we will deserialize the xml into POCOs (Plain old clr/class object).

Requesting ‘GET’ to a server can be done by a native utility class called HttpClient. This utility class provide a method called GetStreamAsync(string uri) which provides a convenient way to download the xml as a stream of data. So Here is the code snippet for requesting ‘GET’ to our link.


var httpClient = new HttpClient();
try
{
    var result = await httpClient.GetStreamAsync(uri);
}
catch
{
    // Details in ex.Message and ex.HResult.       
}
finally
{
    httpClient.Dispose();
}

It is good to wrap a network call in a try catch block, so that if something goes wrong we could catch the exception [I’ll come back later with the await keyword]. Good now comes the second part which is desirializing the xml which we are getting in the result variable asynchronously. Remember that we need to desialize the xml into POCOs, so let’s create the appropriate object classes that maps to our downloaded xml structure. But wait a minute it’s not like we have a small xml document that can be mapped to some simple class objects. We have a huge xml document so creating class objects by typing definitely is a bad idea. So we have an online tool that can ease the process.

Xml2CSharp is an online tool that can be used to parse xml into raw C# class objects. All we have to do now is to paste the xml feed into it. So I copied the xml feed from http://feeds.feedburner.com/JesseLibertyYapcast (if you are not getting raw xml then change the link to this http://feeds.feedburner.com/JesseLibertyYapcast?format=xml and right click on the page and view page source) and paste it in the magic box and abra ka dabra we have our POCOs like below. (If it says invalid Xml, just remove the unnecessary comments at the end and also the extra xml tag on the top)

Go to visual studio and right click on the project > add > new item and select code file, name it whatever you like. Paste the POCOs we have. Change the namespace to your project namespace and save. We are done here.

Next we go back to our xml deserialization. Modify the code we have till now like this


public async Task> GetProdcasts(string url)
{
    var uri = new Uri(url);

    var httpClient = new HttpClient();
    try
    {
        var result = await httpClient.GetStreamAsync(uri);
        XmlSerializer xmlSerializer = new XmlSerializer(typeof(Rss));
        var rss = (Rss)xmlSerializer.Deserialize(result);
        foreach (var item in rss.Channel.Item)
        {
            Prodcasts.Add(item);
        }
    }
    catch
    {
        // Details in ex.Message and ex.HResult.       
    }
    finally
    {
        httpClient.Dispose();
    }

    return Prodcasts;
}

We wrapped our code in a new method named GetProdcasts which takes a URL as a string parameter and returns a list of podcast items we are looking for. A network call to the server can be a synchronous process unless you specify it to be asynchronous. So we’ve used the async keyword at the beginning of the method to tell the method to act asynchronously. Asynchronously returned results are handled with Task. So we have an Observable collection (Equivalent to C# List in addition to, that it can notify changes made in the list) of podcast items as a return value. In the try block we have our XmlSerializer class to take care of the deserialization. Upon instantiating an object of this class we must tell the type of class object which is mapped to the parent node of the xml document. In our case the top/parent node is Rss. Then we desirialize our xml from the node we want from. Again I’m casting the desirialized xml to Rss so that each and every xml node and its value are mapped to our object graph (POCO’s). Finally we loop through the podcast Items and get them into the Observable Collection property

public ObservableCollection Prodcasts { get; set; }

Look carefully on what I’m looping through. Its rss.Channel.Item because as you might have noticed on the top/parent we have the rss node, under which we’ve the Channel and then the podcast items (Item) as its children.

For the UI we’ve a GridView to show the items as a grid and a MediaElement. We will set the source of the MediaElement to the tapped podcast item and play it. So for the UI here is the code I have in my app’s MainPage.xaml


<Page
    x:Class="Podcast.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:Podcast"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d">

    <Page.Resources>
        <DataTemplate x:Key="ProdcastItemTemplate">
            <Grid Height="120" Width="auto" Margin="5">
                <Grid Background="{StaticResource PhoneAccentBrush}" Width="120" Height="120">
                    <TextBlock HorizontalAlignment="Center" TextWrapping="Wrap" Text="{Binding Title}" VerticalAlignment="Center" FontSize="16"/>
                </Grid>
            </Grid>
        </DataTemplate>
    </Page.Resources>
    <Page.Background>
        <SolidColorBrush Color="{StaticResource PhoneBackgroundColor}"/>
    </Page.Background>

    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="100"/>
            <RowDefinition/>
        </Grid.RowDefinitions>
        <GridView ItemTemplate="{StaticResource ProdcastItemTemplate}" x:Name="ProdcastGridView" Grid.Row="1" SelectionChanged="ProdcastGridView_SelectionChanged" />
        <TextBlock HorizontalAlignment="Center" TextWrapping="Wrap" Text="YapCast" VerticalAlignment="Center" FontSize="26.667" FontFamily="Consolas" Margin="5,0" Grid.Row="0">
            <TextBlock.Foreground>
                <SolidColorBrush Color="{ThemeResource PhoneBaseHighColor}"/>
            </TextBlock.Foreground>
        </TextBlock>
        <MediaElement Grid.Row="0" x:Name="MediaElement" AutoPlay="True"/>
    </Grid>
</Page>

And for the code behind we have


public sealed partial class MainPage : Page
{
    private const string Url = "http://feeds.feedburner.com/JesseLibertyYapcast";
    public ObservableCollection Prodcasts { get; set;}

    public MainPage()
    {
        this.InitializeComponent
        this.NavigationCacheMode = NavigationCacheMode.Requir
        Prodcasts = new ObservableCollection();
    }

    protected async override void OnNavigatedTo(NavigationEventArgs e)
    {
        ObservableCollection prodcasts = await GetProdcasts(Url);
        ProdcastGridView.ItemsSource = prodcasts;
    }

    public async Task> GetProdcasts(string url)
    {
        var uri = new Uri(ur
        var httpClient = new HttpClient();
        try
        {
            var result = await httpClient.GetStreamAsync(uri);
            XmlSerializer xmlSerializer = new XmlSerializer(typeof(Rss));
            var rss = (Rss)xmlSerializer.Deserialize(result);
            foreach (var item in rss.Channel.Item)
            {
                Prodcasts.Add(item);
            }
        }
        catch
        {
            // Details in ex.Message and ex.HResult.       
        }
        finally
        {
            httpClient.Dispose();
          }
        return Prodcasts;
      }

    private void ProdcastGridView_SelectionChanged(object sender, SelectionChangedEventArgs e)
    {
        var item = ProdcastGridView.SelectedItem as Item;
        if (item != null)
        {
            MediaElement.Source = new Uri(item.Enclosure.Url);
            MediaElement.Play();
        }
    }
}

Nothing new here except that we are setting the observable collection to our GridView’s ItemsSource. And we have a selection changed event for the GridView items. Upon tapping on the item in the GridView we take the item and cast it into the Item object and if it is not null then set the MediaElement src to the item’s enclosure URL which is of course the mp3 link of the podcast.

That’s it build the project and run it in the emulator. You will have the results given below.

I hope you enjoyed it. See you in the next post. Till then happy coding.