Nutzen des WCF-Diensts über TCP-Transport in Silverlight 4

In diesem Artikel wird beschrieben, wie Sie den WCF-Dienst (Windows Communication Foundation) über TCP-Transport (Transmission Control Protocol) in Microsoft Silverlight 4 nutzen.

Ursprüngliche Produktversion: Silverlight
Ursprüngliche KB-Nummer: 2425652

Zusammenfassung

Silverlight 4 unterstützt ein netTcp-Transportbindungselement, das uns eine neue Wahl zum Implementieren von Duplex-WCF bietet. In diesem Codebeispiel wird veranschaulicht, wie Sie netTcp WCF in Silverlight nutzen, indem Sie ein Wetterberichtsabonnement erstellen.

Um den Zugriff von Silverlight auf WCF zu veranschaulichen, benötigen Sie möglicherweise einen WCF-Dienst und einen Silverlight WCF-Client. Führen Sie die folgenden drei Schritte aus, um eine Abonnementanwendung für Wetterberichte zu erstellen:

Schritt 1: Erstellen eines Duplex-WCF-Diensts mit NetTcpBinding

  1. Erstellen Sie ein neues Konsolenprojekt NetTcpWCFService. Fügen Sie dann dem Projekt einen neuen WCF-Dienst WeatherService hinzu.

  2. Öffnen Sie eine IWeatherService.cs-Datei , und führen Sie den folgenden Code aus, um den Dienstvertrag zu definieren:

     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. Öffnen Sie eine WeatherService.cs-Datei , und verwenden Sie den Statischen Ereignisansatz, um den Abonnementdienst zu implementieren. Sie müssen zunächst das ServiceBehavior Attribut der vorhandenen WeatherService Klasse voranstellen und einen InstanceContext Modus auf einen PerSession Dienst festlegen. Führen Sie dann den folgenden Code aus, um den Standardinhalt der WeatherService -Klasse zu ersetzen:

    [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. Erstellen Sie einen separaten Thread, um in regelmäßigen Abständen einen Simulierten Wetterbericht zu generieren. Führen Sie den folgenden Code aus, um den System.Threading Namespace in einem statischen Konstruktor der WeatherService -Klasse hinzuzufügen:

    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. Führen Sie zum Hinzufügen eines netTcpbinding Endpunkts zum WCF-Dienst den folgenden Code aus, um eine app.configzu konfigurieren:

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

    Hinweis

    Silverlight darf nur auf einige wenige Ports zwischen 4502 und 4534 zugreifen, und Sie benötigen eine Clientzugriffsrichtliniendatei, um den Zugriff auf Silverlight zu ermöglichen. Weitere Informationen zum Zulassen des Silverlight-Zugriffs finden Sie in Schritt 3.

  6. Öffnen Sie eine Program.cs Datei, und fügen Sie einen Namespace System.ServiceModelhinzu. Führen Sie den folgenden Code aus, um einen ServiceHost Dienst in der Main -Methode zu starten:

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

Schritt 2: Erstellen eines Silverlight WCF-Clients

Erstellen Sie eine Silverlight-Anwendung, um wcf zu nutzen. Sie benötigen eine Schaltfläche zum Abonnieren oder Abmelden des Diensts und ein Listenfeld, um den Wetterbericht vom Dienst anzuzeigen.

  1. Erstellen Sie ein neues Silverlight-Projekt CSSL4WCFNetTcp. Aktivieren Sie im Dialogfeld Neue Silverlight-Anwendung das Kontrollkästchen Silverlight-Anwendung in einer neuen Website hosten , und legen Sie die Silverlight-Version auf Silverlight 4 fest.

  2. Führen Sie den folgenden Code aus, um eine Datei "MainPage.xaml " zu öffnen und das Standardmäßige Grid-Element zu bearbeiten:

    <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. Fügen Sie der weatherService Klasse im WCF-Dienst einen Dienstverweis hinzu. Legen Sie dazu das NetTcpWCFService-Projekt als Startprojekt fest, und drücken Sie STRG+F5, um den Dienst zu starten. Klicken Sie dann mit der rechten Maustaste auf das Silverlight-Projekt, wählen Sie die Option Dienstverweis hinzufügen aus, geben Sie im Dialogfeld Dienstverweis hinzufügen die Adresse des Wetterdiensts ein, und drücken Sie OK. Anschließend generiert Visual Studio 2010 WCF-Proxycode im Silverlight-Projekt.

  4. Führen Sie den folgenden Code aus, um die MainPage.xaml.cs-Datei zu öffnen, und initialisieren Sie den WCF-Proxy im Loaded Ereignis:

    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. Führen Sie den folgenden Code aus, um einen Ereignishandler zum Behandeln von Schaltflächenklickereignissen hinzuzufügen:

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

Schritt 3: Bereitstellen einer domänenübergreifenden Richtliniendatei

  1. Erstellen Sie eine XML-Datei clientaccesspolicy.xml, verwenden Sie den folgenden Code zum Konfigurieren von Inhalten:

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

    Hinweis

    Diese Datei gewährt den Silverlight-Clients, die aus einer beliebigen Domäne stammen, Berechtigungen für den Zugriff auf die Serverports zwischen 4502 und 4506.

  2. Ermitteln Sie den Pfad des physischen Stammverzeichnisses (standardmäßig bei C:\inetpub\wwwroot Verwendung von IIS) der Serverwebsite, und platzieren Sie die Richtliniendatei im Pfad.