WCF-service gebruiken via TCP-transport in Silverlight 4

In dit artikel wordt beschreven hoe u de WCF-service (Windows Communication Foundation) gebruikt via TCP-transport (Transmission Control Protocol) in Microsoft Silverlight 4.

Oorspronkelijke productversie: Silverlight
Origineel KB-nummer: 2425652

Samenvatting

Silverlight 4 ondersteunt een netTcp-transportbindingselement dat ons een nieuwe keuze geeft om duplex WCF te implementeren. In dit codevoorbeeld ziet u hoe u netTcp WCF in Silverlight gebruikt door een weerrapportabonnement te maken.

Om te laten zien dat Silverlight toegang heeft tot WCF, hebt u mogelijk een WCF-service en een Silverlight WCF-client nodig. Volg deze drie stappen om een weerrapportabonnement te maken:

Stap 1: Een Duplex WCF-service maken met NetTcpBinding

  1. Maak een nieuw consoleproject NetTcpWCFService. Voeg vervolgens een nieuwe WCF-service WeatherService toe aan het project.

  2. Open een IWeatherService.cs-bestand en voer de volgende code uit om het servicecontract te definiƫren:

     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. Open een WeatherService.cs-bestand en gebruik statische gebeurtenisbenadering om de abonnementsservice te implementeren. U moet eerst het ServiceBehavior kenmerk voorvoegsel toevoegen aan de bestaande WeatherService klasse en een InstanceContext modus instellen op een PerSession service. Voer vervolgens de volgende code uit om de standaardinhoud van de WeatherService klasse te vervangen:

    [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. Maak een afzonderlijke thread om periodiek een mock-weerrapport te genereren. Voer de volgende code uit om de System.Threading naamruimte toe te voegen in een statische constructor van de WeatherService klasse:

    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. Als u een netTcpbinding eindpunt wilt toevoegen aan de WCF-service, voert u de volgende code uit om een app.configte configureren:

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

    Opmerking

    Slechts enkele poorten tussen 4502 en 4534 mogen worden geopend door Silverlight en u hebt een clienttoegangsbeleidsbestand nodig om Silverlight-toegang toe te staan. Raadpleeg Stap 3 voor meer informatie over het toestaan van silverlight-toegang.

  6. Open een Program.cs-bestand en voeg een naamruimte System.ServiceModeltoe. Voer de volgende code uit om een ServiceHost service te starten in Main de methode:

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

Stap 2: Een Silverlight WCF-client maken

Maak een Silverlight-toepassing om de WCF te gebruiken. U hebt een knop nodig om de service te abonneren of af te melden en een keuzelijst om het weerrapport van de service weer te geven.

  1. Maak een nieuw Silverlight-project CSSL4WCFNetTcp. In het dialoogvenster Nieuwe Silverlight-toepassing moet u het selectievakje De Silverlight-toepassing hosten op een nieuwe website inschakelen en vervolgens de Silverlight-versie instellen op Silverlight 4.

  2. Voer de volgende code uit om een MainPage.xaml-bestand te openen en het standaardrasterelement te bewerken:

    <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. Voeg een servicereferentie toe aan de klasse in de weatherService WCF-service. Hiervoor stelt u het project NetTcpWCFService in als opstartproject en drukt u op Ctrl+F5 om de service te starten. Klik vervolgens met de rechtermuisknop op het Silverlight-project, selecteer de optie Serviceverwijzing toevoegen , voer in het dialoogvenster Serviceverwijzing toevoegen het adres van de weerservice in en druk op OK. En vervolgens genereert Visual Studio 2010 WCF-proxycode in het Silverlight-project.

  4. Voer de volgende code uit om het MainPage.xaml.cs-bestand te openen en initialiseer de WCF-proxy in Loaded het geval:

    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. Voer de volgende code uit om een gebeurtenis-handler toe te voegen aan de knop Klik op gebeurtenis:

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

Stap 3: Beleidsbestand voor meerdere domeinen implementeren

  1. Maak een XML-bestand clientaccesspolicy.xml, gebruik de volgende code om inhoud te configureren:

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

    Opmerking

    Dit bestand verleent machtigingen aan de Silverlight-clients die afkomstig zijn van een domein voor toegang tot de serverpoorten tussen 4502 en 4506.

  2. Zoek het pad naar de fysieke hoofdmap (standaard, C:\inetpub\wwwroot als u IIS gebruikt) van de serverwebsite en plaats het beleidsbestand in het pad.