エラーの送受信
SOAP エラーは、エラー状態情報をサービスからクライアントに伝達します。双方向通信の場合は、相互運用可能な方法でクライアントからサービスにも伝達します。通常、サービスは、カスタムのエラー コンテンツを定義し、そのエラー コンテンツを返すことができる操作を指定します (詳細については、「エラーの定義と指定」を参照してください)。ここでは、対応するエラー状態が発生したときにサービスまたは双方向クライアントがエラーを送信する方法、およびクライアントまたはサービス アプリケーションがエラーを処理する方法について説明します。Windows Communication Foundation (WCF) アプリケーションでのエラー処理の概要については、「コントラクトおよびサービスのエラーの指定と処理」を参照してください。
SOAP エラーの送信
宣言された SOAP エラーは、カスタム SOAP エラーの種類を指定する System.ServiceModel.FaultContractAttribute を含む操作で発生します。宣言されていない SOAP エラーとは、操作のコントラクトに指定されていないエラーです。
宣言されたエラーの送信
宣言された SOAP エラーを送信するには、SOAP エラーに該当するエラー状態を検出し、新しい System.ServiceModel.FaultException をスローします。この場合、型パラメーターは、その操作の FaultContractAttribute に指定されている型の新しいオブジェクトです。次のコード例は、SampleMethod
操作で GreetingFault
の詳細な型と共に SOAP エラーを返すことができることを指定するために、FaultContractAttribute を使用しています。
<OperationContract, FaultContractAttribute(GetType(GreetingFault), Action:="https://www.contoso.com/GreetingFault", ProtectionLevel:=ProtectionLevel.EncryptAndSign)> _
Function SampleMethod(ByVal msg As String) As String
GreetingFault
エラー情報をクライアントに伝達するには、適切なエラー状態をキャッチし、次のコード例に示すように、新しい GreetingFault
オブジェクトを引数として使用して GreetingFault
型の新しい System.ServiceModel.FaultException をスローします。クライアントが WCF クライアント アプリケーションの場合、これはマネージ例外として認識されます。この場合の型は、GreetingFault
型の System.ServiceModel.FaultException です。
Throw New FaultException(Of GreetingFault)(New GreetingFault("A Greeting error occurred. You said: " & msg))
End If
宣言されていないエラーの送信
宣言されていないエラーを送信すると、WCF アプリケーションの問題をすばやく診断してデバッグできます。これは非常に便利ですが、デバッグ ツールとしての有用性は制限されています。一般的に、デバッグ時には System.ServiceModel.Description.ServiceDebugBehavior.IncludeExceptionDetailInFaults プロパティを使用することをお勧めします。この値を true に設定すると、クライアントはこのエラーを ExceptionDetail 型の FaultException 例外として認識します。
注 : |
---|
マネージ例外が内部アプリケーション情報を開示する可能性があるので、System.ServiceModel.ServiceBehaviorAttribute.IncludeExceptionDetailInFaults または System.ServiceModel.Description.ServiceDebugBehavior.IncludeExceptionDetailInFaults を true に設定すると、個人の身元を確認できる情報またはその他の機密情報を含む内部サービス操作例外に関する情報を WCF クライアントで取得できます。 したがって、System.ServiceModel.ServiceBehaviorAttribute.IncludeExceptionDetailInFaults または System.ServiceModel.Description.ServiceDebugBehavior.IncludeExceptionDetailInFaults を true に設定することは、サービス アプリケーションを一時的にデバッグする方法としてのみお勧めできます。さらに、このようにして未処理のマネージ例外を返すメソッドの WSDL には、ExceptionDetail 型の FaultException のコントラクトが含まれません。クライアントは、デバッグ情報を適切に取得するために、(System.ServiceModel.FaultException オブジェクトとして WCF クライアントに返される) 不明な SOAP エラーの可能性について想定しておく必要があります。 |
宣言されていない SOAP エラーを送信するには、System.ServiceModel.FaultException (つまり、ジェネリック型の FaultException でない) オブジェクトをスローし、文字列をコンストラクターに渡します。これは、スローされた System.ServiceModel.FaultException 例外として WCF クライアント アプリケーションに公開されるため、System.ServiceModel.FaultException.ToString メソッドを呼び出して文字列を使用できます。
注 : |
---|
文字列型の SOAP エラーを宣言し、これを型パラメーターが System.String の FaultException としてサービス内でスローすると、文字列値が System.ServiceModel.FaultException.Detail プロパティに割り当てられるため、System.ServiceModel.FaultException.ToString から使用できません。 |
エラーの処理
WCF クライアントでは、クライアント アプリケーションに関係する通信中の SOAP エラーは、マネージ例外として発生します。プログラムの実行中にはさまざまな例外が発生する可能性がありますが、WCF クライアント プログラミング モデルを使用するアプリケーションは、通信の結果として、次の 2 種類の例外を処理できます。
TimeoutException オブジェクトは、操作が、指定されたタイムアウト期間を超えた場合にスローされます。
CommunicationException オブジェクトは、回復可能な通信エラー状態がサービスまたはクライアントで発生した場合にスローされます。
CommunicationException クラスには、FaultException および一般的な FaultException 型という 2 つの重要な派生型があります。
FaultException 例外は、予期しないエラーまたは操作コントラクト内に指定されていないエラーをリスナーが受信した場合にスローされます。この例外は、通常、サービスの System.ServiceModel.Description.ServiceDebugBehavior.IncludeExceptionDetailInFaults プロパティを true に設定してアプリケーションをデバッグしている場合に発生します。
FaultException 例外は、操作コントラクト内に指定されたエラーが、双方向操作 (つまり、IsOneWay に false が設定されている OperationContractAttribute 属性を持つメソッド) への応答で受信された場合に、クライアントでスローされます。
注 : |
---|
WCF サービスの System.ServiceModel.ServiceBehaviorAttribute.IncludeExceptionDetailInFaults プロパティまたは System.ServiceModel.Description.ServiceDebugBehavior.IncludeExceptionDetailInFaults プロパティが true に設定されている場合、クライアントは、この例外を ExceptionDetail 型の宣言されていない FaultException として認識します。クライアントは、この特定のエラーをキャッチするか、FaultException の catch ブロックで処理できます。 |
通常、クライアントとサービスには、FaultException、TimeoutException、および CommunicationException の各例外だけが関係します。
注 : |
---|
上記以外の例外も発生します。予期しない例外には System.OutOfMemoryException のような致命的なエラーも含まれますが、通常、アプリケーションでは、このようなメソッドをキャッチしません。 |
正しい順序でエラー例外をキャッチする
FaultException は FaultException から派生します。また、FaultException は CommunicationException からも派生します。したがって、これらの例外を正しい順序でキャッチすることが重要になります。たとえば、try/catch ブロックで最初に CommunicationException がキャッチされたとします。その場合、すべての SOAP エラー (指定されている SOAP エラーおよび指定されていない SOAP エラー) はそこで処理され、カスタムの FaultException 例外を処理する後続の catch ブロックは呼び出されません。
指定した例外が 1 つの操作から複数返される場合があることに注意してください。その場合は、エラーごとに型が異なるため、個別に処理する必要があります。
チャネルを閉じるときに例外を処理する
これまでの説明のほとんどは、アプリケーション メッセージの処理の過程で送信されるエラー (つまり、クライアント アプリケーションが WCF クライアント オブジェクトの操作を呼び出す際に、クライアントによって明示的に送信されるメッセージ) に関するものでした。
ローカル オブジェクトでも、オブジェクトを破棄すると、リサイクル プロセスで起こる例外が発生したり、マスクされたりする場合があります。同様のことは、WCF クライアント オブジェクトを使用する際にも発生します。操作を呼び出すと、既に確立されている接続を通じてメッセージが送信されます。また、チャネルを閉じると、すべての操作が正常に返されたとしても、接続を完全に閉じることができなかったり、接続が既に閉じたりしている場合には、例外がスローされる可能性があります。
通常、クライアント オブジェクトのチャネルは、次のいずれかが発生すると閉じられます。
WCF クライアント オブジェクトがリサイクルされるとき。
クライアント アプリケーションが System.ServiceModel.ClientBase.Close を呼び出すとき。
クライアント アプリケーションが System.ServiceModel.ICommunicationObject.Close を呼び出すとき。
クライアント アプリケーションが、セッションの終了操作となる操作を呼び出すとき。
いずれの場合でも、チャネルを閉じると、アプリケーション レベルで複雑な機能をサポートするためにメッセージを送信している可能性がある基になるチャネルをすべて閉じる操作を開始するように、チャネルに通知されます。たとえば、コントラクトがセッションを要求している場合、バインディングは、セッションが確立されるまでサービス チャネルとメッセージを交換してセッションを確立しようとします。チャネルが閉じられると、基になるセッション チャネルは、セッションが終了したことをサービスに通知します。この場合、チャネルが既に中止されたり閉じられたりしている、または使用できない (たとえば、ネットワーク ケーブルが外れている) ときには、クライアント チャネルはサービス チャネルに対し、セッションが終了し例外が発生する可能性があることを通知できません。
必要に応じてチャネルを中止する
チャネルを閉じると例外がスローされる可能性があるため、正しい順序でエラー状態をキャッチするだけでなく、呼び出しに使用されたチャネルを catch ブロックで中止することが重要です。
エラーによって操作に固有のエラー情報が伝えられた場合、他のユーザーがそのエラー情報を使用できるときはチャネルを中止する必要はありません (ただし、このような状況は非常にまれです)。それ以外の場合は、チャネルを中止することをお勧めします。これらの点をすべて示すサンプルについては、「予期される例外」を参照してください。
次のコード例は、基本的なクライアント アプリケーションで、宣言されたエラーと宣言されていないエラーを含む SOAP エラー例外を処理する方法を示しています。
注 : |
---|
このサンプル コードは、using コンストラクトを使用していません。チャネルを閉じると例外が発生する可能性があるため、まず WCF クライアントをアプリケーションで作成し、その WCF を同じ try ブロックで開いて使用してから、閉じることをお勧めします。詳細については、「WCF クライアントの概要」および「Using ステートメントに関する問題の回避」を参照してください。 |
Imports System
Imports System.ServiceModel
Imports System.ServiceModel.Channels
Imports Microsoft.WCF.Documentation
Public Class Client
Public Shared Sub Main()
' Picks up configuration from the config file.
Dim wcfClient As New SampleServiceClient()
Try
' Making calls.
Console.WriteLine("Enter the greeting to send: ")
Dim greeting As String = Console.ReadLine()
Console.WriteLine("The service responded: " & wcfClient.SampleMethod(greeting))
Console.WriteLine("Press ENTER to exit:")
Console.ReadLine()
' Done with service.
wcfClient.Close()
Console.WriteLine("Done!")
Catch timeProblem As TimeoutException
Console.WriteLine("The service operation timed out. " & timeProblem.Message)
Console.ReadLine()
wcfClient.Abort()
Catch greetingFault As FaultException(Of GreetingFault)
Console.WriteLine(greetingFault.Detail.Message)
Console.ReadLine()
wcfClient.Abort()
Catch unknownFault As FaultException
Console.WriteLine("An unknown exception was received. " & unknownFault.Message)
Console.ReadLine()
wcfClient.Abort()
Catch commProblem As CommunicationException
Console.WriteLine("There was a communication problem. " & commProblem.Message + commProblem.StackTrace)
Console.ReadLine()
wcfClient.Abort()
End Try
End Sub
End Class
参照
処理手順
予期される例外
Using ステートメントに関する問題の回避
リファレンス
FaultException
FaultException
System.ServiceModel.CommunicationException