2016-03-29 11 views
0

無効な列挙型の値に整数をキャストしても、C#ではFlagsによって例外が発生しません。ここでは、DBテーブルにテーブルを指定し、その値をEntityFrameworkで1-3にしました。私のサーバー側では、数値を0-2からenum XyzTypeにキャストします。これは明らかに無効な値(XyzType)3を生成します。今私はこの値をXyzDTOに入れてWCFクライアントに送信します。直列化復元時にこれは、この非常に漠然とした説明で失敗します。 無効な列挙型の値にキャストすると、クライアント側で不特定の例外が発生します

Exception from deserialization

は、今私は、無効なXMLをデシリアライズによって引き起こされた例外を議論するいくつかの他の記事を読んで、それはすべて理にかなっています。

私の質問は、どのような原因が何であるかに関する有用な情報が得られなかったことです。列挙型とDB値の違いがわかるまで、このバグで最後の1.5時間を費やしました。それは有用な情報が与えられなかったWCFエラー処理の欠陥と考えられますか?その場合は、MSに通知する必要がありますか?将来このようなシナリオを避けるための良い習慣はありますか?

編集:web.configはありませんのでご注意ください。私のサーバサイドはWindowsサービス内のWCFサービスです。私はapp.configを持っています。

EDIT2:この問題に関して何か誤解があり、何が挑戦されたかのようです。デバッガでCommunicationExceptionのInnerExceptionsを調べると、有用な情報がまったく提供されません。また、私はすでに "includeExceptionDetailsInFaults" = serversideにtrueを設定していますが、例外はserversideによってスローされません!これはクライアントサイドでの直列化解除時に発生します。

EDIT3:クライアント側でトレースを有効にすることを提案している回答があります。私は今これを試みましたが、確かにこの問題については有益な情報を提供していません。 Hereは出力へのリンクです。

+0

あなたは、さらにあなたの 'XyzType'-列挙型を表示することができますか? – khlr

+0

私は値x、y、z(0,1,2)だけを除外しました。 – LuqJensen

+0

enumを 'x = 1、y = 2、z = 3'から' x = 0、y = 1、z = 2'(あなたのDBに合わせる)に変更すると、 (まだ更新されていない)クライアントが例外をスローする理由かもしれません。 – khlr

答えて

0

それはエラーに関するいくつかのより詳細な情報を取得するためにactivate tracingにほとんど常に良い考えです:

<configuration> 
    <system.diagnostics> 
     <sources> 
      <source name="System.ServiceModel" 
        switchValue="Information, ActivityTracing" 
        propagateActivity="true"> 
      <listeners> 
       <add name="traceListener" 
        type="System.Diagnostics.XmlWriterTraceListener" 
        initializeData= "c:\log\Traces.svclog" /> 
      </listeners> 
     </source> 
     </sources> 
    </system.diagnostics> 
</configuration> 

あなたは両方から詳細情報を取得するには、サーバーとクライアントのウェブ - またはapp.configをファイルにトレースを構成することができます側面。

編集:

<serviceDebug includeExceptionDetailInFaults="true" />は、あなたのサービストランスポートクライアントに発生した例外を(詳細はhereを参照)を行います。クライアントがそのフォルトを処理しない場合は、それに気づかないかもしれません。

+0

こんにちは、私はweb.configを持っていません。私はクライアントとサーバー側の両方でapp.configを持っています。私は既にサーバサイドに例外の詳細を含めるように指定しました。あなたのソリューションは詳細を提供していますか?それはクライアントとサーバーの両方で同じ構文ですか? ' <行動名= ""> ' – LuqJensen

+0

私はいつものようにコメントなしでダウン投票... – khlr

+0

私はdownvoteに1つをwasntしますが、あなたの答えを明確にすることができますか?私は既にサーバサイドで例外の詳細を真に設定しています。しかし、あなたが提供したコードは、クライアントまたはサーバサイドからの情報を私に与えてくれますか?デシリアライゼーションが失敗するクライアント側にも適用できますか? – LuqJensen

0

列挙型とWCFを議論、値は次のようにのDataContractとEnumMember持つ列挙型属性をマークアップすることにより、非直列化/直列化されることを確認:

[DataContract(Namespace = Namespaces.V1)] 
public enum AreaType : int 
{ 
    [EnumMember] 
    Unknown = 0, 
    [EnumMember] 
    Urban = 1, 
    [EnumMember] 
    Suburban = 2, 
    [EnumMember] 
    Rural = 3 
} 

それは明白なようだが、また、デフォルト値があることに注意してください上記のように、トレースを有効にすることができます。開発中にcustomErrorsモードを "オフ"に設定し、web.configのデバッグ用のコンパイルを "true"に設定することができます。

<system.web> 
    <compilation debug="true" /> 
    <customErrors mode="Off" /> 
