2010-11-11 28 views
10

He importado un WSDL y lo uso para enviar una solicitud SOAP. Se ve así:Eliminar el espacio de nombres de la solicitud 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... 

El problema es la parte xmlns="urn:xx.WSDL.xxxxxWebService" en el elemento Calcular. El servicio web no puede aceptar esto. El servicio web no le gustan los espacios de nombres como este ...
Usando SoapUI me encontré con esta solicitud a funcionar muy bien:

<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... 

Así que, ¿cómo cambio la solicitud de la primera a la segunda versión? (Sin usar trucos sucios!)
(volver a importar no es un problema si esto resultaría en el formato de solicitud adecuada.)




Una vez más: no hay trucos sucios permitidos, como la piratería de la corriente de petición de modificarlo !


Y aunque no he probado completamente, parece que C#/VS2010 y Delphi 2010 también son incapaces de utilizar el servicio web que estoy tratando de llamar. Un servicio web que parece estar escrito en Java. SoapUI está escrito en Java, por lo que tenemos un cliente Java que habla con un servicio Java, que parece funcionar bien. ¿Pero algún otro cliente?
De todos modos, es hora de agregar dos etiquetas más: "Java", ya que es un servicio de Java, y "vs2010" porque .NET tampoco le gusta este servicio.
Y estaba a punto de escribir un borrador sobre este servicio en .NET, con la esperanza de que funcione ... No es así. Entonces este es un error muy serio, posiblemente un defecto de Java ...

+0

Buena suerte. Tuve que recurrir a trucos sucios. –

+0

Sí, lo sé. Probablemente pueda resolverlo usando trucos sucios, pero la gerencia no está de acuerdo con eso. Entonces el código necesita estar limpio. –

+2

El código SOAP proporciona ganchos para que pueda examinar el XML que se está enviando y modificarlo si es necesario. Es compatible con la manipulación manual de forma explícita. Y el código estaría allí, nada "sucio" sobre la manipulación posterior a la compilación. Puede que no sea tan bueno como automático, pero nadie debería preocuparse por eso. – mj2008

Respuesta

14

Si un servicio de espera:

<col:Calculate> 
    <ContractdocumentIn> 
     <AL> 

y Delphi SOAP se envía ...

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

... el problema es que ContractdocumentIn es un elemento no calificado y (hasta Delphi XE) Delphi SOAP no admite elementos no calificados que sean elementos de nivel superior de una operación. Los elementos de nivel superior son parámetros de la función y no hay lugar para almacenar el hecho de que el elemento subyacente debe estar sin calificar; para los elementos que se asignan a las propiedades, usamos el índice de la propiedad para almacenar el indicador IS_UNQL.

Por cierto, no es necesario usar un prefijo. El Servicio (debería) también aceptan:

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

Este último es más prolija pero es equivalente al caso prefijo.

En Delphi XE, el importador almacena el hecho de que un parámetro particular se asigna a un elemento no calificado y el tiempo de ejecución actúa sobre esta información. He publicado parches basados ​​en la aplicación XE para D2010 y D2007 en el grupo de noticias cuando se acercó en un hilo reciente:

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

Si alguien tiene acceso a ellos (que estaban en el área de archivos adjuntos, pero podría se han desplazado), por favor envíeme un correo electrónico y los pondré a disposición. [Bbabet en COM de punto embarcadero]

Saludos,

Bruneau

+1

¡Buena explicación! Gracias. Estoy usando D2005 con parches D2007 para las bibliotecas SOAP. ¿Crees que tus correcciones a los parches D2007 funcionarían para mí? –

+4

Sí, debería. El parche que publiqué está aquí: https://forums.embarcadero.com/thread.jspa?messageID=290788 – BruneauB

+0

Si surge algún problema, por favor, indíqueme (o envíeme un correo electrónico) el WSDL y lo investigaré. ¡Aclamaciones! – BruneauB

8

¡OMG! ¡Tomó mucho café y mucha privación del sueño, pero logré resolver mi problema! También es razonablemente simple ...
Primero importo el WSDL, como esperaba. Esto generará varias clases de TRemotable. ¡Entonces, para cada TRemotable que necesita un espacio de nombre diferente, anulo el método ObjectToSOAP()! (E incluya XMLIntf a la fuente WSDL). En mi caso con código como este para varios de los tipos 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; 

que trabajó en Delphi XE. En Delphi 2007 tuve que usar unidades XMLIntf y XMLDoc además el código del tipo de entrada:

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; 

Es un truco, en mi opinión. Pero no es muy sucio. Es un poco de experimentación, capturar las solicitudes y respuestas de SOAP para verificar su contenido y ver si usa los espacios de nombres adecuados. Por desgracia, Delphi XE hace un trabajo mucho mejor en esto que Delphi 2007.

Aún así, mantener esto abierto para cualquier Q soluciones mejores ...


Por cierto, para agregar al col: a la salida, También tuve que cambiar esta línea en WSDL RemClassRegistry.RegisterXSClass(Calculate, 'http://colan.ogconnect.service.wzp/', 'Calculate'); a este: RemClassRegistry.RegisterXSClass(Calculate, 'http://colan.ogconnect.service.wzp/', 'cal:Calculate');. El resultado se convierte en <cal:Calculate xmlns:cal="http://example.webservice/">. Sin embargo, hay que hacer más cosas: mover ese xmlns:cal al encabezado xml. Pero como es ahora, funciona para mí.


Otra nota: para el WSDL que utilizan los siguientes ajustes: 'Una outParam es el retorno', 'Relájese params literales', 'Generar destructores', 'comentarios de advertencia', 'emiten tipos literales', 'Cadena de mapa a cadena ancha'. Otras opciones son: 'Generar información detallada sobre tipos e interfaces', 'Ignorar los tipos con enlaces HTTP', 'Validar miembros de la enumeración', 'Importar tipos de fallas', 'Importar tipos de encabezado', 'Procesos incluidos y esquemas importados', 'Generar alias de clase como tipos de clase ',' Permitir parámetros Out 'y' Procesar elementos nillable y opcionales '. El emitir tipos literales fue práctico porque genera una clase alrededor del único método al que estaba llamando. Desafortunadamente, esto tampoco ayudará mucho, aunque la clase lo ayudará a modificar la solicitud SOAP en el nivel superior dentro del sobre anulando el método ObjectToSOAP().
La creación del sobre en sí está en la unidad SOAPEnv y se usa en la unidad OPToSOAPDomConv. Desafortunadamente, no he encontrado un método fácil de acceder al sobre en sí para alterar el encabezado y agregar este espacio de nombres adicional. Por otra parte, podría anular la clase TSOAPDomConv con mi propia versión que agrega el espacio de nombres adicional. Pero el código me funciona ahora, y como mi padre me dijo, cuando aprendió a programar: nunca arregles nada que no esté roto.

+0

Parece prometedor - Voy a darle un giro. Esto puede ahorrar mucho tiempo/dolor en un gran proyecto que se avecina, por lo que me complace contribuir puntos de recompensa en la discusión. –

+0

¿Realmente le dio salida como esta:

+0

Creo que esto puede darme un buen lugar para conectar, pero puede que necesite hacer más trabajo en la función AlterChildren. –

Cuestiones relacionadas