2010-12-20 2 views
1

Mon C# client de service Web envoie le message suivant de savon au service Web Java:Invoquer une méthode SOAP avec des préfixes d'espace de noms

<?xml version="1.0" encoding="utf-8"?> 
<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope" 
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
       xmlns:xsd="http://www.w3.org/2001/XMLSchema"> 
<soap:Body> 
<getData> 
<request> 
<requestParameters xmlns="http://b..."> 
<equals> 
... 
</equals> 
</requestParameters> 
</request> 
</getData> 
</soap:Body> 
</soap:Envelope> 

et service Web Java renvoie l'erreur:

500 Internal Server Error 
... 
Cannot find dispatch method for {}getData 
... 

client écrit en Java, qui fonctionne, envoie le message suivant:

<?xml version="1.0" encoding="utf-8"?> 
<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope" 
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
       xmlns:xsd="http://www.w3.org/2001/XMLSchema"> 
<soap:Body> 
<ns2:getData xmlns:ns2="http://a..."> 
<ns2:request> 
<ns3:requestParameters xmlns:ns3="http://b..."> 
<ns3:equals> 
... 
</ns3:equals> 
</ns3:requestParameters> 
</ns2:request> 
</ns2:getData> 
</soap:Body> 
</soap:Envelope> 

Y at-il un moyen facile en C# d'envoyer SOAP m essages de la même manière que le client Java envoie: avec des préfixes d'espace de noms?

Ce qui suit est le code C# qui envoie un message:

// class MyService is auto-generated using wsdl.exe tool 
MyService service = new MyService(); 

RequestMessage request = new RequestMessage(); 
... 

ResponseMessage response = service.getData(request); 
... 

MISE À JOUR:

Voici la classe RequestMessage:

/// <remarks/> 
[System.CodeDom.Compiler.GeneratedCodeAttribute("svcutil", "3.0.4506.2152")] 
[System.SerializableAttribute()] 
[System.Diagnostics.DebuggerStepThroughAttribute()] 
[System.ComponentModel.DesignerCategoryAttribute("code")] 
[System.Xml.Serialization.XmlTypeAttribute(Namespace="http://uri.etsi.org/02657/v1.5.1#/RetainedData")] 
public partial class RequestMessage 
{ 

    private byte[] requestPriorityField; 

    private RequestConstraints requestParametersField; 

    private string deliveryPointHIBField; 

    private string maxHitsField; 

    private NationalRequestParameters nationalRequestParametersField; 

    private System.Xml.XmlElement anyField; 

    /// <remarks/> 
    [System.Xml.Serialization.XmlElementAttribute(DataType="hexBinary", Order=0)] 
    public byte[] requestPriority 
    { 
     get 
     { 
      return this.requestPriorityField; 
     } 
     set 
     { 
      this.requestPriorityField = value; 
     } 
    } 

    /// <remarks/> 
    [System.Xml.Serialization.XmlElementAttribute(Order=1)] 
    public RequestConstraints requestParameters 
    { 
     get 
     { 
      return this.requestParametersField; 
     } 
     set 
     { 
      this.requestParametersField = value; 
     } 
    } 

    /// <remarks/> 
    [System.Xml.Serialization.XmlElementAttribute(Order=2)] 
    public string deliveryPointHIB 
    { 
     get 
     { 
      return this.deliveryPointHIBField; 
     } 
     set 
     { 
      this.deliveryPointHIBField = value; 
     } 
    } 

    /// <remarks/> 
    [System.Xml.Serialization.XmlElementAttribute(DataType="integer", Order=3)] 
    public string maxHits 
    { 
     get 
     { 
      return this.maxHitsField; 
     } 
     set 
     { 
      this.maxHitsField = value; 
     } 
    } 

    /// <remarks/> 
    [System.Xml.Serialization.XmlElementAttribute(Order=4)] 
    public NationalRequestParameters nationalRequestParameters 
    { 
     get 
     { 
      return this.nationalRequestParametersField; 
     } 
     set 
     { 
      this.nationalRequestParametersField = value; 
     } 
    } 

    /// <remarks/> 
    [System.Xml.Serialization.XmlAnyElementAttribute(Order=5)] 
    public System.Xml.XmlElement Any 
    { 
     get 
     { 
      return this.anyField; 
     } 
     set 
     { 
      this.anyField = value; 
     } 
    } 
} 

MISE À JOUR # 2:

La raison pour laquelle Java- service Web basé n'a pas aimé mon client C# produit message SOAP n'est pas une omission de namespac préfixes e, mais seulement en raison de l'omission de xmlns dans l'élément getData, donc si mon message ressemble à ceci:

... 
<getData xmlns="http://a..."> 
... 
</getData> 
... 

ça marche!

J'ai réussi à mettre xmlns dans getData en éditant manuellement SoapRpcMethodAttribute dans le code source produit par wsdl.exe. Voici un extrait:

