次の方法で共有


WCF トラブルシューティング クイックスタート

このトピックでは、WCF クライアントと WCF サービスの開発時に生じるさまざまな既知の問題の一覧を示します。発生している問題がこの一覧にない場合は、サービスに対してトレースを構成することをお勧めします。これにより、トレース ファイル ビューアーで表示し、サービス内で発生することがある例外に関する詳細情報を取得できるトレース ファイルが生成されます。トレースの構成の詳細については、「トレースの構成」を参照してください。トレース ファイル ビューアーの詳細については、「サービス トレース ビューアー ツール (SvcTraceViewer.exe)」を参照してください。

  1. 最初の要求の後でクライアントがしばらくアイドル状態になった場合、2 番目の要求で MessageSecurityException を受け取ることがあります。どうしてでしょうか。

  2. サービスと対話しているクライアントの数が約 10 個になると、サービスが新しいクライアントを拒否し始めます。どうしてでしょうか。

  3. WCF アプリケーションの構成ファイル以外の場所からサービス構成を読み込むことはできますか。

  4. サービスとクライアントの動作に問題はないのですが、クライアントが別のコンピューター上にあるときにサービスとクライアントがうまく動作しません。どうしてでしょうか。

  5. 型が例外である場合に FaultException<Exception> をスローすると、必ずクライアントで、ジェネリック型ではなく一般的な FaultException 型を受け取ります。どうしてでしょうか。

  6. 応答にデータがない場合、一方向操作と要求/応答操作が戻る速度がほぼ同じになるようです。どうしてでしょうか。

  7. サービスで X.509 証明書を使用していますが、System.Security.Cryptography.CryptographicException を受け取ります。どうしてでしょうか。

  8. 操作の最初のパラメーターを大文字から小文字に変更したら、クライアントが例外をスローするようになりました。どうしてでしょうか。

  9. トレース ツールの 1 つを使用していますが、EndpointNotFoundException を受け取りました。どうしてでしょうか。

What is the base address? How does it relate to an endpoint address?

最初の要求の後でクライアントがしばらくアイドル状態になった場合、2 番目の要求で MessageSecurityException を受け取ることがあります。どうしてでしょうか。

2 番目の要求は、主に次の 2 つの理由から失敗する可能性があります。(1) セッションがタイムアウトした。(2) サービスをホストしている Web サーバーがリサイクルされている。最初の理由の場合、セッションはサービスがタイムアウトするまで有効です。サービスは、サービスのバインディング (ReceiveTimeout) で指定された期間内にクライアントから要求を受信しなかった場合、セキュリティ セッションを終了します。それ以降のクライアント メッセージでは、MessageSecurityException が発生します。クライアントは、セキュリティで保護されたセッションをサービスとの間に再度確立して、後続のメッセージを送信するか、ステートフルなセキュリティ コンテキスト トークンを使用する必要があります。また、ステートフルなセキュリティ コンテキスト トークンによって、セキュリティで保護されたセッションは、リサイクルされている Web サーバーを有効な状態に保つことができます。セキュリティで保護されたセッションでのステートフルなセキュリティ コンテキスト トークンの使用方法詳細情報、「方法 : セキュリティで保護されたセッションに対しセキュリティ コンテキスト トークンを作成する」を参照してください。また、セキュリティで保護されたセッションは無効にできます。<wsHttpBinding> バインディングを使用する場合は、establishSecurityContext プロパティを false に設定して、セキュリティで保護されたセッションを無効にできます。その他のバインディングでセキュリティで保護されたセッションを無効にするには、カスタム バインディングを作成する必要があります。カスタム バインディングの作成の詳細については、「方法 : SecurityBindingElement を使用してカスタム バインディングを作成する」を参照してください。このオプションを適用する前に、アプリケーションのセキュリティ要件を確認する必要があります。

サービスと対話しているクライアントの数が約 10 個になると、サービスが新しいクライアントを拒否し始めます。どうしてでしょうか。

既定では、サービスは、10 個の同時セッションだけをサポートできます。したがって、サービス バインディングでセッションを使用する場合、サービスは 10 個に到達するまで新しいクライアント接続を受け入れますが、その数に到達した後は、現在実行中のセッションの 1 つが終了するまで新しいクライアント接続を拒否します。いくつかの方法で、より多くのクライアントをサポートできます。サービスにセッションが必要ない場合、セッションの多いバインディングを使用しないでください (詳細については、次のトピックを参照してください。 セッションの使用.)他には、MaxConcurrentSessions プロパティの値をユーザーの環境に適した数値に変更することによって、セッションの制限値を増やす方法があります。

WCF アプリケーションの構成ファイル以外の場所からサービス構成を読み込むことはできますか。

できます。ただし、ApplyConfiguration メソッドをオーバーライドするカスタムの ServiceHost クラスを作成する必要があります。そのメソッドでは、ベースを呼び出して最初に構成を読み込むことができますが (標準の構成情報も読み込む場合)、構成読み込みシステム全体を置き換えることもできます。アプリケーションの構成ファイルとは異なる構成ファイルから構成を読み込む場合は、構成ファイルを自分で解析して構成を読み込む必要があります。

