2010-09-08 9 views
6

Ich versuche, eine bestimmte FaultException auf einem WCF-Client abzufangen. Ich muss im Grunde eine innere Beschreibung aus der Fehlerklasse extrahieren, so dass ich sie dann in eine andere Ausnahme für die oberen Schichten verpacken kann, um was auch immer zu tun.FaultException.Detail kommt leer zurück

Ich habe dies erfolgreich einige Male gemacht, was es anders macht, ist dieser Fehler als ein Array deklariert, wie Sie aus dem Service-Referenzattribut oben auf der Methode, die die Ausnahme auslöst, erkennen kann:

[System.ServiceModel.FaultContractAttribute(typeof(FaultClass[]), Action = "http://whatever/", Name = "whateverBusinessFault")] 

Dies ist mein Code:

try 
{ 
    // call service here 
} 
catch (FaultException<FaultClass[]> ex) 
{ 
    if (ex.Detail != null && ex.Detail.Length > 0) 
    { 
    throw new CustomException(ex.Detail[0].description); 
    } 
    else 
    { 
    throw; 
    } 
} 

Problem ist Detail (die ein Array ist) kommt immer wieder leer im Code selbst wenn ich die Daten sehen kann (Beschreibungsfeld usw.) in der SOAP-Respo nse aus der WCF-Ablaufverfolgung.

Also das Zeug, das ich brauche, kommt definitiv zurück, aber aus irgendeinem Grund wird es entweder nicht deserialisiert oder ich kann es nicht vom Code bekommen.

Jede Hilfe wird geschätzt!

UPDATE:

Der Versuch, mit @Darin Vorschlag aber kein Glück, der Saite, die ich aus dem XmlReader bin Extrahieren "/ r/n":

var sb = new StringBuilder(); 

using (XmlReader reader = fault.GetReaderAtDetailContents()) 
{ 
    while (reader.Read()) 
    sb.AppendLine(reader.ReadOuterXml()); 
} 

var detail = sb.ToString(); 

Sieht aus wie der Detailabschnitt ist kommt überhaupt nicht auf!

+0

Was passiert, wenn Sie Ihren Code ändern (nur für den Test), um nur FaultClass zu verwenden (nicht Array)? –

+0

bereits versucht, dass es die Ausnahme überhaupt nicht abfängt – JohnIdol

+0

Diese Frage kann nicht beantwortet werden, ohne entweder eine Beispielfehlerantwort oder das tatsächliche Schema des benutzerdefinierten Fehlers in der WSDL definiert –

Antwort

2

Ich kam mit dem einfachsten Testfall, den ich könnte. Ich hoffe es hilft dir. Server-Seite:

[ServiceContract] 
public interface IService1 
{ 
    [OperationContract] 
    [FaultContract(typeof(FaultClass[]))] 
    string Crash(); 
} 

public class Service1 : IService1 
{ 
    public string Crash() 
    { 
     var exception = new FaultException<FaultClass[]>(new FaultClass[] { new FaultClass { Data = "TEST" } }, new FaultReason("Boom")); 

     throw exception; 
    } 
} 

[DataContract] 
public class FaultClass 
{ 
    [DataMember] 
    public string Data { get; set; } 
} 

Client-Seite:

try 
{ 
    using (var client = new Service1Client()) 
    { 
     client.Crash(); 
    } 
} 
catch(FaultException<FaultClass[]> e) 
{ 
    //Break here 
} 
+1

Danke, ich habe keinen Zugriff auf den Dienst selbst (es ist ein Java-Achsen-Dienst). Ich konsumiere mit einem WCF-Client und es fängt den Fehler, aber das Array ist leer, obwohl ich (aus der Ablaufverfolgung) sehen kann, gibt es ein Element in der Antwort vom Dienst. – JohnIdol

+0

Das liegt möglicherweise an einem Unterschied in einem XML-Namespace, der verhindern würde, dass die Daten im Fehler deserialisiert werden. Haben Sie den Inhalt der FaultClass von WCF mit dem Inhalt einer FaultClass von Java verglichen? –

