2010-10-01 9 views
12

Mein Team ist mit der Aufgabe mehrere intern entwickelte .NET-Client-Anwendungen zu erhalten, um eine Verbindung zu einigen neuen Java-Web-Services herzustellen. Der Java-Webdienst ist eine von Drittanbietern gelieferte WSDL-Datei, die unser Team nur eingeschränkt modifizieren/steuern kann. Das bedeutet, dass wir wahrscheinlich unseren Lieferanten bitten können, geringfügige Änderungen an der WSDL vorzunehmen entweder unausführbar oder schwer zu beantragen.WCF Serialisierung Probleme mit WSDL-Datei von Java-Tools erstellt

Das heißt, wir WCF/.NET 4.0 verwenden versuchen, die .NET-Proxy-Klasse Dateien, die wir auf der Clientseite müssen zu erzeugen. Der Proxy-Client-Klassendatei-Generierungsprozess wird ohne Probleme ausgeführt.

Das Problem ist, wenn wir die Proxy-Klasse-Datei in einer Client-Anwendung zu verwenden versuchen. Ich habe über das Web-Trace-Tool Fiddler verifiziert, dass die rohe SOAP-Nachrichtenanforderung nicht über die Verbindung zum Server gesendet werden kann.

Die spezifische .NET Ausnahmemeldung erhalte ich beim Versuch, die Web-Service-Methode in Frage zu stellen, sieht wie folgt aus:

System.InvalidOperationException wurde nicht behandelt Message = XmlSerializer Attribut System.Xml.Serialization.XmlAttributeAttribute ist nicht gültig in baseLanguage. Nur die Attribute XmlElement, XmlArray, XmlArrayItem, XmlAnyAttribute und XmlAnyElement werden unterstützt, wenn IsWrapped true ist. Source = System.ServiceModel

Wenn ich die .NET automatisch generierte Proxy-Klasse-Datei untersuchen, Reference.cs, bemerkte ich, dass die Anfrage- und Antwortnachrichten für meine Web-Service-Methode etwa wie folgt aussieht:

[System.Diagnostics.DebuggerStepThroughAttribute()] 
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "4.0.0.0")] 
[System.ServiceModel.MessageContractAttribute(WrapperName="QueryPBOT_MXWO_OS", WrapperNamespace="http://www.ibm.com/maximo", IsWrapped=true)] 
public partial class QueryPBOT_MXWO_OSRequest { 

