2016-03-29 10 views
0

Ich weiß, dass das Ausgeben einer ganzen Zahl an einen ungültigen Aufzählungswert aufgrund von Flags nicht zu einer Ausnahme in C# führt. Hier war ich, eine Tabelle in einer DB-Tabelle spezifizierend und seine Werte 1-3 mit EntityFramework erhalten. Auf meiner Serverseite werfe ich die Werte in eine Enum XyzType Bereich von 0-2, die offensichtlich den ungültigen Wert (XyzType)3 generiert. Jetzt lege ich diesen Wert in eine XyzDTO und sende es an einen WCF-Client. Die bei der Deserialisierung Einzahler dieser sehr vage Beschreibung:Das Konvertieren in einen ungültigen Aufzählungswert führt zu einer nicht angegebenen Ausnahme auf der Clientseite.

Exception from deserialization

Jetzt habe ich einige andere Beiträge gelesen Ausnahmen von Deserialisieren ungültige XML verursacht zu diskutieren und es macht alles Sinn.

Meine Frage ist, wie kommt es, dass ich keine nützlichen Informationen bekommen habe, was die Ursache überhaupt war? Ich habe die letzten 1,5 Stunden mit diesem Fehler verbracht, bis ich den Unterschied zwischen den Enum- und den DB-Werten herausgefunden habe. Ist es ein Fehler in der WCF-Fehlerbehandlung, dass keine nützlichen Informationen angegeben wurden? Wenn ja, sollte MS benachrichtigt werden? Haben Sie gute Praktiken, um solche Szenarien in Zukunft zu vermeiden?

EDIT: Bitte beachten Sie, ich habe keine web.config. Meine Serverseite ist ein WCF-Dienst innerhalb eines Windows-Dienstes, dh. Ich habe app.config.

EDIT2: Es scheint mir einige Missverständnisse in Bezug auf dieses Problem und was ive versucht. Das Überprüfen der InnerExceptions der CommunicationException im Debugger liefert überhaupt keine nützlichen Informationen. Ich habe auch bereits "includeExceptionDetailsInFaults" = true auf der Serverseite, aber die Ausnahme wird nicht von der Serverseite geworfen! Es wird während der Deserialisierung auf der Clientseite verursacht.

EDIT3: Einige Antworten haben vorgeschlagen, die Verfolgung auf der Clientseite zu aktivieren. Ich habe das jetzt versucht, aber für dieses Problem gibt es auch keine nützlichen Informationen. Here ist eine Verbindung zum Ausgang.

+0

Können Sie zusätzlich zeigen Sie Ihre 'XyzType'-Enum? – khlr

+0

Ich habe es als nichts als Werte x, y, z (0,1,2) ausgeschlossen. – LuqJensen

+0

Ich fragte, weil, wenn Sie die enum von geändert haben, sagen wir, "x = 1, y = 2, z = 3" zu "x = 0, y = 1, z = 2" (um mit Ihrer DB zu entsprechen), dass könnte der Grund für einen (noch nicht aktualisierten) Client sein, eine Ausnahme auszulösen. – khlr

Antwort

0

Es ist fast immer eine gute Idee, activate tracing einige detailliertere Informationen über den Fehler zu erhalten:

<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> 

konfigurieren Sie können Ihre Server-und Client-bahn- oder app.config Dateien Tracing in von beiden zu erhalten Details Seiten.

Edit:

<serviceDebug includeExceptionDetailInFaults="true" /> macht Ihren Service Transport einer aufgetretenen Ausnahme an den Client (here für weitere Details). Wenn der Client diesen Fehler nicht behandelt, werden Sie ihn möglicherweise nicht bemerken.

+0

Hallo, ich habe keine web.config. Ich habe eine app.config auf Client- und Serverseite. Ich habe bereits angegeben, Ausnahmendetails serverseitig zu berücksichtigen. Bietet Ihre Lösung weitere Details? Ist es die gleiche Syntax für Client und Server? ' ' – LuqJensen

+0

ich immer wie down-votes ohne Kommentar ... – khlr

+0

Ich war nicht derjenige, den ich abwertete, aber könnten Sie bitte Ihre Antwort klären? Ich habe bereits Include-Ausnahmedetails auf der Serverseite auf true gesetzt. Aber gibt der Code, den Sie mir zur Verfügung stellen, mir weitere Informationen von Client- oder Serverseite? Ist es auf der Clientseite anwendbar, wo die Deserialisierung fehlschlägt? – LuqJensen

