WCFでの例外処理

例外は、実行時に発生するエラーです。例外処理は、これらのランタイムエラーを処理する手法です。通常、例外を処理するには、アプリケーションのコードでtry、catch、finallyブロック(例外ブロックとも呼ばれます)を使用します。アプリケーションのコードで例外が適切に処理されず、実行時に例外が発生した場合、アプリケーションの実行は終了します。

WCFでの例外処理は、それほど単純ではありません。.Netオブジェクトをネットワーク経由で送信するように制限されており、WCFサービスはシリアル化されたデータ(SOAPメッセージなど)のみをクライアントに送信できます。WCFで例外を処理するには、次の3つの方法のいずれかを使用します。

  1. FaultExceptionの使用
  2. IErrorHandlerの使用
  3. returnUnknownExceptionsAsFaultsの使用

この投稿では、WCFサービスからサービスのコンシューマーに例外メッセージを送信するさまざまな方法について説明します。

この単純なWCFサービスについて考えてみましょう。

[ServiceContract]

パブリックインターフェイスIDBManagerService

    {{

        【OperationContract】

        void Save(Employee emp);

    }

IDBManagerServiceサービスコントラクトには、従業員オブジェクトをデータベースに永続化するための1つの操作コントラクトが含まれています。

パブリッククラスDBManagerService:IDBManagerService

    {{

        void Save(Employee emp)

        {{

         試してみてください

           {{

            //従業員オブジェクトをデータベースに保存するコード

           }

           catch(例外例)

           {{

               新しい例外をスローします(「データの保存中にエラーが発生しました…」);

           }

        }

    }

ここで、サービスを利用しようとしているときに、データベースへの接続またはデータベースへの従業員オブジェクトの保存でエラーが発生したとします。次に、次のメッセージで例外が発生します。 "System.ServiceModel.FaultException:サーバーは内部エラーのために要求を処理できませんでした。エラーの詳細については、IncludeExceptionDetailInFaultsをオンにします(ServiceBehaviorAttributeまたは構成から)動作)サーバー上で例外情報をクライアントに送り返すか、Microsoft .Net Framework 3.0 SDKのドキュメントに従ってトレースをオンにして、サーバーのトレースログを調べます。」

web.configファイルでincludeExceptionDetailInFaults要素をtrueに設定すると、例外の追加の詳細が障害に含まれるため、実際に何が問題になったかを簡単に調べることができます。

コードを書くことによってこれを達成することもできます。これは、このプロパティをtrueに設定する方法を示すコードスニペットです。

    typeof(ServiceDebugBehavior));

    new ServiceDebugBehavior {IncludeExceptionDetailInFaults = true});

以下に示すように、ServiceBehaviorタグを使用してこれをtrueに設定することもできます。

[ServiceBehavior(IncludeExceptionDetailInFaults = true)]

パブリッククラスDBManagerService:IDBManagerService

{{

}

サービスを再度使用しようとすると、より正確な例外メッセージが表示されます。

FaultExceptionの使用

ただし、サービスからユーザーフレンドリーな例外メッセージを渡す必要がある場合は、障害例外をスローする必要があります。障害例外は、実行時に例外が発生したときにWCFサービスによってスローされる例外です。このような例外は通常、型指定されていない障害データをサービスコンシューマーに送信するために使用されます。他のメソッドとほぼ同じ方法でサービスメソッドの例外を処理し、それらを障害例外に変えることができます。

以下のコードスニペットは、更新されたサービスメソッドを示しています。サービスメソッドはフォールト例外をスローするようになりました。

パブリッククラスDBManagerService:IDBManagerService

    {{

        void Save(Employee emp)

        {{

            試してみてください

            {{

               //従業員オブジェクトをデータベースに保存するコード

            }

            catch(例外例)

            {{

               新しいFaultException( "データの保存中にエラーが発生しました…");をスローします。

            }

        }

    }

このサービスを利用するときは、コードで障害例外を処理する必要があります。このMSDNの記事から、WCFの障害例外について詳しく知ることができます。

DataContract属性でマークされたカスタム障害クラスを作成することもできます。

[DataContract]

パブリッククラスCustomFault

{{

[DataMember]

パブリック文字列ソース;

[DataMember]

パブリック文字列ExceptionMessage;

[DataMember]

パブリック文字列InnerException;

[DataMember]

パブリック文字列StackTrace;

}

次のコードスニペットは、CustomFaultクラスを使用して強く型付けされたFaultExceptionをスローする方法を示しています。

void Save(Employee emp)

{{

試してみてください

{{

  //従業員オブジェクトをデータベースに保存するコード

}

キャッチ(例外例)

{{

CustomFault cx = new CustomFault();

新しいFaultException(ex、new FaultReason( "これは強く型付けされた障害のある例外です"));をスローします。

}

}

また、FaultExceptionを発生させるサービスメソッドのFaultContract属性を指定する必要があります。変更されたSaveメソッドは次のようになります。

[ServiceContract]

パブリックインターフェイスIDBManagerService

    {{

        【OperationContract】

        [FaultContract]

        void Save(Employee emp);

    }

returnUnknownExceptionsAsFaultsの使用

サービス動作設定でreturnUnknownExceptionsAsFaults属性を使用して、SOAP障害として例外を自動的に発生させることができます。次のコードスニペットは、これを実現する方法を示しています。

                 returnUnknownExceptionsAsFaults = "True">

グローバルに例外を処理する

WCFで例外を処理する別の方法は、サービスクラスにIErrorHandlerインターフェイスを実装して、すべての例外をグローバルに処理し、SOAP準拠のFaultExceptionを提供することです。このインターフェースには、HandleErrorとProvideFaultの2つのメソッドが含まれています。前者はエラーのあるアクティビティを実行するために使用されますが、後者は障害メッセージを返すために使用されます。サービス構成可能ファイルでIErrorHandlerを構成(オンまたはオフ)することもできることに注意してください。