Consumir serviço WCF por meio do transporte TCP no Silverlight 4

Este artigo descreve como consumir o transporte TCP (Protocolo de Controle de Transmissão) do Windows Communication Foundation (WCF) no Microsoft Silverlight 4.

Versão original do produto: Silverlight
Número de KB original: 2425652

Resumo

O Silverlight 4 dá suporte a um elemento de associação de transporte netTcp que nos dá uma nova opção para implementar o WCF duplex. Este exemplo de código demonstra como consumir netTcp WCF em Silverlight criando uma assinatura de relatório meteorológico.

Para demonstrar o acesso do Silverlight ao WCF, talvez seja necessário um serviço WCF e um cliente Silverlight WCF. Para criar um aplicativo de assinatura de relatório meteorológico, siga estas três etapas:

Etapa 1: criar um serviço duplex WCF com NetTcpBinding

  1. Crie um novo projeto NetTcpWCFServicede console . Em seguida, adicione um novo Serviço WeatherService WCF ao projeto.

  2. Abra um arquivo IWeatherService.cs , execute o seguinte código para definir o contrato de serviço:

     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. Abra um arquivo WeatherService.cs , use a abordagem de evento estático para implementar o serviço de assinatura. Primeiro, você precisa prefixar o ServiceBehavior atributo para a classe existente WeatherService , definir um InstanceContext modo como um PerSession serviço. Em seguida, execute o seguinte código para substituir o conteúdo padrão da WeatherService classe:

    [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. Crie um thread separado para gerar um relatório meteorológico simulado periodicamente. Execute o seguinte código para adicionar o System.Threading namespace em um construtor estático da WeatherService classe:

    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. Para adicionar um ponto de netTcpbinding extremidade ao serviço WCF, execute o seguinte código para configurar um 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>
    

    Observação

    Apenas algumas portas que são de 4502 a 4534 têm permissão para serem acessadas pelo Silverlight, e você precisa de um arquivo de política de acesso ao cliente para permitir o acesso ao Silverlight. Para obter mais informações sobre como permitir o acesso ao Silverlight, consulte a Etapa 3.

  6. Abra um arquivo Program.cs , adicione um namespace System.ServiceModel. Execute o seguinte código para iniciar um ServiceHost serviço no Main método:

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

Etapa 2: criar um cliente WCF silverlight

Crie um aplicativo Silverlight para consumir o WCF. Você precisa de um botão para assinar ou cancelar assinatura do serviço e uma caixa de listagem para exibir o relatório meteorológico do serviço.

  1. Crie um novo projeto silverlight CSSL4WCFNetTcp. Na caixa de diálogo Novo Aplicativo Silverlight, você precisa marcar o aplicativo Host the Silverlight em uma nova caixa de seleção do site e, em seguida, definir a Versão Silverlight como Silverlight 4.

  2. Execute o seguinte código para abrir um arquivo MainPage.xaml e editar o elemento grid padrão:

    <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. Adicione uma referência de serviço à weatherService classe no serviço WCF. Para fazer isso, defina o projeto NetTcpWCFService como um projeto de inicialização, pressione Ctrl+F5 para iniciar o serviço. Em seguida, clique com o botão direito do mouse no projeto Silverlight, selecione Adicionar Referência de Serviço , na caixa de diálogo Adicionar Referência de Serviço , insira o endereço do serviço meteorológico e pressione OK. E, em seguida, o Visual studio 2010 gera o código proxy do WCF no projeto Silverlight.

  4. Execute o seguinte código para abrir o arquivo MainPage.xaml.cs e Inicializar o proxy WCF no Loaded evento:

    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. Execute o seguinte código para adicionar um manipulador de eventos para manipular o evento clique no botão:

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

Etapa 3: Implantação de arquivo de política de domínio cruzado

  1. Crie um arquivo xml clientaccesspolicy.xml, use o seguinte código para configurar o conteúdo:

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

    Observação

    Esse arquivo concede permissões aos clientes Silverlight que são de qualquer domínio para acessar as portas do servidor entre 4502 e 4506.

  2. Descubra o caminho do diretório físico raiz (por padrão, C:\inetpub\wwwroot se você usar o IIS) do site do servidor, coloque o arquivo de política no caminho.