2009-06-05 7 views
0

In letzter Zeit wir haben Ausnahmen wie dies in unserer .NET (ASMX) einen Web Service zu sehen:Wie kann ich fehlerhafte Soap-Anfragen debuggen?

System.Web.Services.Protocols.SoapException: Server was unable to read request. ---> System.InvalidOperationException: There is an error in XML document (868, -3932). ---> System.Xml.XmlException: '.', hexadecimal value 0x00, is an invalid character. Line 868, position -3932. 
    at System.Xml.XmlTextReaderImpl.Throw(Exception e) 
    at System.Xml.XmlTextReaderImpl.Throw(String res, String[] args) 
    at System.Xml.XmlTextReaderImpl.Throw(Int32 pos, String res, String[] args) 
    at System.Xml.XmlTextReaderImpl.ThrowInvalidChar(Int32 pos, Char invChar) 
    at System.Xml.XmlTextReaderImpl.ParseNumericCharRefInline(Int32 startPos, Boolean expand, BufferBuilder internalSubsetBuilder, Int32& charCount, EntityType& entityType) 
    at System.Xml.XmlTextReaderImpl.ParseText(Int32& startPos, Int32& endPos, Int32& outOrChars) 
    at System.Xml.XmlTextReaderImpl.ParseText() 
    at System.Xml.XmlTextReaderImpl.ParseElementContent() 
    at System.Xml.XmlTextReaderImpl.Read() 
    at System.Xml.XmlTextReader.Read() 
    at System.Web.Services.Protocols.SoapServerProtocol.SoapEnvelopeReader.Read() 
    at System.Xml.XmlReader.ReadElementString() 
    at Microsoft.Xml.Serialization.GeneratedAssembly.XmlSerializationReader1.Read14_SendErrlog() 
    at Microsoft.Xml.Serialization.GeneratedAssembly.ArrayOfObjectSerializer12.Deserialize(XmlSerializationReader reader) 
    at System.Xml.Serialization.XmlSerializer.Deserialize(XmlReader xmlReader, String encodingStyle, XmlDeserializationEvents events) 
    --- End of inner exception stack trace --- 
    at System.Xml.Serialization.XmlSerializer.Deserialize(XmlReader xmlReader, String encodingStyle, XmlDeserializationEvents events) 
    at System.Xml.Serialization.XmlSerializer.Deserialize(XmlReader xmlReader, String encodingStyle) 
    at System.Web.Services.Protocols.SoapServerProtocol.ReadParameters() 
    --- End of inner exception stack trace --- 
    at System.Web.Services.Protocols.SoapServerProtocol.ReadParameters() 
    at System.Web.Services.Protocols.WebServiceHandler.CoreProcessRequest() 

Wie kann ich diese Ausnahme debuggen? Diese Ausnahme wird uns von einem SOAP-Filter gemeldet, der nach Ausnahmen in message.Stage = SoapMessageStage.AfterSerialize sucht.

Gibt es eine Möglichkeit, die ursprüngliche Soap-Anfrage zu bekommen? Wie bekomme ich ein ungültiges Zeichen in Zeile 868, Spalte -3932? Wie kann eine negative Spalte 3932?

Antwort

3

Dies ist eine der ärgerlichsten Dinge über die Microsoft Web Services-Ansatz - wenn die Anfrage nicht in die Objekte in Ihrer Web-Methode Signatur deserialisiert werden kann, erhält der Service-Verbraucher eine kryptische Nachricht. Und um das Ganze abzurunden, gelangt die Anfrage niemals in Ihren Web-Service, weil sie nicht deserialisiert werden kann, so dass Sie den Fehler nicht korrekt behandeln können.

Was ich tun würde, um mit diesen Arten von Problemen zu helfen, ist eine neue SoapExtension zu erstellen, die Sie einfach die Roh-XML an ein Ziel, das für Sie bequem (Datei oder Trace, um von DebugView oder was auch immer Sie sonst gelesen werden soll) ausgeben können mögen). Der Code würde in die Phase BeforeDeserialize gehen. Sie könnten die SoapExtension über web.config aktivieren, falls Sie eines dieser Probleme untersuchen möchten. Der Nachteil der Verwendung von web.config zum Hinzufügen der SoapExtension ist, dass sie für die gesamte Webanwendung aktiv ist. Sie könnten einige zusätzliche benutzerdefinierte Konfigurationen hinzufügen, die es Ihrem Dienst ermöglichen, nur Informationen für einen bestimmten Endpunkt oder eine bestimmte Webmethode zu protokollieren, wenn Sie dies wünschen.