</system.web> 

開発をやり終えたら、カスタムエラーページを用意してdebug = "false"に設定するとよいでしょう。

<system.web> 
    <compilation debug="false" /> 
    <customErrors mode="RemoteOnly" defaultRedirect="ErrorRedirectPage.html" /> 
</system.web> 

また、例外処理についていくつかの考え方と設計を考慮する必要があります。あなたは情報を失わないようにする必要があります。あなたが例外を再スローしている場合は例外です。私はNLogのような単純なロギングフレームワークを使用して例外を記録するのが好きです。その後、私がFaultExceptionで例外をラップするサービスの元のメソッドに例外を戻します。ここでTは私が作成するクラスです例外情報のシリアライズと保持。たとえば:

[DataContract(Namespace=Namespaces.V1)] 
public class MyFaultException 
{ 
    [DataMember] 
    public string Reason { get; set; } 

    public MyFaultException() 
    { 
     this.Reason = "Service encountered an error"; 
    } 

    public MyFaultException(string reason) 
    { 
     this.Reason = reason; 
    } 
} 

そして、私のサービスメソッドに:

try 
{ 
    //... 
} 
catch (Exception ex) 
{ 
     // Asynchronously log the error message in a helper class using NLog 
     LogHelper.LogException(ex, "Error calculating blah.", LogLevel.Error); 

     throw new FaultException<MyFaultException>(
       new MyFaultException(ex.Message), new FaultReason(ex.Message)); 
} 

独自の例外をスローするExceptionから派生する独自のクラスを定義することもできます。

+0

こんにちは、私はweb.configを持っていません。私は自分の投稿を更新する必要があります... 標準的な慣行についてこのように詳しく説明してくれてうれしいですが、無効なenumキャストが例外をスローしないため、該当するものはありません。しかし、クライアント側のエラー出力を変更することは解決策になります。 – LuqJensen

+0

問題ありません。一般的な慣例のいくつかの例を提供するだけです。私はCommunicationExceptionが上記で提供した例外処理の慣行に該当しないことを理解しています。はい、クライアント側でこれをキャッチできます。私は通常、FaultException、TimeoutException、およびCommunicationExceptionをクライアント側で明示的にキャッチします。 web.configの場合もapp.configの場合も、serviceDebugのサービス例外を含める必要があります。includeExceptionDetailInFaults = "True"他の人の言葉通りです。 http://stackoverflow.com/questions/6906953/wcf-communication-exception – iCode

+0

他の人は自分自身です:)その部分はクライアント側にも当てはまりますか?私はそれをserverside – LuqJensen

0

シリアライズ/デシリアライズに問題があります。また、より多くのロギングが必要であることが既に示唆されているようになっています。そして、その一部を有効にしましたが、すべてではなく、シリアル化に特有のものではありません。

は、ロギングのための以下の設定を使用するようにしてください:

ここ
<configuration> 
    <system.diagnostics> 
     <sources> 
      <source name="System.ServiceModel" 
        switchValue="Information, ActivityTracing" 
        propagateActivity="true"> 
       <listeners> 
        <add name="traceListener" /> 
       </listeners> 
      </source> 
      <source name="System.ServiceModel.MessageLogging"> 
       <listeners> 
        <add name="traceListener" /> 
       </listeners> 
      </source> 
      <source name="System.Runtime.Serialization" 
        switchValue="Information"> 
       <listeners> 
        <add name="traceListener" /> 
       </listeners> 
      </source> 
     </sources> 
     <sharedListeners> 
      <add name="traceListener" 
       type="System.Diagnostics.XmlWriterTraceListener" 
       initializeData= "c:\log\Traces.svclog" /> 
     </sharedListeners> 
    </system.diagnostics> 
    <system.serviceModel> 
     <diagnostics> 
      <messageLogging 
       logEntireMessage="true" 
       logMessagesAtServiceLevel="true" 
       maxSizeOfMessageToLog="16777216"/> 
     </diagnostics>  
    </system.serviceModel> 
</configuration> 

を私は、2つの追加のトレースソース(および有効なメッセージ・ロギング)を追加しました:System.Runtime.Serializationはシリアライズ/デシリアライズプロセスに関するすべてのエラー(もしあれば)を生成します。メッセージのロギングは、クライアント側で何かを受け取ったかどうかを理解するのに役立ちます。

公開したログの呼び出しスタックから、例外がサーバー側で発生することは明らかです。しかし、メッセージロギングはこれをより良く示します。

0

WCFでEnumを使用する場合は、にEnumに0の値を定義する必要があります。 非常に重要です。

public enum MyEnum{ 
    Default = 0, 
    SomeValue1 = 1, 
    SomeValue2= 2, 
    .... 
} 
関連する問題