次の方法で共有


エンドポイント アドレスの指定

Windows Communication Foundation (WCF) サービスとの通信はすべて、そのエンドポイントを介して行われます。 各 ServiceEndpoint には、 AddressBinding、および Contractが含まれています。 コントラクトは、使用できる操作を指定します。 バインディングはサービスと通信する方法を指定し、アドレスはサービスを検索する場所を指定します。 すべてのエンドポイントには一意のアドレスが必要です。 エンドポイント アドレスは、サービスのアドレスを表す URI (Uniform Resource Identifier) を含む EndpointAddress クラス、サービスのセキュリティ ID を表す Identity、オプションの Headersのコレクションによって表されます。 オプションのヘッダーは、エンドポイントを識別または操作するためのより詳細なアドレス指定情報を提供します。 たとえば、ヘッダーは、受信メッセージの処理方法、エンドポイントが応答メッセージを送信する場所、または複数のインスタンスが使用可能な場合に特定のユーザーからの受信メッセージを処理するために使用するサービスのインスタンスを示すことができます。

エンドポイント アドレスの定義

WCF では、 EndpointAddress は、WS-Addressing 標準で定義されているエンドポイント参照 (EPR) をモデル化します。

ほとんどのトランスポートのアドレス URI には 4 つの部分があります。 たとえば、この URI http://www.fabrikam.com:322/mathservice.svc/secureEndpoint には次の 4 つの部分があります。

  • スキーム: http:

  • マシン: www.fabrikam.com

  • (省略可能)ポート: 322

  • パス : /mathservice.svc/secureEndpoint

EPR モデルの一部として、各エンドポイント参照には、追加の識別情報を追加する参照パラメーターを含めることができます。 WCF では、これらの参照パラメーターは、 AddressHeader クラスのインスタンスとしてモデル化されます。

サービスのエンドポイント アドレスは、コードを使用して命令的に指定することも、構成を通じて宣言によって指定することもできます。 通常、コードでのエンドポイントの定義は実用的ではありません。デプロイされたサービスのバインドとアドレスは、通常、サービスの開発中に使用されるものとは異なるためです。 一般に、コードではなく構成を使用してサービス エンドポイントを定義する方が実用的です。 バインディングとアドレス指定の情報をコードから除外すると、アプリケーションを再コンパイルして再デプロイしなくても変更できます。 コードまたは構成でエンドポイントが指定されていない場合、ランタイムは、サービスによって実装されるコントラクトごとに、各ベース アドレスに 1 つの既定のエンドポイントを追加します。

WCF でサービスのエンドポイント アドレスを指定するには、2 つの方法があります。 サービスに関連付けられている各エンドポイントの絶対アドレスを指定することも、サービスの ServiceHost のベース アドレスを指定して、このベース アドレスに対して定義されているこのサービスに関連付けられている各エンドポイントのアドレスを指定することもできます。 これらの各手順を使用して、構成またはコードでサービスのエンドポイント アドレスを指定できます。 相対アドレスを指定しない場合、サービスはベース アドレスを使用します。 1 つのサービスに対して複数のベース アドレスを使用することもできますが、各サービスで許可されるベース アドレスはトランスポートごとに 1 つだけです。 複数のエンドポイントがあり、それぞれが異なるバインディングで構成されている場合、それらのアドレスは一意である必要があります。 同じバインディングを使用するが、コントラクトが異なるエンドポイントでは、同じアドレスを使用できます。

IIS を使用してホストする場合、 ServiceHost インスタンスは自分で管理しません。 ベース アドレスは、IIS でホストする場合、サービスの .svc ファイルで常に指定されたアドレスです。 そのため、IIS でホストされるサービス エンドポイントには相対エンドポイント アドレスを使用する必要があります。 完全修飾エンドポイント アドレスを指定すると、サービスのデプロイでエラーが発生する可能性があります。 詳細については、「 WCF サービス Services-Hosted インターネット情報の展開」を参照してください。

構成でのエンドポイント アドレスの定義

構成ファイルでエンドポイントを定義するには、 <endpoint> 要素を使用します。

<configuration>
  <system.serviceModel>
    <services>
      <service name="UE.Samples.HelloService"
               behaviorConfiguration="HelloServiceBehavior">
        <endpoint address="/Address1"
                  binding="basicHttpBinding" 
                  contract="UE.Samples.IHello"/>

        <endpoint address="mex"
                  binding="mexHttpBinding"
                  contract="IMetadataExchange" />
      </service>
    </services>
    <behaviors>
      <serviceBehaviors>
        <behavior name="HelloServiceBehavior">
          <serviceMetadata httpGetEnabled="true" />
        </behavior>
      </serviceBehaviors>
    </behaviors>
  </system.serviceModel>