In der Regel können Sie durch das eingehende XML sehen, was das Problem ist. Wenn nicht, könnten Sie versuchen, die erfasste XML-Datei manuell durch ein kleines Programm auszuführen, das den XML-Serializer aufruft, um zu sehen, ob Sie herausfinden können, was vor sich geht. Ein weiteres nützliches Tool ist Web Service Studio 2, das eine Testumgebung ist, in der Sie Daten eingeben und Ihren Dienst aufrufen können (und auch XML-Dateien senden können, die Sie möchten).

In Bezug auf Ihr spezifisches Problem, hier ist mein Take/rate. Es sieht so aus, als würde das ASCII-Zeichen null verschlüsselt und an Ihren Dienst gesendet, was gemäß der XML-Spezifikation ungültig ist. Die einfache Antwort ist nicht, dieses Zeichen zu senden. Aber wer sendet diesen Charakter? Ist es ein .NET-Client? Haben Sie die Kontrolle über den Kunden?Wenn Sie den Fehler eines anderen umgehen müssen, müssen Sie möglicherweise die fehlerhaften Zeichen durch ein anderes Zeichen (möglicherweise eine leere Zeichenfolge) ersetzen.

+0

Unsere App ist der Client und es ist nur einige XML-Literal Escape-Text (& (<, > und dergleichen). Es sollte niemals Nullen geben. Diese Ausnahme tritt sogar bei einer Soap-Anfrage ohne Parameter auf. Der Client benutzt eine "Web Reference", um auf den Server zuzugreifen, also machen wir nicht einmal Crafting die SOAP von Hand. Ich denke, du hast Recht, dass ich nur alle SOAP-Anfragen erfassen muss. Unser NOC wird mich lieben, wenn ich den Log-Ordner befülle ;-) –

2

Sie sollten in der Lage sein, die ursprüngliche Nachricht zu erhalten, indem Sie eine andere SoapExtension verwenden. In der Tat könnte die gleiche Erweiterung wahrscheinlich modifiziert werden, um eine Kopie der Eingabe zu erstellen und sie zu verwerfen, wenn es keine Ausnahme gibt. Die ursprüngliche Eingabe wäre dann für Sie verfügbar, wenn eine Ausnahme aufgetreten ist.

Sie können auch ein externes Tool wie Fiddler verwenden, um zu sehen, was an Sie gesendet wird.

+0

Also im Grunde kopieren Sie es in message.Stage = SoapMessageStage.BeforeDeserialize? Kann ich garantieren, dass die erste AfterDeserialize für Nachricht A unmittelbar nach A's BeforeDeserialize kommt? –

+0

Ich möchte auch die Antwort auf Bob Kings Frage wissen; Das war der Ansatz, den ich mir alleine ausgedacht hatte, und schrieb die SoapExtension, und mir wurde klar, dass ich keine Möglichkeit fand, es threadsicher zu machen. :( – Grank

+0

Entschuldigung, ich habe nicht geantwortet. Die Antwort ist: Wenn die Dokumentation keine Garantie gibt, gibt es keine Garantie. –

0

FYI: SoapException.Message ist absichtlich vage, um zu verhindern, zu viele Informationen verfügbar zu machen, die möglicherweise verwendet werden könnten, um das System auszunutzen.

Für Ihren speziellen Fall würde ich Johns Rat nehmen und Fiddler installieren, um den tatsächlichen HTTP-Verkehr zu überwachen und die Nachricht auf dem Draht zu sehen.

Der Teil Ihrer Ausnahme, der bei mir herausspringt, ist der "hexadezimale Wert 0x00, ist ein ungültiges Zeichen", aber wie Sie erwähnten, ist die Zeilennummer, auf die er zeigt, Koje - also nichts Konkretes.

Welche Parameter geben Sie an den Service weiter? Machst du irgendeine benutzerdefinierte Kodierung mit einer SOAP-Erweiterung? Werden zusätzliche SOAP-Header hinzugefügt?