2010-11-11 17 views
10

Ho importato un WSDL e lo uso per inviare una richiesta SOAP. Ecco come si presenta:Rimozione dello spazio dei nomi dalla richiesta SOAP

<?xml version="1.0"?> 
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> 
    <SOAP-ENV:Body> 
     <Calculate xmlns="urn:xx.WSDL.xxxxxWebService"> 
      <ContractdocumentIn> 
       <AL> 
       ...More XML... 

Il problema è la parte xmlns="urn:xx.WSDL.xxxxxWebService" nell'elemento Calcola. Il servizio web non può accettarlo. Il servizio web non piace namespace come questo ...
Utilizzando SoapUI Ho trovato questa richiesta a funzionare bene:

<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://www.w3.org/2003/05/soap-envelope" xmlns:col="http://example.com.service.xxx/"> 
    <SOAP-ENV:Body> 
     <col:Calculate> 
      <ContractdocumentIn> 
       <AL> 
        ...More XML... 

Allora, come faccio a cambiare la richiesta dalla prima alla seconda versione? (Senza usare trucchi sporchi!)
(Re-importazione non è un problema se questo comporterebbe il formato della richiesta corretta.)




ancora: No trucchi sporchi permessi, come l'hacking il flusso di richiesta di modificarlo !


E mentre non ho completamente testato, sembra che C#/VS2010 e Delphi il 2010 sono anche in grado di utilizzare il servizio web che sto cercando di chiamare. Un servizio web che sembra essere scritto in Java. SoapUI sembra essere scritto in Java, quindi abbiamo un client Java che parla con un servizio Java, che sembra funzionare bene. Ma qualsiasi altro cliente?
Ad ogni modo, è ora di aggiungere altri due tag: "Java", poiché è un servizio Java e "vs2010" perché anche a .NET questo servizio non piace.
E stavo per scrivere un wrapper su questo servizio in .NET, sperando che funzionasse ... Non è così. Quindi questo è un difetto molto serio, forse un difetto Java ...

+0

Buona fortuna. Ho dovuto ricorrere a trucchi sporchi. –

+0

Sì, lo so. Posso probabilmente risolverlo usando trucchi sporchi, ma la gestione non è d'accordo. Quindi il codice deve essere pulito. –

+2

Il codice SOAP fornisce agganci per esaminare l'XML che viene inviato e per modificarlo se necessario. Supporta la manipolazione manuale in modo esplicito. E il codice sarebbe lì - niente di "sporco" sulla manipolazione post-build. Potrebbe non essere bello come automatico, ma nessuno dovrebbe preoccuparsene. – mj2008

risposta

14

se un servizio si aspetta:

<col:Calculate> 
    <ContractdocumentIn> 
     <AL> 

e Delphi SOAP sta inviando ...

<Calculate xmlns="urn:xx.WSDL.xxxxxWebService"> 
     <ContractdocumentIn> 
      <AL> 

... il problema è che ContractdocumentIn è un elemento senza riserve e (fino Delphi XE) Delphi SOAP non supportava elementi non qualificati che sono elementi di livello superiore di un'operazione. Gli elementi di livello superiore sono i parametri della funzione e non esiste da nessuna parte il fatto che l'elemento sottostante debba essere non qualificato; per gli elementi che si associano alle proprietà, utilizziamo l'indice della proprietà per archiviare il flag IS_UNQL.

BTW, non è necessario utilizzare un prefisso. Il Servizio sarà (dovrebbe) accetta anche:

<Calculate xmlns="urn:xx.WSDL.xxxxxWebService"> 
     <ContractdocumentIn xmlns=""> 
      <AL> 

Quest'ultimo è più prolisso, ma è equivalente al caso prefisso.

In Delphi XE l'importatore memorizza il fatto che un determinato parametro esegue il mapping su un elemento non qualificato e il runtime agisce su tali informazioni. Ho postato patch basate sull'attuazione XE per D2010 e D2007 nel gruppo di discussione quando si è in un filo di recente:

https://forums.embarcadero.com/thread.jspa?threadID=43057

Se qualcuno ha bisogno di accedere ad essi (erano nella zona allegati, ma potrebbe si è scrollato di dosso), scrivetemi e li renderò disponibili. [Bbabet a Embarcadero dot com]

Cheers,

Bruneau

+1

Bella spiegazione! Grazie. Sto usando D2005 con patch D2007 per le librerie SOAP. Pensi che le tue correzioni alle patch D2007 funzionerebbero per me? –

+4

Sì, dovrebbe. La patch che ho postato è qui: https://forums.embarcadero.com/thread.jspa?messageID=290788 – BruneauB

+0

In caso di problemi, per favore, indicami (o mandami una e-mail) il WSDL e indagherò. Saluti! – BruneauB

8

