例外とエラーの処理Handling Exceptions and Faults

例外は、サービスまたはクライアント実装内でエラーをローカルに伝達するために使用されます。Exceptions are used to communicate errors locally within the service or the client implementation. 一方、エラーは、サーバーからクライアントまたはクライアントからサーバーのように、サービス境界を越えてエラーを伝達するために使用されます。Faults, on the other hand, are used to communicate errors across service boundaries, such as from the server to the client or vice versa. このようなエラーに加え、多くの場合、トランスポート チャネルはトランスポート固有の機構を使用して、トランスポート レベルのエラーを伝達します。In addition to faults, transport channels often use transport-specific mechanisms to communicate transport-level errors. たとえば、HTTP トランスポートは、404 などのステータス コードを使用して、存在しないエンドポイントの URL (エラーを返信するエンドポイントが存在しないこと) を伝達します。For example, HTTP transport uses status codes such as 404 to communicate a non-existing endpoint URL (there is no endpoint to send back a fault). このドキュメントは、カスタム チャネル作成者にガイダンスを示す 3 つのセクションで構成されています。This document consists of three sections that provide guidance to custom channel authors. 最初のセクションでは、例外を定義しスローする状況と方法に関するガイダンスを示します。The first section provides guidance on when and how to define and throw exceptions. 2 番目のセクションでは、エラーの生成と使用に関するガイダンスを示します。The second section provides guidance around generating and consuming faults. 3 番目のセクションでは、実行中のアプリケーションのトラブルシューティングを行う際に、カスタム チャネルのユーザーにとって役立つトレース情報を提供する方法について説明します。The third section explains how to provide trace information to aid the user of your custom channel in troubleshooting running applications.

例外Exceptions

例外がスローされるときに留意する 2 つのことがあります。最初の例外を適切に対処できる正しいコードを記述できる型があります。There are two things to keep in mind when throwing an exception: First it has to be of a type that allows users to write correct code that can react appropriately to the exception. もう 1 つは、例外では、問題点、エラーの影響、およびエラーの修正方法をユーザーが理解できるだけの情報を提供する必要があります。Second, it has to provide enough information for the user to understand what went wrong, the failure impact, and how to fix it. 次のセクションでは、例外の種類と Windows Communication Foundation (WCF) チャネルのメッセージに関するガイダンスを提供します。The following sections give guidance around exception types and messages for Windows Communication Foundation (WCF) channels. また、「Design Guidelines for Exceptions」に記載された .NET の例外に関する一般的なガイダンスも示します。There is also general guidance around exceptions in .NET in the Design Guidelines for Exceptions document.

例外の種類Exception Types

チャネルがスローするすべての例外は、System.TimeoutExceptionSystem.ServiceModel.CommunicationException、または CommunicationException から派生した種類のいずれかである必要があります All exceptions thrown by channels must be either a System.TimeoutException, System.ServiceModel.CommunicationException, or a type derived from CommunicationException. (ObjectDisposedException のような例外をスローすることもできますが、これは呼び出し元のコードがチャネルを誤用したことを示す場合だけです。(Exceptions such as ObjectDisposedException may also be thrown, but only to indicate that the calling code has misused the channel. チャネルを正しく使用する場合にする必要がありますのみ特定の例外をスローします。)派生する 7 つの例外型を提供する WCFCommunicationExceptionチャネルで使用するよう設計されています。If a channel is used correctly, it must only throw the given exceptions.) WCF provides seven exception types that derive from CommunicationException and are designed to be used by channels. CommunicationException から派生した例外には、システムのその他の部分で使用するように設計されているものもあります。There are other CommunicationException-derived exceptions that are designed to be used by other parts of the system. これらの例外の種類を以下に示します。These exception types are:

