Windows Communication FoundationとはWindows Communication Foundation概説(3/4 ページ)

» 2006年03月21日 00時00分 公開
[伊藤英豪マイクロソフト株式会社]

 例えば、先ほどのクラスのメソッドをサービスとして実装するには、WCFでは以下のようになる。

// サービス・コントラクトの定義
[ServiceContract]
public interface IMyService
{
  [OperationContract]
  string MyOperation1(string myValue1);
}

// サービス・コントラクトを実装するサービス・クラス
public class MyService : IMyService
{
  public string MyOperation1(string myValue1)
  {
    return "Hello: " + myValue1;
  }
}

WCFで実装したサービス・サイドのソース・コード

 このコードは先ほどの単なるクラスのメソッドを、サービスのメソッドに変更している。これには、まず外部に公開するサービスのインターフェイスをコントラクトとして定義する。ここではIMyServiceインターフェイスがこのサービスのコントラクトに当たり、このインターフェイスにServiceContract属性および、公開するメソッドにOperationContract属性を付与する。

 後はこのインターフェイスを実装するクラス(いわばサービス自体の実装クラス)を作ればよい。これにより単なるクラスでしかなかったものが、WCFのサービスとして変身することになる。

 次のコードは上記のサービスを利用するクライアント・サイドのコードになる。

localhost.MyServiceProxy proxy = new localhost.MyServiceProxy();
string str = proxy.MyOperation1(textBox1.Text);
proxy.Close();

WCFで実装したサービスを利用するクライアント・サイドのソース・コード
クライアント・サイドのアプリケーション開発時には、従来のWebサービス参照のようにVS 2005から「参照の追加」によりWCFサービスへの参照を追加し、サービス・プロキシおよびクライアント・サイドのコンフィグレーションを自動生成する。その際に指定したサービス参照名として、ここではローカル・サービス参照時のデフォルト値の「localhost」を使用している(詳細は次回に掲載予定)。

 WCFで実装したサービスを利用するには、クライアントとサービス間で共有すべきコントラクトを定義した後、従来のプログラミング・モデルにおけるWebサービスの呼び出しと同じように、クライアント・サイドのプロキシをインスタンス化して、サービスの提供するメソッドを使用すればよい。最も簡単な例だが、これが基本的なWCFでのプログラミング・スタイルとなる。

 なお、このアプリケーションの使用するプロトコルは、コンフィグレーションによって外部から臨機応変に変更可能である。

 デフォルトですでにメッセージは署名暗号化されるし、メッセージの安全な伝送(順序制御、重複受信の排除、欠落時の再送要求)も行われる。また使用できるプロトコルは、名前付きパイプ(Named Pipe)、TCP、HTTP、MSMQと選択肢の幅も広く、エンコーディングに関してもネイティブのバイナリ(Binary Serialization)や、MTOM(SOAP Message Transmission Optimization Mechanism:バイナリ・データを含むSOAPメッセージ)、Text/XML(テキスト形式XML)などと用途に応じて柔軟に変更可能だ。

 つまり、基本的な実装コードの構造は同じ(=ServiceContract属性やOperationContract属性を付加するだけ)にもかかわらず、分散アプリケーションが持つさまざまな要件に応じて下位の転送プロトコル、エンコーダ、適用するWS-*仕様を柔軟に差し替えられるのである。

WCFのコンフィグレーション・ベースによる設定

 例えば、先ほど示したサービスに対するコンフィグレーションは下記のようになっている。

<?xml version="1.0" encoding="utf-8" ?>
<configuration
  xmlns="http://schemas.microsoft.com/.NetConfiguration/v2.0">
  <!--サービス・サイドのコンフィグレーション-->
  <system.serviceModel>
    <services>
      <service name="Microsoft.ServiceModel.Samples.MyService">
        <!-- サービスのEndpoint定義-->
        <endpoint
          address=""
          binding="basicHttpBinding"
          contract="Microsoft.ServiceModel.Samples.IMyService" />
      </service>
    </services>
  </system.serviceModel>
</configuration>

WS-I Basic Profile準拠のサービス・サイドのコンフィグレーション・コード
<endpoint>要素のbinding属性で「basicHttpBinding」が指定されているが、これは通信プロトコルにHTTPを、メッセージ・エンコーディングにText/XMLを使用することを意味する。

 このコンフィグレーションでは、プロトコルにHTTPを使用し、メッセージ・エンコーディングにはText/XMLを使用した、WS-I Basic Profile準拠の相互運用性が高いサービスの構成例である。

 この場合のメッセージは、パケットモニタで以下のように確認できる。

<s:Envelope
  xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
  <s:Body>
    <MyOperation1 xmlns="http://tempuri.org/">
      <myValue1>伊藤</myValue1>
    </MyOperation1>
  </s:Body>
</s:Envelope

 非常に単純なSOAPメッセージとなっており、もちろんメッセージの秘匿性、完全性は保証されておらず、内容も平文で確認することが可能な状況である。

 さて、ここでメッセージ・セキュリティを確保したくなった場合、どうすればよいか。最もシンプルな方法は、WS-SecurityなどのWebサービスの拡張仕様を適用するようにコンフィグレーションを変えることである。

 下記は実際にWS-Securityを適用するように変更した後のコンフィグレーションである。

