6

WCF サービスが、無効な値 (Enum 型に存在しない int) を持つ列挙型メンバーを持つ DataContract を返すシナリオでは、クライアント側でスローされる例外The underlying connection was closed: The connection was closed unexpectedly.
が発生します。接続のサーバー側。

サーバーサイドでの実行時に、もっと便利で重要なものを投げてもらいたいのですが、おそらくコンパイラの警告...

WCF サービス コントラクト

    [ServiceContract]
    public interface IDtoService
    {
        [OperationContract]
        MyDto GetData(int value);
    }

    public enum Rating
    {
        None = 0,
        NotSet = 1,
        Somevalue = 34
    }

    [DataContract]
    public class MyDto
    {
        Rating _rate;

        [DataMember]
        public Rating Rating 
        { 
            get { return _rate; } 
            set 
            {
                _rate = value; 
            } 
        }

    }

サービスの実装

    public class DtoService : IDtoService
    {
        public MyDto GetData(int value)
        {
            var dto = new MyDto {  Rating = (Rating) 42 }; // not in ENUM!
            return dto;
        }
    }

クライアント

var cl = new DtoServiceClient.DtoServiceClient();
var tada = cl.GetData(1);  // connection closed exception

実際の例外をスローするには、VS2010 のデバッグ オプションで [自分のコードのみを有効にする] を無効にし、[例外] ダイアログで [共通言語ランタイムの例外] のスローを有効にする必要がありました。

その設定では、貴重な例外は次のとおりです。

SerializationException
Enum 値 '42' はタイプ 'WcfService1.Rating' に対して無効であり、シリアル化できません。型に DataContractAttribute 属性がある場合は、必要な列挙値が存在し、EnumMemberAttribute 属性でマークされていることを確認します

これには、デバッガーがスローされた他のすべての種類の例外について非常にうるさくなり、AFAIK を無視できるという犠牲が伴います。

ノイズなしでこの例外をスローするにはどうすればよいですか?

WCF パイプラインで微調整または追加できるものはありますか?

手直しのコストで早期に失敗する可能性のある解決策の 1 つは、enum メンバーのセッターに追加の Assert を追加することです。

Debug.Assert(Enum.IsDefined(typeof(Rating), value),"value is not valid for this enum");

私が試した別の方法は、警告が生成されることを期待して契約を追加することでした。基本的に Debug.Assert のコピーよりも優れたものは見つかりませんでした。

System.Diagnostics.Contracts.Contract.Assert(Enum.IsDefined(typeof(Rating), value));

コンパイラにこのチェックを発行させるオプションはありますか、それとも私が知らない代替手段はありますか? (成功することを期待せずに有効にし
てコンパイルしようとしました)check for arithmetic overflow/underflow

CodeContracts は警告を発します (Implicit Enum 書き込み義務を有効にする必要があります) が、それは実際には役に立ちません

実際の値は、この列挙値に対して定義された範囲内にない可能性があります

この動作は、VS2010/.Net 4.0 コンテキストにあります。

4

1 に答える 1

3

いくつかのことができます。

WCF 側でIncludeExceptionDetailInFaults( ServiceBehavior属性を使用するか、app.configで) を使用します。これにより、WCF は詳細な例外をクライアントに送信します。これは、サーバー スタック トレースをクライアント側に公開するため、「安全でない」設定と見なされることに注意してください。そのため、開発中にのみ使用してください。運用環境では、WCF エラー ハンドラーを使用してすべてのサービス エラーをログに記録する (または WCF トレースをオンにする) 必要があります。

コード コントラクトを使用してコンパイル時にこのエラーをキャッチする場合は、オブジェクトの不変条件を使用できます。

public class MyDto
{
    public Rating Rating { get; set; }

    [ContractInvariantMethod]
    void Invariant()
    {
        Contract.Invariant(Enum.IsDefined(typeof(Rating), Rating));
    }
}

静的分析を有効にすると、次の行に警告が表示されます。

new MyDto {  Rating = (Rating) 42 };
于 2013-09-15T06:29:17.187 に答える