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

ここでは、Q&A 形式で最も起こりやすい問題の一部を挙げ、その問題の解決方法とその問題の詳細情報を掲載している場所について説明します。

質問

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

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

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

既定では、サービスは、10 個の同時セッションだけをサポートできます。したがって、サービス バインディングでセッションを使用する場合、サービスは 10 個に到達するまで新しいクライアント接続を受け入れますが、その数に到達した後は、現在実行中のセッションの 1 つが終了するまで新しいクライアント接続を拒否します。いくつかの方法で、より多くのクライアントをサポートできます。サービスにセッションが必要ない場合、セッションの多いバインディングを使用しないでください。(詳細については、「Using Sessions」を参照してください。)他には、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 サンプルから「ファイアウォール手順」を参照してください。

  • 他の考えられる問題については、サンプル トピックの「サンプルのワークグループでの実行、および別のコンピュータでの実行」を参照してください。

  • クライアントが 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 プロトコルの詳細については、「Security Concepts Used in WCF」および以下を参照してください。

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

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

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

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

  • クライアントに内部実装の詳細が公開されます。詳細については、「Specifying and Handling Faults in Contracts and Services」を参照してください。

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

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

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

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

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

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

特定の X.509 証明書について、秘密キーを格納しているファイルへのアクセス権を適切なユーザー アカウントに与える方法の詳細については、「How to: Make X.509 Certificates Accessible to 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 では、ベース アドレスは仮想ディレクトリに相当します。

質問 : 1 つのサービスで複数のエンドポイントを公開する方法を教えてください。

アプリケーション構成ファイルで <endpoint> 要素を <service> 要素に追加するか、同等の手順をプログラムで実行します。詳細については、「Specifying an Endpoint Address」、「How to: Create a Service Endpoint in Configuration」、および「How to: Create a Service Endpoint in Code」を参照してください。

質問 : 各バインディングがサポートする動作について教えてください。

システム指定のバインディングとそのバインディングがサポートする機能の詳細については、「System-Provided Bindings」を参照してください。

質問 : 任意の属性に別の値を使用して標準バインディングを構成する方法を教えてください。

詳細については、「Configuring Bindings for Windows Communication Foundation Services」を参照してください。

質問 : HTTP をトランスポートとして使用する場合、HTTP サーバーにサービスを導入する必要はありますか。

その必要はありません。システム指定のバインディングの中には、任意のホスト アプリケーションから使用するときに、HTTP トランスポートをサポートするバインディングがいくつかあります。システム指定のバインディングとそのバインディングがサポートする機能の詳細については、「System-Provided Bindings」を参照してください。

質問 : 標準バインディングを使用するサービスの既定の動作について教えてください。

これは、選択した標準バインディングによって異なります。一般的に、セッションを使用するバインディングの既定の動作では、新しいクライアントごとに新しいサービス インスタンスを作成します。特定のクライアントからのそれ以降の呼び出しは、関連するサービス インスタンスにルーティングされます。システム指定のバインディングとそのバインディングがサポートする機能の詳細については、「System-Provided Bindings」を参照してください。

質問 : 機能とバインディングのマッピングを簡単に確認する方法はありますか。たとえば、どのバインディングがトランザクション、セキュリティなどをサポートしているかを知る方法はありますか。

あります。「System-Provided Bindings」を参照してください。

質問 : カスタム データ型をサービスからクライアントに渡す方法を教えてください。

2 つのエンドポイント間で渡されるデータ型は、シリアル化できる型である必要があります。サービスにとって最も簡単で相互運用性の高いシリアル化機構は、DataContractAttribute クラスと DataMemberAttribute クラスを使用することです。このシリアル化機構や他のサポートされているシリアル化機構の詳細については、「Specifying Data Transfer in Service Contracts」を参照してください。

質問 : 構成ファイルを使用すべき状況とコードで構成すべき状況について教えてください。

アプリケーション構成ファイルによって、開発者は配置ユーザーの管理下にある実行時の構成を決定できるため、配置ユーザーが決定すべきでない構成が、製品コードでの構成の優れた候補となります。配置担当ユーザーとは、自分のコンピュータにプログラムをインストールするユーザー、またはコンピュータの構成ファイルを変更するために企業のグループ ポリシーを使用して、ローカルでの変更に対してその構成ファイルをロックダウンする企業の管理者です。後者の例については、「How to: Lockdown Endpoints in the Enterprise」を参照してください。

質問 : 適切に動作するサービスを設計する方法を教えてください。

Designing and Implementing Services」を参照してください。

質問 : 生成されたクライアント コードの中身について教えてください。

生成されたクライアント コードの詳細については、「Understanding Generated Client Code」を参照してください。クライアント アーキテクチャの詳細については、「WCF Client Architecture」を参照してください。

質問 : WCF クライアント オブジェクトで Close メソッドを呼び出す理由について教えてください。

WCF クライアント オブジェクトで Close を呼び出すことによって、クライアントとサービスは正常にメッセージ交換を行い、メッセージ交換に関連付けられたリソースをリサイクルすることができます。また、セッションを使用している場合は、Close の呼び出しが、おそらく、最後の呼び出し以降にセッションにエラーが発生していないかどうかを確認できる最も速い方法であり、クライアント アプリケーションにとって意味のあるシナリオです。詳細については、「Consuming Services Using a WCF Client」およびサンプルの「予期される例外」を参照してください。