ApplyConfiguration メソッドをオーバーライドし、エンドポイントを直接構成する方法を次のコード例に示します。

public class MyServiceHost : ServiceHost
{
  public MyServiceHost(Type serviceType, params Uri[] baseAddresses)  
    : base(serviceType, baseAddresses)
  { Console.WriteLine("MyServiceHost Constructor"); }

  protected override void ApplyConfiguration()
  {
    string straddress = GetAddress();
    Uri address = new Uri(straddress);
    Binding binding = GetBinding();
    base.AddServiceEndpoint(typeof(IData), binding, address);
  }

  string GetAddress()
  { return "http://MyMachine:7777/MyEndpointAddress/"; }

  Binding GetBinding()
  {
    WSHttpBinding binding = new WSHttpBinding();
    binding.Security.Mode = SecurityMode.None;
    return binding;
  }
}

サービスとクライアントの動作に問題はないのですが、クライアントが別のコンピューター上にあるときにサービスとクライアントがうまく動作しません。どうしてでしょうか。

例外によっては、次のようないくつかの問題が存在する可能性があります。

  • 場合によっては、クライアントのエンドポイント アドレスを "localhost" ではなくホスト名に変更する必要があります。

  • 場合によっては、アプリケーションに対してポートを開く必要があります。詳細については、SDK サンプルから「ファイアウォール手順」を参照してください。

  • 他の考えられる問題については、サンプル トピックの「Running the Samples in a Workgroup and Across Machines」を参照してください。

  • クライアントが Windows 資格情報を使用し、例外が SecurityNegotiationException の場合、次のように Kerberos を設定します。

    1. クライアントの App.config ファイルのエンドポイント要素に ID 資格情報を追加します。

      <endpoint 
        address="http://MyServer:8000/MyService/" 
        binding="wsHttpBinding" 
        bindingConfiguration="WSHttpBinding_IServiceExample" 
        contract="IServiceExample" 
        behaviorConfiguration="ClientCredBehavior" 
        name="WSHttpBinding_IServiceExample">
        <identity>
          <userPrincipalName value="name@corp.contoso.com"/>
        </identity>
      </endpoint>
      
    2. System または NetworkService アカウントで自己ホスト型サービスを実行します。次のコマンドを実行すると、System アカウントでコマンド ウィンドウを作成できます。

      at 12:36  /interactive "cmd.exe"
      
    3. 既定でサービス プリンシパル名 (SPN) アカウントを使用するインターネット インフォメーション サービス (IIS) でのサービスをホストします。

    4. SetSPN を使用してドメインに新しい SPN を登録します。この操作を行えるのは、ドメイン管理者のみです。

Kerberos プロトコル詳細情報、「WCF で使用されるセキュリティの概要」および以下を参照してください。

型が例外である場合に FaultException<Exception> をスローすると、必ずクライアントで、ジェネリック型ではなく一般的な FaultException 型を受け取ります。どうしてでしょうか。

独自のカスタム エラー データ型を作成し、エラー コントラクトで詳細な型としてその型を宣言することをお勧めします。その理由は、システム指定の例外型を使用すると、次のような状況が起こるためです。

  • サービス指向アプリケーションの長所の 1 つを排除する型依存関係が作成されます。

  • 標準的な方法でシリアル化している例外に依存できません。SecurityException のような例外はまったくシリアル化できない可能性があります。

  • クライアントに内部実装の詳細が公開されます。詳細については、次のトピックを参照してください。 コントラクトおよびサービスのエラーの指定と処理.

ただし、アプリケーションをデバッグしている場合、ServiceDebugBehavior クラスを使用することによって例外情報をシリアル化して、その情報をクライアントに返すことができます。

応答にデータがない場合、一方向操作と要求/応答操作が戻る速度がほぼ同じになるようです。どうしてでしょうか。

操作を一方向に指定すると、操作コントラクトは入力メッセージを受け入れるだけで、出力メッセージを返しません。WCF では、送信データがネットワークに書き込まれるか、例外がスローされたとき、すべてのクライアント呼び出しが戻ります。一方向操作は同様に動作し、この操作では、サービスが見つからない場合は例外をスローし、サービスがネットワークからのデータの受け入れ準備を完了していない場合はブロックできます。このため、WCF では通常、一方向呼び出しは要求/応答よりも速くクライアントに戻りますが、ネットワーク上でデータの送信速度が遅くなると、一方向操作の速度も要求/応答操作の速度と同様に遅くなります。詳細については、次のトピックを参照してください。、「One-Way Services」および「クライアントを使用したサービスへのアクセス」を参照してください。

サービスで X.509 証明書を使用していますが、System.Security.Cryptography.CryptographicException を受け取ります。どうしてでしょうか。

この例外は通常、IIS ワーカー プロセスの実行に使用しているユーザー アカウントを変更すると発生します。たとえば、Windows XP で、既定のユーザー アカウントを使用して Aspnet_wp.exe を実行しているときにそのアカウントを ASPNET からカスタムのユーザー アカウントに変更した場合、このエラーが発生します。秘密キーを使用している場合、そのキーを使用するプロセスには、そのキーを格納しているファイルにアクセスするためのアクセス許可が必要になります。