</configuration>

Open メソッドが呼び出されると (つまり、ホスティング アプリケーションがサービスを開始しようとしたときに)、システムは"UE" を指定する name 属性を持つ <service> 要素を検索します。Samples.HelloService"。 <service>要素が見つかった場合、システムは指定されたクラスを読み込み、構成ファイルで指定されたエンドポイント定義を使用してエンドポイントを作成します。 このメカニズムを使用すると、コードのバインドとアドレス指定の情報を保持しながら、2 行のコードでサービスを読み込んで開始できます。 この方法の利点は、アプリケーションを再コンパイルまたは再デプロイしなくても、これらの変更を行うことができるということです。

省略可能なヘッダーは、 <ヘッダー>で宣言されます。 2 つのヘッダーを区別する構成ファイル内のサービスのエンドポイントを指定するために使用される要素の例を次に示します。"Gold" クライアントと http://tempuri1.org/ クライアントと "Standard" クライアントと http://tempuri2.org/。 このサービスを呼び出すクライアントの構成ファイルには、適切な <ヘッダー> が必要です。

<configuration>
  <system.serviceModel>
    <services>
      <service name="UE.Samples.HelloService"
               behaviorConfiguration="HelloServiceBehavior">
        <endpoint address="/Address1"
                  binding="basicHttpBinding" 
                  contract="UE.Samples.IHello">
          <headers>
            <Member xmlns="http://tempuri1.org/">Gold</Member>
          </headers>
        </endpoint>
        <endpoint address="/Address2"
          binding="basicHttpBinding" 
          contract="UE.Samples.IHello">
          <headers>
            <Member xmlns="http://tempuri2.org/">Silver</Member>
          </headers>
        </endpoint>

        <endpoint address="mex"
                  binding="mexHttpBinding"
                  contract="IMetadataExchange" />
      </service>
    </services>
    <behaviors>
      <serviceBehaviors>
        <behavior name="HelloServiceBehavior">
          <serviceMetadata httpGetEnabled="true" />
        </behavior>
      </serviceBehaviors>
    </behaviors>
  </system.serviceModel>
</configuration>

ヘッダーは、(前に示したように) エンドポイント上のすべてのメッセージではなく、個々のメッセージに設定することもできます。 これを行うには、次の例に示すように、 OperationContextScope を使用してクライアント アプリケーションに新しいコンテキストを作成し、送信メッセージにカスタム ヘッダーを追加します。

SampleServiceClient wcfClient = new SampleServiceClient(new InstanceContext(this));
try
{
  using (OperationContextScope scope = new OperationContextScope(wcfClient.InnerChannel))
  {
    MessageHeader header
      = MessageHeader.CreateHeader(
      "Service-Bound-CustomHeader",
      "http://Microsoft.WCF.Documentation",
      "Custom Happy Value."
      );
    OperationContext.Current.OutgoingMessageHeaders.Add(header);

    // Making calls.
    Console.WriteLine("Enter the greeting to send: ");
    string greeting = Console.ReadLine();

    //Console.ReadLine();
    header = MessageHeader.CreateHeader(
        "Service-Bound-OneWayHeader",
        "http://Microsoft.WCF.Documentation",
        "Different Happy Value."
      );
    OperationContext.Current.OutgoingMessageHeaders.Add(header);

    // One-way
    wcfClient.Push(greeting);
    this.wait.WaitOne();

    // Done with service.
    wcfClient.Close();
    Console.WriteLine("Done!");
    Console.ReadLine();
  }
}
catch (TimeoutException timeProblem)
{
  Console.WriteLine("The service operation timed out. " + timeProblem.Message);
  Console.ReadLine();
  wcfClient.Abort();
}
catch (CommunicationException commProblem)
{
  Console.WriteLine("There was a communication problem. " + commProblem.Message);
  Console.ReadLine();
  wcfClient.Abort();
}
Dim wcfClient As New SampleServiceClient(New InstanceContext(Me))
Try
    Using scope As New OperationContextScope(wcfClient.InnerChannel)
        Dim header As MessageHeader = MessageHeader.CreateHeader("Service-Bound-CustomHeader", _
                            "http://Microsoft.WCF.Documentation", "Custom Happy Value.")
        OperationContext.Current.OutgoingMessageHeaders.Add(header)

        ' Making calls.
        Console.WriteLine("Enter the greeting to send: ")
        Dim greeting As String = Console.ReadLine()

        'Console.ReadLine();
        header = MessageHeader.CreateHeader("Service-Bound-OneWayHeader", _
                                            "http://Microsoft.WCF.Documentation", "Different Happy Value.")
        OperationContext.Current.OutgoingMessageHeaders.Add(header)

        ' One-way
        wcfClient.Push(greeting)
        Me.wait.WaitOne()

        ' Done with service. 
        wcfClient.Close()
        Console.WriteLine("Done!")
        Console.ReadLine()
    End Using