+0

das einzige, was ich habe, ist die WSDL, aus dem ich die WCF-Service-Referenz generieren. Ich habe den Inhalt der WSDL mit der generierten Service-Referenz verglichen und es sieht gut aus. Wenn dies Fall sein würde (Namespace-Probleme) würde ich Deserialisierungsprobleme auch auf anderen Typen erwarten, da Fehler im selben Namespace sind wie die anderen Typen – JohnIdol

5

Es ist schwer zu sagen, wo das Problem ist, aber ich vermute, der smoking gun diese Achse Web-Service ist nicht Standard-Nachricht zu generieren. Eine Möglichkeit, dies zu umgehen wäre die XML zu analysieren selbst:

try 
{ 
    proxy.CallSomeMethod(); 
} 
catch (FaultException ex) 
{ 
    var fault = ex.CreateMessageFault(); 
    using (XmlReader reader = fault.GetReaderAtDetailContents()) 
    { 
     // TODO: read the XML fault and extract the necessary information. 
    } 
} 
+0

gibt es eine Chance - Tnx – JohnIdol

+0

Ich denke, wir kommen näher ! Problem ist, ich weiß nicht, wie dieses Detail gebildet wird, also weiß nicht, welche Elemente/Attribute ich suchen sollte. Wird es genau so aussehen wie die Antwort, die ich in der Seife sehe, die aus dem Service kommt? – JohnIdol

+0

(aus irgendeinem Grund lässt SO mich nicht upvote Sie, sagt ich bereits gewählt, was nicht der Fall ist) – JohnIdol

1

Ich hatte eine ähnliche Situation bei dem Versuch, Daten mit Fehlern zu kommunizieren (genauer gesagt ein Stack-Trace). Siehe this question. Am Ende habe ich es gelöst, indem ich meine eigene serialisierbare Stack-Trace erstellt und sie in eine abgeleitete FaultException-Klasse aufgenommen habe.

2

Es dauerte ewig, bis ich herausgefunden habe, wie man die Nachricht mit den vollständigen Details von einer FaultException als String erhält. Habe ich es schließlich heraus und schrieb diese Erweiterung Methode:

public static string GetDetail(this FaultException faultException) 
{ 
    if (faultException == null) 
     throw new ArgumentNullException(nameof(faultException)); 

    MessageFault messageFault = faultException.CreateMessageFault(); 
    if (messageFault.HasDetail) { 
     using (XmlDictionaryReader reader = messageFault.GetReaderAtDetailContents()) { 
      return reader.ReadContentAsString(); 
     } 
    } 
    return null; 
} 

Ursprünglich ich reader.Value wurde mit aber das schien nur auf die Rückkehr der ersten Zeile eines mehrzeiligen Nachrichtendetails. reader.ReadContentAsString() scheint das Ganze zu bekommen, neue Zeilen enthalten, was ich wollte.

+0

Ich habe bemerkt, das funktioniert gut, wenn Details ein mehrzeiliger String ist, aber nicht so gut, wenn es eine XML-Elementhierarchie ist. –

4

ich die Lösung auf einem UPS Forum gefunden:

https://developerkitcommunity.ups.com/index.php/Special:AWCforum/st/id371

ErrorDetail "„. Das Problem der Visual Studio war ziemlich die ErrorDetail nicht kartieren Objekte rechts Der ErrorDetail Knoten genannt wird", aber Der dafür generierte Typ lautet "ErrorDetailType". Ich habe die Klasse reference.cs für jeden von mir verwendeten Dienst bearbeitet und einen TypeName hinzugefügt: "

+1

Mein Held! :) Um zu verdeutlichen, redet er darüber das XmlTypeAttribute, füge 'TypeName =" ErrorDetail "dort hinzu und es wird funktionieren. – stroborobo

Verwandte Themen