そのため、WCF サービスで Enterprise Library を使用して、例外関連の作業をいくつか実行しようとしています。
私の考えは、「NullReferenceException」などの「カスタム例外ハンドラー」を設定し、「カスタム例外ハンドラー」で FaultException 例外を作成することです。
私の理解では、この「新しい」例外はネットワークを通過し、クライアントでキャッチします。
理解を深めるためのコード:
WCF サービス:
[ServiceContract(Name="MyService", ConfigurationName="MyNamespace.MyService")]
[ExceptionShielding("PolicyName")]
public interface IMyService
{
[OperationContract]
[FaultContract(typeof(MyFaultContract))]
string Method(String Param);
}
public class MyService : IMyService
{
public string Method(String Param)
{
throw new NullReferenceException("code-created null message here");
}
}
カスタム例外ハンドラ: (エンタープライズ ライブラリ)
public class MyExceptionHandler : IExceptionHandler
{
public MyExceptionHandler(NameValueCollection collection) { }
public MyExceptionHandler() { }
public System.Exception HandleException(System.Exception exception,
Guid handlingInstanceId)
{
MyFaultContract details = new MyFaultContract();
if (exception is NullReferenceException)
{
details.ErrorCode = MyFaultCode.NullReferenceException;
details.OriginalMessage = exception.Message;
details.MyMessage = "Null Reference exception here!";
}
return new FaultException<MyFaultContract>(details);
}
}
NullReferenceException を「カスタム例外ハンドラー」にマップするアプリ構成ファイル:
<exceptionPolicies>
<add name="PolicyName">
<exceptionTypes>
<add name="NullReferenceException" type="System.NullReferenceException, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"
postHandlingAction="ThrowNewException">
<exceptionHandlers>
<add type="MyExceptionHandler, MyApplication, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"
name="MyExceptionHandler" />
</exceptionHandlers>
</add>
</exceptionTypes>
</add>
</exceptionPolicies>
そして最後に、この FaultException をキャッチすることを期待するクライアント コード:
MyService.MyServiceClient client = new MyService.MyServiceClient();
client.Open();
try
{
string result = client.Method(string parameter);
}
catch (System.ServiceModel.FaultException<MyService.MyFaultContract> ex)
{
// where I think exception should end up
}
catch (System.ServiceModel.FaultException ex)
{
// general FaultException
}
しかし、代わりに、応答アクションが必要であることを示す ProtocolException が発生します。
アクション '' の操作 'メソッド' に対する応答メッセージを受信しました。ただし、クライアント コードにはアクション 'http://tempuri.org/MyService/MethodResponse' が必要です。
私は何を間違っていますか?「カスタム例外ハンドラー」でカスタム FaultContract を使用して FaultException を返す (明示的にスローしない) ことは可能ですか?
アドバイスをいただければ幸いです。
更新: ご覧のとおり、「カスタム例外ハンドラー」の処理後のアクションは「ThrowNewException」に設定されています。「NotifyRethrow」に変更すると、「ProtocolException」が発生しなくなります。代わりに、クライアントは通常の "FaultException" (カスタム型ではない) をキャッチします。
ここで問題となるのは、元のカスタム型の FaultException がネットワークを通過しない理由です。
Update 2 忘れていたことの 1 つは、WCF サービスが IIS ではなく ServiceHost 内で実行されていることです。したがって、基本的には、ServiceHost を作成し、この ServiceHost を介して Service1 インターフェイスを公開する Windows サービスがあります。
これがこの問題と関係があると私が考える理由は、Enterprise Library が、サービス境界内だけでなく、アプリケーション全体で例外を処理すると主張しているためです。これにより、例外のスローが遅すぎる可能性がありますか? それとも適切なレベルではありませんか?
更新 3
投稿ありがとうございます。そうです、私がカスタム ハンドラーをいじっている唯一の理由は、MyFaultCode 値を設定したいからです。私はあなたのアドバイスを試しました-2つのハンドラーを構成しました。
最初はカスタム ハンドラーで、NullReference 例外をキャッチします。次に、MyFaultContract フィールドを使用して、新しい例外 - MyApplicationException をスローします。
次に、2 番目のハンドラーを構成しました。組み込みの "Fault Contract Exception Handler" は、MyApplicationException をキャッチし、新しい FaultException を作成し、MyFaultcontract を MyApplicationException から新しく作成された FaultException に自動的にマップします。
WCF クライアントは、カスタム コントラクトではなく、一般的な FaultException を引き続きキャッチします。