例外の種類Exception Type 説明Meaning 内部例外の内容Inner Exception Content 回復方法Recovery Strategy
AddressAlreadyInUseException リッスン用に指定されたエンドポイント アドレスは既に使用されています。The endpoint address specified for listening is already in use. エラーの詳細情報が得られるようであれば、この例外の原因となったトランスポート エラーについての情報を提供します。If present, provides more details about the transport error that caused this exception. たとえば、For example. PipeExceptionHttpListenerException または SocketExceptionPipeException, HttpListenerException, or SocketException. 別のアドレスで実行してください。Try a different address.
AddressAccessDeniedException このプロセスは、リッスン用に指定されたエンドポイント アドレスへのアクセスを許可されていません。The process is not allowed access to the endpoint address specified for listening. エラーの詳細情報が得られるようであれば、この例外の原因となったトランスポート エラーについての情報を提供します。If present, provides more details about the transport error that caused this exception. 例 : PipeException または HttpListenerExceptionFor example, PipeException, or HttpListenerException. 別の資格情報を使用して試行します。Try with different credentials.
CommunicationObjectFaultedException ICommunicationObject Faulted 状態では使用されている (詳細については、次を参照してください。について状態の変化)。The ICommunicationObject being used is in the Faulted state (for more information, see Understanding State Changes). 複数の呼び出しが保留になっているオブジェクトが Faulted 状態に遷移した場合、エラーに関連する例外をスローする呼び出しは 1 つだけであり、それ以外の呼び出しは CommunicationObjectFaultedException をスローします。Note that when an object with multiple pending calls transitions to the Faulted state, only one call throws an exception that is related to the failure and the rest of the calls throw a CommunicationObjectFaultedException. 通常、この例外がスローされるのは、アプリケーションが何らかの例外を認識しておらず、おそらく最初の例外をキャッチしたスレッド以外のスレッドで、既に Faulted 状態のオブジェクトを使用しようとしたためです。This exception is typically thrown because an application overlooks some exception and tries to use an already faulted object, possibly on a thread other than the one that caught the original exception. 詳細情報を使用できる場合は、内部例外についての詳細を示します。If present provides details about the inner exception. 新規オブジェクトを作成します。Create a new object. ICommunicationObject にエラーが発生した第一の原因によっては、回復するために他の作業が必要になることがあります。Note that depending on what caused the ICommunicationObject to fault in the first place, there may be other work required to recover.
CommunicationObjectAbortedException ICommunicationObject使用されているが中止されました (詳細については、次を参照してください。について状態の変化)。The ICommunicationObject being used has been Aborted (for more information, see Understanding State Changes). CommunicationObjectFaultedException と同様に、この例外は、アプリケーションがおそらく別のスレッドからオブジェクトに対して Abort を呼び出したときに、オブジェクトが既に Aborted 状態であるため、使用できなくなっていることを示しています。Similar to CommunicationObjectFaultedException, his exception indicates the application has called Abort on the object, possibly from another thread, and the object is no longer usable for that reason. 詳細情報を使用できる場合は、内部例外についての詳細を示します。If present provides details about the inner exception. 新規オブジェクトを作成します。Create a new object. ICommunicationObject が中止された第一の原因によっては、回復するために他の作業が必要になることがあります。Note that depending on what caused the ICommunicationObject to abort in the first place, there may be other work required to recover.
EndpointNotFoundException 対象のリモート エンドポイントがリッスンしていません。The target remote endpoint is not listening. これは、エンドポイント アドレスの一部に誤りがある、エンドポイント アドレスの一部を解決できない、またはエンドポイントがダウンしていることが原因として考えられます This can result from any part of the endpoint address being incorrect, irresolvable, or the endpoint being down. (DNS エラー、キュー マネージャーを使用できない、サービスが実行されていないなど)。Examples include DNS error, Queue Manager not available, and service not running. この内部例外では、一般に、基になるトランスポートの詳細が示されます。The inner exception provides details, typically from the underlying transport. 別のアドレスで実行してください。Try a different address. また、サービスがダウンしている場合は、送信元がしばらく待機し、再試行することもできます。Alternatively, the sender may wait a while and try again in case the service was down
ProtocolException エンドポイントのポリシーで示されている通信プロトコルがエンドポイント間で一致していません The communication protocols, as described by the endpoint’s policy, are mismatched between endpoints. (フレーム コンテンツの種類の不一致や、最大メッセージ サイズの超過など)。For example, framing content type mismatch or max message size exceeded. 詳細情報を使用できる場合は、特定のプロトコル エラーの詳細を示します。If present provides more information about the specific protocol error. たとえば、MaxReceivedMessageSize を超えていることがエラーの原因である場合、QuotaExceededException が内部例外です。For example, QuotaExceededException is the inner exception when the error cause is exceeding MaxReceivedMessageSize. 回復:送信側と受信したプロトコル設定と一致することを確認します。Recovery: Ensure sender and received protocol settings match. この方法の 1 つとして、サービス エンドポイントのメタデータ (ポリシー) を再度インポートし、生成されたバインディングを使用してチャネルを再作成します。One way to do this is to re-import the service endpoint’s metadata (policy) and use the generated binding to recreate the channel.
ServerTooBusyException リモート エンドポイントはリッスンしていますが、メッセージを処理する準備ができていません。The remote endpoint is listening but is not prepared to process messages. 詳細情報を使用できる場合は、内部例外で SOAP エラーまたはトランスポート レベルのエラーの詳細を示します。If present, the inner Exception provides the SOAP fault or transport-level error details. 回復:しばらく待機し、後で操作を再試行します。Recovery: Wait and retry the operation later.
TimeoutException タイムアウト期間内に操作を完了できませんでした。The operation failed to complete within the timeout period. タイムアウトの詳細を示します。May provide details about the timeout. しばらく待機し、後で操作を再試行します。Wait and retry the operation later.

新しい例外の種類を定義するのは、その種類が既存の例外の種類のいずれとも異なる回復方法に対応する場合だけです。Define a new exception type only if that type corresponds to a specific recovery strategy different from all of the existing exception types. 新しい例外の種類を定義する場合は、CommunicationException または派生クラスのいずれかから派生する必要があります。If you do define a new exception type, it must derive from CommunicationException or one of its derived classes.

例外メッセージException Messages

例外メッセージは、プログラムではなくユーザーを対象としています。したがって、ユーザーが問題を理解し、解決する上で役立つ十分な情報を提供する必要があります。Exception messages are targeted at the user not the program so they should provide sufficient information to help the user understand and solve the problem. 優れた例外メッセージに不可欠な 3 つの構成要素を以下に示します。The three essential parts of a good exception message are:

問題の内容。What happened. ユーザーの経験に関連する用語を使用して、問題を明確に説明します。Provide a clear description of the problem using terms that relate to the user’s experience. たとえば、"無効な構成セクション" という例外メッセージは適切とはいえません。For example, a bad exception message would be "Invalid configuration section". このようなメッセージでは、ユーザーは、どの構成セクションに誤りがあり、それがなぜ誤りなのか疑問を抱いたままになります。This leaves the user wondering which configuration section is incorrect and why it is incorrect. 改善のメッセージが表示されます"無効な構成セクション<customBinding >"。An improved message would be "Invalid configuration section <customBinding>". これをさらに改善し、"myBinding というバインディングには myTransport というトランスポートが既に含まれているため、このバインディングに myTransport というトランスポートを追加することはできません" というメッセージにします。An even better message would be "Cannot add the transport named myTransport to the binding named myBinding because the binding already has a transport named myTransport". これは、アプリケーションの構成ファイル内でユーザーが容易に特定できる用語と名前を使用した、非常に明確なメッセージです。This is a very specific message using terms and names that the user can easily identify in the application’s configuration file. ただし、まだ重要な要素がいくつか欠けています。However, there are still a few key components missing.

