Silverlight Tutorial Part 3: Using Networking to Retrieve Data and Populate a DataGrid

This is part three of eight tutorials that walk through how to build a simple client application using Silverlight 2.  These tutorials are intended to be read in-order, and help explain some of the core programming concepts of Silverlight. 

<Download Code> Click here to download a completed version of the Bing Image Search sample. </Download Code> 

<Download Code> Click here to download a completed version of the Digg Search sample. </Download Code>

Using Networking to Retrieve Data

Silverlight 2 has built-in networking APIs that enable Silverlight clients to call remote REST, SOAP/WS*, RSS, JSON and XML HTTP services.  Silverlight 2 also includes a built-in sockets API (System.Net.Sockets) that enables Silverlight clients to communicate over non-HTTP protocols (ideal for scenarios like chat servers, etc).

Cross Domain Network Access

Silverlight 2 applications can always call back to their "origin" server when making network calls (meaning they can call URLs on the same domain that the application was downloaded from).  Silverlight 2 applications can also optionally make cross-domain network calls (meaning they can call URLs on different domains from where the application was downloaded from) when the remote web server has an XML policy file in place that indicates that clients are allowed to make these cross-domain calls. 

Silverlight 2 defines an XML policy file format that allows server administrators to precisely control what access a client should have.  Silverlight 2 also honors the default Flash cross domain policy file format - which means that you can use Silverlight 2 to call any existing remote REST, SOAP/WS*, RSS, JSON or XML end-point on the web that already enables cross-domain access for Flash clients.

Digg.com has a pretty cool set of Digg APIs that they publish over HTTP.  Because they have a Flash cross-domain policy file in place on their server, we can call them directly from our Silverlight application (and not require us to tunnel back through our web-server to reach their APIs).

Digg.com Topic Feed API

We want to enable end-users using our application to type in a search topic (for example: "Programming") and then click the "Search" button to pull back the top stories from Digg.com that match it:

We can use the Digg.com List Stories REST API feed API to-do this.  It takes a topic parameter in its URL (for example: GET /stories/topic/programming), and then returns back an XML payload of Digg stories that match that topic.  Click here to see an example of what this XML looks like.

Using System.Net.WebClient to Asynchronously Call the Digg REST Feed

When the SearchButton is clicked above, we'll handle its "Click" event, retrieve the topic string to search for from the TextBox control, and then initiate a network call to Digg to retrieve the XML listing for that topic.

Silverlight includes the WebClient helper class within the System.Net namespace (this is also in the full .NET Framework).  We can use this class to asynchronously download content from a URL.  The benefit of downloading our Digg stories asynchronously is that our UI will not block or become unresponsive while waiting on the remote server (allowing us to have a very fluid user experience). 

All we need to-do to perform an async download with the WebClient class is to register a "DownloadStringCompleted" event handler method that will be invoked once the requested content has been downloaded, and then call the WebClient.DownloadStringAsync(url) helper method to initiate the download:

And with the code above we can now asynchronously retrieve a string of XML data that contains the Digg stores about any topic a user wants.

Using LINQ to XML to Parse Digg XML Stories into Story Classes

Now that we can retrieve an XML snippet back of Digg story data, our next step will be to parse and convert it into "DiggStory" objects that we can manipulate and databind our controls against.

We'll do this by first defining a "DiggStory" class that has properties that map to the XML content from Digg (we'll take advantage of the new C# "automatic properties" feature to-do this):

We can then use LINQ (which is built-into Silverlight 2) and LINQ to XML (which is an extra library we can include with our Silverlight application) to easily parse and filter the XML document that was returned from Digg, and translate it into a sequence of "DiggStory" objects using the code below:

Notice above how we now have strongly typed DiggStory objects from our XML that we can work against.

Displaying our Digg Stories in a DataGrid Control