この場合、秘密キーを格納しているファイルについて、プロセスのアカウントに読み取りアクセス権を与える必要があります。たとえば、IIS ワーカー プロセスを Bob というアカウントで実行している場合、秘密キーを格納しているファイルへの読み取りアクセス権を Bob に与える必要があります。

特定の X.509 証明書について、秘密キーを格納しているファイルへのアクセス権を適切なユーザー アカウントに与える方法詳細情報、「方法 : X.509 証明書を WCF からアクセス可能にする」を参照してください。

操作の最初のパラメーターを大文字から小文字に変更したら、クライアントが例外をスローするようになりました。どうしてでしょうか。

操作シグネチャのパラメーター名の値はコントラクトに含まれ、大文字と小文字が区別されます。ローカル パラメーター名と、クライアント アプリケーションの操作を記述するメタデータを区別する必要がある場合は、System.ServiceModel.MessageParameterAttribute 属性を使用します。

トレース ツールの 1 つを使用していますが、EndpointNotFoundException を受け取りました。どうしてでしょうか

使用しているトレース ツールが、システム指定の WCF トレース機構でなく、アドレス フィルターの不一致があることを示す EndpointNotFoundException を受け取った場合は、ClientViaBehavior クラスを使用してメッセージをトレース ユーティリティに送信し、そのユーティリティがそのメッセージをサービス アドレスにリダイレクトするようにする必要があります。ClientViaBehavior クラスは、Via アドレス指定ヘッダーを変更して、To アドレス指定ヘッダーで示されている最終受信者とは別に、次のネットワーク アドレスを指定します。ただし、このとき、エンドポイント アドレスは To 値の設定に使用されるので変更しないでください。

次のコード例は、クライアント構成ファイルの例を示しています。

<endpoint 
  address=https://localhost:8000/MyServer/
  binding="wsHttpBinding"
  bindingConfiguration="WSHttpBinding_IMyContract"
  behaviorConfiguration="MyClient" 
  contract="IMyContract" 
  name="WSHttpBinding_IMyContract">
</endpoint>
<behaviors>
  <endpointBehaviors>
    <behavior name="MyClient">
      <clientVia viaUri="https://localhost:8001/MyServer/"/>
    </behavior>
  </endpointBehaviors>
</behaviors>

ベース アドレスについて教えてください。エンドポイント アドレスとどのように関連していますか。

ベース アドレスとは、ServiceHost クラスのルート アドレスです。既定では、ServiceMetadataBehavior クラスをサービス構成に追加する場合、ホストが発行するすべてのエンドポイントの Web サービス記述言語 (WSDL) は、HTTP ベース アドレスから取得され、それにメタデータ動作に提供される相対アドレスと "?wsdl" が追加されます。ASP.NET と IIS では、ベース アドレスは仮想ディレクトリに相当します。

NetTcpBinding を使用したサービス エンドポイントと MEX エンドポイント間でのポートの共有

サービスのベース アドレスとして net.tcp://MyServer:8080/MyService を指定して次のエンドポイントを追加します。

<services>
      <service name="Microsoft.Samples.NetTcp.CalculatorService">
        <endpoint address="calcsvc" binding ="netTcpBinding" contract="Microsoft.Samples.NetTcp.ICalculator"/>
        <endpoint address="mex" binding="mexTcpBinding" contract="IMetadataExchange" />
      </service>
    </services>

次の構成スニペットに示すように、NetTcpBinding 設定の 1 つを変更するとします。

<bindings>
      <netTcpBinding>
        <binding closeTimeout="00:01:00" openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00" transactionFlow="false" transferMode="Buffered" transactionProtocol="OleTransactions" hostNameComparisonMode="StrongWildcard" listenBacklog="10" maxBufferPoolSize="524288" maxBufferSize="65536" maxConnections="11" maxReceivedMessageSize="65536">
          <readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384" maxBytesPerRead="4096" maxNameTableCharCount="16384"/>
          <reliableSession ordered="true" inactivityTimeout="00:10:00" enabled="false"/>
          <security mode="Transport">
            <transport clientCredentialType="Windows" protectionLevel="EncryptAndSign"/>
          </security>
        </binding>
      </netTcpBinding>
    </bindings>

"ハンドルされない例外: System.ServiceModel.AddressAlreadyInUseException: IP エンドポイント 0.0.0.0:9000 には既にリスナーがあります。" というエラーが表示されます。このエラーは、次の構成スニペットに示すように、ポートが異なる完全修飾 URL を MEX エンドポイントに対して指定することで回避できます。

<services>
      <service name="Microsoft.Samples.NetTcp.CalculatorService">
        <endpoint address="calcsvc" binding ="netTcpBinding" contract="Microsoft.Samples.NetTcp.ICalculator"/>
        <endpoint address="net.tcp://localhost:9001/servicemodelsamples/mex" binding="mexTcpBinding" contract="IMetadataExchange" />
      </service>
    </services>

参照

概念

Windows 認証エラーのデバッグ