Использование службы WCF через транспорт TCP в Silverlight 4
В этой статье описывается использование службы Windows Communication Foundation (WCF) по протоколу TCP в Microsoft Silverlight 4.
Исходная версия продукта: Silverlight
Исходный номер базы знаний: 2425652
Сводка
Silverlight 4 поддерживает элемент привязки транспорта netTcp, который предоставляет нам новый выбор для реализации дуплексного WCF. В этом примере кода показано, как использовать NETTcp WCF в Silverlight путем создания подписки на отчет о погоде.
Чтобы продемонстрировать доступ Silverlight к WCF, может потребоваться служба WCF и клиент WCF Silverlight. Чтобы создать приложение подписки на отчет о погоде, сделайте следующее:
Шаг 1. Создание дуплексной службы WCF с помощью NetTcpBinding
Создайте проект консоли
NetTcpWCFService
. Затем добавьте в проект новую службуWeatherService
WCF.Откройте файл IWeatherService.cs , выполните следующий код, чтобы определить контракт службы:
namespace NetTcpWCFService { [ServiceContract(CallbackContract=typeof(IWeatherServiceCallback))] public interface IWeatherService { [OperationContract(IsOneWay = true)] void Subscribe(); [OperationContract(IsOneWay = true)] void UnSubscribe(); } public interface IWeatherServiceCallback { [OperationContract(IsOneWay=true)] void WeatherReport(string report); } }
Откройте файл WeatherService.cs , используйте подход к статическим событиям для реализации службы подписки. Сначала необходимо префиксировать
ServiceBehavior
атрибут к существующемуWeatherService
классу, а вInstanceContext
режимеPerSession
— службу. Затем выполните следующий код, чтобы заменить содержимое класса по умолчаниюWeatherService
:[ServiceBehavior(InstanceContextMode=InstanceContextMode.PerSession)] public class WeatherService : IWeatherService { static event EventHandler<WeatherEventArgs> WeatherReporting; IWeatherServiceCallback _callback; public void Subscribe() { _callback = OperationContext.Current.GetCallbackChannel<IWeatherServiceCallback>(); WeatherReporting += new EventHandler<WeatherEventArgs>(WeatherService_WeatherReporting); } public void UnSubscribe() { WeatherReporting -= new EventHandler<WeatherEventArgs>(WeatherService_WeatherReporting); } void WeatherService_WeatherReporting(object sender, WeatherEventArgs e) { // Remember check the callback channel's status before using it. if (((ICommunicationObject)_callback).State == CommunicationState.Opened) _callback.WeatherReport(e.WeatherReport); else UnSubscribe(); } } class WeatherEventArgs:EventArgs { public string WeatherReport{set;get;} }
Создайте отдельный поток для периодического создания макетного отчета о погоде. Выполните следующий код, чтобы добавить
System.Threading
пространство имен в статический конструкторWeatherService
класса :static WeatherService() { ThreadPool.QueueUserWorkItem ( new WaitCallback(delegate { string[] weatherArray = { "Sunny", "Windy", "Snow", "Rainy" }; Random rand = new Random(); while (true) { Thread.Sleep(1000); if (WeatherReporting != null) WeatherReporting( null, new WeatherEventArgs { WeatherReport = weatherArray[rand.Next(weatherArray.Length)] }); } }) ); }
Чтобы добавить конечную
netTcpbinding
точку в службу WCF, выполните следующий код, чтобы настроить app.config:<system.serviceModel> <behaviors> <serviceBehaviors> <behavior name="NetTcpWCFService.WeatherServiceBehavior"> <serviceMetadata /> <serviceDebug includeExceptionDetailInFaults="false" /> </behavior> </serviceBehaviors> </behaviors> <services> <service behaviorConfiguration="NetTcpWCFService.WeatherServiceBehavior" name="NetTcpWCFService.WeatherService"> <endpoint address="" binding="netTcpBinding" bindingConfiguration="b1" contract="NetTcpWCFService.IWeatherService" /> <endpoint address="mex" binding="mexTcpBinding" contract="IMetadataExchange" /> <host> <baseAddresses> <add baseAddress="net.tcp://localhost:4504/WeatherService" /> </baseAddresses> </host> </service> </services> <bindings> <netTcpBinding> <binding name="b1"> <security mode="None"/> </binding> </netTcpBinding> </bindings> </system.serviceModel>
Примечание.
Только к нескольким портам от 4502 до 4534 разрешен доступ Silverlight, и вам нужен файл политики доступа клиента, чтобы разрешить доступ к Silverlight. Дополнительные сведения о том, как разрешить доступ Silverlight, см. в разделе Шаг 3.
Откройте файл Program.cs , добавьте пространство имен
System.ServiceModel
. Выполните следующий код, чтобы запуститьServiceHost
службу вMain
методе :static void Main(string[] args) { using (var host = new ServiceHost(typeof(WeatherService))) { host.Open(); Console.WriteLine("Service is running..."); Console.WriteLine("Service address: "+host.BaseAddresses[0]); Console.Read(); } }
Шаг 2. Создание клиента WCF Silverlight
Создайте приложение Silverlight для использования WCF. Вам потребуется кнопка для подписки или отмены подписки на службу, а также поле со списком для отображения отчета о погоде из службы.
Создайте проект Silverlight CSSL4WCFNetTcp. В диалоговом окне Создание приложения Silverlight необходимо проверка флажок Разместить приложение Silverlight на новом веб-сайте, а затем установить для параметра Версия Silverlight значение Silverlight 4.
Выполните следующий код, чтобы открыть файл MainPage.xaml и изменить элемент Grid по умолчанию:
<Grid x:Name="LayoutRoot" Background="White"> <Grid.RowDefinitions> <RowDefinition Height="46*" /> <RowDefinition Height="26*" /> <RowDefinition Height="228*" /> </Grid.RowDefinitions> <TextBlock Text="Silverlight NetTcp Sample" Grid.Row="0" Margin="0,0,0,10" FontSize="24"/> <StackPanel Orientation="Horizontal" Grid.Row="1"> <Button Content="Subscribe weather report" Name="btnSubscribe" Click="Button_Click"/> <TextBlock VerticalAlignment="Center" FontStyle="Italic" Foreground="Red" Margin="5,0,0,0" Name="tbInfo"/> </StackPanel> <ListBox Name="lbWeather" Grid.Row="2" Margin="0,5,0,0"/> </Grid>
Добавьте ссылку на
weatherService
службу в класс в службе WCF. Чтобы сделать это, задайте проект NetTcpWCFService в качестве запускаемого проекта, нажмите клавиши CTRL+F5, чтобы запустить службу. Затем щелкните правой кнопкой мыши проект Silverlight, выберите Добавить ссылку на службу , в диалоговом окне Добавление ссылки на службу введите адрес службы погоды и нажмите кнопку ОК. Затем Visual Studio 2010 создает код прокси-сервера WCF в проекте Silverlight.Выполните следующий код, чтобы открыть файл MainPage.xaml.cs и инициализировать прокси-сервер WCF в событии
Loaded
:public partial class MainPage : UserControl,IWeatherServiceCallback { public MainPage() { InitializeComponent(); Loaded += new RoutedEventHandler(MainPage_Loaded); } bool _subscribed; WeatherServiceClient _client; void MainPage_Loaded(object sender, RoutedEventArgs e) { _client = new WeatherServiceClient( new System.ServiceModel.InstanceContext(this)); _client.SubscribeCompleted += _client_SubscribeCompleted; _client.UnSubscribeCompleted += _client_UnSubscribeCompleted; } void _client_UnSubscribeCompleted(object sender, System.ComponentModel.AsyncCompletedEventArgs e) { if (e.Error == null) { _subscribed = false; btnSubscribe.Content = "Subscribe weather report"; tbInfo.Text = ""; }else tbInfo.Text = "Unable to connect to service."; btnSubscribe.IsEnabled = true; } void _client_SubscribeCompleted(object sender, System.ComponentModel.AsyncCompletedEventArgs e) { if (e.Error == null) { _subscribed = true; btnSubscribe.Content = "UnSubscribe weather report"; tbInfo.Text = ""; } else tbInfo.Text="Unable to connect to service."; btnSubscribe.IsEnabled = true; } // Display report when callback channel get called. public void WeatherReport(string report) { lbWeather.Items.Insert( 0, new ListBoxItem { Content = string.Format("{0} {1}",DateTime.Now, report) }); } }
Выполните следующий код, чтобы добавить обработчик событий для обработки события нажатия кнопки:
private void Button_Click(object sender, RoutedEventArgs e) { if (!_subscribed) { _client.SubscribeAsync(); } else { _client.UnSubscribeAsync(); } btnSubscribe.IsEnabled = false; }
Шаг 3. Развертывание файла междоменной политики
Создайте XML-файл clientaccesspolicy.xml, используйте следующий код для настройки содержимого:
<access-policy> <cross-domain-access> <policy> <allow-from> <domain uri="*"/> </allow-from> <grant-to> <socket-resource port="4502-4506" protocol="tcp" /> </grant-to> </policy> </cross-domain-access> </access-policy>
Примечание.
Этот файл предоставляет разрешения клиентам Silverlight, которые находятся из любого домена, на доступ к портам сервера, которые находятся в диапазоне от 4502 до 4506.
Узнайте путь к корневому физическому каталогу (по умолчанию,
C:\inetpub\wwwroot
если вы используете IIS) веб-сайта сервера, поместите файл политики в путь.