エラーの重大度。The significance of the error. メッセージがエラーの意味を明確に示していない場合、ユーザーはそれが致命的なエラーかどうか、または無視できるのかどうか疑問を抱くと考えられます。Unless the message states clearly what the error means, the user is likely to wonder whether it is a fatal error or if it can be ignored. 一般に、メッセージではエラーの意味や重大度を示す必要があります。In general, messages should lead with the meaning or significance of the error. 前の例を向上させるのには、メッセージ可能性があります"構成エラーが原因で開く を ServiceHost に失敗しました。MyBinding という名前のバインディングに myTransport というトランスポートを追加することはできません、バインド myTransport というトランスポートが既に"。To improve the previous example, the message could be "ServiceHost failed to Open due to a configuration error: Cannot add the transport named myTransport to the binding named myBinding because the binding already has a transport named myTransport".

ユーザーが問題を修正する方法。How the user should correct the problem. メッセージの最も重要な要素は、ユーザーによる問題の修正を支援することにあります。The most important part of the message is helping the user fix the problem. メッセージには、問題を改善するためのチェックや修正の内容に関する何らかのガイダンスやヒントを含める必要があります。The message should include some guidance or hints about what to check or fix to remedy the problem. たとえば、"構成エラーが原因で開く を ServiceHost に失敗しました。MyBinding という名前のバインディングに myTransport というトランスポートを追加することはできません、バインド myTransport というトランスポートが既にします。For example, "ServiceHost failed to Open due to a configuration error: Cannot add the transport named myTransport to the binding named myBinding because the binding already has a transport named myTransport. バインディングに含まれているトランスポートが 1 つだけであることを確認してください" というメッセージにします。Please ensure there is only one transport in the binding".

エラーの伝達Communicating Faults

SOAP 1.1 および SOAP 1.2 では、エラーの具体的な構造が定義されています。SOAP 1.1 and SOAP 1.2 both define a specific structure for faults. この 2 つの仕様にはいくつかの違いがありますが、通常、Message 型と MessageFault 型を使用して、エラーを作成および使用します。There are some differences between the two specifications but in general, the Message and MessageFault types are used to create and consume faults.

例外とエラーの処理Handling exceptions and faults
SOAP 1.2 エラー (左) と SOAP 1.1 エラー (右)。SOAP 1.2 Fault (left) and SOAP 1.1 Fault (right). Fault 要素が名前空間で修飾されているのは SOAP 1.1 のみ。Note that in SOAP 1.1 only the Fault element is namespace qualified.

SOAP では、エラー メッセージとは、<env:Fault> の子要素としてエラー要素 (<env:Body> という名前の要素) だけを含むメッセージと定義されています。SOAP defines a fault message as a message that contains only a fault element (an element whose name is <env:Fault>) as a child of <env:Body>. 図 1 に示すように、エラー要素の内容は SOAP 1.1 と SOAP 1.2 で若干異なります。The contents of the fault element differ slightly between SOAP 1.1 and SOAP 1.2 as shown in figure 1. ただし、次のように、System.ServiceModel.Channels.MessageFault クラスでは、これらの違いを 1 つのオブジェクト モデルに正規化します。However, the System.ServiceModel.Channels.MessageFault class normalizes these differences into one object model:

public abstract class MessageFault  
{  
    protected MessageFault();  
  
    public virtual string Actor { get; }  
    public virtual string Node { get; }  
    public static string DefaultAction { get; }  
    public abstract FaultCode Code { get; }  
    public abstract bool HasDetail { get; }  
    public abstract FaultReason Reason { get; }  
  
    public T GetDetail<T>();  
    public T GetDetail<T>( XmlObjectSerializer serializer);  
    public System.Xml.XmlDictionaryReader GetReaderAtDetailContents();  
  
    // other methods omitted  
}  

Code プロパティは、env:Code (または SOAP 1.1 の faultCode) に対応し、エラーの種類を識別します。The Code property corresponds to the env:Code (or faultCode in SOAP 1.1) and identifies the type of the fault. SOAP 1.2 では、faultCode の 5 つの許容値 (Sender や Receiver など) が定義されており、サブコード値を格納できる Subcode 要素も定義されています SOAP 1.2 defines five allowable values for faultCode (for example, Sender and Receiver) and defines a Subcode element which can contain any subcode value. (を参照してください、 SOAP 1.2 仕様使用できるエラー コードとその意味の一覧についてはします)。SOAP 1.1 では、若干異なるメカニズムがあります。4 つ定義faultCodeまったく新しい値を定義するかより具体的に作成する、ドット表記を使用して、拡張可能な値 (たとえば、クライアントとサーバー) faultCodes、たとえば、Client.Authentication します。(See the SOAP 1.2 specification for the list of allowable fault codes and their meaning.) SOAP 1.1 has a slightly different mechanism: It defines four faultCode values (for example, Client and Server) that can be extended either by defining entirely new ones or by using the dot notation to create more specific faultCodes, for example, Client.Authentication.

MessageFault を使用してエラーをプログラミングする場合、FaultCode.Name と FaultCode.Namespace は、SOAP 1.2 の env:Code または SOAP 1.1 の faultCode の名前と名前空間に割り当てられます。When you use MessageFault to program faults, the FaultCode.Name and FaultCode.Namespace maps to the name and namespace of the SOAP 1.2 env:Code or the SOAP 1.1 faultCode. FaultCode.SubCode は、SOAP 1.2 では env:Subcode に割り当てられ、SOAP 1.1 では null になります。The FaultCode.SubCode maps to env:Subcode for SOAP 1.2 and is null for SOAP 1.1.