Catch timeProblem As TimeoutException
    Console.WriteLine("The service operation timed out. " & timeProblem.Message)
    Console.ReadLine()
    wcfClient.Abort()
Catch commProblem As CommunicationException
    Console.WriteLine("There was a communication problem. " & commProblem.Message)
    Console.ReadLine()
    wcfClient.Abort()
End Try

メタデータ内のエンドポイント アドレス

エンドポイント アドレスは、Web サービス記述言語 (WSDL) で、対応するエンドポイントのwsdl:port要素内の WS-Addressing EndpointReference (EPR) 要素として表されます。 EPR には、エンドポイントのアドレスと任意のアドレス プロパティが含まれます。 次の例に示すように、 wsdl:port 内の EPR によって soap:Address が置き換えられます。

コードでのエンドポイント アドレスの定義

エンドポイント アドレスは、 EndpointAddress クラスを使用してコード内に作成できます。 エンドポイント アドレスに指定される URI には、完全修飾パスまたはサービスのベース アドレスを基準とするパスを指定できます。 次のコードは、 EndpointAddress クラスのインスタンスを作成し、サービスをホストしている ServiceHost インスタンスに追加する方法を示しています。

次の例では、コードで完全なエンドポイント アドレスを指定する方法を示します。

Uri baseAddress = new Uri("http://localhost:8000/HelloService");
string address = "http://localhost:8000/HelloService/MyService";

using (ServiceHost serviceHost = new ServiceHost(typeof(HelloService), baseAddress))
{
    serviceHost.AddServiceEndpoint(typeof(IHello), new BasicHttpBinding(), address);
    serviceHost.Open();
    Console.WriteLine("Press <enter> to terminate service");
    Console.ReadLine();
    serviceHost.Close();
}

次の例では、サービス ホストのベース アドレスに相対アドレス ("MyService") を追加する方法を示します。

Uri baseAddress = new Uri("http://localhost:8000/HelloService");

using (ServiceHost serviceHost = new ServiceHost(typeof(HelloService), baseAddress))
{
    serviceHost.AddServiceEndpoint(typeof(IHello), new BasicHttpBinding(), "MyService");
    serviceHost.Open();
    Console.WriteLine("Press <enter> to terminate service");
    Console.ReadLine();
    serviceHost.Close();
}

サービス アプリケーションのServiceDescriptionのプロパティは、OnOpeningServiceHostBase メソッドの後で変更しないでください。 Credentials プロパティや、ServiceHostBaseおよびServiceHostAddServiceEndpoint メソッドなど、一部のメンバーは、その後に変更された場合に例外をスローします。 他の項目は変更可能ですが、結果は未定義です。

同様に、クライアントでは、ServiceEndpointOnOpeningを呼び出した後に、ChannelFactory値を変更することはできません。 Credentials プロパティは、その後に変更された場合に例外をスローします。 他のクライアント記述値はエラーなしで変更できますが、結果は未定義です。

サービスでもクライアントでも、 Openを呼び出す前に説明を変更することをお勧めします。

既定のエンドポイントの使用

コードまたは構成でエンドポイントが指定されていない場合、ランタイムは、サービスによって実装される各サービス コントラクトの各ベース アドレスに 1 つの既定のエンドポイントを追加することで、既定のエンドポイントを提供します。 ベース アドレスはコードまたは構成で指定でき、 OpenServiceHostで呼び出されたときに既定のエンドポイントが追加されます。

エンドポイントが明示的に指定されている場合でも、AddDefaultEndpointsを呼び出す前にServiceHostOpenを呼び出すことによって、既定のエンドポイントを追加できます。 既定のエンドポイント、バインディング、および動作の詳細については、「WCF サービスの 簡略化された構成簡略化された構成」を参照してください。

こちらも参照ください