4

WCFについて私が理解していなかったことの1つは、サーバーで未処理の例外が発生したときに、例外メッセージの詳細が呼び出し元のクライアントに伝播されない理由です。

たとえば、次のサーバーコードがある場合

[ServiceBehavior(IncludeExceptionDetailInFaults = true)]
public class Server : IServer
{
    public DTO GetDTO()
    {
        DTO dto = new DTO();
        dto.dto = dto;
        return dto;
    }

}

public class DTO
{
    public DTO dto;
}

[ServiceContract]
public interface IServer
{
    [OperationContract]
    DTO GetDTO();
}

DTOオブジェクトが返されたときにシリアル化例外を発生させるために、意図的にObjectGraphを導入しました。

このサーバーのGetDTO()メソッドを呼び出すクライアントがある場合、次のようになりますCommunicationException

ソケット接続が中止されました。これは、メッセージの処理エラー、リモートホストによる受信タイムアウトの超過、または根本的なネットワークリソースの問題が原因である可能性があります。ローカルソケットのタイムアウトは「00:00:58.9350000」でした。

これは絶対に役に立たない。内部例外はなく、実際の例外メッセージもありません。

その後、Microsoft Service TraceViewerを使用すると、例外が表示されますが、このために診断トレースをオンにする必要があります。

返送する必要のある例外メッセージは次のとおりです。

パラメータ http://tempuri.org/:GetDTOResultをシリアル化しようとしたときにエラーが発生しました。InnerExceptionメッセージは「タイプ「TestWCFLib.DTO」のオブジェクトグラフにサイクルが含まれており、参照追跡が無効になっている場合はシリアル化できません。」でした。詳細については、InnerExceptionを参照してください。

では、クライアント側に適切な例外メッセージを表示する方法を教えてもらえますか?明らかに、IncludeExceptionDetailInFaultstrueに設定しても違いはありません。

4

1 に答える 1

2

サーバーエラーがクライアントに伝播されないのは設計によるものだと思います。クライアントサーバーアーキテクチャの主な目的はサーバーの独立性であるため、これは一般的にサーバーの内部をクライアントに公開しないことです。

Fault Exceptionを使用することで、これを実現できます

障害契約でサービス宣言を飾る

[ServiceContract]
public interface IServer
{
    [OperationContract]
    [FaultContract(typeof(MyApplicationFault))]
    DTO GetDTO();
}

次に、サービスの実装でエラーをキャッチし、フォールト例外をスローします。

[ServiceBehavior(IncludeExceptionDetailInFaults = true)]
    public class Server : IServer
    {
        public DTO GetDTO()
        {
            try
              {
                   DTO dto = new DTO();
                   dto.dto = dto;
                   return dto;
               }
            catch (Exception ex)
                 {
                     MyApplicationFault fault = new MyApplicationFault(...);
                     throw new FaultException<MyApplicationFault>(fault);
                 }
        }

    }

そして、クライアントで例外をキャッチします

IServer proxy = ...;    //Get proxy from somewhere
try 
{
    proxy.GetDTO();
}
catch (TimeoutException) { ... }
catch (FaultException<MyApplicationFault> myFault) {
    MyApplicationFault detail = myFault.Detail;
    //Do something with the actual fault
}
catch (FaultException otherFault) { ... }
catch (CommunicationException) { ... }

お役に立てれば。優れたチュートリアルについては、Fault Exception に関するコード プロジェクト チュートリアルを参照してください。

于 2012-12-04T08:34:32.740 に答える