We'll use the Silverlight DataGrid control to display the Digg stories in our application.  To enable this we'll reference the Silverlight Data controls assembly, and then replace our previous "Todo" text on the page with a DataGrid control declaration (note: you can double click on the "datagrid" control in the toolbox to automatically add one to the page):

The DataGrid allows you to explicitly configure column declarations and display types (for maximum control). Alternatively if you do not specify these, the DataGrid control will use reflection on its datasource to create default columns for you based on the schema of your objects. 

We'll then update our code-behind class to programmatically bind the "ItemSource" property of the DataGrid to the sequence of stories we receive back from Digg when the search button is clicked:

And now when we run our Silverlight application and do a search, we'll see a listing of live topic story data pulled from Digg:

The Silverlight Datagrid supports all the standard features you expect with a client-side grid control: two way in-place editing, selection, scrolling, column resizing, column re-ordering, etc.  It also supports auto-flow layout, which means it can dynamically expand or shrink to fill the content container it is in.  The DataGrid also has a rich templating model that allows you to customize both the display and editing of column data. 

Next Steps

We can now retrieve Digg story data from Digg.com and display the story data within our application.

Our next step will be to go back to our Page.xaml markup and remove the in-line style declarations we are currently using there. 

To-do that let's jump to our next tutorial: Using Style Elements to Better Encapsulate Look and Feel.

