2010-02-19 13 views
8

Sto tentando di accedere a un servizio SOAP che non controllo. Una delle azioni è denominata ProcessMessage. Ho seguito l'esempio e generato una richiesta SOAP, ma ho ricevuto un errore che diceva che l'azione non esiste. Ho tracciato il problema sul modo in cui viene generato il corpo dell'involucro.Perché lo spazio dei nomi "wsdl" è interposto nel nome dell'azione quando si utilizza savon per la comunicazione ruby ​​soap?

<env:Envelope ... "> 
    <env:Header> 
     <wsse:Security ... "> 
      <wsse:UsernameToken ..."> 
       <wsse:Username>USER</wsse:Username> 
        <wsse:Nonce>658e702d5feff1777a6c741847239eb5d6d86e48</wsse:Nonce> 
        <wsu:Created>2010-02-18T02:05:25Z</wsu:Created> 
        <wsse:Password ... >password</wsse:Password> 
      </wsse:UsernameToken> 
     </wsse:Security> 
    </env:Header> 
    <env:Body> 
     <wsdl:ProcessMessage> 
      <payload> 
       ...... 
      </payload> 
     </wsdl:ProcessMessage> 
    </env:Body> 
</env:Envelope>  

Che ProcessMessage tag deve essere:

<ProcessMessage xmlns="http://www.starstandards.org/webservices/2005/10/transport"> 

Questo è ciò che è quando si è generato dalla applicazione del campione di Java, e funziona. Quel tag è l'unica differenza tra ciò che genera la mia app Ruby e l'app Java di esempio. C'è un modo per sbarazzarsi dello spazio dei nomi "wsdl:" davanti a quel tag e aggiungere un attributo del genere. Escludendo, c'è un modo per forzare l'azione a non essere generata appena passata come una stringa come il resto del corpo?

Ecco il mio codice:

require 'rubygems' 
require 'savon' 
client = Savon::Client.new "https://gmservices.pp.gm.com/ProcessMessage?wsdl" 

response = client.process_message! do | soap, wsse | 
wsse.username = "USER" 
wsse.password = "password" 
soap.namespace = "http://www.starstandards.org/webservices/2005/10/transport" #makes no difference 
soap.action = "ProcessMessage" #makes no difference 
soap.input = "ProcessMessage" #makes no difference 

#my body at this point is jsut one big xml string 

soap.body = "<payload>...</payload>" 
# putting <ProccessMessage> tag here doesn't help as it just creates a duplicate tag in the body, since Savon keeps interjecting <wsdl:ProcessMessage> tag. 

    end 

ho provato handsoap ma non supporta HTTPS ed è fonte di confusione. Ho provato soap4r ma è ancora più complicato del handsoap.

+0

un biglietto per questo è stato aperto: http://github.com/rubiii/savon/issues#issue/39 – rubiii

+0

Ciao Nick, sei arrivato da nessuna parte con questo come sto vedendo lo stesso problema. –

+0

Ciao Steve. Ho messo questa parte del progetto in attesa - poiché c'erano altre, più importanti, funzionalità che necessitavano di implementazione, e questo era su una lista "carina da avere". Proverò la tua soluzione più tardi oggi e vedrò se funziona. Grazie per avermi fatto sapere! – konung

risposta

4

Steve, vedi che wsdl: davanti al tag ProcessMessage? - Pensavo che fosse l'unica cosa che mi stava buttando fuori ma non è (dal modo in cui è impostato su soap.rb in Savon lib sulla linea 160). Anche se non lo distinguo in soap.namespaces, è generato e collegato in modo definitivo nell'XML finale. Quale non è permesso dal mio servizio.

Mentre l'xml generato è un xml valido, non è completo dai requisiti del servizio con cui sto cercando di parlare. Vale a dire: in XML generato,

<?xml version="1.0" encoding="UTF-8"?> 

tag non è presente, anche, ho bisogno PayloadManifest nell'intestazione, più ho bisogno di WSU: creato e WSU: scade nel mio wsse: tag, ma essi non sono implementate, etc. , ecc. un mucchio di altre piccole stranezze che sono troppo specifiche per il mio caso. Tuttavia soap ha un metodo privato = xml_body. Anche soap lib nel metodo to_xml sta verificando se @xml_body fosse già impostato, prima di generare il proprio xml. Così ho finito per modificare leggermente il comportamento del sapone. rendendo soap.xml_body = accessibile al pubblico. Così sono stato in grado di fare:

response = client.process_message! do |soap| 
soap.action = "http://www.starstandards.org/webservices/2005/10/transport/operations/ProcessMessage" 
soap.xml_body = "MY XML STRING GENERATED ELSEWHERE GOES HERE" 
end 

Che funziona finalmente !!!!

Suggerirò questo a rubii - se questa opzione diventa disponibile che risolverà molti casi rari - dove le persone possono generare il loro xml personalizzato e usare il resto della lib di savon.

+0

Questa sarebbe una buona soluzione, penso. Ho scoperto che IIS/.net si lamentava della mancanza di uno spazio dei nomi, ma non gli importava se esistesse una direttiva nella parte superiore del file. Buona fortuna, è stato piuttosto doloroso arrivare a quel punto. –

10

È necessario passare una matrice a soap.input il cui secondo elemento è un hash contenente i dettagli dello spazio dei nomi.

soap.input = [ 
    "ProcessMessage", 
    {"xmlns" => "http://www.starstandards.org/webservices/2005/10/transport"} 
] 

Questo dovrebbe garantire di finire con la dichiarazione dello spazio dei nomi come attributo all'elemento principale.

Si avrà probabilmente anche finire con una dichiarazione dello spazio dei nomi prima che l'elemento in questo modo

<env:Body> 
    <wsdl:ProcessMessage xmlns="........." > 
     <payload> 
      ...... 
     </payload> 
    </wsdl:ProcessMessage> 
</env:Body> 

ma questo non era un problema per me, è stata la mancanza di un attributo dello spazio dei nomi che è stato il problema, non il presenza dello spazio dei nomi prima dell'elemento.

+0

Steve. Grazie per il tuo messaggio, non è la mia soluzione, ma mi ha fatto riflettere e osservare i registri in modo più attento. Vedi la mia risposta. Non c'è abbastanza spazio qui nei commenti. :-) – konung

+0

Grazie alla tua soluzione ha funzionato un fascino proprio ora quando stavo avendo lo stesso identico problema. –

+0

La tua soluzione ha funzionato per me. Mi mancavano gli xmlns all'interno dell'azione! Ricevo ancora il wsdl: namespace nel corpo, ma non influenza la richiesta SOAP. – pedrofalcaocosta

7

Per il mio servizio web, dovevo liberarmi dello spazio dei nomi "wsdl" in aggiunta alla soluzione di Steve.

Testato con Savon 0.9.6:

client = Savon::Client.new "https://example.com/webservice/account.asmx?WSDL" 
response = client.request "GetAccount" do 
    # Gotcha 1: set default namespace for body elements 
    soap.input = ["GetAccount", {"xmlns" => "https://example.com/webservice/"}] 
    soap.body = { 
    "AccountID" => 1234 
    } 
    # Gotcha 2: get rid of namespace declaration of body elements 
    soap.element_form_default = :unqualified 
    # Gotcha 3: set SOAPAction different from default 
    http.headers["SOAPAction"] = '"https://example.com/webservice/GetAccount"' 
end 
+2

+1 per gotcha # 2 .. – abhijit

+0

risposta brillante. –

+0

Gotcha 2 mi stava uccidendo, grazie Kenji! – zrl3dx

Problemi correlati