OMG! Ci sono voluti un sacco di caffè e un sacco di depravazione del sonno, ma sono riuscito a risolvere il mio problema! È anche semplice ragionevole ...
Prima di tutto importare il WSDL, come previsto. Questo genererà diverse classi TRemotable. Quindi, per ogni TRemotable che richiede uno spazio dei nomi diverso, sostituisco il metodo ObjectToSOAP()! (E includere XMLIntf alla sorgente WSDL.) Nel mio caso con il codice come questo per molti dei tipi remotable:

function AL2.ObjectToSOAP(RootNode, ParentNode: IXMLNode; const ObjConverter: IObjConverter; const NodeName, NodeNamespace, ChildNamespace: InvString; ObjConvOpts: TObjectConvertOptions; out RefID: InvString): IXMLNode; 
begin 
    Result := inherited ObjectToSOAP(RootNode, ParentNode, ObjConverter, NodeName, '', '', ObjConvOpts, RefID); 
end; 

che ha lavorato in Delphi XE. In Delphi 2007 ho dovuto usare le unità XMLIntf e XMLDoc oltre a questo codice sul tipo di ingresso:

function ContractdocumentInType.ObjectToSOAP(RootNode, ParentNode: IXMLNode; const ObjConverter: IObjConverter; const Name, URI: InvString; ObjConvOpts: TObjectConvertOptions; out RefID: InvString): IXMLNode; 

    procedure AlterChildren(Child: IXMLNode); 
    var 
    I: Integer; 
    begin 
    if (Child.NodeType = ntElement) then Child.SetAttributeNS('xmlns', '', ''); 
    for I := 0 to Pred(Child.ChildNodes.Count) do 
     AlterChildren(Child.ChildNodes[I]); 
    end; 

begin 
    Result := inherited ObjectToSOAP(RootNode, ParentNode, ObjConverter, Name, '', ObjConvOpts, RefID); 
    AlterChildren(Result); 
end; 

Si tratta di un hack, a mio parere. Ma non è molto sporco. È un po 'di sperimentazione, catturare le richieste e le risposte SOAP per controllare il loro contenuto e vedere se usa gli spazi dei nomi appropriati. Purtroppo, Delphi XE fa un lavoro di gran lunga migliore a questo che Delphi 2007.

Eppure, continuo questo Q aperto per eventuali soluzioni migliori ...


Btw, per aggiungere il col: all'uscita, Ho anche dovuto modificare questa riga nel WSDL RemClassRegistry.RegisterXSClass(Calculate, 'http://colan.ogconnect.service.wzp/', 'Calculate'); a questo: RemClassRegistry.RegisterXSClass(Calculate, 'http://colan.ogconnect.service.wzp/', 'cal:Calculate');. Il risultato diventa quindi <cal:Calculate xmlns:cal="http://example.webservice/">. Tuttavia, è necessario fare altro: spostando il valore xmlns:cal nell'intestazione xml. Ma come è adesso, funziona per me.


Un'altra nota: per il WSDL ho usato le seguenti impostazioni: 'One Outparam è di ritorno', 'Rilassatevi params letterali', 'Genera distruttori', 'commenti di avvertimento', 'emettono tipi letterali', 'Mappa stringa a widestring'. Altre opzioni sono: 'Genera informazioni dettagliate su tipi e interfacce', 'Ignora porttypes con binding HTTP', 'Convalida membri di enumerazione', 'Importa tipi di errore', 'Importa tipi di intestazione', 'Elabora file inclusi e importati', 'Genera alias di classe come tipi di classe "," Parametri Consenti "e" Elabora elementi inutili e nillable ". Il tipo emit letterale era pratico perché genera una classe attorno al singolo metodo che stavo chiamando. Sfortunatamente, questo non sarà di grande aiuto, sebbene la classe ti aiuti a modificare la richiesta SOAP sul livello superiore all'interno della busta sovrascrivendo il metodo ObjectToSOAP().
La creazione della busta stessa si trova nell'unità SOAPEnv e viene utilizzata nell'unità OPToSOAPDomConv. Sfortunatamente, non ho trovato un metodo semplice per accedere alla busta stessa per modificare l'intestazione per aggiungere questo spazio dei nomi aggiuntivo. Poi di nuovo, potrei scavalcare la classe TSOAPDomConv con la mia versione personale che aggiunge lo spazio dei nomi aggiuntivo. Ma ora il codice funziona per me e, come mi ha detto mio padre, quando mi ha imparato a programmare: non aggiustare mai nulla che non sia rotto.

+0

Sembra promettente - ho intenzione di dargli un vortice. Ciò potrebbe far risparmiare un sacco di tempo/dolore a un grande progetto in arrivo, quindi sono felice di contribuire con i punti di merito alla discussione. –

+0

Ti ha davvero dato un output come questo:

+0

Penso che questo possa darmi un bel posto dove collegarmi, ma potrei aver bisogno di fare più lavoro nella funzione AlterChildren. –

Problemi correlati