Использование службы 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

  1. Создайте проект консоли NetTcpWCFService. Затем добавьте в проект новую службу WeatherService WCF.

  2. Откройте файл 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);
        }
    }
    
  3. Откройте файл 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;}
        }
    
  4. Создайте отдельный поток для периодического создания макетного отчета о погоде. Выполните следующий код, чтобы добавить 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)]
                            });
                }
            })
        );
    }
    
  5. Чтобы добавить конечную 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.

  6. Откройте файл 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. Вам потребуется кнопка для подписки или отмены подписки на службу, а также поле со списком для отображения отчета о погоде из службы.

  1. Создайте проект Silverlight CSSL4WCFNetTcp. В диалоговом окне Создание приложения Silverlight необходимо проверка флажок Разместить приложение Silverlight на новом веб-сайте, а затем установить для параметра Версия Silverlight значение Silverlight 4.

  2. Выполните следующий код, чтобы открыть файл 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>
    
  3. Добавьте ссылку на weatherService службу в класс в службе WCF. Чтобы сделать это, задайте проект NetTcpWCFService в качестве запускаемого проекта, нажмите клавиши CTRL+F5, чтобы запустить службу. Затем щелкните правой кнопкой мыши проект Silverlight, выберите Добавить ссылку на службу , в диалоговом окне Добавление ссылки на службу введите адрес службы погоды и нажмите кнопку ОК. Затем Visual Studio 2010 создает код прокси-сервера WCF в проекте Silverlight.

  4. Выполните следующий код, чтобы открыть файл 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)
                });
        }
    }
    
  5. Выполните следующий код, чтобы добавить обработчик событий для обработки события нажатия кнопки:

    private void Button_Click(object sender, RoutedEventArgs e)
    {
        if (!_subscribed)
        {
            _client.SubscribeAsync();
        }
        else
        {
            _client.UnSubscribeAsync();
        }
        btnSubscribe.IsEnabled = false;
    }
    

Шаг 3. Развертывание файла междоменной политики

  1. Создайте 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.

  2. Узнайте путь к корневому физическому каталогу (по умолчанию, C:\inetpub\wwwroot если вы используете IIS) веб-сайта сервера, поместите файл политики в путь.