Uso del servicio WCF a través del transporte TCP en Silverlight 4

En este artículo se describe cómo usar el servicio Windows Communication Foundation (WCF) sobre el transporte del Protocolo de control de transmisión (TCP) en Microsoft Silverlight 4.

Versión original del producto: Silverlight
Número de KB original: 2425652

Resumen

Silverlight 4 admite un elemento de enlace de transporte netTcp que nos ofrece una nueva opción para implementar WCF dúplex. En este ejemplo de código se muestra cómo consumir NETTcp WCF en Silverlight mediante la creación de una suscripción de informe meteorológico.

Para demostrar que Silverlight tiene acceso a WCF, es posible que necesite un servicio WCF y un cliente WCF de Silverlight. Para crear una aplicación de suscripción de informe meteorológico, siga estos tres pasos:

Paso 1: Crear un servicio WCF dúplex con NetTcpBinding

  1. Cree un nuevo proyecto NetTcpWCFServicede consola . A continuación, agregue un nuevo servicio WeatherService WCF al proyecto.

  2. Abra un archivo IWeatherService.cs y ejecute el código siguiente para definir el contrato de servicio:

     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 un archivo WeatherService.cs y use el enfoque de eventos estáticos para implementar el servicio de suscripción. Primero debe anteponer el ServiceBehavior atributo a la clase existente WeatherService , establecer un InstanceContext modo en un PerSession servicio. A continuación, ejecute el código siguiente para reemplazar el contenido predeterminado de la WeatherService clase :

    [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. Cree un subproceso independiente para generar periódicamente un informe meteorológico ficticio. Ejecute el código siguiente para agregar el System.Threading espacio de nombres, en un constructor estático de la WeatherService clase :

    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 agregar un netTcpbinding punto de conexión al servicio WCF, ejecute el código siguiente para configurar un 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>
    

    Nota:

    Silverlight solo tiene acceso a algunos puertos que van de 4502 a 4534 y necesita un archivo de directiva de acceso de cliente para permitir el acceso de Silverlight. Para obtener más información sobre cómo permitir el acceso a Silverlight, consulte el paso 3.

  6. Abra un archivo Program.cs y agregue un espacio de nombres System.ServiceModel. Ejecute el código siguiente para iniciar un ServiceHost servicio en el 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();
        }
    }
    

Paso 2: Creación de un cliente WCF de Silverlight

Cree una aplicación de Silverlight para consumir WCF. Necesita un botón para suscribirse o cancelar la suscripción del servicio y un cuadro de lista para mostrar el informe meteorológico del servicio.

  1. Cree un nuevo proyecto de Silverlight CSSL4WCFNetTcp. En el cuadro de diálogo Nueva aplicación de Silverlight , debe activar la casilla Hospedar la aplicación de Silverlight en un nuevo sitio web y, a continuación, establecer la versión de Silverlight en Silverlight 4.

  2. Ejecute el código siguiente para abrir un archivo MainPage.xaml y editar el elemento Grid predeterminado:

    <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. Agregue una referencia de servicio a la clase en el weatherService servicio WCF. Para ello, establezca el proyecto NetTcpWCFService como proyecto de inicio y presione Ctrl+F5 para iniciar el servicio. A continuación, haga clic con el botón derecho en el proyecto de Silverlight, seleccione la opción Agregar referencia de servicio , en el cuadro de diálogo Agregar referencia de servicio, escriba la dirección del servicio meteorológico y presione Aceptar. Y, a continuación, Visual Studio 2010 genera código proxy WCF en el proyecto de Silverlight.

  4. Ejecute el código siguiente para abrir el archivo MainPage.xaml.cs e Inicializar el proxy WCF en Loaded caso de que:

    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. Ejecute el código siguiente para agregar un controlador de eventos para controlar el evento de clic del botón:

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

Paso 3: Implementación del archivo de directiva entre dominios

  1. Cree un archivo xml clientaccesspolicy.xml, use el código siguiente para configurar el contenido:

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

    Nota:

    Este archivo concede permisos a los clientes de Silverlight que proceden de cualquier dominio para acceder a los puertos de servidor comprendidos entre 4502 y 4506.

  2. Descubra la ruta de acceso del directorio físico raíz (de forma predeterminada, C:\inetpub\wwwroot si usa IIS) del sitio web del servidor, coloque el archivo de directiva en la ruta de acceso.