65.9K
CodeProject 正在变化。 阅读更多。
Home

编写 Silverlight 客户端以消耗 WCF 服务

starIconstarIconstarIcon
emptyStarIcon
starIcon
emptyStarIcon

3.57/5 (4投票s)

2009年3月20日

CPOL

4分钟阅读

viewsIcon

60620

描述如何编写 Silverlight 客户端来消耗 WCF 服务的文章

引言

在上一篇文章《用于 Silverlight 的货币转换 WCF 服务》中,我讨论了如何编写一个可以被 Silverlight 客户端或所有可以消耗ASMXWeb 服务的客户端使用的 WCF 服务。本文将讨论如何编写一个使用 WCF 服务的 Silverlight 应用程序。下图显示了应用程序的用户界面外观

currencyconverter.PNG

正如你所见,它的布局非常简单。有两个下拉组合框,其中包含可用货币的列表,还有一个按钮,你可以点击该按钮提交选定的货币以获取汇率

添加 WCF 服务引用

由于整个应用程序依赖于与提供货币转换率的 WCF 服务的通信,因此需要做的第一件事是添加对该服务的引用,以便可以创建代理类。应用程序使用这些代理类来连接 WCF 服务。你可以右键单击解决方案资源管理器中的“引用”或“服务引用”节点,然后按照向导步骤添加对我们创建的 WCF 服务的引用。下图显示了添加服务引用的过程。

SLAddServiceRef1.PNG

SLAddServiceRef2.PNG

填充 Silverlight ComboBox

此 Silverlight 控件或应用程序有两个输入数据点。一个是源(来自)货币,另一个是目标(到)货币,你想获取它们的转换率。应用程序本身不包含此列表。此列表来自我实现的 WCF 服务。在如今大国分裂成小国的情况下,从服务中提供此列表而不是在应用程序本身中硬编码列表更有意义。让我们看一下 ComboBox 的 XAML 标记。

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

出于演示目的,我使用 DataTemplate 渲染 ComboBox 项。我本可以只将每个项绑定到数据项中的一个显示字段。你可以从标记中看到,combobox 通过控件的 ItemSource 属性使用 Binding 绑定到数据源。而在 DataTemplte 中,每个显示元素也使用 Binding 绑定到数据项中的特定路径或属性。例如,第一个 TextBlock 绑定到 Currency 数据项的 Country 属性。绑定这两个 ComboBox 控件的代码隐藏如下所示

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;
}

当控件加载时,它会调用 WCF 服务来获取货币列表。我们的 WCF 服务公开了一个名为 GetCurrencies 的方法,该方法返回一个 Currency 对象列表,这些对象代表了可获取转换率的货币。以下代码片段显示了如何在示例项目中完成此操作

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();
}

由于 Silverlight 中的所有网络通信都是异步的,因此会将一个完成事件注册到调用中,当调用返回时会触发该事件。应用程序收到列表后,它会将两个 ComboBox 控件与列表绑定,并启用相应的控件。

获取转换率

现在 ComboBox 控件已填充了货币列表。从这些下拉列表中选择“来自”“到”货币,然后单击“转换”按钮。在按钮的点击事件中,我向 WCF 服务发送一条消息以获取转换率。该服务公开了 Convert 方法,该方法将货币符号作为输入参数并返回转换率。示例项目中的代码如下所示

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);
}

错误处理

当 Silverlight 应用程序与 WCF 服务通信时,或者对于任何网络通信,有时都会发生错误。这些错误可能包括以下任何一种

  • 网络/通信错误
  • 安全错误
  • 应用程序错误

通信和安全错误将显示为相应的异常,或者你可以查看异步响应的完成参数的 Error 属性。最常见的安全类型错误是由于托管 WCF 服务的服务器上缺少 CrossDomain 访问策略文件。你可以查看 Silverlight 通信诊断以获取有关如何处理大量通信或网络相关问题的更多详细信息。

棘手的部分是 WCF 服务或其他 Silverlight 应用程序通信的 Web 服务中抛出的应用程序异常。如果服务中抛出任何异常,它将显示为 404 状态异常。一瞬间,你可能会认为 Silverlight 应用程序无法连接到你的服务,或者端点配置存在问题。这是你可以探索的一种可能性。当你确定配置没有问题并且你可以直接从浏览器连接到 WCF 服务时,那就意味着 WCF 服务应用程序本身正在抛出异常,或者它正在使用异常来向调用者报告错误。在这种情况下,Silverlight 应用程序将收到的唯一异常或错误是 404 (NotFound) 异常。如果你正在为 Silverlight 应用程序编写 WCF 服务,那么你可以做的一件事就是为每个方法公开一个 OUT 参数,你可以在其中填写状态信息以及你希望与调用者通信的任何消息。我在上一篇文章 用于 Silverlight 的货币转换 WCF 服务中讨论了这一点。在你的完成方法中,你将在事件参数上将该 OUT 参数作为属性接收。你可以从以下代码片段中看到示例项目中是如何使用此方法的

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;
}

在下一篇文章中,我将展示如何扩展此 WCF 服务来创建一个实时货币汇率监控器。

© . All rights reserved.