0

Wenn Aufzählungen und WCF, sicherzustellen, dass die Werte serialisiert/deserialisiert durch Markierung auf der Enum mit dem Datacontract und EnumMember diskutieren Attribute wie folgt:

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

Es scheint offensichtlich, aber auch bewusst sein, dass der Standardwert ist 0. Wie bereits erwähnt, können Sie die Verfolgung aktivieren. Sie sollten den customErrors-Modus auf "Aus" setzen und das Kompilieren für das Debug in der Datei "web.config" während der Entwicklung auf "true" setzen.

Sobald Sie die Entwicklung verlassen haben, sollten Sie eine benutzerdefinierte Fehlerseite bereitstellen und debug = "false" festlegen.

Sie sollten auch etwas über die Ausnahmebehandlung denken. Sie müssen sicherstellen, dass Sie keine Informationen verlieren. auf die Ausnahme, wenn Sie die Ausnahmen erneut auslösen. Ich möchte ein einfaches Protokollierungsframework wie NLog verwenden, um die Ausnahme zu protokollieren, und dann werde ich die Ausnahme an die ursprüngliche Methode im Service zurückholen, wo ich die Ausnahme in eine FaultException umwandele, wobei T eine Klasse ist, für die ich erstellt habe Serialisieren und Halten von Ausnahmeinformationen. Zum Beispiel:

[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; 
    } 
} 

Und in meinem Service-Methode:

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)); 
} 

Vielleicht möchten Sie Ihre eigenen Klassen definieren, die von Exception leiten Sie Ihre eigene Ausnahmen zu werfen.

+0

Hallo, ich habe keine web.config. Ich sollte meinen Beitrag aktualisieren ... Es ist nett von Ihnen, in so viel Detail über Standardpraktiken zu gehen, aber Sie sehen, dass es nicht anwendbar ist, weil ungültige Enum-Formen keine Ausnahmen werfen. Das Ändern der Fehlerausgabe auf der Clientseite könnte jedoch die Lösung sein. – LuqJensen

+0

Kein Problem. Ich gebe nur einige Beispiele für gängige Praktiken. Ich verstehe, dass die CommunicationException nicht in die Ausnahmebehandlungspraktiken fällt, die ich oben angegeben habe. Ja, Sie können dies auf der Clientseite abfangen. Normalerweise fange ich FaultException, TimeoutException und CommunicationException explizit auf der Clientseite ab. In einer web.config oder wie in Ihrem Fall in einer app.config möchten Sie ein Servicebehabe für serviceDebug includeExceptionDetailInFaults = "True" wie von anderen erwähnt enthalten. http://StackOverflow.com/Questions/6906953/WCF-Communication-Exception – iCode

+0

Jene anderen sind ich selbst :) Ist dieser Teil anwendbar auf clientside obwohl? Ich benutze es serverside – LuqJensen

0

Sie haben Probleme mit der Serialisierung/Deserialisierung und wie andere bereits vorgeschlagen haben, benötigen Sie mehr Protokollierung. Und Sie haben einige davon aktiviert, aber nicht alle und nicht spezifisch für die Serialisierung.

Versuchen folgende Konfiguration für die Anmeldung zu verwenden:

<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> 

Hier habe ich zwei weitere Spurenquellen (und aktiviert Nachrichtenprotokollierung): System.Runtime.Serialization Fehler (falls vorhanden) in Bezug auf die Serialisierung/Deserialisierung produzieren wird. Die Nachrichtenprotokollierung hilft Ihnen dabei, zu verstehen, ob Sie auf der Clientseite etwas erhalten.

Von Callstack in dem Protokoll, das Sie veröffentlicht haben, ist mir klar, dass die Ausnahme auf der Serverseite passiert. Aber Nachrichtenprotokollierung wird dies besser zeigen.

0

Wenn Sie Enum in WCF verwenden möchten, müssen Sie definieren 0 Wert für Enum. Es ist sehr wichtig.

public enum MyEnum{ 
    Default = 0, 
    SomeValue1 = 1, 
    SomeValue2= 2, 
    .... 
} 
Verwandte Themen