/// <remarks/> 
[System.CodeDom.Compiler.GeneratedCodeAttribute("wsdl", "2.0.50727.3038")] 
[System.Diagnostics.DebuggerStepThroughAttribute()] 
[System.ComponentModel.DesignerCategoryAttribute("code")] 
[System.Web.Services.WebServiceBindingAttribute(
    Name="AxxxPortTypeBinding", Namespace="http://a...")] 
public partial class AxxxService 
    : System.Web.Services.Protocols.SoapHttpClientProtocol { 

    ... 

    /// <remarks/> 
    [System.Web.Services.Protocols.SoapRpcMethodAttribute(
     "http://a.../getData", 
     RequestNamespace = "http://a...", 
     ResponseNamespace = "http://a...", 
     Use = System.Web.Services.Description.SoapBindingUse.Literal)] 
    [return: System.Xml.Serialization.XmlElementAttribute("response")] 
    public ResponseMessage getData(RequestMessage request) { 
     object[] results = this.Invoke("getData", new object[] { 
        request}); 
     return ((ResponseMessage)(results[0])); 
    } 

    ... 
} 

Avant mon changement, SoapRpcMethodAttribute avait suivant constructeur:

[System.Web.Services.Protocols.SoapRpcMethodAttribute(
    "", RequestNamespace = "", ResponseNamespace = "", 
    Use = System.Web.Services.Description.SoapBindingUse.Literal)] 

Maintenant, la question est: ce qu'il faut mettre dans le fichier WSDL afin que SoapRpcMethodAttribute ont ces chaînes dans le constructeur (rempli par l'outil wsdl.exe) en premier lieu?

+0

Avez-vous généré votre proxy de service avec wsdl.exe? –

+0

Oui (voir le commentaire dans le code au bas de la question). – mvladic

Répondre

1

J'ai déjà vu ce problème avant que l'outil WSDL.exe ne tire pas correctement dans l'espace de noms lors de la génération du code de service. Vérifiez la définition d'objet request dans votre code généré. Ma conjecture est qu'il n'y a aucun attribut XmlRootAttribute défini sur la définition de classe pour l'objet request. L'ajout de l'attribut [XmlRootAttribute(Namespace "http://a...")] à la définition de classe pour l'objet request doit résoudre ce problème.

En note, je recommande d'ajouter cet attribut supplémentaire dans un fichier de code séparé en utilisant une définition de classe partielle. La définition de l'attribut dans un fichier séparé vous permettra de régénérer le code de service Web en utilisant WSDL.exe chaque fois que nécessaire sans écraser le correctif pour définir correctement l'espace de noms de l'élément racine.

+0

Oui, vous avez raison, il n'y a pas XmlRootAttribute dans la définition de la classe RequestMessage (ou dans toute autre classe dans le même fichier généré automatiquement). – mvladic

+0

J'ai ajouté XmlRootAttribute à la définition de classe et cela n'aide pas. – mvladic

+0

@mvladic L'exemple que vous avez posté ci-dessus montre que vous avez ajouté l'attribut 'XmlTypeAttribute', pas l'attribut' XmlRootAttribute'. Compte tenu de votre exemple de requête SOAP, la classe RequestMessage doit être identifiée comme l'élément racine du message XML envoyé. Je remarque également dans votre exemple que le service renvoie un respone (probable dans la classe ResponseMessage?). Vous devrez également décorer cette classe de réponse avec l'attribut 'XmlRootAttribute' pour vous assurer que la réponse est renvoyée en utilisant l'espace de noms correct. – pmartin

0

La classe proxy générée doit contenir l'espace de nom correct. Je recommande deux choses:

1) Exécutez WSDL.EXE à partir de la ligne de commande et notez s'il existe des erreurs ou des avertissements. Si oui, veuillez modifier votre question pour les inclure.2) Sauf si vous êtes bloqué avec .NET 2.0, vous devriez essayer de créer vos classes proxy en utilisant soit "Add Service Reference", soit l'équivalent "SVCUTIL.EXE" qui utilisera l'infrastructure WCF moderne du côté client , qui est beaucoup plus susceptible d'avoir été corrigé pour résoudre ce problème.

+0

"Ajouter une référence de service" fonctionne uniquement avec asmx, et j'ai seulement un fichier wsdl et un fichier xsd. – mvladic

+0

J'ai créé un client avec "svcutil my.wsdl my.xsd/language: C#" et cela ne fonctionne toujours pas - il n'y a pas de préfixe d'espace de noms. – mvladic

+0

J'ai ajouté la définition de la classe RequestMessage dans ma question. – mvladic

0

J'ai eu le même problème et a résolu le problème en changeant la valeur de la propriété Utilisation dans System.Web.Services.Protocols.SoapDocumentMethodAttribute attribut corrisponding à chaque méthode de service Web. System.Web.Services.Description.SoapBindingUse. Literal La valeur par défaut a été remplacée par System.Web.Services.Description.SoapBindingUse. Encodé.

Questions connexes