エラーをプログラムによって区別する場合は、新しいエラー サブコード (SOAP 1.1 を使用する場合は新しいエラー コード) を作成します。You should create new fault subcodes (or new fault codes if using SOAP 1.1) if it is interesting to programmatically distinguish a fault. これは、新しい例外の種類を作成することに似ています。This is analogous to creating a new exception type. SOAP 1.1 エラー コードではドット表記を使用しないようにすることをお勧めします You should avoid using the dot notation with SOAP 1.1 fault codes. (、 WS-Basic profileもエラー コードのドット表記の使用を抑制します)。(The WS-I Basic Profile also discourages the use of the fault code dot notation.)

public class FaultCode  
{  
    public FaultCode(string name);  
    public FaultCode(string name, FaultCode subCode);  
    public FaultCode(string name, string ns);  
    public FaultCode(string name, string ns, FaultCode subCode);  
  
    public bool IsPredefinedFault { get; }  
    public bool IsReceiverFault { get; }  
    public bool IsSenderFault { get; }  
    public string Name { get; }  
    public string Namespace { get; }  
    public FaultCode SubCode { get; }  
  
//  methods omitted  
  
}  

Reason プロパティは、env:Reason (または SOAP 1.1 の faultString) に対応しています。これは、例外のメッセージと同様に、ユーザーが判読できるエラー状態の記述です。The Reason property corresponds to the env:Reason (or faultString in SOAP 1.1) a human-readable description of the error condition analogous to an exception’s message. FaultReason クラス (および SOAP の env:Reason/faultString) には、グローバリゼーションのために、複数の変換を使用するためのサポートが組み込まれています。The FaultReason class (and SOAP env:Reason/faultString) has built-in support for having multiple translations in the interest of globalization.

public class FaultReason  
{  
    public FaultReason(FaultReasonText translation);  
    public FaultReason(IEnumerable<FaultReasonText> translations);  
    public FaultReason(string text);  
  
    public SynchronizedReadOnlyCollection<FaultReasonText> Translations   
    {   
       get;   
    }  
  
 }  

エラーの詳しい内容がなど、さまざまなメソッドを使用して、MessageFault で公開されている、 GetDetail <T > とGetReaderAtDetailContents()。The fault detail contents are exposed on MessageFault using various methods including the GetDetail<T> and GetReaderAtDetailContents(). エラーの詳細は、エラーに関する追加情報を伝達するための不透明な要素です。The fault detail is an opaque element for carrying additional detail about the fault. これは、エラーと共に伝達する任意の構造化された詳細がある場合に役立ちます。This is useful if there is some arbitrary structured detail that you want to carry with the fault.

エラーの生成Generating Faults

このセクションでは、チャネルまたはチャネルによって作成されたメッセージ プロパティで検出されるエラー状態に応じてエラーを生成するプロセスについて説明します。This section explains the process of generating a fault in response to an error condition detected in a channel or in a message property created by the channel. 一般的な例として、無効なデータが含まれた要求メッセージに対するエラーの送信が挙げられます。A typical example is sending back a fault in response to a request message that contains invalid data.

エラーの生成時には、カスタム チャネルからエラーを直接送信するのではなく、例外をスローするようにし、その例外をエラーに変換するかどうかの判断とエラーの送信方法の決定は上位のレイヤーで行います。When generating a fault, the custom channel should not send the fault directly, rather, it should throw an exception and let the layer above decide whether to convert that exception to a fault and how to send it. この変換を支援するために、チャネルは FaultConverter を実装し、カスタム チャネルがスローした例外を適切なエラーに変換できるようにします。To aid in this conversion, the channel should provide a FaultConverter implementation that can convert the exception thrown by the custom channel to the appropriate fault. FaultConverter は次のように定義します。FaultConverter is defined as:

public class FaultConverter  
{  
    public static FaultConverter GetDefaultFaultConverter(  
                                   MessageVersion version);  
    protected abstract bool OnTryCreateFaultMessage(  
                                   Exception exception,   
                                   out Message message);  
    public bool TryCreateFaultMessage(  
                                   Exception exception,   
                                   out Message message);  
}  

カスタム エラーを生成する各チャネルは FaultConverter を実装し、GetProperty<FaultConverter> の呼び出しからこれを返す必要があります。Each channel that generates custom faults must implement FaultConverter and return it from a call to GetProperty<FaultConverter>. カスタム OnTryCreateFaultMessage 実装では、例外をエラーに変換するか、内部チャネルの FaultConverter に委任する必要があります。The custom OnTryCreateFaultMessage implementation must either convert the exception to a fault or delegate to the inner channel’s FaultConverter. チャネルがトランスポートの場合する必要がありますが例外を変換またはエンコーダーの委任FaultConverterまたは既定FaultConverterWCF で提供します。If the channel is a transport it must either convert the exception or delegate to the encoder’s FaultConverter or the default FaultConverter provided in WCF . 既定の FaultConverter は、WS-Addressing および SOAP で指定されたエラー メッセージに対応するエラーを変換します。The default FaultConverter converts errors corresponding to fault messages specified by WS-Addressing and SOAP. OnTryCreateFaultMessage 実装の例を次に示します。Here is an example OnTryCreateFaultMessage implementation.

