1

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がエラーの生成などの特別なことを行わないようにします。

4

1 に答える 1

1

私が見る2つのオプション:

  1. DataContractの何かをシリアル化できないようです。そこで調べて、それが何であるか、なぜシリアル化されていないのか、そしてセッター内で問題を処理できる他の方法があるかどうかを判断します。それが何であるかによっては、try-catchブロックなしでそれを行うことができるかもしれません。コードを見たり、実際のエラーが何であるかを知らなければ、より具体的なことを言うのは難しいです。

  2. サービスにIErrorHandlerインターフェイスを実装します。これにより、未処理の例外がキャッチされ、サービスの必要に応じて処理できます(たとえば、FaultExceptionを介してエラーメッセージをシリアル化する)。それを行う方法の例はウェブ上にたくさんあります-単にグーグルIErrorHandlerとWCF。

私の個人的な好みは、アプローチ#1を試すことです-おそらく、DTOがシリアル化されていない特定の理由(または理由のグループ)があり、ある種のグローバルエラーに依存するよりも、コード内でこれらの問題を処理する方が良いと思いますハンドラー(これは#2になります)。

また、セッターのロジックによっては、すでにDTOを複雑にしている場合があります。nullチェックのような単純なものでない限り、私は通常、セッターのロジックを避けようとします。

問題の2回目の編集後に追加

IErrorHandlerのドキュメントには次のように記載されています。

「すべてのProvideFault実装が呼び出され、応答メッセージがチャネルに渡された後に例外が発生する可能性があります。チャネル例外が発生した場合(たとえば、メッセージのシリアル化が困難な場合)、IErrorHandlerオブジェクトは通知されません。この場合、次のことを確認する必要があります。開発環境は、そのような例外をキャッチして表示するか、トレースを利用して問題を発見します。」(エンファシスマイン)

シリアル化が失敗する原因を知っていますか?もしそうなら、私はあなたがコード自体でそれに対処できると思います。トレースを有効にしましたか?DTOがシリアル化できない理由を特定する必要があるように思われます。

于 2011-12-05T08:11:39.147 に答える