<?xml version="1.0" encoding="utf-8" ?>
<configuration
  xmlns="http://schemas.microsoft.com/.NetConfiguration/v2.0">
  <!--サービス・サイドの・コンフィグレーション-->
  <system.serviceModel>
    <services>
      <service name="Microsoft.ServiceModel.Samples.MyService">
        <!-- サービスのEndpoint定義-->
        <endpoint
          address=""
          binding="wsHttpBinding"
          contract="Microsoft.ServiceModel.Samples.IMyService"/>
      </service>
    </services>
  </system.serviceModel>
</configuration>

WS-*準拠のサービス・サイドのコンフィグレーション・コード
<endpoint>要素のbinding属性に指定する値を、先ほどの「basicHttpBinding」から「wsHttpBinding」に変更しただけのコンフィグレーション。これだけの変更で、WS-Securityを適用することができる。

 この場合のメッセージはパケットモニタで以下のように確認できる。

<s:Envelope
  xmlns:s="http://www.w3.org/2003/05/soap-envelope"
  xmlns:a="http://www.w3.org/2005/08/addressing"
  xmlns:u="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
  ……中略……
  <s:Header>
    ……中略……
  </s:Header>
  <s:Body u:Id="_2">
    ……中略……
    <e:EncryptedDataId="_3"
          Type="http://www.w3.org/2001/04/xmlenc#Content"
          xmlns:e="http://www.w3.org/2001/04/xmlenc#">
      <e:EncryptionMethod
          Algorithm="http://www.w3.org/2001/04/xmlenc#aes256-cbc" />
      ……中略……
      <KeyInfo xmlns="http://www.w3.org/2000/09/xmldsig#">
        ……中略……
        <o:SecurityTokenReference xmlns:o="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
          <o:Reference URI="#_1" />
        </o:SecurityTokenReference>
      </KeyInfo>
      ……中略……
      <e:CipherData>
        <e:CipherValue>HMbw5+O0jgqk+kHhKwasdsKo0T2bhD/4mY3CB2/l17tAD…
        </e:CipherValue>
      </e:CipherData>
    </e:EncryptedData>
  </s:Body>
</s:Envelope>

 上記はメッセージの一部を掲載したものであるが、先ほどのWS-I Basic Profile準拠のシンプルなSOAPメッセージとは異なり、メッセージ本体が暗号化されメッセージ・セキュリティが確保されていることが分かる。コンフィグレーションは、<endpoint>要素のbinding属性の値を「basicHttpBinding」から「wsHttpBinding」に変更しただけである。

 もしここで転送パフォーマンスを重視した構成に変えたい場合には(例えばイントラネットの信頼ドメイン内にあるアプリケーション・サーバとの間でWCF対向通信を行うような場合)、あえてセキュリティは確保せず、プロトコルもTCPで特定ポートを使用し、エンコーディングにはバイナリ(Binary Serialization)を使用した方が効率的だ。

 このようなとき、従来であればASP.NET Webサービスから.NETリモート処理へアプリケーションの通信方式を移行するといった対処となり、それなりの手間が発生したわけである。

 これがWCFの場合は、下記のようにコンフィグレーションを変更するだけで対処ができ、大幅に手間が軽減される。

<?xml version="1.0" encoding="utf-8" ?>
<configuration
  xmlns="http://schemas.microsoft.com/.NetConfiguration/v2.0">
  <!-- サービス・サイドのコンフィグレーション-->
  <system.serviceModel>
    <services>
      <service type="Microsoft.ServiceModel.Samples.MyService">
      <!-- サービスのEndpoint定義-->
      <endpoint
        address=""
        binding="netTcpBinding"
        bindingConfiguration="Binding1"
        contract="Microsoft.ServiceModel.Samples.IMyService"/>
      </service>
    </services>

    <!-- サービスのBinding定義-->
    <bindings>
      <!-- netTcpBinding用 -->
      <netTcpBinding>
        <binding name="Binding1">
          <security mode="None"/>
        </binding>
      </netTcpBinding>

    </bindings>
  </system.serviceModel>
</configuration>

転送パフォーマンスを重視したコンフィグレーション・コード
この設定ではトランスポートTCPにおけるノンセキュアかつバイナリ形式(Binary Serialization)のエンコーディングが使用される。コンフィグレーション・ファイルのわずかな変更で、トランスポートやエンコーディングを簡単に切り替えられえる。

 このように1つのプログラミング・モデルに基づきサービスを実装することになるので、状況に応じた変更が非常に容易なものとなっているわけだ。このようなプログラミングに関するより詳細な解説は、次回以降に行う予定だ*3。ここではそのWCFの持つプログラミング上のメリットを理解していただきたい。

*3 上記の例のようにコンフィグレーションを状況に応じて書き換えるといった手法もあるが、さまざまな状況に対応可能なエンドポイントを並列に用意しておくといった手法も取れる。詳細は次回以降で解説する。


 次にWCFのWinFXにおける位置付けについて説明しよう。

Copyright© Digital Advantage Corp. All Rights Reserved.

RSSについて

アイティメディアIDについて

メールマガジン登録

@ITのメールマガジンは、 もちろん、すべて無料です。ぜひメールマガジンをご購読ください。