1

これが私が観察したことです

サービスからクライアントにカスタム例外サブタイプをスローする必要があります。(特定の操作でFaultContractとしてリストされています)。CustomExceptionに特定のフィールドがあり、クライアントが受け取る必要があります。

[Serializable]
class MyCustomException : Exception
{
    public string From { get; private set; }

    public MyCustomException(string where)
    {
        From = where;
    }

}

}

FaultExceptionインスタンス内に例外が存在するにもかかわらず、フィールドが逆シリアル化されていないことがわかりました。GetObjectDataとシリアル化コンストラクターをオーバーライドしてISerializableを実装しようとしましたが、ダイスはありませんでした。私がそれを理解する唯一の方法は、MyCustomExceptionをDataContractに変更し、Exceptionから派生しないようにすることでした。

[DataContract]
class MyCustomException
{
    [DataMember]
    public string From { get; private set; }

    public MyCustomException(string where)
    {
        From = where;
    }
}

これは機能します。ただし、Exceptionから派生することはできなくなりました。ExceptionはSerializable属性でマークされており、タイプにSerializableとDataContractの両方を含めることはできないためです。(確認済み:実行時例外がスローされました)

だから私の質問は:WCFでカスタム例外サブタイプのフィールドを伝播する正しい方法は何ですか?

4

2 に答える 2

2

... 型に Serializable と DataContract の両方を持つことはできません。(確認済み: 実行時に例外がスローされます)

DataContractまず、Serializable一緒に持つことができます。実際、これがなければ、現在取り組んでいる Web サイトは機能しません。なぜなら、私の WCF サービスは Web 経由で$.ajax. このSO スレッドは、正式な詳細を提供します。

次に、からカスタム エラーを継承しないことを強くお勧めしますException。理由は、FaultException<TDetail>組み込みクラスが既にあるためです。どこTDetailにカスタム フォールトがありますか。実装の詳細については、このMSDNの記事を参照してください。展開中は、クライアントで「例外の詳細」をオフにすることを忘れないでください。

catch (FaultException<MyFault> e)
{
    //e is the full exception (with StackTrace et al.) when 'exception details' is on
    //e.Detail is your custom fault which is always available
}
于 2012-07-18T13:23:13.223 に答える
1

これが私がそれを機能させる方法です..それが正しい方法であるかどうかはわかりません。の TDetail パラメータとして Exception サブタイプを使用することを想定していないことを示す明示的なガイドラインは見つかりませんでしたFaultException<TDetail>

を投げてFaultException<FileNotFoundException>みたところ、ファイル名フィールドが実際に正しく伝播されていることがわかりました。

では、FileNotFoundException と MyCustomException の間の差分は何ですか?

基本例外は ISerializable を実装しているため、サーバー側でメソッドをオーバーライドする必要がありました..

    protected MyCustomException(SerializationInfo info, StreamingContext context) :
        base(info, context)
    {
        this.From = info.GetString("From");
    }
    public override void GetObjectData(SerializationInfo info, StreamingContext context)
    {
        base.GetObjectData(info, context);
        info.AddValue("From", this.From);
    }

次に、svcutil を使用してクライアント プロキシ クラスを生成しました。FileNotFoundException は生成されていませんが (組み込み型であるため)、MyCustomException は生成されています。ただし、フィールドがなく、空の逆シリアル化 ctor しかありません。

プロキシ クラスの ctor にブレークポイントを設定したときにヒットしなかったため、以前は ISerializable について掘り下げませんでした。その調査行を誤って中止しました (クラスの DebuggerStepThrough 属性と GeneratedCode 属性を確認できませんでした。svcutil によって追加されました)。

そのため、自動生成されたクラスを手動で編集してフィールドを追加し、そのように ctor に設定します..

[System.SerializableAttribute()]
    public partial class MyCustomException : System.Exception
    {
        public string From { get; private set; } // manual edit

        public MyCustomException(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) :
            base(info, context)
        {
             this.From = info.GetString("From");  // manual edit
        }
    }

期待どおりに動作するようになりました。フィールド データはそのままです。

これにより、別の疑問が生じます: プロキシ生成ステップでこれが自動的に行われないのはなぜですか?

于 2012-07-19T09:56:23.423 に答える