Click here to Skip to main content
Click here to Skip to main content

Write a Silverlight Client to Consume WCF Service

, 23 Mar 2009
Rate this:
Please Sign up or sign in to vote.
Article describing how to write a Silverlight client to consume a WCF service

Introduction

In the last article, Currency Conversion WCF Service For Silverlight, I discussed how you will go about writing a WCF service that can be consumed by Silverlight clients or all clients that can consume ASMX based web services. This article will discuss how to write a Silverlight application that will consume WCF service. The following image shows how the UI for the application looks like:

currencyconverter.PNG

As you can see, it has a very simple layout. There are 2 dropdown combo boxes that contain a list of currencies available, and a button that you can click to submit selected currencies to get the conversion rate.

Adding Reference to WCF Service

Since the whole application depends on communication with a WCF service that serves currency conversion rates, the first thing that needs to be done is to add a reference to the service so the proxy classes can be created. The application uses these proxy classes to connect to WCF service. You can right click on References or Service Reference node in solution explorer and then follow the wizard steps to add a reference to WCF service that we created. The following images show the process of adding a service reference.

SLAddServiceRef1.PNG

SLAddServiceRef2.PNG

Populating Silverlight ComboBox

There are two input data points for this Silverlight control or application. A source (from) and target (to) currency for which you want to get the conversion rate. The application itself does not contain that list. This list comes from the WCF service that I implemented. In this day and age where bigger countries get broken into smaller ones, it made more sense to serve this list from service instead of having a hard coded list in the application itself. Let's look at the XAML markup for ComboBox.

<ComboBox Grid.Column="1" Grid.Row="1" x:Name="cbFromCurrency" 
   ItemsSource="{Binding}" Width="250" 
   IsEnabled="False" Margin="0 0 0 10">
	<ComboBox.ItemTemplate>
		<DataTemplate>
		<StackPanel Orientation="Horizontal">
			<TextBlock Text="{Binding Country}"></TextBlock>
			<TextBlock Text=","></TextBlock>
			<TextBlock Text="{Binding Name}"></TextBlock>
			<TextBlock Text="("></TextBlock>
			<TextBlock Text="{Binding Symbol}"></TextBlock>
			<TextBlock Text=")"></TextBlock>
		</StackPanel>
		</DataTemplate>
		</ComboBox.ItemTemplate>
</ComboBox>

For demo purposes, I am rendering ComboBox items using DataTemplate. I could have just bound each item to one display field in data items. You can see from markup that combobox is being bound to a data source using Binding through ItemSource property of the control. And in DataTemplte each display element is also using Binding to specific path or property in data item. For example first TextBlock is bound to Country property of Currency data item. The codebehind that binds these 2 ComboBox controls is as below:

void BindCurrencyDropDowns()
{
	cbFromCurrency.DataContext = _currencyList;
	cbFromCurrency.SelectedIndex = 0;
	cbToCurrency.DataContext = _currencyList;
	cbToCurrency.SelectedIndex = 1;
	// Make button clickable now.
	cbToCurrency.IsEnabled = cbFromCurrency.IsEnabled = 
	btnSubmit.IsEnabled = _currencyList.Count > 0;
}

When the control loads, it calls into WCF service to get the list of currencies. Our WCF service exposes a method GetCurrencies that returns a list of Currency objects representing currencies for which conversion rates are available. The following code snippet shows how this is accomplished in the sample project:

private void GetListOfCurrencies()
{
	txtMessage.Text = "Getting currencies..Wait";
	App.CurrencyClient.GetCurrenciesCompleted += 
	new EventHandler<GetCurrenciesCompletedEventArgs>
			(CurrencyClient_GetCurrenciesCompleted);
	App.CurrencyClient.GetCurrenciesAsync();
}

void CurrencyClient_GetCurrenciesCompleted(object sender,  
				GetCurrenciesCompletedEventArgs e)
{
	if (e.Error != null)
	{
		txtMessage.Text = "Failed to get currencies list: " 
						+ e.Error.Message;
		return;
	}
	txtMessage.Text = "Select currencies to get conversion rate";
	_currencyList = e.Result as ObservableCollection<Currency>;
	BindCurrencyDropDowns();
}

Since all network communications in Silverlight are asynchronous, a completion event is registered with call which gets calls when call returns. Once the application receives the lists, it binds two ComboBox controls with list and enables the appropriate controls.