    [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://www.ibm.com/maximo", Order=0)] 
    public ConsoleApplication7.wsMaximo.PBOT_MXWO_OSQueryType PBOT_MXWO_OSQuery; 

    [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://www.ibm.com/maximo", Order=1)] 
    [System.Xml.Serialization.XmlAttributeAttribute()] 
    public string baseLanguage; 

    [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://www.ibm.com/maximo", Order=2)] 
    [System.Xml.Serialization.XmlAttributeAttribute()] 
    public string transLanguage; 

    [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://www.ibm.com/maximo", Order=3)] 
    [System.Xml.Serialization.XmlAttributeAttribute()] 
    public string messageID; 

    [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://www.ibm.com/maximo", Order=4)] 
    [System.Xml.Serialization.XmlAttributeAttribute()] 
    public string maximoVersion; 

    [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://www.ibm.com/maximo", Order=5)] 
    [System.Xml.Serialization.XmlAttributeAttribute()] 
    [System.ComponentModel.DefaultValueAttribute(false)] 
    public bool uniqueResult; 

    [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://www.ibm.com/maximo", Order=6)] 
    [System.Xml.Serialization.XmlAttributeAttribute(DataType="positiveInteger")] 
    public string maxItems; 

    [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://www.ibm.com/maximo", Order=7)] 
    [System.Xml.Serialization.XmlAttributeAttribute(DataType="integer")] 
    [System.ComponentModel.DefaultValueAttribute("0")] 
    public string rsStart; 

    public QueryPBOT_MXWO_OSRequest() { 
    } 

    public QueryPBOT_MXWO_OSRequest(ConsoleApplication7.wsMaximo.PBOT_MXWO_OSQueryType PBOT_MXWO_OSQuery, string baseLanguage, string transLanguage, string messageID, string maximoVersion, bool uniqueResult, string maxItems, string rsStart) { 
     this.PBOT_MXWO_OSQuery = PBOT_MXWO_OSQuery; 
     this.baseLanguage = baseLanguage; 
     this.transLanguage = transLanguage; 
     this.messageID = messageID; 
     this.maximoVersion = maximoVersion; 
     this.uniqueResult = uniqueResult; 
     this.maxItems = maxItems; 
     this.rsStart = rsStart; 
    } 
} 

Ich weiß, dass Leute, die diesen Beitrag lesen, die tatsächliche WSDL-Datei sehen wollen, die wir konsumieren wollen, aber sie ist ziemlich groß, und ich bin besorgt, dass die bloße Größe es schwierig machen würde, den Fehler genau zu lokalisieren.

Ich hoffe, dass die automatisch generierte Client-Proxy-Datei und die .NET Ausnahme jemand dieses WCF-Serialisierung Problem erkennen helfen.

Wir von unserem Java-Anbieter bestätigt haben, dass der Stil der WSDL erzeugen sie doc-Literal ist. Nach einigen Recherchen im Internet erscheint WCF standardmäßig. übersetzt WSDL-Dateien mit doc-literal Wrapped und das erklärt, zumindest teilweise, warum wir dieses WCF-Serialisierungsproblem mit der WSDL-Datei sehen.

Ich habe entdeckt, durch Versuch und Irrtum, dass das folgende Attribut Dekorateur in der Proxy-Klasse-Datei ist der Täter hinter der Serialisierung Ausgabe:

[System.Xml.Serialization.XmlAttributeAttribute()]

Wenn ich alle Instanzen dieses Attributs in der Proxy-Klasse-Datei kommentieren und meine Client-Anwendung erneut ausführen, wird die SOAP-Nachricht erfolgreich über den Draht geschickt, und ich bekomme eine gültige Web-Service-Antwort vom Server zurückkommen.

Dieses Update ist besser als nichts, aber ich würde sehr viel lieber eine Lösung, die nicht selbst oder jemand in meinem Team erfordert, ständig diese .NET automatisch generierte Proxy-Klasse-Dateien zu optimieren.

Ich würde gerne wissen, ob es etwas gibt, was ich tun kann, entweder durch die verschiedenen WCF-Tools oder durch Änderung der WSDL-Datei, die verhindert, dass [System.Xml.Serialization.XmlAttributeAttribute()] auf meine Anfrage angewendet wird und Antwortobjekteigenschaften?

Oder zumindest eine High-Level-Beschreibung von WARUM sehen wir dieses Serialisierungsverhalten in .NET mit der Java-WSDL-Datei?

Vielen Dank im Voraus, John

+0

Wird das XmlAttributeAttribute von Ihnen hinzugefügt oder von WCF generiert? –

+0

Das XMLAttributeAttribute wird von den WCF-Tools generiert, und ich verstehe nicht warum. Wenn es im Tool eine Art Schalter gibt, um zu verhindern, dass es erstellt wird, oder etwas, das wir in der Quell-WSDL-Datei ändern können, können wir vermeiden, die Proxy-Klassendatei zu optimieren, um sie zum Laufen zu bringen. –

+0

Haben Sie eine Beispiel-Soap-Anfrage von Ihrem Java-Anbieter? –

Antwort

3

Basierend auf generierten Code es wie Ihr Java-Service sieht erwartet verlangen wie:

<s:Envelope xmlns:s="..."> 
    ... 
    <s:Body> 
    <QueryPBOT_MXWO_OS xmlns="http://www.ibm.com/maximo" baseLanguage="..." transLanguage="..." ...> 
     <PBOT_MXWO_OSQuery> 
     ... 
     </PBOT_MXWO_OSQuery> 
    </QueryPBOT_MXWO_OS> 
    </s:Body> 
</s:Envelope> 

Das Problem ist, dass WCF für die Anforderung QueryPBOT_MXWO_OS als Hüllenelement erfasst. Ich bin mir nicht sicher, warum es eine Ausnahme auslöst, aber wahrscheinlich gibt es eine Einschränkung, dass das Wrapper-Element keine Attribute haben kann. Ich bin verdächtig, dass dies nur die globale Fehlerbehandlung ist, die mit der Version geteilt wird, die IsWrapped = false verwendet, wo die Verwendung von Attributen ein Fehler ist.

Sie können versuchen, Ihre Proxy auf diese Weise zu ändern:

[System.Diagnostics.DebuggerStepThroughAttribute()]   
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "4.0.0.0")]   
[System.ServiceModel.MessageContractAttribute(IsWrapped=false)]   
public partial class QueryPBOT_MXWO_OSRequest 
{ 
    [MessageBodyMemberAttribute(Name="QueryPBOT_MXWO_OS", Namespace="http://www.ibm.com/maximo")] 
    public QueryPBOT_MXWO_OS QueryPBOT_MXWO_OS { get; set; } 
} 

[XmlRoot(ElementName="QueryPBOT_MXWO_OS", Namespace="http://www.ibm.com/maximo")] 
public class QueryPBOT_MXWO_OS 
{ 
    [XmlElement(Namespace="http://www.ibm.com/maximo")]  
    public ConsoleApplication7.wsMaximo.PBOT_MXWO_OSQueryType PBOT_MXWO_OSQuery;   

    [XmlAttribute(Namespace="http://www.ibm.com/maximo")]   
    public string baseLanguage;   

    [XmlAttribute(Namespace="http://www.ibm.com/maximo")]   
    public string transLanguage;   

    [XmlAttribute(Namespace="http://www.ibm.com/maximo")]  
    public string messageID;   

    [XmlAttribute(Namespace="http://www.ibm.com/maximo")]  
    public string maximoVersion;   

    [XmlAttribute(Namespace="http://www.ibm.com/maximo")]  
    [System.ComponentModel.DefaultValueAttribute(false)]   
    public bool uniqueResult;   

    [XmlAttribute(Namespace="http://www.ibm.com/maximo")]  
    public string maxItems;   

    [XmlAttribute(Namespace="http://www.ibm.com/maximo")]   
    [System.ComponentModel.DefaultValueAttribute("0")]   
    public string rsStart; 
}  
+0

Laislav, danke für deinen Kommentar, aber was ich wirklich suche, ist eine Lösung, bei der ich die Proxy-Klassendatei überhaupt nicht anfassen muss, damit der Web-Service funktioniert. Wenn ich alle Instanzen von [XmlAttribute()] aus der Proxy-Klassendatei auskommentiert, funktioniert der Webdienst. –

+1

Aber in diesem Fall werden alle diese Parameter als Elemente transportiert. Brauchen Sie diese Parameter? Wenn Sie sie nicht einfach aus WSDL entfernen und den Proxy neu generieren. –

9

Verwenden svcutil.exe Dienstprogramm mit der /gewickelt Option auf Proxy-Klassen zu erzeugen.

Dies wird etwas andere Klassen als die erstellen, die durch Visual Studio in einer Weise erstellt wurden, die Ladislav Mrnka hier beschreibt. Die resultierenden Proxies sollten bei der Verwendung auf der Clientseite frei von dem XmlAttribute-Problem sein.

Beispiel:

svcutil /t:code wsdl.xml /out:wsdl.cs /serializer:XmlSerializer /wrapped 
2

Hier ist, wie Mikhail G-Lösung innerhalb von IDE zu tun:

  • öffnen Reference.svcmap unter Service Referenzen
  • hinzufügen <Wrapped>true</Wrapped> unter <ClientOptions> und Speichern
  • Recht Klicken Sie auf Reference.svcmap und klicken Sie auf "Run Custom Tool"

Visual Studio, in der Magie :)

Hinweis passiert: Versuchte mit VS 2015. Frühere Versionen dieselbe Option mit einem anderen Namen haben als "Run Custom Tool"

+1

Super, das hat mein Problem gelöst! –

1

Als Folge der Antwort von stratovarius, in VS 2017 wird der Ordner "Service-Referenzen" durch "Connected Services" ersetzt:

  • Öffnen Sie den Ordner "{project}/Connected Services" in Wi ndows Explorer
  • Suche und bearbeiten Sie die Reference.svcmap mit einem Texteditor
  • hinzufügen <Wrapped>true</Wrapped> zum <ClientOptions> Abschnitt
  • Speichern Sie die Datei
  • In VS, direkt unter Connected Services auf der Dienstverweis klicken und wählen Sie „Update Servicereferenz "
  • Dies löste die Ausnahme von meinem Serviceanruf.

    Verwandte Themen