public override bool OnTryCreateFaultMessage(Exception exception,   
                                             out Message message)  
{  
    if (exception is ...)  
    {  
        message = ...;  
        return true;  
    }  
  
#if IMPLEMENTING_TRANSPORT_CHANNEL  
    FaultConverter encoderConverter =   
                    this.encoder.GetProperty<FaultConverter>();  
    if ((encoderConverter != null) &&               
        (encoderConverter.TryCreateFaultMessage(  
         exception, out message)))  
    {  
        return true;  
    }  
  
    FaultConverter defaultConverter =   
                   FaultConverter.GetDefaultFaultConverter(  
                   this.channel.messageVersion);  
    return defaultConverter.TryCreateFaultMessage(  
                   exception,   
                   out message);  
#else  
    FaultConverter inner =   
                   this.innerChannel.GetProperty<FaultConverter>();  
    if (inner != null)  
    {  
        return inner.TryCreateFaultMessage(exception, out message);  
    }  
    else  
    {  
        message = null;  
        return false;  
    }  
#endif  
}  

このパターンでは、エラーを必要とするエラー状態についてレイヤー間でスローされる例外に、対応するエラー ジェネレーターが適切なエラーを作成できるだけの情報が含まれている必要があります。An implication of this pattern is that exceptions thrown between layers for error conditions that require faults must contain enough information for the corresponding fault generator to create the correct fault. カスタム チャネル作成者は、さまざまなエラー状態に対応する例外の種類を定義できます (特定のエラー状態に対応する既存の例外がない場合)。As a custom channel author, you may define exception types that correspond to different fault conditions if such exceptions do not already exist. チャネル レイヤーを越えて伝播する例外では、不明瞭なエラー データではなく、エラー状態を伝える必要があります。Note that exceptions traversing channel layers should communicate the error condition rather than opaque fault data.

エラーのカテゴリFault Categories

一般に、エラーは次の 3 つのカテゴリに分類されます。There are generally three categories of faults:

  1. スタック全体にわたるエラー。Faults that are pervasive throughout the entire stack. このようなエラーは、チャネル スタックのどのレイヤーでも発生する可能性があります (例 : InvalidCardinalityAddressingException)。These faults could be encountered at any layer in the channel stack, for example InvalidCardinalityAddressingException.

  2. スタックの特定のレイヤーより上位の任意の場所で発生する可能性があるエラー (例 : フローされたトランザクションやセキュリティ ロールに関するエラー)。Faults that can be encountered anywhere above a certain layer in the stack for example some errors that pertain to a flowed transaction or to security roles.

  3. スタックの単一のレイヤーを対象とするエラー (例 : WS-RM シーケンス番号エラー)。Faults that are directed at a single layer in the stack, for example errors like WS-RM sequence number faults.

カテゴリ 1 です。Category 1. 一般に、WS-Addressing エラーおよび SOAP エラーです。Faults are generally WS-Addressing and SOAP faults. 基本FaultConverterWCF によってエラー メッセージに対応するエラーを変換で指定された Ws-addressing および SOAP これらの例外の変換を処理する必要はありませんので自分で提供されるクラスします。The base FaultConverter class provided by WCF converts errors corresponding to fault messages specified by WS-Addressing and SOAP so you do not have to handle conversion of these exceptions yourself.