Get Conversion Rate

Now the ComboBox controls are populated with the list of currencies. Pick from and to currency from these dropdowns and click on Convert It button. In click event of the button, I send a message to WCF service to get the conversion rate. The service exposes the Convert method that takes the currency symbols as input parameters and returns conversion rate. The code in the sample project looks as below:

private void Submit_Click(object sender, RoutedEventArgs e)
{
	btnSubmit.IsEnabled = false;
	txtMessage.Text = "Getting conversion rate ...";
	var fromCurrency = cbFromCurrency.SelectedItem as Currency;
	var toCurency = cbToCurrency.SelectedItem as Currency;

	App.CurrencyClient.ConvertCompleted += 
	 new EventHandler<ConvertCompletedEventArgs>(CurrencyClient_ConvertCompleted);
	App.CurrencyClient.ConvertAsync(fromCurrency.Symbol, toCurency.Symbol);
}

void CurrencyClient_ConvertCompleted(object sender, ConvertCompletedEventArgs e)
{
	btnSubmit.IsEnabled = true;
	if (e.Error != null)
	{
		txtMessage.Text = "Failed to get conversion rate: " 
						+ e.Error.Message;
		return;
	}

	if (e.status.StatusCode != 0)
	{
		txtMessage.Text = string.Format("[{0}]:{1} ", 
		 e.status.StatusCode, e.status.StatusMessage);
		if (string.IsNullOrEmpty(e.status.ExceptionDetails))
		{
			txtMessage.Text += e.status.ExceptionDetails;
		}
		return;
	}
	var fromCurrency = cbFromCurrency.SelectedItem as Currency;
	var toCurency = cbToCurrency.SelectedItem as Currency;

	double rate = e.Result;
	txtMessage.Text = string.Format("{0} {1} = {2} {3}", 1, 
	  fromCurrency.Symbol, rate, toCurency.Symbol);
}

Error Handling

When Silverlight application is communicating with a WCF service or for that matter for any network communication, there will be times when errors will occur. These errors could be any of the following:

  • Network/Communication errors
  • Security errors
  • Application errors

Communication and Security errors will appear as appropriate exceptions or you will be able to look at Error property of the completion arguments of async response. The most common cause of security type error will be due to missing CrossDomain access policy file on server where WCF service is hosted. You can look at Silverlight Communication Diagnostics to get more details about how you can take care of a lot of communication or network related issues.

The tricky part is application exceptions that get thrown from WCF service or any other web services that Silverlight applications communicate with. If there is any exceptions thrown from the service, it appears as 404 status exception. For a moment, you will think that the Silverlight application could not connect to your service or there is something wrong with end point configuration. That is a possibility that you could explore. When you know that there is nothing wrong with the configuration and you can directly connect to WCF service from the browser, that would mean that WCF service application itself is throwing an exception or it's using exceptions to report errors to the caller. The only exception or error that Silverlight application is going to get in this case is a 404 (NotFound) exception. If you are writing WCF service for Silverlight application, then one thing you can do is to expose an OUT parameter for each method where you can fill in the status information and any messages that you want to communicate to the caller. I discussed this in the last article Currency Conversion WCF Service For Silverlight. In your completion method, you will receive that OUT parameter as a property on event argument. You can see from the following code snippet how this is used in the example project:

if (e.status.StatusCode != 0)
{
	txtMessage.Text = string.Format("[{0}]:{1} ",
	  e.status.StatusCode, e.status.StatusMessage);
	if (string.IsNullOrEmpty(e.status.ExceptionDetails))
	{
		txtMessage.Text += e.status.ExceptionDetails;
	}
	return;
}

In the next article, I will show how this WCF service will be extended to create a live currency rate monitor.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

ByteBlocks

United States United States
No Biography provided

Comments and Discussions

 
GeneralCommunicating between Silverlight and wcf service using MessageHeaders Pingroupelizas23-Feb-10 23:22 
GeneralRe: Communicating between Silverlight and wcf service using MessageHeaders Pinmemberdchurch2421-Mar-13 0:34 
QuestionCan we do synchronize communication? PinmemberWin Myan23-Mar-09 3:57 
AnswerRe: Can we do synchronize communication? PinmemberByteBlocks23-Mar-09 5:19 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Mobile
Web01 | 2.8.140721.1 | Last Updated 23 Mar 2009
Article Copyright 2009 by ByteBlocks
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid