次の方法で共有


ASP.NET Web サービスと開発に基づく WCF の比較

Windows Communication Foundation (WCF) には、ASP.NET Web サービスのように WCF アプリケーションをプログラミングして構成し、その動作を模倣するための ASP.NET 互換モード オプションがあります。 次のセクションでは、両方のテクノロジ ASP.NET 使用してアプリケーションを開発するために必要な内容に基づいて、Web サービスと WCF を比較します。

データ表現

ASP.NET を使用した Web サービスの開発は、通常、サービスが使用する複雑なデータ型の定義から始まります。 ASP.NET は、サービスとの間で送受信するために .NET Framework 型で表されるデータを XML に変換し、XML として受信したデータを .NET Framework オブジェクトに変換するために、 XmlSerializer に依存します。 ASP.NET サービスが使用する複合データ型を定義するには、 XmlSerializer が XML との間でシリアル化できる .NET Framework クラスの定義が必要です。 このようなクラスは、手動で記述することも、コマンド ラインの XML スキーマ/データ型サポート ユーティリティを使用して XML スキーマ内の型の定義から生成 xsd.exe。

XmlSerializerが XML との間でシリアル化できる .NET Framework クラスを定義するときに知っておくべき重要な問題の一覧を次に示します。

  • .NET Framework オブジェクトのパブリック フィールドとプロパティのみが XML に変換されます。

  • コレクション クラスのインスタンスは、クラスが IEnumerable または ICollection インターフェイスを実装する場合にのみ XML にシリアル化できます。

  • IDictionaryなど、Hashtable インターフェイスを実装するクラスを XML にシリアル化することはできません。

  • System.Xml.Serialization名前空間の非常に多くの属性型を .NET Framework クラスとそのメンバーに追加して、クラスのインスタンスを XML で表す方法を制御できます。

WCF アプリケーションの開発は、通常、複合型の定義から始まります。 WCF は、ASP.NET Web サービスと同じ .NET Framework 型を使用するように作成できます。

次のサンプル コードに示すように、WCFDataContractAttributeDataMemberAttribute を .NET Framework 型に追加して、型のインスタンスを XML にシリアル化し、型の特定のフィールドまたはプロパティをシリアル化することを示すことができます。

//Example One:
[DataContract]
public class LineItem
{
    [DataMember]
    public string ItemNumber;
    [DataMember]
    public decimal Quantity;
    [DataMember]
    public decimal UnitPrice;
}

//Example Two:
public class LineItem
{
    [DataMember]
    private string itemNumber;
    [DataMember]
    private decimal quantity;
    [DataMember]
    private decimal unitPrice;

    public string ItemNumber
    {
      get
      {
          return this.itemNumber;
      }

      set
      {
          this.itemNumber = value;
      }
    }

    public decimal Quantity
    {
        get
        {
            return this.quantity;
        }

        set
        {
            this.quantity = value;
        }
    }

    public decimal UnitPrice
    {
      get
      {
          return this.unitPrice;
      }

      set
      {
          this.unitPrice = value;
      }
    }
}

//Example Three:
public class LineItem
{
     private string itemNumber;
     private decimal quantity;
     private decimal unitPrice;

     [DataMember]
     public string ItemNumber
     {
       get
       {
          return this.itemNumber;
       }

       set
       {
           this.itemNumber = value;
       }
     }

     [DataMember]
     public decimal Quantity
     {
          get
          {
              return this.quantity;
          }

          set
          {
             this.quantity = value;
          }
     }

     [DataMember]
     public decimal UnitPrice
     {
          get
          {
              return this.unitPrice;
          }

          set
          {
              this.unitPrice = value;
          }
     }
}

DataContractAttributeは、0 個以上の型のフィールドまたはプロパティをシリアル化することを示しますが、DataMemberAttributeは特定のフィールドまたはプロパティをシリアル化することを示します。 DataContractAttributeは、クラスまたは構造体に適用できます。 DataMemberAttributeはフィールドまたはプロパティに適用でき、属性が適用されるフィールドとプロパティはパブリックまたはプライベートにすることができます。 DataContractAttributeが適用されている型のインスタンスは、WCF ではデータ コントラクトと呼ばれます。 これらは、 DataContractSerializerを使用して XML にシリアル化されます。

DataContractSerializerの使用と、XmlSerializerSystem.Xml.Serialization名前空間のさまざまな属性の使用の重要な違いの一覧を次に示します。

  • XmlSerializer名前空間のSystem.Xml.Serializationと属性は、.NET Framework 型を XML スキーマで定義されている任意の有効な型にマップできるように設計されているため、XML での型の表現方法を非常に正確に制御できます。 DataContractSerializerDataContractAttribute、およびDataMemberAttributeでは、XML での型の表現方法をほとんど制御できません。 XML 内の型とそのフィールドまたはプロパティを表すために使用される名前空間と名前、および XML にフィールドとプロパティが表示されるシーケンスのみを指定できます。

    [DataContract(
    Namespace="urn:Contoso:2006:January:29",
    Name="LineItem")]
    public class LineItem
    {
          [DataMember(Name="ItemNumber",IsRequired=true,Order=0)]
          public string itemNumber;
          [DataMember(Name="Quantity",IsRequired=false,Order = 1)]
          public decimal quantity;
          [DataMember(Name="Price",IsRequired=false,Order = 2)]
          public decimal unitPrice;
    }
    

    .NET 型を表すために使用される XML の構造に関するその他のすべてが、 DataContractSerializerによって決定されます。

  • XML で型を表現する方法をあまり制御できないことで、シリアル化プロセスは DataContractSerializerに対して非常に予測可能になり、最適化が容易になります。 DataContractSerializerの設計の実用的な利点は、パフォーマンスが向上し、パフォーマンスが約 10% 向上することです。

  • XmlSerializerで使用する属性では、型のどのフィールドまたはプロパティが XML にシリアル化されるかは示されませんが、DataMemberAttributeで使用するDataContractSerializerでは、シリアル化されるフィールドまたはプロパティが明示的に示されます。 したがって、データ コントラクトは、アプリケーションが送受信するデータの構造に関する明示的なコントラクトです。

  • XmlSerializerでは、.NET オブジェクトのパブリック メンバーのみを XML に変換できます。DataContractSerializerは、それらのメンバーのアクセス修飾子に関係なく、オブジェクトのメンバーを XML に変換できます。

  • 型の非パブリック メンバーを XML にシリアル化できるため、 DataContractSerializer は XML にシリアル化できるさまざまな .NET 型に対する制限が少なくなります。 特に、Hashtable インターフェイスを実装するIDictionaryなどの XML 型に変換できます。 DataContractSerializerは、既存の .NET 型のインスタンスを XML にシリアル化できる可能性が高くなります。この場合、型の定義を変更したり、ラッパーを開発したりする必要はありません。

  • 型の非パブリック メンバーにアクセスできる DataContractSerializer のもう 1 つの結果は、完全な信頼が必要であるのに対し、 XmlSerializer では必要ありません。 完全信頼コード アクセス許可は、コードが実行されている資格情報を使用してアクセスできるコンピューター上のすべてのリソースへの完全なアクセスを提供します。 完全に信頼されたコードがコンピューター上のすべてのリソースにアクセスする場合は、このオプションを慎重に使用する必要があります。

  • DataContractSerializerには、バージョン管理のサポートがいくつか組み込まれています。

    • DataMemberAttributeには、以前のバージョンに存在しなかったデータ コントラクトの新しいバージョンに追加されたメンバーに対して false の値を割り当てることができるIsRequired プロパティがあり、これにより、コントラクトの新しいバージョンのアプリケーションで以前のバージョンを処理できるようになります。

    • データ コントラクトに IExtensibleDataObject インターフェイスを実装することで、 DataContractSerializer は、以前のバージョンのコントラクトを持つアプリケーションを介して、データ コントラクトの新しいバージョンで定義されたメンバーを渡すことができます。

すべての違いにもかかわらず、既定で XmlSerializer が型をシリアル化する XML は、XML の名前空間が明示的に定義されていれば、 DataContractSerializer が型をシリアル化する XML と意味的に同じです。 シリアライザーの両方で使用する属性を持つ次のクラスは、 XmlSerializerDataContractAttributeによって意味的に同一の XML に変換されます。

[Serializable]
[XmlRoot(Namespace="urn:Contoso:2006:January:29")]
[DataContract(Namespace="urn:Contoso:2006:January:29")]
public class LineItem
{
     [DataMember]
     public string ItemNumber;
     [DataMember]
     public decimal Quantity;
     [DataMember]
     public decimal UnitPrice;
}

Windows ソフトウェア開発キット (SDK) には、 ServiceModel メタデータ ユーティリティ ツール (Svcutil.exe) と呼ばれるコマンド ライン ツールが含まれています。 ASP.NET Web サービスで使用される xsd.exe ツールと同様に、Svcutil.exe は XML スキーマから .NET データ型の定義を生成できます。 型は、 DataContractSerializer が XML スキーマで定義された形式で XML を出力できる場合はデータ コントラクトです。それ以外の場合は、 XmlSerializerを使用したシリアル化を目的としています。 Svcutil.exe は、 dataContractOnly スイッチを使用してデータ コントラクトから XML スキーマを生成することもできます。

ASP.NET Web サービスは XmlSerializerを使用し、WCF ASP.NET 互換モードでは WCF サービスが ASP.NET Web サービスの動作を模倣しますが、ASP.NET 互換性オプションでは、 XmlSerializerを使用するように制限されません。 ASP.NET 互換モードで実行されているサービスで DataContractSerializer を引き続き使用できます。

サービス開発

ASP.NET を使用してサービスを開発するには、 WebService 属性をクラスに追加し、サービスの操作となるクラスのいずれかのメソッドに WebMethodAttribute を追加することが慣例されています。

