Silverlight 4 で TCP トランスポート経由で WCF サービスを使用する

この記事では、Microsoft Silverlight 4 で Windows Communication Foundation (WCF) Service over Transmission Control Protocol (TCP) トランスポートを使用する方法について説明します。

元の製品バージョン: Silverlight
元の KB 番号: 2425652

概要

Silverlight 4 では、双方向 WCF を実装するための新しい選択肢を提供する netTcp トランスポート バインド要素がサポートされています。 このコード サンプルでは、天気予報サブスクリプションを作成して Silverlight で netTcp WCF を使用する方法を示します。

Silverlight が WCF にアクセスする方法を示すために、WCF サービスと Silverlight WCF クライアントが必要になる場合があります。 天気予報サブスクリプション アプリケーションを作成するには、次の 3 つの手順に従います。

手順 1: NetTcpBinding を使用して双方向 WCF サービスを作成する

  1. 新しいコンソール プロジェクト NetTcpWCFServiceを作成します。 次に、新しい WCF サービス WeatherService をプロジェクトに追加します。

  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クラスを指定し、モードをInstanceContextサービスに設定する必要がありますPerSessionWeatherService 次に、次のコードを実行して、 クラスの既定の内容を 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. WCF サービスにエンドポイントを netTcpbinding 追加するには、次のコードを実行して 、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>
    

    注:

    Silverlight によるアクセスが許可されているポートは 4502 から 4534 までの少数のポートのみで、Silverlight アクセスを許可するにはクライアント アクセス ポリシー ファイルが必要です。 Silverlight アクセスを許可する方法の詳細については、 手順 3 を参照してください。

  6. Program.cs ファイルを開き、名前空間 を追加しますSystem.ServiceModel。 メソッドでサービスを開始するには、次のMainコードをServiceHost実行します。

    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: Silverlight WCF クライアントを作成する

WCF を使用する Silverlight アプリケーションを作成します。 サービスをサブスクライブまたはサブスクライブ解除するためのボタンと、サービスからの天気予報を表示するためのリスト ボックスが必要です。

  1. 新しい Silverlight プロジェクト CSSL4WCFNetTcp を作成します。 [新しい Silverlight アプリケーション] ダイアログ ボックスで、[新しい Web サイトで 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. WCF サービスの クラスにサービス参照を weatherService 追加します。 これを行うには、NetTcpWCFService プロジェクトをスタートアップ プロジェクトとして設定し、Ctrl キーを押しながら F5 キーを押してサービスを開始します。 次に、Silverlight プロジェクトを右クリックし、[ サービス参照の追加 ] オプションを選択し、[ サービス参照の追加 ] ダイアログ ボックスで weatherservice アドレスを入力し、[ OK] を押します。 次に、Visual Studio 2010 は Silverlight プロジェクトで WCF プロキシ コードを生成します。

  4. 次のコードを実行して 、MainPage.xaml.cs ファイルを開き、イベントで Loaded WCF プロキシを初期化します。

    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. clientaccesspolicy.xmlxml ファイルを作成 、次のコードを使用してコンテンツを構成します。

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

    注:

    このファイルは、4502 から 4506 の間のサーバー ポートにアクセスするための、任意のドメインの Silverlight クライアントにアクセス許可を付与します。

  2. サーバー Web サイトのルート物理ディレクトリ (既定では C:\inetpub\wwwroot IIS を使用する場合) のパスを確認し、ポリシー ファイルをパスに配置します。