Using the WebClient Class
Silverlight's WebClient class is located in the System.Net namespace and acts much like its big brother found in the full version of the .NET Framework. It allows asynchronous requests to be made to Web resources and provides a way to specify a callback method to process response data. It's arguably the easiest way to initiate a request and handle a response in Silverlight since it doesn't require knowledge of stream objects or the process of converting byte arrays into strings. In fact, WebClient allows you to access data returned from a REST API as a string.
WebClient provides a DownloadStringAsync method as well as a DownloadStringCompleted event that can be used to initiate asynchronous calls and process response data, as shown in the following code sample:
private void StartWebClient() {
WebClient restClient = new WebClient(); restClient.DownloadStringCompleted +=
new DownloadStringCompletedEventHandler(restClient_DownloadStringCompleted); restClient.DownloadStringAsync(CreateRESTUri());
private void restClient_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e)
ProcessData(e.Result);
private Uri CreateRESTUri() {
return new Uri(String.Format("{0}?method={1}&api_key={2}&text={3}&per_page={4}", _BaseUri, "flickr.photos.search", _APIKey, this.txtSearchText.Text, 50));
This example wires the WebClient's DownloadStringCompleted event to an event handler named restClient_DownloadStringCompleted that kicks off parsing of XML data returned from a call to the Flickr REST API. The data retrieval process is started by calling the DownloadStringAsync method, which accepts a URI object as a parameter. Data returned from the RESTful call is accessed through the DownloadStringCompletedEventArgs object's Result property as a string.
The WebClient class also exposes an UploadStringAsync method and UploadString Completed event that can be used to upload data to a web site. They work in a similar manner to the DownloadStringAsync method and DownloadStringCompleted event.
WebClient also provides an OpenReadAsync method and an associated OpenReadCompleted event that can be used to access resources such as font files on a server. This can be useful when server resources used in an application need to be retrieved dynamically. The code that follows shows how the OpenReadAsync method can be used to download a .zip file named ArialFonts.zip from the ClientBin folder on the server and assign a font resource extracted from the file to a TextBlock object named tbDynamicArial. In addition to the WebClient class, you'll notice that the code also relies on a StreamResourcelnfo object to access the .zip file contents as well as a font file named ARIALN.TTF within the file.
private void Page_Loaded(object sender, RoutedEventArgs e) {
WebClient client = new WebClient(); client.OpenReadCompleted +=
new OpenReadCompletedEventHandler(client_OpenReadCompleted); client.OpenReadAsync(new Uri("ArialFonts.zip",UriKind.Relative));
private void client_OpenReadCompleted(object sender, OpenReadCompletedEventArgs e) {
StreamResourcelnfo zip = new StreamResourceInfo(e.Result, "application/zip");
StreamResourcelnfo font = Application.GetResourceStream(zip, new Uri("ARIALN.TTF",UriKind.Relative));
FontSource fSource = new FontSource(font.Stream);
FontFamily ff = new FontFamily("Arial Narrow");
UpdateUI(fSource, ff);
private void UpdateUI(FontSource fSource, FontFamily ff) {
this.tbDynamicArial.FontSource = fSource; this.tbDynamicArial.FontFamily = ff;
Looking through this code, you may wonder if there isn't an easier way to grab a font resource and use it. After all, there's quite a bit of work involved to extract the ARIALN.TTF font from the ArialFonts.zip file and assign it as the FontSource for the TextBlock. Fortunately, a shortcut does exist that can be used directly within XAML. To do this, right-click on the .zip file containing one or more of the fonts used in your application, and select Properties from the menu. In the Properties window, set the Build Action property to Resource to include the .zip file in the .xap that gets generated. Once this is done, you can use the FontFamily attribute to define the .zip file resource to access as well as the font that should be referenced inside the file. Here's an example of referencing the Arial and Arial Black fonts in TextBlock elements. Notice that the file and font are separated with a # character.
|
<UserControl x:Class="SilverlightFontClient.Page" | |
|
xmlns:x="http://schemas.microsoft.com/winfx/200 6/xaml" | |
|
Width="600" Height="3 00"> | |
|
<Grid x:Name="LayoutRoot" Background="White"> | |
|
<Canvas Margin="10"> | |
|
<TextBlock x:Name="tbArial" Canvas.Top="50" Text=' |
"Arial Text" |
|
FontSize="30" FontFamily="ArialFonts.zip#Arial' |
" /> |
|
<TextBlock X' |
:Name="tbArialBold" Canvas.Top="100" Text="Arial Black" |
|
FontSize=' |
"30" FontFamily="ArialFonts.zip#Arial Black" /> |
|
</Canvas> | |
|
</Grid> | |
|
</UserControl> |
Using the HttpWebRequest and HttpWebResponse Classes
WebClient isn't the only class available for accessing web resources. Silverlight also provides HttpWeb Request and HttpWebResponse classes, which can be used to call REST APIs or any web resource that's accessible, for that matter. These classes are also available in the standard .NET Framework (as is WebClient), so they're familiar to many ASP.NET developers. An example of using the HttpWebRequest and HttpWebResponse classes to retrieve data asynchronously from the Flickr REST API is shown next:
private void StartWebRequest() {
//Add reference to System.Net.dll if it's not already referenced HttpWebRequest request = (HttpWebRequest)WebRequest.Create(CreateRESTUri()); //Start async REST request request.BeginGetResponse(new AsyncCallback(GetResponseCallBack),request);
private void GetResponseCallBack(IAsyncResult asyncResult) {
HttpWebRequest request = (HttpWebRequest)asyncResult.AsyncState; HttpWebResponse response =
(HttpWebResponse)request.EndGetResponse(asyncResult); Stream dataStream = response.GetResponseStream(); StreamReader reader = new StreamReader(dataStream); string data = reader.ReadToEnd(); reader.Close(); response.Close();
Dispatcher.BeginInvoke(() => ProcessData(data));
private Uri CreateRESTUri() {
return new Uri(String.Format("{0}?method={1}&api_key={2}&text={3}&per_page={4}", _BaseUri, "flickr.photos.search", _APIKey, this.txtSearchText.Text, 50));
Looking through the code, you can see that the HttpWebRequest class uses a different asynchronous pattern than WebClient. To use the HttpWebRequest class, you first create an instance by using an abstract class named WebRequest. WebRequest provides a static Create method that can be used to create a request to a URL (that is encapsulated in a URI object). Once an HttpWebRequest object is created, it can make an asynchronous request to the desired resource and get a response by calling the BeginGetResponse method. BeginGetResponse accepts an AsyncCallback object that points to a callback method as well as a state object (which is typically the HttpWebRequest object that started the operation).
Once the response is received, the callback method is invoked (GetResponseCallBack in this example), and data within the IAsyncResult parameter is accessed. The state object (the original HttpWebRequest) passed when the asynchronous call was first started can be accessed through the AsyncState property of the IAsyncResult object. The response data can be accessed through an HttpWebResponse object, which is made available by calling the request object's EndGetResponse method. Once the HttpWebResponse object is available, its GetResponseStream method can be called to access the response data as a stream.
Post a comment