Wahlin on .NET
Using Silverlight's WebClient Class
The WebClient class gives you a straightforward way to access distributed service data without having to worry about a lot of asynchronous complexities.
Silverlight provides several different networking classes that can be used to retrieve data from distributed resources such as Web services, REST APIs and even sockets. By learning to use these classes, you can access data from nearly any source without having to write a lot of custom code to do it. In this article, I'll focus on the one of the key classes in the System.Net namespace named WebClient and show how it can be used to make asynchronous calls. By using it, you can call a variety of services exposed by Web sites such as Flickr.com, Digg.com and many more.
Before jumping into details about the WebClient class, it's important to understand that Silverlight only allows calls to be made back to the "origin" server by default. In other words, if a Silverlight application is served up from http://www.acmecorp.com, then Silverlight only allows calls back to that same domain. If a call is made to a different domain or even the same domain running on a different port, an exception will be raised due to the cross-domain call.
In cases where you don't have any control over the server that's being called by Silverlight, you can create a middleman service on your server to handle calling the remote service. Silverlight can then call your middleman service, which in turn calls the remote server to access the data.
If this sounds like too much work, you'll be happy to know that another option does exist to help mitigate cross-domain call issues. If the owner of distributed service wants Silverlight clients to be able to call the service, they can place a Flash crossdomain.xml file or a Silverlight clientaccesspolicy.xml file at the root of their server. These specialized XML files define whether remote callers such a Flash and Silverlight are allowed to call services on the server. Although I won't provide details about these files here, Microsoft provides a nice summary here if you're interested in additional details. Silverlight supports a subset of Flash's crossdomain.xml specification.
Now that we've touched on some of the cross-domain issues you may encounter, let's talk more about using the WebClient class.
Using the WebClient Class
If you've worked with any of the classes in the System.Net namespace, you've more than likely used or seen the WebClient class. It's been in the .NET Framework since it was first released.
Silverlight also provides a WebClient class that can be used to make asynchronous calls to a distributed service. Unlike the .NET Framework's WebClient class, the Silverlight version is asynchronous by default since remote service calls can lock up the browser -- leading to an unpleasant end user experience.
Fortunately, you don't have to be an expert in asynchronous communications and threading to work with the WebClient class. It provides several different properties, methods and events that simplify the process.
To use the WebClient, class you'll need to follow three simple steps:
- Create an instance of System.Net.WebClient in your Silverlight application code.
- Wire up the DownloadStringCompleted event to an event handler.
- Call the DownloadStringAsync method.
- Add code into the DownloadStringCompleted event handler to process the data returned from the remote service call.
Once the System.Net namespace has been imported, an instance of the WebClient class can be created. From there, the DownloadStringCompleted event can be wired to an event handler. The DownloadStringCompleted event is raised after data is returned from a remote service.
Here's an example of performing the first two steps listed above. This code wires the WebClient object's DownloadStringCompleted event to an event handler named linqClient_DownloadStringCompleted that's responsible for processing the data returned from the service. It accepts two parameters, including the sender and a DownloadStringCompletedEventArgs object that provides access to the service data.
To call the target service and retrieve data from it, invoke the WebClient's DownloadStringAsync() method and pass the remote service's address as a parameter:
This begins the call to the service and automatically routes any data returned to the appropriate event handler. Data is returned as a string, so you'll need to write code to process the data depending upon the format (XML, JSON, etc.). The code shown here demonstrates how data returned from a service can be accessed through a DownloadStringCompletedEventArgs object and processed using LINQ to XML functionality available in Silverlight. I'll provide additional information about different parsing techniques such as LINQ to XML in future articles.
You can see that the WebClient class provides a straightforward way to access distributed service data without having to worry about a lot of asynchronous complexities. In the next article, I'll discuss a different way to access and work with data using streams.
Dan Wahlin (Microsoft MVP for ASP.NET and XML Web Services) is the founder of The Wahlin Group which specializes in .NET and SharePoint onsite, online and video training and consulting solutions. Dan also founded the XML for ASP.NET Developers Web site, which focuses on using ASP.NET, XML, AJAX, Silverlight and Web Services in Microsoft's .NET platform. He's also on the INETA Speaker's Bureau and speaks at conferences and user groups around the world. Dan has written several books on .NET including "Professional Silverlight 2 for ASP.NET Developers," "Professional ASP.NET 3.5 AJAX, ASP.NET 2.0 MVP Hacks and Tips," and "XML for ASP.NET Developers." Read Dan's blog here.