[WebService]
public class Service : T:System.Web.Services.WebService
{
    [WebMethod]
    public string Echo(string input)
    {
       return input;
    }
}

ASP.NET 2.0 では、属性 WebServiceWebMethodAttribute をクラスではなくインターフェイスに追加し、インターフェイスを実装するクラスを記述するオプションが導入されました。

[WebService]
public interface IEcho
{
    [WebMethod]
    string Echo(string input);
}

public class Service : IEcho
{

   public string Echo(string input)
   {
        return input;
    }
}

WebService属性を持つインターフェイスは、同じコントラクトをさまざまな方法で実装する可能性のあるさまざまなクラスで再利用できるサービスによって実行される操作のコントラクトを構成するため、このオプションを使用することをお勧めします。

WCF サービスは、1 つ以上の WCF エンドポイントを定義することによって提供されます。 エンドポイントは、アドレス、バインディング、およびサービス コントラクトによって定義されます。 このアドレスは、サービスが配置される場所を定義します。 バインディングは、サービスとの通信方法を指定します。 サービス コントラクトは、サービスが実行できる操作を定義します。

サービス コントラクトは、通常、インターフェイスに ServiceContractAttributeOperationContractAttribute を追加することによって、最初に定義されます。

[ServiceContract]
public interface IEcho
{
     [OperationContract]
     string Echo(string input);
}

ServiceContractAttributeは、インターフェイスが WCF サービス コントラクトを定義することを指定し、OperationContractAttributeは、インターフェイスのメソッドのうち、サービス コントラクトの操作を定義するメソッド (存在する場合) を示します。

サービス コントラクトが定義されると、サービス コントラクトが定義されているインターフェイスをクラスに実装することで、サービス コントラクトがクラスに実装されます。

public class Service : IEcho
{
    public string Echo(string input)
    {
       return input;
    }
}

サービス コントラクトを実装するクラスは、WCF ではサービス型と呼ばれます。

次の手順では、アドレスとバインディングをサービスの種類に関連付けます。 これは通常、ファイルを直接編集するか、WCF で提供される構成エディターを使用して、構成ファイルで行われます。 構成ファイルの例を次に示します。

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
     <system.serviceModel>
      <services>
      <service name="Service ">
       <endpoint
        address="EchoService"
        binding="basicHttpBinding"
        contract="IEchoService "/>
      </service>
      </services>
     </system.serviceModel>
</configuration>

バインディングは、アプリケーションと通信するためのプロトコルのセットを指定します。 次の表に、一般的なオプションを表すシステム提供のバインドを示します。

名前 目的
BasicHttpBinding WS-BasicProfile 1.1 および Basic Security Profile 1.0 をサポートする Web サービスおよびクライアントとの相互運用性。
WSHttpBinding HTTP 経由の WS-* プロトコルをサポートする Web サービスおよびクライアントとの相互運用性。
WSDualHttpBinding 初期メッセージの受信者が最初の送信者に直接応答せず、WS-* プロトコルに準拠した HTTP を使用して一定期間にわたって任意の数の応答を送信できる双方向 HTTP 通信。
WSFederationBinding サービスのリソースへのアクセスを、明示的に識別された資格情報プロバイダーによって発行された資格情報に基づいて制御できる HTTP 通信。
NetTcpBinding ネットワーク経由で WCF ソフトウェア エンティティ間のセキュリティで保護された信頼性の高い高パフォーマンス通信。
NetNamedPipeBinding 同じコンピューター上の WCF ソフトウェア エンティティ間のセキュリティで保護された信頼性の高い高パフォーマンス通信。
NetMsmqBinding MSMQ を使用した WCF ソフトウェア エンティティ間の通信。
MsmqIntegrationBinding (MSMQ統合バインディング) MSMQ を使用した WCF ソフトウェア エンティティと別のソフトウェア エンティティ間の通信。
NetPeerTcpBinding Windows ピア ツー ピア ネットワークを使用した WCF ソフトウェア エンティティ間の通信。

システム提供のバインディング BasicHttpBindingには、ASP.NET Web サービスでサポートされるプロトコルのセットが組み込まれています。

WCF アプリケーションのカスタム バインドは、WCF が個々のプロトコルを実装するために使用するバインディング要素クラスのコレクションとして簡単に定義できます。 新しいバインド要素は、追加のプロトコルを表すために記述できます。

サービスの種類の内部動作は、動作と呼ばれるクラス ファミリのプロパティを使用して調整できます。 ここでは、 ServiceBehaviorAttribute クラスを使用して、サービスの種類をマルチスレッドにすることを指定します。

[ServiceBehavior(ConcurrencyMode=ConcurrencyMode.Multiple)]
public class DerivativesCalculatorServiceType: IDerivativesCalculator

ServiceBehaviorAttributeなどの一部の動作は属性です。 他には、管理者が設定したいプロパティを持つものは、アプリケーションの構成で変更できます。

