C#での私のWCFサービスは次のようになります。
[ServiceContract]
public class MySecretService
{
[OperationContract]
[FaultContract(typeof(ErrorMessage))]
public MyDTO ReturnMyDTOMethod(int id, out string errorMessage)
{
try
{
//Do stuff...
//Do some more stuff... pseudocode
if (biz rule 1 && etc)
{
return MyDTO;
}
else if (biz rule 2 && etc)
{
return null;
}
else
{
throw new FaultException<ErrorMessage>(blah etc..)
}
}
catch (Exception e)
{
throw new FaultException<ErrorMessage>(blah etc...);
}
}//end-method
}//end-class
メソッドから返されるDTOは次のようになります。
[DataContract]
public class MyDTO
{
[DataMember]
public XElement XmlRep
{
get
{
//do something within setter, etc...
//error occurs prior to returnin from setter, where to i catch it?
return _xmlRep
}
set
{
_xmlRep = value;
}
}
}
私が見つけた典型的な例は、メソッド内からFaultExceptionをスローすることを示しています。しかし、私の場合、私のメソッドはエラーになりません。このエラーは、オブジェクトがクライアント/コンシューマーに返されるときに発生します。つまり、DataMember /PropertyXmlRepがシリアル化されているとき。
したがって、throwFaultExceptionをメソッド内に配置することはできません。ただし、「基になる接続が閉じられました。接続が予期せず閉じられました」というメッセージが表示されないようにします。ゲッター内で発生する適切なエラーをスローします。
MyDTOのゲッター内にtry/catchを入れようとはしていません。また、DTOをできるだけ単純にし、FaultExceptionsやWCFについて何も知らないようにしたいからです。他のアイデアはありますか?
編集:明確にするために、MyDtoDataContractのゲッターでエラーが発生していることを知っています。しかし、ゲッターの内部は危険な場所のように見えるので、他にどこでFaultExceptionをスローしますか?
編集#2:以下のTimが提案するように、サービス側にキャッチオールエラーハンドラーを実装しました(IErrorHandlerを使用)。これは私の特定のケースでは機能しません。これは、エラーがOperationContract ReturnMyDTOMethod()内では発生せず、シリアル化されているときにMyDto内で発生するためだと思います。言い換えると、馬がボルトで固定されているように見え(メソッドは正常に戻ります)、IErrorHandlerが使用できるようになるのは遅れています。具体的には、ProvideFault()は起動しませんが、HandleError()は起動します。その結果、まだチャネルが壊れているというメッセージが表示されます。これには、図面に戻る必要があります。つまり、MyDtoがエラーの生成などの特別なことを行わないようにします。