カテゴリ 2 です。Category 2. レイヤーに関するメッセージ情報を完全に使用しているわけではないメッセージに対して、そのレイヤーがプロパティを追加したときに発生します。Faults occur when a layer adds a property to the message that does not completely consume message information that pertains to that layer. 後で上位のレイヤーがメッセージ情報をさらに処理するために、メッセージ プロパティを要求したときに、エラーが検出されることがあります。Errors may be detected later when a higher layer asks the message property to process message information further. このようなチャネルでは、前述の GetProperty を実装して、上位のレイヤーが適切なエラーを返すことができるようにする必要があります。Such channels should implement the GetProperty specified previously to enable the higher layer to send back the correct fault. プロパティの例として、TransactionMessageProperty があります。An example of this is the TransactionMessageProperty. このプロパティは、ヘッダー内のすべてのデータが完全には検証されずにメッセージに追加されます (この検証には、分散トランザクション コーディネーター (DTC) への接続が必要になることがあります)。This property is added to the message without fully validating all the data in the header (doing so may involve contacting the distributed transaction coordinator (DTC).

カテゴリ 3. Category 3. エラーは、プロセッサ内の単一のレイヤーによって生成され、送信されるだけです。Faults are only generated and sent by a single layer in the processor. したがって、すべての例外はそのレイヤー内に含まれます。Therefore all the exceptions are contained within the layer. チャネル間の整合性を向上させ、保守を容易にするために、カスタム チャネルでは、前述のパターンを使用して、内部エラーについてもエラー メッセージを生成することをお勧めします。To improve consistency among channels and ease maintenance, your custom channel should use the pattern specified previously to generate fault messages even for internal faults.

受信したエラーの解釈Interpreting Received Faults

このセクションでは、エラー メッセージを受信したときに、適切な例外を生成するためのガイダンスを示します。This section provides guidance for generating the appropriate exception when receiving a fault message. スタックのすべてのレイヤーにおけるメッセージ処理に関するデシジョン ツリーを以下に示します。The decision tree for processing a message at every layer in the stack is as follows:

  1. レイヤーがメッセージを無効と見なした場合、レイヤーは "無効なメッセージ" の処理を実行する必要があります。If the layer considers the message to be invalid, the layer should do its ‘invalid message’ processing. このような処理はレイヤーに固有のものですが、メッセージの破棄、トレース、エラーに変換される例外のスローなどの処理が可能です。Such processing is specific to the layer but could include dropping the message, tracing, or throwing an exception that gets converted to a fault. たとえば、適切に保護されていないメッセージをセキュリティが受信した場合や、RM が不正なシーケンス番号を持つメッセージを受信した場合などです。Examples include security receiving a message that is not secured properly, or RM receiving a message with a bad sequence number.

  2. メッセージが特定のレイヤーに適用されるエラー メッセージであり、そのレイヤーの対話以外では意味がないものである場合、該当のレイヤーがエラー状態を処理する必要があります。Otherwise, if the message is a fault message that applies specifically to the layer, and the message is not meaningful outside the layer’s interaction, the layer should handle the error condition. この一例として、RM シーケンス拒否エラーが挙げられます。これは、RM チャネルにエラーが発生し、保留中の操作からスローされていることを示しており、RM チャネルより上位のレイヤーにとっては意味のないエラーです。An example of this is an RM Sequence Refused fault that is meaningless to layers above the RM channel and that implies faulting the RM channel and throwing from pending operations.

  3. それ以外の場合は、Request() または Receive() からメッセージを返すようにします。Otherwise, the message should be returned from Request() or Receive(). たとえば、レイヤーはエラーを認識しているが、そのエラーは要求が失敗したことを示しているにすぎず、チャネルにエラーが発生し、保留中の操作からスローされていることを意味しているわけではない場合などです。This includes cases where the layer recognizes the fault, but the fault just indicates that a request failed and does not imply faulting the channel and throwing from pending operations. このような場合にユーザビリティを向上させるには、レイヤーで GetProperty<FaultConverter> を実装し、FaultConverter 派生クラスを返すようにします。この派生クラスは、OnTryCreateException をオーバーライドすることで、エラーを例外に変換できます。To improve usability in such a case, the layer should implement GetProperty<FaultConverter> and return a FaultConverter derived class that can convert the fault to an exception by overriding OnTryCreateException.

次のオブジェクト モデルは、メッセージから例外への変換をサポートします。The following object model supports converting messages to exceptions:

public class FaultConverter  
{  
    public static FaultConverter GetDefaultFaultConverter(  
                                  MessageVersion version);  
    protected abstract bool OnTryCreateException(  
                                 Message message,   
                                 MessageFault fault,   
                                 out Exception exception);  
    public bool TryCreateException(  
                                 Message message,   
                                 MessageFault fault,   
                                 out Exception exception);  
}  

チャネル レイヤーは、GetProperty<FaultConverter> を実装することで、エラー メッセージから例外への変換をサポートできます。A channel layer can implement GetProperty<FaultConverter> to support converting fault messages to exceptions. これを行うには、OnTryCreateException をオーバーライドし、エラー メッセージを検査します。To do so, override OnTryCreateException and inspect the fault message. エラー メッセージを認識した場合は、変換を実行します。それ以外の場合は、エラー メッセージの変換を内部チャネルに要求します。If recognized, do the conversion, otherwise ask the inner channel to convert it. トランスポート チャネルでは、FaultConverter.GetDefaultFaultConverter に既定の SOAP/WS-Addressing FaultConverter の取得を委任する必要があります。Transport channels should delegate to FaultConverter.GetDefaultFaultConverter to get the default SOAP/WS-Addressing FaultConverter.

一般的な実装は、次のようになります。A typical implementation looks like this:

public override bool OnTryCreateException(  
                            Message message,   
                            MessageFault fault,   
                            out Exception exception)  
{  
    if (message.Action == "...")  
    {  
        exception = ...;  
        return true;  
    }  
    // OR  
    if ((fault.Code.Name == "...") && (fault.Code.Namespace == "..."))  
    {  
        exception = ...;  
        return true;  
    }  
  
    if (fault.IsMustUnderstand)  
    {  
        if (fault.WasHeaderNotUnderstood(  
                   message.Headers, "...", "..."))  
        {  
            exception = new ProtocolException(...);  
            return true;  
        }  
    }  
  
#if IMPLEMENTING_TRANSPORT_CHANNEL  
    FaultConverter encoderConverter =   
              this.encoder.GetProperty<FaultConverter>();  
    if ((encoderConverter != null) &&   
        (encoderConverter.TryCreateException(  
                              message, fault, out exception)))  
    {  
        return true;  
    }  
  
    FaultConverter defaultConverter =  
             FaultConverter.GetDefaultFaultConverter(  
                             this.channel.messageVersion);  
    return defaultConverter.TryCreateException(  
                             message, fault, out exception);  
#else  
    FaultConverter inner =   
                    this.innerChannel.GetProperty<FaultConverter>();  
    if (inner != null)  
    {  
        return inner.TryCreateException(message, fault, out exception);  
    }  
    else  
    {  
        exception = null;  
        return false;  
    }  
#endif  
}  

明確な回復シナリオが用意されたエラー状態については、ProtocolException の派生クラスを定義することを検討してください。For specific fault conditions that have distinct recovery scenarios, consider defining a derived class of ProtocolException.

MustUnderstand の処理MustUnderstand Processing

SOAP には、必須のヘッダーが受信側で認識されなかったことを通知するための一般的なエラーが定義されています。SOAP defines a general fault for signaling that a required header was not understood by the receiver. このエラーは、mustUnderstand エラーと呼ばれます。This fault is known as the mustUnderstand fault. カスタム チャネル WCF では、生成されませんmustUnderstandエラー。In WCF, custom channels never generate mustUnderstand faults. 確認する、WCF 通信スタックの上部には、WCF ディスパッチャーをチェックする代わりに、MustUndestand としてマークされたすべてのヘッダー = true を基になるスタックで認識します。Instead, the WCF Dispatcher, which is located at the top of the WCF communication stack, checks to see that all headers that were marked as MustUndestand=true were understood by the underlying stack. 認識されていないヘッダーが見つかった場合、その時点で mustUnderstand エラーが生成されます If any were not understood, a mustUnderstand fault is generated at that point. (ユーザーは、この mustUnderstand の処理を無効にし、すべてのメッセージ ヘッダーをアプリケーションで受信するようにすることができます。(The user can choose to turn off this mustUnderstand processing and have the application receive all message headers. その場合、mustUnderstand の処理はアプリケーションが実行します)。生成されたエラーには、NotUnderstood ヘッダーが含まれます。このヘッダーには、MustUnderstand=true でマークされたヘッダーの中で、認識されなかったすべてのヘッダーの名前が含まれています。In that case the application is responsible for performing mustUnderstand processing.) The generated fault includes a NotUnderstood header that contains the names of all headers with MustUnderstand=true that were not understood.

プロトコル チャネルから MustUnderstand=true でマークされたカスタム ヘッダーを送信し、mustUnderstand エラーを受信した場合、そのエラーが送信したヘッダーに起因するものかどうかを確認する必要があります。If your protocol channel sends a custom header with MustUnderstand=true and receives a mustUnderstand fault, it must figure out whether that fault is due to the header it sent. MessageFault クラスには、このために役立つ 2 つのメンバーが存在します。There are two members on the MessageFault class that are useful for this:

public class MessageFault  
{  
    ...  
    public bool IsMustUnderstandFault { get; }  
    public static bool WasHeaderNotUnderstood(MessageHeaders headers,   
        string name, string ns) { }  
    ...  
  
}  

エラーが IsMustUnderstandFault エラーの場合、truemustUnderstand を返します。IsMustUnderstandFault returns true if the fault is a mustUnderstand fault. 指定した名前と名前空間を持つヘッダーが NotUnderstood ヘッダーとしてエラーに含まれている場合、WasHeaderNotUnderstoodtrue を返します。WasHeaderNotUnderstood returns true if the header with the specified name and namespace is included in the fault as a NotUnderstood header. それ以外の場合は、 falseを返します。Otherwise, it returns false.

MustUnderstand = true でマークされたヘッダーをチャネルで出力する場合は、該当のレイヤーも例外生成 API パターンを実装し、出力したヘッダーが原因で発生した mustUnderstand エラーを前述のより有用な例外に変換する必要があります。If a channel emits a header that is marked MustUnderstand = true, then that layer should also implement the Exception Generation API pattern and should convert mustUnderstand faults caused by that header to a more useful exception as described previously.

トレースTracing

デバッガーをアタッチしてコードを段階的に実行できない場合に、運用アプリケーションや断続的な問題の診断を支援する 1 つの方法として、.NET Framework にはプログラムの実行をトレースする機構が用意されています。The .NET Framework provides a mechanism to trace program execution as a way to aid diagnosing production applications or intermittent problems where it is not possible to just attach a debugger and step through the code. この機構のコア コンポーネントは System.Diagnostics 名前空間にあり、以下で構成されます。The core components of this mechanism are in the System.Diagnostics namespace and consist of:

例外とエラーの処理Handling exceptions and faults

カスタム チャネルからのトレースTracing from a Custom Channel

実行中のアプリケーションにデバッガーをアタッチできないときに問題の診断を支援するために、カスタム チャネルはトレース メッセージを書き込む必要あります。Custom channels should write out trace messages to assist in diagnosing problems when it is not possible to attach a debugger to the running application. これには、2 つの高度なタスクが含まれます。インスタンス化する、TraceSourceトレースを書き込むためのメソッドを呼び出すとします。This involves two high level tasks: Instantiating a TraceSource and calling its methods to write traces.

TraceSource をインスタンス化する場合、指定した文字列が対象のソースの名前になります。When instantiating a TraceSource, the string you specify becomes the name of that source. この名前を使用して、トレース ソースを構成 (有効化/無効化/トレース レベルの設定) します。This name is used to configure (enable/disable/set tracing level) the trace source. また、トレース出力にもこの名前が表示されます。It also appears in the trace output itself. カスタム チャネルは、一意のソース名を使用して、トレース出力の利用者にトレース情報のソースがわかるようにする必要があります。Custom channels should use a unique source name to help readers of the trace output understand where the trace information comes from. トレース ソースの名前として、情報を書き込むアセンブリの名前を使用するのが一般的です。Using the name of the assembly that is writing the information as the name of the trace source is the common practice. など、WCF は、System.ServiceModel アセンブリから書き込まれた情報のトレース ソースとして System.ServiceModel を使用します。For example, WCF uses System.ServiceModel as the trace source for information written from the System.ServiceModel assembly.

トレース ソースを用意したら、TraceDataTraceEvent、または TraceInformation の各メソッドを呼び出して、トレース エントリをトレース リスナーに書き込みます。Once you have a trace source, you call its TraceData, TraceEvent, or TraceInformation methods to write trace entries to the trace listeners. 書き込む各トレース エントリのイベントの種類は、TraceEventType に定義されたイベントの種類のいずれかとして分類する必要があります。For each trace entry you write, you need to classify the type of event as one of the event types defined in TraceEventType. この分類と構成でのトレース レベルの設定によって、トレース エントリをリスナーに出力するかどうかが決まります。This classification and the trace level setting in configuration determine whether the trace entry is output to the listener. たとえば、構成でトレース レベルを Warning に設定すると、WarningError、および Critical の各トレース エントリを書き込むことができますが、Information エントリと Verbose エントリはブロックされます。For example, setting the trace level in configuration to Warning allows Warning, Error and Critical trace entries to be written but blocks Information and Verbose entries. トレース ソースをインスタンス化し、Information レベルでエントリを書き込む例を次に示します。Here is an example of instantiating a trace source and writing out an entry at Information level:

using System.Diagnostics;  
//...  
TraceSource udpSource=new TraceSource("Microsoft.Samples.Udp");  
//...  
udpsource.TraceInformation("UdpInputChannel received a message");  

重要

カスタム チャネル固有のトレース ソース名を指定して、トレース出力の利用者に出力のソースがわかるようにすることを強くお勧めします。It is highly recommended that you specify a trace source name that is unique to your custom channel to help trace output readers understand where the output came from.

トレース ビューアーとの統合Integrating with the Trace Viewer

読み取り可能な形式で出力できるは、チャネルによって生成されたトレース、サービス トレース ビューアー ツール (SvcTraceViewer.exe)を使用してSystem.Diagnostics.XmlWriterTraceListenerトレース リスナーとして。Traces generated by your channel can be output in a format readable by the Service Trace Viewer Tool (SvcTraceViewer.exe) by using System.Diagnostics.XmlWriterTraceListener as the trace listener. これは、チャネル開発者が行う必要はありません。This is not something you, as the channel developer, need to do. アプリケーション ユーザー (またはアプリケーションのトラブルシューティング担当者) が、アプリケーションの構成ファイルでこのトレース リスナーを構成する必要があります。Rather, it is the application user (or the person troubleshooting the application) that needs to configure this trace listener in the application’s configuration file. たとえば、次の構成では、System.ServiceModelMicrosoft.Samples.Udp の両方から TraceEventsFile.e2e というファイルにトレース情報が出力されます。For example, the following configuration outputs trace information from both System.ServiceModel and Microsoft.Samples.Udp to the file named TraceEventsFile.e2e:

<configuration>  
  <system.diagnostics>  
    <sources>  
      <!-- configure System.ServiceModel trace source -->  
      <source name="System.ServiceModel" switchValue="Verbose"   
              propagateActivity="true">  
        <listeners>  
          <add name="e2e" />  
        </listeners>  
      </source>  
      <!-- configure Microsoft.Samples.Udp trace source -->  
      <source name="Microsoft.Samples.Udp" switchValue="Verbose" >  
        <listeners>  
          <add name="e2e" />  
        </listeners>  
      </source>  
    </sources>  
    <!--   
    Define a shared trace listener that outputs to TraceFile.e2e  
    The listener name is e2e   
    -->  
    <sharedListeners>  
      <add name="e2e" type="System.Diagnostics.XmlWriterTraceListener"  
        initializeData=".\TraceFile.e2e"/>  
    </sharedListeners>  
    <trace autoflush="true" />  
  </system.diagnostics>  
</configuration>  

構造化されたデータのトレースTracing Structured Data

System.Diagnostics.TraceSource には、トレース エントリに含まれる 1 つ以上のオブジェクトを取得する TraceData メソッドがあります。System.Diagnostics.TraceSource has a TraceData method that takes one or more objects that are to be included in the trace entry. 通常、Object.ToString メソッドは各オブジェクトに対して呼び出され、生成された文字列はトレース エントリの一部として書き込まれます。In general, the Object.ToString method is called on each object and the resulting string is written as part of the trace entry. System.Diagnostics.XmlWriterTraceListener を使用してトレースを出力する場合、データ オブジェクトとして System.Xml.XPath.IXPathNavigableTraceData に渡すことができます。When using System.Diagnostics.XmlWriterTraceListener to output traces, you can pass an System.Xml.XPath.IXPathNavigable as the data object to TraceData. 生成されるトレース エントリには、System.Xml.XPath.XPathNavigator によって提供された XML が含まれます。The resulting trace entry includes the XML provided by the System.Xml.XPath.XPathNavigator. XML アプリケーション データが含まれたエントリの例を次に示します。Here is an example entry with XML application data:

<E2ETraceEvent xmlns="http://schemas.microsoft.com/2004/06/E2ETraceEvent">  
  <System xmlns="...">  
    <EventID>12</EventID>  
    <Type>3</Type>  
    <SubType Name="Information">0</SubType>  
    <Level>8</Level>  
    <TimeCreated SystemTime="2006-01-13T22:58:03.0654832Z" />  
    <Source Name="Microsoft.ServiceModel.Samples.Udp" />  
    <Correlation ActivityID="{00000000-0000-0000-0000-000000000000}" />  
    <Execution  ProcessName="UdpTestConsole"   
                ProcessID="3348" ThreadID="4" />  
    <Channel />  
    <Computer>COMPUTER-LT01</Computer>  
  </System>  
<!-- XML application data -->  
  <ApplicationData>  
  <TraceData>  
   <DataItem>  
   <TraceRecord   
     Severity="Information"  
     xmlns="…">  
        <TraceIdentifier>some trace id</TraceIdentifier>  
        <Description>EndReceive called</Description>  
        <AppDomain>UdpTestConsole.exe</AppDomain>  
        <Source>UdpInputChannel</Source>  
      </TraceRecord>  
    </DataItem>  
  </TraceData>  
  </ApplicationData>  
</E2ETraceEvent>  

WCF トレース ビューアーのスキーマの理解、TraceRecord前に示した要素とその子要素からデータを抽出し、表形式で表示します。The WCF trace viewer understands the schema of the TraceRecord element shown previously and extracts the data from its child elements and displays it in a tabular format. チャネルで構造化されたアプリケーション データをトレースするときには、このスキーマを使用して Svctraceviewer.exe のユーザーがデータを判読しやすいようにします。Your channel should use this schema when tracing structured application data to help Svctraceviewer.exe users read the data.