プログラミング サービスの種類では、 OperationContext クラスを頻繁に使用します。 その静的 Current プロパティは、操作が実行されているコンテキストに関する情報へのアクセスを提供します。 OperationContext は、 HttpContext クラスと ContextUtil クラスの両方に似ています。

ホスティング

ASP.NET Web サービスはクラス ライブラリ アセンブリにコンパイルされます。 .asmx という拡張子を持つサービス ファイルと呼ばれるファイルが提供され、サービスのコードとサービスが配置されているアセンブリを含むクラスを識別する @ WebService ディレクティブが含まれています。

<%@ WebService Language="C#" Class="Service,ServiceAssembly" %>

サービス ファイルはインターネット インフォメーション サービス (IIS) の ASP.NET アプリケーション ルートにコピーされ、アセンブリはそのアプリケーション ルートの \bin サブディレクトリにコピーされます。 アプリケーションは、アプリケーション ルート内のサービス ファイルの UNIFORM Resource Locator (URL) を使用してアクセスできます。

WCF サービスは、IIS 5.1 または 6.0、IIS 7.0 の一部として提供される Windows プロセス アクティブ化サービス (WAS) 内、および任意の .NET アプリケーション内で簡単にホストできます。 IIS 5.1 または 6.0 でサービスをホストするには、通信トランスポート プロトコルとして HTTP を使用する必要があります。

IIS 5.1、6.0 内、または WAS 内でサービスをホストするには、次の手順を使用します。

  1. サービス型をクラス ライブラリ アセンブリにコンパイルします。

  2. @ ServiceHost ディレクティブを持つ .svc 拡張子を持つサービス ファイルを作成して、サービスの種類を識別します。

    <%@ServiceHost language="c#" Service="MyService" %>

  3. サービス ファイルを仮想ディレクトリにコピーし、アセンブリをその仮想ディレクトリの \bin サブディレクトリにコピーします。

  4. 構成ファイルを仮想ディレクトリにコピーし、Web.config名前を付けます。

アプリケーションは、アプリケーション ルート内のサービス ファイルの URL を使用してアクセスできます。

.NET アプリケーション内で WCF サービスをホストするには、サービスの種類をアプリケーションによって参照されるクラス ライブラリ アセンブリにコンパイルし、 ServiceHost クラスを使用してサービスをホストするようにアプリケーションをプログラムします。 必要な基本的なプログラミングの例を次に示します。

string httpBaseAddress = "http://www.contoso.com:8000/";
string tcpBaseAddress = "net.tcp://www.contoso.com:8080/";

Uri httpBaseAddressUri = new Uri(httpBaseAddress);
Uri tcpBaseAddressUri = new Uri(tcpBaseAddress);

Uri[] baseAddresses = new Uri[] {
 httpBaseAddressUri,
 tcpBaseAddressUri};

