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.

Published Friday, February 22, 2008 5:54 AM by ScottGu

Comments

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

Friday, February 22, 2008 1:42 PM by 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.

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

Friday, February 22, 2008 6:27 PM by Mike Strobel

@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.

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

Saturday, February 23, 2008 5:42 AM by Branko

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

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

Saturday, February 23, 2008 6:29 PM by David

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

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

Sunday, February 24, 2008 8:30 AM by Alex

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

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

Sunday, February 24, 2008 5:56 PM by David

Fantastic! Thanks Alex!

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

Sunday, February 24, 2008 11:39 PM by ScottGu

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

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

Monday, February 25, 2008 1:06 PM by Jules

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.

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

Monday, February 25, 2008 2:34 PM by Michael

You say that Silverlight 2.0 includes REST support. Does that mean you can make a true HTTP PUT or DELETE, not just the GET and POST supported by the browser? Also, does you application have access to HTTP Response Headers natively?

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

Monday, February 25, 2008 7:02 PM by David

BUG - the Linq To XML query should alternatively contain the following for the thumbnail:

  ...

  select new DiggStory

  {

      ...

      ThumbNail = (string)story.Element("thumbnail").Attribute("src"),

      ...

  };

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

Sunday, March 2, 2008 9:56 AM by John DeHope

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?

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

Monday, March 3, 2008 2:02 PM by Rick Anderson

using System.Xml.Linq;

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

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

Monday, March 3, 2008 2:28 PM by Rick Anderson

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.

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

Monday, March 3, 2008 11:21 PM by Rick Anderson

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.

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

Wednesday, March 5, 2008 7:11 PM by Carl Caulkett

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!

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

Wednesday, March 5, 2008 11:21 PM by Matt

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!

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

Wednesday, March 5, 2008 11:37 PM by OG

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

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

Thursday, March 6, 2008 9:12 AM by Murtaza Rizvi

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

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

Thursday, March 6, 2008 10:43 AM by Mike

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 <data:dataGrid ... >

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

Thursday, March 6, 2008 8:52 PM by OG

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.

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

Thursday, March 6, 2008 10:07 PM by khay

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?

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

Friday, March 7, 2008 12:56 PM by Thia

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?

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

Friday, March 7, 2008 1:04 PM by Thia

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!

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

Friday, March 7, 2008 1:33 PM by khay

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.

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

Friday, March 7, 2008 4:30 PM by Ahmed

Nice tutorial :)

Have few issues..

1- I'm not able to find the reference to the Silverlight Data controls assembly?

2- I tried using <my:DataGrid></my:DataGrid> 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 <my:Data> 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

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

Saturday, March 8, 2008 2:34 AM by Coder

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 :)

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

Saturday, March 8, 2008 3:17 AM by sigh

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.

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

Sunday, March 9, 2008 8:16 PM by silverkiwi

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! :-)

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

Monday, March 10, 2008 3:08 PM by James Scott

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

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

Tuesday, March 11, 2008 5:44 PM by Rich John

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

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

Wednesday, March 12, 2008 12:38 AM by Jeff Almeida

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?

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

Wednesday, March 12, 2008 9:45 AM by Bill B

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?

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

Wednesday, March 12, 2008 10:35 AM by Greg McCarty

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...

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

Wednesday, March 12, 2008 1:20 PM by L Harrington

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?

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

Thursday, March 13, 2008 3:36 AM by Peter

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,

                         };

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

Thursday, March 13, 2008 5:46 AM by Annelie

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!

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

Thursday, March 13, 2008 12:38 PM by Shankar

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?

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

Thursday, March 13, 2008 8:54 PM by Bill B

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.

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

Friday, March 14, 2008 7:33 AM by Greg McCarty

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

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

Friday, March 14, 2008 8:18 AM by Greg McCarty

Bill B solved it!  So simple....

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

Friday, March 14, 2008 10:49 AM by Thia

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

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

Friday, March 14, 2008 11:09 AM by Nuno

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?

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

Friday, March 21, 2008 10:17 AM by Paul Antoine

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

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

Friday, March 21, 2008 12:03 PM by Paul Antoine

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 !

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

Friday, April 4, 2008 10:01 AM by Alvin Ashcraft

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.