質問 : コードに問題はないのに、予想どおりにサービスが動作しません。どうしてでしょうか。

サービス アプリケーションがアプリケーション構成ファイルを使用して構成されている場合、そのファイルを調査して、構成要素または属性が予想外の方法で実行動作を変更していないかどうかを確認することをお勧めします。特に、ランタイム動作は、エンドポイントでコントラクトを実装するバインディングに左右されます。構成ファイル内のバインディングで、必要な機能が期待どおりにサポートされているか確認します。

構成ファイルが適切な場合、ログ記録やトレースなどの診断機能を使用して、アプリケーションのランタイム動作をさらに調査できます。詳細については、「Administration and Diagnostics」を参照してください。

質問 : サービスでエラーが発生したことをクライアントに通知する最も良い方法を教えてください。

最も良い方法は、FaultContractAttribute クラスをカスタムのシリアル化可能なエラー データ型と共に操作に追加する方法です。次に、操作で検出可能なエラー状態が発生した場合、型パラメータがシリアル化可能なエラー型である新しい FaultException をスローします。詳細については、「Specifying and Handling Faults in Contracts and Services」を参照してください。

質問 : クライアントに返してもよい情報について教えてください。

サービスのクライアントが知る必要がある情報だけを返します。サービスの設計者として、非承認のクライアントに対する内部実装の詳細の公開を最小限に抑えるために、その量の情報だけを提供することをお勧めします。SOAP エラーで Exception オブジェクトを返さないことを推奨しているのもそのためです。詳細については、「Specifying and Handling Faults in Contracts and Services」を参照してください。

質問 : クライアント アプリケーションはどのようにしてサービスへの接続が終了していることを検出するのですか。

クライアント チャネルの CommunicationObject 状態変更イベントを処理することができますが、チャネルの終了またはエラーが通知されるタイミングは、チャネル実装によって異なります。たとえば、NetTcpBinding クラスでは、セッションの有効期間が基になるソケットの有効期間に関連付けられているので、チャネルの終了またはエラーをすばやく通知します。

ただし、ReliableSessionBindingElement クラスによって提供されるセッションのように、小さいネットワーク障害からアプリケーションを保護するために作成されたセッションの多いバインディングは、セッションを再確立しようとしている間、通知を行わない可能性があります。このような理由から、切断を直接検出しないことをお勧めします。

代わりに、セッションをメッセージ交換として処理します。チャネルを開き、複数の操作呼び出しを行い、チャネルを正常に閉じた場合は、チャネルが予期しない方法で閉じられたのではないと想定できます。クライアントとセッションの詳細については、「Using Sessions」を参照してください。クライアントでチャネル関連の例外を処理する方法の詳細については、「Consuming Services Using a Client」を参照してください。例外処理の全般的な情報については、「Specifying and Handling Faults in Contracts and Services」を参照してください。

質問 : WCF サービス セキュリティで Secure Sockets Layer 証明書を設定する方法を教えてください。

How To: Configure a Port with An SSL Certificate」を参照してください。

質問 : メッセージ インスペクタを使用してメッセージのログを記録し、メッセージを変更する方法を教えてください。

次のトピックを参照してください。

質問 : 追加情報が含まれるエンドポイント アドレスを追加する方法を教えてください。

プログラムによって複雑なエンドポイント アドレスを追加する場合 (特定のヘッダーまたは ID が含まれる EndpointAddress クラスをプログラムによって指定する必要がある場合など) は、以下を実行する必要があります。relativeOrAbsoluteAddress は、相対 URI (Uniform Resource Identifier) または絶対 URI です。

// Do this:
ServiceEndpoint e = myServiceHost.AddServiceEndpoint(c,b,"relativeOrAbsoluteAddress");
e.Address = new EndpointAddress(e.Address.Uri, /*other info like headers */);

質問 : Web ホストのサンプルをビルドしようとしていますが、ディレクトリ作成、コピー、および削除のいずれかのコマンドが失敗するため、ビルドできません。なぜ、こうなるのでしょうか。

Web ホストのサンプルの中には、ビルド プロセスの一貫としてコンパイル済みの WCF サービスのバイナリを %SystemDrive%\inetpub\wwwroot\ServiceModelSamples フォルダにコピーしようとするものがあります。これによりサービスを IIS に効率的に配置できます。SDK コマンド プロンプトまたは Visual Studio を実行しているアカウントがこのフォルダを変更するアクセス許可を持っていない場合は、ビルドが中断されます。これを解決するには、次のいずれかを行います。

  • サンプルをビルドするアカウントに対して %SystemDrive%\inetpub\wwwroot の変更権限を付与します。

    または

  • SDK コマンド プロンプトまたは Visual Studio を管理者として実行します。

関連項目

その他の技術情報

Debugging Windows Authentication Errors

Footer image

Copyright © 2007 by Microsoft Corporation.All rights reserved.