using(ServiceHost host = new ServiceHost(
typeof(Service), //"Service" is the name of the service type baseAddresses))
{
     host.Open();

     […] //Wait to receive messages
     host.Close();
}

この例では、 ServiceHostの構築で 1 つ以上のトランスポート プロトコルのアドレスを指定する方法を示します。 これらのアドレスはベース アドレスと呼ばれます。

WCF サービスの任意のエンドポイントに提供されるアドレスは、エンドポイントのホストのベース アドレスに対する相対アドレスです。 ホストは、通信トランスポート プロトコルごとに 1 つのベース アドレスを持つことができます。 前の構成ファイルのサンプル構成では、エンドポイント用に選択された BasicHttpBinding はトランスポート プロトコルとして HTTP を使用するため、エンドポイントのアドレス ( EchoService) はホストの HTTP ベース アドレスに対して相対的です。 前の例のホストの場合、HTTP ベース アドレスは http://www.contoso.com:8000/。 IIS または WAS 内でホストされているサービスの場合、ベース アドレスはサービスのサービス ファイルの URL です。

WCF ASP.NET 互換モード オプションを使用するには、IIS または WAS でホストされ、HTTP を使用して排他的に構成されているサービスのみを使用できます。 このオプションをオンにする場合は、次の手順が必要です。

  1. プログラマは、 AspNetCompatibilityRequirementsAttribute 属性をサービスの種類に追加し、互換性モード ASP.NET 許可するか必須にするかを指定する必要があります。

    [System.ServiceModel.Activation.AspNetCompatibilityRequirements(
          RequirementsMode=AspNetCompatibilityRequirementsMode.Require)]
    public class DerivativesCalculatorServiceType: IDerivativesCalculator
    
  2. 管理者は、ASP.NET 互換モードを使用するようにアプリケーションを構成する必要があります。

    <configuration>
         <system.serviceModel>
          <services>
          […]
          </services>
          <serviceHostingEnvironment aspNetCompatibilityEnabled="true"/>
        </system.serviceModel>
    </configuration>
    

    WCF アプリケーションは、.svc ではなく、サービス ファイルの拡張子として .asmx を使用するように構成することもできます。

    <system.web>
         <compilation>
          <compilation debug="true">
          <buildProviders>
           <remove extension=".asmx"/>
           <add extension=".asmx"
            type="System.ServiceModel.ServiceBuildProvider,
            System.ServiceModel,
            Version=3.0.0.0,
            Culture=neutral,
            PublicKeyToken=b77a5c561934e089" />
          </buildProviders>
          </compilation>
         </compilation>
    </system.web>
    

    このオプションを使用すると、WCF を使用するようにサービスを変更するときに、.asmx サービス ファイルの URL を使用するように構成されているクライアントを変更する必要ができなくなります。

クライアント開発

ASP.NET Web サービスのクライアントは、コマンド ライン ツール (WSDL.exe) を使用して生成されます。これは、.asmx ファイルの URL を入力として提供します。 WCF によって提供される対応するツールは、 ServiceModel メタデータ ユーティリティ ツール (Svcutil.exe) です。 サービス コントラクトの定義と WCF クライアント クラスの定義を含むコード モジュールが生成されます。 また、サービスのアドレスとバインドを含む構成ファイルも生成されます。

リモート サービスのクライアントのプログラミングでは、通常、非同期パターンに従ってプログラムすることをお勧めします。 WSDL.exe ツールによって生成されるコードは、既定で同期パターンと非同期パターンの両方に対して常に提供されます。 ServiceModel メタデータ ユーティリティ ツール (Svcutil.exe) によって生成されたコードは、どちらのパターンにも対応できます。 既定では同期パターンが提供されます。 ツールが /async スイッチを使用して実行される場合、生成されたコードは非同期パターンを提供します。

ASP.NET の WSDL.exe ツールによって生成された WCF クライアント クラスの名前は、既定では、Svcutil.exe ツールによって生成された WCF クライアント クラスの名前と一致する保証はありません。 特に、 XmlSerializer を使用してシリアル化する必要があるクラスのプロパティの名前は、既定では、Svcutil.exe ツールによって生成されたコードのサフィックスプロパティが指定されます。これは、WSDL.exe ツールの場合ではありません。

メッセージ表現

ASP.NET Web サービスによって送受信される SOAP メッセージのヘッダーはカスタマイズできます。 クラスは SoapHeader から派生してヘッダーの構造を定義し、 SoapHeaderAttribute を使用してヘッダーの存在を示します。

public class SomeProtocol : SoapHeader
{
     public long CurrentValue;
     public long Total;
}

[WebService]
public interface IEcho
{
     SomeProtocol ProtocolHeader
     {
      get;
     set;
     }

     [WebMethod]
     [SoapHeader("ProtocolHeader")]
     string PlaceOrders(PurchaseOrderType order);
}

public class Service: WebService, IEcho
{
     private SomeProtocol protocolHeader;

     public SomeProtocol ProtocolHeader
     {
         get
         {
              return this.protocolHeader;
         }

         set
         {
              this.protocolHeader = value;
         }
     }

     string PlaceOrders(PurchaseOrderType order)
     {
         long currentValue = this.protocolHeader.CurrentValue;
     }
}

WCF は、サービスによって送受信される SOAP メッセージの構造を記述するための属性、 MessageContractAttributeMessageHeaderAttribute、および MessageBodyMemberAttribute を提供します。

[DataContract]
public class SomeProtocol
{
     [DataMember]
     public long CurrentValue;
     [DataMember]
     public long Total;
}

[DataContract]
public class Item
{
     [DataMember]
     public string ItemNumber;
     [DataMember]
     public decimal Quantity;
     [DataMember]
     public decimal UnitPrice;
}

[MessageContract]
public class ItemMessage
{
     [MessageHeader]
     public SomeProtocol ProtocolHeader;
     [MessageBody]
     public Item Content;
}

[ServiceContract]
public interface IItemService
{
     [OperationContract]
     public void DeliverItem(ItemMessage itemMessage);
}

この構文は、メッセージの構造を明示的に表しますが、メッセージの構造は ASP.NET Web サービスのコードによって暗黙的に示されます。 また、ASP.NET 構文では、メッセージ ヘッダーはサービスのプロパティ (前の例の ProtocolHeader プロパティなど) として表されますが、WCF 構文では、メッセージのプロパティとしてより正確に表されます。 また、WCF では、メッセージ ヘッダーをエンドポイントの構成に追加できます。

<service name="Service ">
     <endpoint
      address="EchoService"
      binding="basicHttpBinding"
      contract="IEchoService ">
      <headers>
      <dsig:X509Certificate
       xmlns:dsig="http://www.w3.org/2000/09/xmldsig#">
       ...
      </dsig:X509Certificate>
      </headers>
     </endpoint>
</service>

このオプションを使用すると、クライアントまたはサービスのコード内のインフラストラクチャ プロトコル ヘッダーへの参照を回避できます。エンドポイントの構成方法により、ヘッダーがメッセージに追加されます。

サービスの説明

クエリ WSDL を使用して ASP.NET Web サービスの .asmx ファイルに対して HTTP GET 要求を発行すると、ASP.NET はサービスを記述する WSDL を生成します。 その WSDL が要求への応答として返されます。

ASP.NET 2.0 では、サービスが Web Services-Interoperability Organization (WS-I) の Basic Profile 1.1 に準拠していることを検証し、サービスが WSDL に準拠していることを示す要求を挿入できるようになりました。 これは、ConformsTo属性のEmitConformanceClaimsパラメーターとWebServiceBindingAttribute パラメーターを使用して行われます。

[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(
     ConformsTo = WsiProfiles.BasicProfile1_1,
     EmitConformanceClaims=true)]
public interface IEcho

サービス ASP.NET 生成する WSDL はカスタマイズできます。 カスタマイズは、WSDL に項目を追加する ServiceDescriptionFormatExtension の派生クラスを作成することによって行われます。

IIS 51、6.0、または WAS 内でホストされている HTTP エンドポイントを持つ WCF サービスの .svc ファイルに対するクエリ WSDL を使用して HTTP GET 要求を発行すると、WCF は WSDL で応答してサービスを記述します。 .NET アプリケーション内でホストされているサービスの HTTP ベース アドレスに対してクエリ WSDL を使用して HTTP GET 要求を発行すると、httpGetEnabled が true に設定されている場合も同じ効果があります。

ただし、WCF は、サービスを記述するために生成される WSDL を使用して WS-MetadataExchange 要求にも応答します。 ASP.NET Web サービスには、WS-MetadataExchange 要求のサポートが組み込まれていません。

WCF によって生成される WSDL は、広範囲にカスタマイズできます。 ServiceMetadataBehavior クラスには、WSDL をカスタマイズするためのいくつかの機能が用意されています。 WCF は、WSDL を生成するのではなく、特定の URL で静的 WSDL ファイルを使用するように構成することもできます。

<behaviors>
     <behavior name="DescriptionBehavior">
     <metadataPublishing
      enableMetadataExchange="true"
      enableGetWsdl="true"
      enableHelpPage="true"
      metadataLocation=
      "http://localhost/DerivativesCalculatorService/Service.WSDL"/>
     </behavior>
</behaviors>

例外処理

ASP.NET Web サービスでは、未処理の例外が SOAP エラーとしてクライアントに返されます。 SoapException クラスのインスタンスを明示的にスローし、クライアントに送信される SOAP エラーの内容をより詳細に制御することもできます。

WCF サービスでは、未処理の例外は SOAP エラーとしてクライアントに返されず、例外によって機密情報が誤って公開されるのを防ぎます。 デバッグの目的でクライアントに返される未処理の例外を含む構成設定が提供されます。

SOAP エラーをクライアントに返すには、ジェネリック型としてデータ コントラクト型を使用して、 FaultException<TDetail>ジェネリック型のインスタンスをスローできます。 また、 FaultContractAttribute 属性を操作に追加して、操作によって生成される可能性があるエラーを指定することもできます。

[DataContract]
public class MathFault
{
     [DataMember]
     public string operation;
     [DataMember]
     public string problemType;
}

[ServiceContract]
public interface ICalculator
{
     [OperationContract]
     [FaultContract(typeof(MathFault))]
     int Divide(int n1, int n2);
}

これにより、サービスの WSDL でエラーがアドバタイズされる可能性があるため、クライアント プログラマは、操作の結果として発生する可能性のあるエラーを予測し、適切な catch ステートメントを記述できます。

try
{
     result = client.Divide(value1, value2);
}
catch (FaultException<MathFault> e)
{
 Console.WriteLine("FaultException<MathFault>: Math fault while doing "
  + e.Detail.operation
  + ". Problem: "
  + e.Detail.problemType);
}

状態管理

ASP.NET Web サービスの実装に使用されるクラスは、 WebServiceから派生できます。

public class Service : WebService, IEcho
{

 public string Echo(string input)
 {
  return input;
 }
}

その場合、 WebService 基底クラスの Context プロパティを使用して、 HttpContext オブジェクトにアクセスするようにクラスをプログラミングできます。 HttpContext オブジェクトは、Application プロパティを使用してアプリケーション状態情報を更新および取得するために使用でき、Session プロパティを使用してセッション状態情報を更新および取得するために使用できます。

ASP.NET では、 HttpContext の Session プロパティを使用してアクセスされるセッション状態情報が実際に格納される場所を大幅に制御できます。 Cookie、データベース、現在のサーバーのメモリ、または指定されたサーバーのメモリに格納できます。 選択は、サービスの構成ファイルで行われます。

WCF には、状態管理用の拡張可能なオブジェクトが用意されています。 拡張可能なオブジェクトは、 IExtensibleObject<T>を実装するオブジェクトです。 最も重要な拡張可能オブジェクトは、 ServiceHostBaseInstanceContextです。 ServiceHostBase を使用すると、同じホスト上のすべてのサービスの種類のすべてのインスタンスがアクセスできる状態を維持できますが、 InstanceContext では、サービスの種類の同じインスタンス内で実行されている任意のコードがアクセスできる状態を維持できます。

ここで、サービスの種類 TradingSystemには、同じ WCF クライアント インスタンスからのすべての呼び出しがサービスの種類の同じインスタンスにルーティングされることを指定する ServiceBehaviorAttribute があります。

[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerSession)]
public class TradingSystem: ITradingService

DealDataクラスは、サービスの種類の同じインスタンスで実行されている任意のコードからアクセスできる状態を定義します。

internal class DealData: IExtension<InstanceContext>
{
 public string DealIdentifier = null;
 public Trade[] Trades = null;
}

サービス コントラクトのいずれかの操作を実装するサービスの種類のコードでは、 DealData 状態オブジェクトがサービスの種類の現在のインスタンスの状態に追加されます。

string ITradingService.BeginDeal()
{
 string dealIdentifier = Guid.NewGuid().ToString();
 DealData state = new DealData(dealIdentifier);
 OperationContext.Current.InstanceContext.Extensions.Add(state);
 return dealIdentifier;
}

その状態オブジェクトは、サービス コントラクトの別の操作を実装するコードによって取得および変更できます。

void ITradingService.AddTrade(Trade trade)
{
 DealData dealData =  OperationContext.Current.InstanceContext.Extensions.Find<DealData>();
 dealData.AddTrade(trade);
}

ASP.NET では、 HttpContext クラスの状態情報が実際に格納される場所を制御できます。一方、WCF は、少なくとも初期バージョンでは、拡張可能なオブジェクトが格納される場所を制御できません。 これは、WCF サービスの ASP.NET 互換モードを選択する最適な理由を構成します。 構成可能な状態管理が不可欠な場合は、ASP.NET 互換モードを選択すると、ASP.NET で使用されているのとまったく同じ HttpContext クラスの機能を使用したり、 HttpContext クラスを使用して管理される状態情報を格納する場所を構成したりできます。

安全

ASP.NET Web サービスをセキュリティで保護するオプションは、IIS アプリケーションをセキュリティで保護するためのオプションです。 WCF アプリケーションは IIS 内だけでなく、任意の .NET 実行可能ファイル内でもホストできるため、WCF アプリケーションをセキュリティで保護するためのオプションは、IIS の機能から独立している必要があります。 ただし、ASP.NET Web サービス用に提供される機能は、ASP.NET 互換モードで実行されている WCF サービスでも使用できます。

セキュリティ: 認証

IIS には、匿名アクセスまたはさまざまな認証モード (Windows 認証、ダイジェスト認証、基本認証、.NET Passport 認証) を選択できるアプリケーションへのアクセスを制御するための機能が用意されています。 Windows 認証オプションを使用して、ASP.NET Web サービスへのアクセスを制御できます。 ただし、WCF アプリケーションが IIS 内でホストされている場合は、WCF 自体で認証を管理できるように、アプリケーションへの匿名アクセスを許可するように IIS を構成する必要があります。WCF 自体は、他のさまざまなオプションの中で Windows 認証をサポートします。 組み込みのその他のオプションには、ユーザー名トークン、X.509 証明書、SAML トークン、CardSpace カードなどがありますが、カスタム認証メカニズムを定義することもできます。

セキュリティ: 偽装

ASP.NET は、特定のユーザーを偽装するために ASP.NET Web サービスを作成したり、現在の要求で提供されるユーザーの資格情報を取得したりするための ID 要素を提供します。 この要素は、ASP.NET 互換性モードで実行されている WCF アプリケーションで偽装を構成するために使用できます。

WCF 構成システムは、偽装する特定のユーザーを指定するための独自の ID 要素を提供します。 また、WCF クライアントとサービスは、偽装用に個別に構成できます。 クライアントは、要求を送信するときに現在のユーザーを偽装するように構成できます。

<behaviors>
     <behavior name="DerivativesCalculatorClientBehavior">
      <clientCredentials>
      <windows allowedImpersonationLevel="Impersonation"/>
      </clientCredentials>
     </behavior>
</behaviors>

サービス操作は、現在の要求で提供されるユーザーの資格情報を偽装するように構成できます。

[OperationBehavior(Impersonation = ImpersonationOption.Required)]
public void Receive(Message input)

セキュリティ: アクセス制御リストを使用した承認

アクセス制御リスト (ACL) を使用して、.asmx ファイルへのアクセスを制限できます。 ただし、WCF .svc ファイルの ACL は、互換性モード ASP.NET 除いて無視されます。

セキュリティ : ロール ベースの承認

IIS Windows 認証オプションは、ASP.NET 構成言語によって提供される承認要素と組み合わせて使用して、ユーザーが割り当てられている Windows グループに基づく ASP.NET Web サービスのロールベースの承認を容易にすることができます。 ASP.NET 2.0 では、より一般的なロールベースの承認メカニズムであるロール プロバイダーが導入されました。

ロール プロバイダーは、すべてのユーザーが割り当てられているロールに関する問い合わせのための基本的なインターフェイスを実装するクラスですが、各ロール プロバイダーは、別のソースからその情報を取得する方法を知っています。 ASP.NET 2.0 には、Microsoft SQL Server データベースからロールの割り当てを取得できるロール プロバイダーと、Windows Server 2003 承認マネージャーからロールの割り当てを取得できるロール プロバイダーが用意されています。

ロール プロバイダー のメカニズムは、WCF アプリケーションを含む任意の .NET アプリケーションで、ASP.NET とは別に実際に使用できます。 WCF アプリケーションの次の構成例は、ASP.NET ロール プロバイダーの使用が、 ServiceAuthorizationBehaviorによって選択されるオプションである方法を示しています。

<system.serviceModel>
     <services>
         <service name="Service.ResourceAccessServiceType"
             behaviorConfiguration="ServiceBehavior">
             <endpoint
              address="ResourceAccessService"
              binding="wsHttpBinding"
              contract="Service.IResourceAccessContract"/>
         </service>
     </services>
     <behaviors>
       <behavior name="ServiceBehavior">
       <serviceAuthorization principalPermissionMode="UseAspNetRoles"/>
      </behavior>
     </behaviors>
</system.serviceModel>

セキュリティ: クレーム ベースの承認

WCF の最も重要なイノベーションの 1 つは、要求に基づいて保護されたリソースへのアクセスを承認するための完全なサポートです。 クレームは、たとえば、種類、権限、値、ドライバーのライセンスで構成されます。 ベアラーに対する主張のセットを作成します。そのうちの 1 つはベアラーの生年月日です。 その要求の種類は生年月日ですが、要求の値はドライバーの生年月日です。 ベアラーに対して要求が付与する権限は、ベアラーが要求の値を使用して何を実行できるかを指定します。 ドライバーの生年月日の請求の場合、権利は所有しています:ドライバーはその生年月日を所有していますが、たとえば変更することはできません。 要求ベースの承認はロールを要求の一種として含むため、ロールベースの承認を包含します。

要求に基づく承認は、一連の要求を操作のアクセス要件と比較し、その比較の結果に応じて、操作へのアクセスを許可または拒否することによって実現されます。 WCF では、ServiceAuthorizationManagerServiceAuthorizationBehavior プロパティに値を割り当てることで、要求ベースの承認の実行に使用するクラスを再度指定できます。

<behaviors>
     <behavior name='ServiceBehavior'>
     <serviceAuthorization
     serviceAuthorizationManagerType=
                   'Service.AccessChecker, Service' />
     </behavior>
</behaviors>

要求ベースの承認を実行するために使用するクラスは、ServiceAuthorizationManagerから派生し、オーバーライドする必要があるメソッドが 1 つだけであるAccessCheck()を持たなければなりません。 WCF は、サービスの操作が呼び出されるたびにそのメソッドを呼び出し、 OperationContext オブジェクトを提供します。このオブジェクトには、 ServiceSecurityContext.AuthorizationContext プロパティにユーザーの要求が含まれます。 WCF は、ユーザーが認証のために指定したセキュリティ トークンからユーザーに関する要求をアセンブルする作業を行います。この場合、それらの要求が問題の操作に十分かどうかを評価するタスクが残されます。

WCF があらゆる種類のセキュリティ トークンから要求を自動的にアセンブルすることは、認証メカニズムとは完全に独立したクレームに基づいて承認用のコードを作成するため、非常に重要なイノベーションです。 これに対し、ASP.NET の ACL またはロールを使用した承認は、Windows 認証に密接に関連付けられています。

セキュリティ: 機密性

セキュリティで保護されたハイパーテキスト転送プロトコル (HTTPS) を使用するように IIS 内のアプリケーションを構成することで、ASP.NET Web サービスと交換されるメッセージの機密性をトランスポート レベルで確保できます。 IIS 内でホストされている WCF アプリケーションでも同じことができます。 ただし、IIS の外部でホストされている WCF アプリケーションは、セキュリティで保護されたトランスポート プロトコルを使用するように構成することもできます。 さらに重要なのは、WS-Security プロトコルを使用して、メッセージをトランスポートする前にメッセージをセキュリティで保護するように WCF アプリケーションを構成することもできます。 WS-Security を使用してメッセージの本文だけをセキュリティで保護すると、最終的な宛先に到達する前に、中間局間で機密性の高い方法で送信できます。

グローバリゼーション

ASP.NET 構成言語を使用すると、個々のサービスのカルチャを指定できます。 WCF は、ASP.NET 互換モードでのみ、その構成設定をサポートしています。 ASP.NET 互換モードを使用しない WCF サービスをローカライズするには、サービスの種類をカルチャ固有のアセンブリにコンパイルし、カルチャ固有のアセンブリごとに個別のカルチャ固有のエンドポイントを用意します。

こちらも参照ください