44 Comments

  • Why DataGrid and not ListView? It seems weird that it would include a Windows Forms control when WPF proper doesn't even have it.

  • @Jon: If you read Scott's last blog post about the planned updates for WPF 3.5, a DataGrid control will be included, in addition to a Ribbon, DatePicker, etc. A CTP of the WPF updates should be available this spring, not far off from when the Silverlight beta hits.

  • Excellent article. Quite simple, but powerful. Thank you!

  • Hi Scott,

    Thanks for these tutorials, this is fantastic. One (possibly noob) question:

    I'm trying to follow along with WPF, but I get the following REST response from Digg: "The remote server returned an error: (403) Forbidden." When in the browser, the XML comes back fine. What am I doing wrong?

    TIA,
    David

  • Hi David,

    The problem you're seeing is with the headers generated by the WebClient. Because you're hosting in WPF - there isn't a user-agent specified.

    If you add this line to the code before calling downloadstring - it will solve your problem:

    diggService.Headers.Add("user-agent", "Silverlight Sample App");

    Cheers
    Alex

  • Fantastic! Thanks Alex!

  • Hi Jon,

    >>>>>>> Why DataGrid and not ListView? It seems weird that it would include a Windows Forms control when WPF proper doesn't even have it.

    The nice thing about DataGrid is that it makes common data entry scenarios super easy. ListBox and ItemsControl (both of which are included in SL) provide a bunch of list customization scenarios you can use as well.

    Thanks,

    Scott

  • My Boss says that we cannot use Silverlight on our projects, because it is unsafe/insecure :(

    Could you assure him that Silverlight will be safe, and not generate lots of unwanted popups/ graphics etc.

  • BUG - the Linq To XML query should alternatively contain the following for the thumbnail:
    ...
    select new DiggStory
    {
    ...
    ThumbNail = (string)story.Element("thumbnail").Attribute("src"),
    ...
    };

  • I added the line...
    diggService.Headers.Add("user-agent", "Silverlight Sample App");
    And nothing changed! I made sure to add it before the call to DownloadStringAsync. I am still getting 403s. As others have mentioned, I am using a WPF windows project. Also I made the project Full Trust. Any thoughts anybody?

  • using System.Xml.Linq;
    I think I had to add a ref to System.Xml.Linq.dll too.

  • Josh,

    Your question didn't show up in the title as I intended so I'll repeat it.
    >>I got blocked on this tutorial because I'm unsure of what using directive is required to access the XDocument class.

    using System.Xml.Linq;

    I think I had to add a ref to System.Xml.Linq.dll too.

  • To use <Data:DataGrid x:Name="StoriesList" you need to add the following XML NS
    xmlns:Data="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Data"

    This is shown in the next tutorial.

  • If anyone is trying this with the Silverlight 2 beta rather than WPF, and the browser seems to hang, stop the app and try again in a few minutes. This worked for me. I guess Digg is getting somewhat ScottGu'ed, as it were!

  • I was getting an unknown error at runtime when data binding the stories to the datagrid... turns out the DiggStory class has to be public... otherwise, weird stuff happen :)

    Thanks for the tutorial!

  • I'm unable to get the DataGrid to work. It says it doesnt have an ItemSource propery (System.Windows.Controls.DataGrid)

  • Sorry Scott, it was my mistake, havent read the article carefully :)

  • Which assembly do you reference for the data controls?? I've tried all of them and still don't get the intelli-sense for the

  • Alright, my code is the same as the code in the tutorial, however when I click "search", instead of downloading the digg stories, my browser just takes me to a blank page with nothing on it. Tried in both Firefox and IE.

  • I've got a question that I don't see a post for yet on the site. I've got the app to compile, but upon execution I get a System.Security.SecurityException in System.Windows.dll and the program breaks on the line...

    diggService.DownloadStringAsync(new Uri(diggUrl));

    any clue what I did wrong?

  • Love the tutorials as I have been itching to get my hands on Silverlight 2, but I am coming across a couple errors I am not sure what to do with.

    "The name 'txtSearchTopic' does not exist in the current context." Now, I even tried going back to the XAML and giving the WatermarkedTextBox an x:Name of txtSearchTopic but that still doesn't work.

    "The name 'StoriesList' does not exist in the current context." My DataGrid has that x:Name, so I don't understand why its not working.

    ANy ideas?

  • LOL Figured it out! I had replaced the original public partial class Page: User Control with public class DiggStory.

    When I looked at it again I thought - that isn't right. :) Now it works!

    Thanks again for these tutorials!

  • Thanks for the quick response. I originally created the project using the TestHtml page rather than creating a separate web project. So, the url was coming up with c:\...

    I'm really fired up about SilverLight 2. Thanks for the tutorials.

  • Nice tutorial :)
    Have few issues..
    1- I'm not able to find the reference to the Silverlight Data controls assembly?
    2- I tried using but it's not working, because when i use it inside TextBlock, it shows a message (TextBlock does not support DataGrid as content.)
    3- Even when i move block outside TextBlock or comment it out, to just see the page even without the data, it come blank, white. When i'm trying to run the application it shows no error but white page only..!!!!!?????

    can any one help please..
    Or even place the code, explaining what assembly references have to be add to the app???
    Thanks

  • Scottie my old chum,

    This might be "biting the hand that feeds you" but do you think you could create your code samples as text so slow error prone programmers like me can do the old "copy and paste" and save a few hours here and there? :)

    Otherwise thanks for all your hard work :)

  • This tutorial sucks. It's missing important information. Like, why the search button does nothing even though it's wired up to a event, just takes me to a blank page.

  • There's a few holes in this step of the tutorial:

    In the DiggSample project, add references to System.Xml and System.Xml.Linq to get access to the XDocument class.
    Again, in the DiggSample project, add a reference to System.Windows.Control.Data to get access to the DataGrid.

    Hope this helps somebody! :-)

  • Thanks for the tutorials! I'll definitely read all of them. I do have a big concern however:

    I noticed in Silverlight 2 you seem to have removed all synchronous downloading capabilities. Is this an indication that there will be no synchronous capabilties for HttpWebRequest in the future? If so this is unfortunate. I have an app that makes many Ajax-like calls, and if I have to segragate my code into a chain of callbacks it will make the solution much less clean and maintainable. I've scratched my head all day thinking of ways to fix this problem, but everyone leads me to a dead end. The most common one I've tried is:

    1) Have a State class that includes a AutoResetEvent
    2) Pass in this state class with BeginGetResponse
    3) Inside my handler for BeginGetResponse I set the flag after I've processed data successfully
    4) In the thread that started BeginGetResponse I have a Wait() on the AutoResetEvent.

    The problem is the event never fires (I assume its because its on the UI thread, and since my UI thread is Wait()ing it can't call the handler to process the Response).

    Is there any way I can do this cleanly?

    Thanks,

    James

  • Datagrid not supported in Microsoft Expression Blend 2.5 March 2008 Preview ?

  • I am also getting the Download Failure result from Digg. When i test the http request url in the browser, i get the resulting XML - but not from within the SilverLight app. Did anyone find the solution to this yet?

  • I'm getting the Download Failure as well. I've googled around and I've not seen anyone give any relevant advice for fixing it. Anyone have idears? Anyone have this error and then fix it?

  • I downloaded the sample. When I run it, I get the same 'Download Failure' that I get when I built the example by hand. Still looking around for the answer...

  • I have a data grid bound to a LIST. If I update the LIST the grid does not change. If I scroll the row that was changed out of view and then back into view the value has changed. Is there a way to tell the grid to repaint?

  • Can someone please translate this from C# to VB


    var stories = from story in xmlStories.Descendants("story")
    where story.Element("thumbnail") != null && !story.Element("thumbnail").Attribute("src").Value.EndsWith(".gif")
    select new DiggStory
    {
    Id = (int)story.Attribute("id"),
    Title = ((string)story.Element("title")).Trim(),
    Description = ((string)story.Element("description")).Trim(),
    ThumbNail = (string)story.Element("thumbnail").Attribute("src").Value,
    HrefLink = new Uri((string)story.Attribute("link")),
    NumDiggs = (int)story.Attribute("diggs"),
    UserName = (string)story.Element("user").Attribute("name").Value,
    };

  • Hiya, I'm having problems with the DataGrid. I've added the reference to System.Windows.Controls.Date, but the intellisense can't see <Data:DataGrid... or using System.Windows.Controls.Date. If I drag a datagrid on there it adds <my:DataGrid... but that throws the 'TextBlock does not support DataGrid as content' error. I'm assuming something's wrong with the way I've added the reference, but not sure what it could be as it seems to be there!

  • I am accessing a service in a different domain. I have placed both the clientaccesspolicy.xml and crossdomain.xml files on the server hosting the services. When i access the service i get a crossdomain error. I am running silverlight 2.0 with vs2008. What should i be looking for in trying to debug this problem?

  • With a little help from a friend, I solved the mystery. Search for 'basketball' and it will work. Basically, if not topics are found, it returns the download failure.

  • Yeah, I think I'm wrong. Imagine that. I'll bring up the VM and try again.

  • Bill B solved it! So simple....

  • I get a White screen, even if I put in basketball.

  • can someone please explain me wath does that mean: "To enable this we'll reference the Silverlight Data controls assembly..."? How do i do that?

  • Hello,


    Scott, thanks for your tutorial !

    I am a bit new in .net world. I did not succeed in running this tutorial. I have a system security error. I downloaded yours that works perfectly. I then noticed that your .net solution contains a web server. I do not understand why it is required. Moreover i added one to my solution without success. Could you give me more explanation on that part ? Why it is required ? What kind of web site project should i add ? Is there any required configuration ?

    Thanks in advance,

    Paul

  • Hi again,

    I've just noticed that when you create a silverlight application project in VS2008, it also add a web server. I created my project via Expression Blend and no web server was added !

  • Here's a tip for anyone who's having issues connecting to APIs that do not have a cross-domain policy. Send the owner of the site an email and ask them to add one. I did this yesterday, and within an hour he gladly added it. Now's he's asking for my input on how the API can be improved or expanded.

    The site will remain anonymous for now, but keep your eye on my blog. I'll be posting an app to CodePlex in the near future.

Comments have been disabled for this content.