Jump to content
Fórum Script Brasil
  • 0
Sign in to follow this  
kartter

WebService

Question

Boa noite, 

Estou fazendo um WebService em Delphi 10.3. Fiz e consegui importá-lo sem problemas. Quando mandei para o meu cliente, ele me informou que importou o WSDL no SOAPUI e a estrutura complexa não foi carregada. Realmente estas estruturas complexas não são carregadas no SOAP UI quando faço um WebService em Delphi. Porém se recebo um WSDL escrito em outra linguagem, estas estruturas são carregadas. Coloquei somente o básico da interface que fiz para que vocês possam me auxiliar.

 

unit UInterfaceDelivery;

interface

uses
  Soap.InvokeRegistry,Soap.XSBuiltIns;

Type
  Item = class(TRemotable)
    private
      FNome:string;
    published
      property nome: string read FNome write FNome;
  end;

  Array_Of_Items          = array of Item;


  Deliveries = class(TRemotable)
  private
    FDelivery      : string;
    FItems         : Array_Of_Items;
  published
    property Delivery:         string                 read FDelivery write FDelivery;
    property Items:            Array_Of_Items         read FItems write FItems;
  end;

 ContDeliveryModel = Deliveries;
 ContDeliveryModelRequest =  type ContDeliveryModel;

  ContDeliveryModel_In_Sync_it = interface(IInvokable)
    ['{5EAA2E15-891D-4BA4-BEDD-BF2AEFEB11BF}']
      function  ContDeliveryModel_In_Sync(const ContDeliveryModelRequest: ContDeliveryModelRequest): boolean; stdcall;
  end;

implementation

initialization
  InvRegistry.RegisterInterface(TypeInfo(ContDeliveryModel_In_Sync_it));

end.

Veja que a propriedade Items é um array da Classe Item

Quando importo o WSDL abaixo no SOAP ele monta a estrutura conforme o segundo quadro

<?xml version="1.0"?>
<definitions xmlns="http://schemas.xmlsoap.org/wsdl/" xmlns:xs="http://www.w3.org/2001/XMLSchema" name="ContDeliveryModel_In_Sync_itservice" targetNamespace="http://tempuri.org/" xmlns:tns="http://tempuri.org/" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:mime="http://schemas.xmlsoap.org/wsdl/mime/" xmlns:ns1="urn:UInterfaceDelivery">
  <types>
    <xs:schema targetNamespace="urn:UInterfaceDelivery" xmlns="urn:UInterfaceDelivery">
      <xs:complexType name="ContDeliveryModelRequest">
        <sequence xmlns="http://www.w3.org/2001/XMLSchema">
          <xs:element name="Delivery" type="xs:string"/>
          <xs:element name="Items" type="ns1:Array_Of_Items"/>
        </sequence>
      </xs:complexType>
      <xs:complexType name="Array_Of_Items">
        <xs:complexContent>
          <xs:restriction base="soapenc:Array">
            <sequence xmlns="http://www.w3.org/2001/XMLSchema"/>
            <xs:attribute ref="soapenc:arrayType" n1:arrayType="ns1:Item[]" xmlns:n1="http://schemas.xmlsoap.org/wsdl/"/>
          </xs:restriction>
        </xs:complexContent>
      </xs:complexType>
      <xs:complexType name="Item">
        <sequence xmlns="http://www.w3.org/2001/XMLSchema">
          <xs:element name="nome" type="xs:string"/>
        </sequence>
      </xs:complexType>
    </xs:schema>
  </types>
  <message name="ContDeliveryModel_In_Sync0Request">
    <part name="ContDeliveryModelRequest" type="ns1:ContDeliveryModelRequest"/>
  </message>
  <message name="ContDeliveryModel_In_Sync0Response">
    <part name="return" type="xs:boolean"/>
  </message>
  <portType name="ContDeliveryModel_In_Sync_it">
    <operation name="ContDeliveryModel_In_Sync">
      <input message="tns:ContDeliveryModel_In_Sync0Request"/>
      <output message="tns:ContDeliveryModel_In_Sync0Response"/>
    </operation>
  </portType>
  <binding name="ContDeliveryModel_In_Sync_itbinding" type="tns:ContDeliveryModel_In_Sync_it">
    <binding xmlns="http://schemas.xmlsoap.org/wsdl/soap/" style="rpc" transport="http://schemas.xmlsoap.org/soap/http"/>
    <operation name="ContDeliveryModel_In_Sync">
      <operation xmlns="http://schemas.xmlsoap.org/wsdl/soap/" soapAction="urn:UInterfaceDelivery-ContDeliveryModel_In_Sync_it#ContDeliveryModel_In_Sync" style="rpc"/>
      <input>
        <body xmlns="http://schemas.xmlsoap.org/wsdl/soap/" use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" namespace="urn:UInterfaceDelivery-ContDeliveryModel_In_Sync_it"/>
      </input>
      <output>
        <body xmlns="http://schemas.xmlsoap.org/wsdl/soap/" use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" namespace="urn:UInterfaceDelivery-ContDeliveryModel_In_Sync_it"/>
      </output>
    </operation>
  </binding>
  <service name="ContDeliveryModel_In_Sync_itservice">
    <port name="ContDeliveryModel_In_Sync_itPort" binding="tns:ContDeliveryModel_In_Sync_itbinding">
      <address xmlns="http://schemas.xmlsoap.org/wsdl/soap/" location="http://localhost/wsdl_lh/ServerLH.dll/soap/ContDeliveryModel_In_Sync_it"/>
    </port>
  </service>
</definitions>


Como a estrutura é montada no SOAP UI

<soapenv:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:urn="urn:UInterfaceDelivery-ContDeliveryModel_In_Sync_it" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/">
   <soapenv:Header/>
   <soapenv:Body>
      <urn:ContDeliveryModel_In_Sync soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
         <ContDeliveryModelRequest xsi:type="urn:ContDeliveryModelRequest" xmlns:urn="urn:UInterfaceDelivery">
            <Delivery xsi:type="xsd:string">?</Delivery>
            <Items xsi:type="urn:Array_Of_Items" soapenc:arrayType="urn:Item[]"/>
         </ContDeliveryModelRequest>
      </urn:ContDeliveryModel_In_Sync>
   </soapenv:Body>
</soapenv:Envelope>

 

Então meu cliente indagou que a estrutura ITEM não foi carrega. Como faço para o SOAP UI importar este WSDL conforme abaixo, sabendo que o ITEM é um array?:

<soapenv:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:urn="urn:UInterfaceDelivery-ContDeliveryModel_In_Sync_it" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/">
   <soapenv:Header/>
   <soapenv:Body>
      <urn:ContDeliveryModel_In_Sync soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
         <ContDeliveryModelRequest xsi:type="urn:ContDeliveryModelRequest" xmlns:urn="urn:UInterfaceDelivery">
            <Delivery xsi:type="xsd:string">?</Delivery>
            <Items xsi:type="urn:Items">
               <nome xsi:type="xsd:string">?</nome>
            </Items>  
         </ContDeliveryModelRequest>
      </urn:ContDeliveryModel_In_Sync>
   </soapenv:Body>
</soapenv:Envelope>


Obrigado pelo auxílio!

Jean Carlos

 

Edited by kartter

Share this post


Link to post
Share on other sites

15 answers to this question

Recommended Posts

  • 0

Ei @Jhonas, bom dia,

O problema não está no soapui e sim no wsdl gerado pelo delphi.

Veja este exemplo de WSDL gerado por outra ferramenta. 


<xsd:element name="Deliveries" maxOccurs="unbounded">
	<xsd:complexType>
		<xsd:sequence>
			<xsd:element name="Delivery" type="xsd:string"/>
			<xsd:element name="Country" type="xsd:string" minOccurs="0"/>
			<xsd:element name="Items" maxOccurs="unbounded">
				<xsd:complexType>
					<xsd:sequence>
						<xsd:element name="Item" type="xsd:string"/>
						<xsd:element name="Material" type="xsd:string"/>
					</xsd:sequence>
				</xsd:complexType>
			</xsd:element>
			<xsd:element name="Partners" type="PartnersModel" minOccurs="0" maxOccurs="unbounded"/>
		</xsd:sequence>
	</xsd:complexType>
</xsd:element>

Se gerar no Delphi, o WSDL é gerado da seguinte maneira:
 

<sequence xmlns="http://www.w3.org/2001/XMLSchema">
  <xs:element name="Delivery" type="xs:string"/>
  <xs:element name="Country" type="xs:string"/>
  <xs:element name="Items" type="ns1:Array_Of_Items"/>
  <xs:element name="Partners" type="ns1:Array_Of_PartnersModel"/>
</sequence>

Por este motivo dá erro no SOAPUI e em qualquer ferramenta que mapeie os campos de maneira padrão, como por exemplo no SAP.

Obrigado pela ajuda!

Jean

 

Share this post


Link to post
Share on other sites
  • 0

Tente usar outra versão do delphi para gerar o WSDL e veja se são iguais

me passe o endereço da URL para que eu faça um teste aqui

 

 

Share this post


Link to post
Share on other sites
  • 0

Bom dia @Jhonas

Coloquei o codigo fonte e o wsdl no link: encurtador.com.br/fptx5

 

E um exemplo bem basico de um webservice. Veja no print abaixo, como o wsdl montado pelo delphi não tem nada a ver com a realidade. um nodo filho é montado de forma totalmente incorreta.

A classe pedido tem dois campos: Código e Data
A classe item tem dois campos: Nome e Filial

Obrigado!

Jean

soapui.png

Edited by kartter

Share this post


Link to post
Share on other sites
  • 0

o wsdl montado pelo delphi não tem nada a ver com a realidade.

Quero que voce me passe o endereço da URL para importar o  WSDL  em outra versão do delphi e comparar o código

quero ver se é bug de versão

Share this post


Link to post
Share on other sites
  • 0

O código que eu quero que voce compare é esse

// ************************************************************************ //
// The types declared in this file were generated from data read from the
// WSDL File described below:
// WSDL     : http://35.247.246.18/wslh/ScriptBrasil.dll/wsdl/IiTeste
// Version  : 1.0
// (25/4/2020 11:16:39 - 1.33.2.5)
// ************************************************************************ //

unit IiTeste1;

interface

uses InvokeRegistry, SOAPHTTPClient, Types, XSBuiltIns;

type

  // ************************************************************************ //
  // The following types, referred to in the WSDL document are not being represented
  // in this file. They are either aliases[@] of other types represented or were referred
  // to but never[!] declared in the document. The types from the latter category
  // typically map to predefined/known XML or Borland types; however, they could also
  // indicate incorrect WSDL documents that failed to declare or import a schema type.
  // ************************************************************************ //
  // !:string          - "http://www.w3.org/2001/XMLSchema"
  // !:date            - "http://www.w3.org/2001/XMLSchema"
  // !:boolean         - "http://www.w3.org/2001/XMLSchema"

  TItem                = class;                 { "urn:iTesteIntf" }
  TPedido              = class;                 { "urn:iTesteIntf" }
  tnew                 = class;                 { "urn:iTesteIntf" }
  TFinal               = class;                 { "urn:iTesteIntf" }



  // ************************************************************************ //
  // Namespace : urn:iTesteIntf
  // ************************************************************************ //
  TItem = class(TRemotable)
  private
    Fnome: WideString;
    Ffilial: WideString;
  published
    property nome: WideString read Fnome write Fnome;
    property filial: WideString read Ffilial write Ffilial;
  end;



  // ************************************************************************ //
  // Namespace : urn:iTesteIntf
  // ************************************************************************ //
  TPedido = class(TRemotable)
  private
    Fcodigo: WideString;
    FData: TXSDate;
    Fitem: TItem;
  public
    destructor Destroy; override;
  published
    property codigo: WideString read Fcodigo write Fcodigo;
    property Data: TXSDate read FData write FData;
    property item: TItem read Fitem write Fitem;
  end;



  // ************************************************************************ //
  // Namespace : urn:iTesteIntf
  // ************************************************************************ //
  tnew = class(TItem)
  private
  published
  end;

  Item_array = array of tnew;                   { "urn:iTesteIntf" }


  // ************************************************************************ //
  // Namespace : urn:iTesteIntf
  // ************************************************************************ //
  TFinal = class(TPedido)
  private
    Fx: Item_array;
  public
    destructor Destroy; override;
  published
    property x: Item_array read Fx write Fx;
  end;


  // ************************************************************************ //
  // Namespace : urn:iTesteIntf-IiTeste
  // soapAction: urn:iTesteIntf-IiTeste#efetuarPedido
  // transport : http://schemas.xmlsoap.org/soap/http
  // style     : rpc
  // binding   : IiTestebinding
  // service   : IiTesteservice
  // port      : IiTestePort
  // URL       : http://35.247.246.18/wslh/ScriptBrasil.dll/soap/IiTeste
  // ************************************************************************ //
  IiTeste = interface(IInvokable)
  ['{4AAAB37A-05B4-EC30-B6BA-0CB935687988}']
    function  efetuarPedido(const pedido: TFinal): Boolean; stdcall;
  end;

function GetIiTeste(UseWSDL: Boolean=System.False; Addr: string=''; HTTPRIO: THTTPRIO = nil): IiTeste;


implementation

function GetIiTeste(UseWSDL: Boolean; Addr: string; HTTPRIO: THTTPRIO): IiTeste;
const
  defWSDL = 'http://35.247.246.18/wslh/ScriptBrasil.dll/wsdl/IiTeste';
  defURL  = 'http://35.247.246.18/wslh/ScriptBrasil.dll/soap/IiTeste';
  defSvc  = 'IiTesteservice';
  defPrt  = 'IiTestePort';
var
  RIO: THTTPRIO;
begin
  Result := nil;
  if (Addr = '') then
  begin
    if UseWSDL then
      Addr := defWSDL
    else
      Addr := defURL;
  end;
  if HTTPRIO = nil then
    RIO := THTTPRIO.Create(nil)
  else
    RIO := HTTPRIO;
  try
    Result := (RIO as IiTeste);
    if UseWSDL then
    begin
      RIO.WSDLLocation := Addr;
      RIO.Service := defSvc;
      RIO.Port := defPrt;
    end else
      RIO.URL := Addr;
  finally
    if (Result = nil) and (HTTPRIO = nil) then
      RIO.Free;
  end;
end;


destructor TPedido.Destroy;
begin
  if Assigned(FData) then
    FData.Free;
  if Assigned(Fitem) then
    Fitem.Free;
  inherited Destroy;
end;

destructor TFinal.Destroy;
var
  I: Integer;
begin
  for I := 0 to Length(Fx)-1 do
    if Assigned(Fx[I]) then
      Fx[I].Free;
  SetLength(Fx, 0);
  inherited Destroy;
end;

initialization
  InvRegistry.RegisterInterface(TypeInfo(IiTeste), 'urn:iTesteIntf-IiTeste', '');
  InvRegistry.RegisterDefaultSOAPAction(TypeInfo(IiTeste), 'urn:iTesteIntf-IiTeste#efetuarPedido');
  RemClassRegistry.RegisterXSClass(TItem, 'urn:iTesteIntf', 'TItem');
  RemClassRegistry.RegisterXSClass(TPedido, 'urn:iTesteIntf', 'TPedido');
  RemClassRegistry.RegisterXSClass(tnew, 'urn:iTesteIntf', 'tnew');
  RemClassRegistry.RegisterXSInfo(TypeInfo(Item_array), 'urn:iTesteIntf', 'Item_array');
  RemClassRegistry.RegisterXSClass(TFinal, 'urn:iTesteIntf', 'TFinal');

end.

Veja se tem alguma diferença com o código gerado na versão Delphi 10.3

Share this post


Link to post
Share on other sites
  • 0

Boa noite,

As diferenças são apenas no tipo. No Delphij 10.3 gerou os tipos como STRING. No seu exemplo gerou como WIDESTRING.

Outra diferença se refere ao destroy. No restante é tudo igual

destructor TPedido.Destroy;
begin
  System.SysUtils.FreeAndNil(FData);
  System.SysUtils.FreeAndNil(Fitem);
  inherited Destroy;
end;

destructor TFinal.Destroy;
var
  I: Integer;
begin
  for I := 0 to System.Length(Fx)-1 do
    System.SysUtils.FreeAndNil(Fx[I]);
  System.SetLength(Fx, 0);
  inherited Destroy;
end;

 

Share this post


Link to post
Share on other sites
  • 0

Utilize o código que eu te passei e veja se ocorre o mesmo problema que voce relatou

Share this post


Link to post
Share on other sites
  • 0

O codigo que passou é a importação do WSDL que foi gerado incorreto. O problema está no WSDL publicado. 

Se criar um SOAP SERVER APPLICATION no Delphi, utilizando os métodos de exemplo que são inseridos, e mandar publicar, verá que até o exemplo gera um WSDL incorreto.

Share this post


Link to post
Share on other sites
  • 0

Não tem nada a ver a maneira como estou enviando os dados Jhonas. A construção do webservice que não está correta.

Vou mudar a pergunta. Tem idéia de como criar um webservice, onde um nodo possua limite? Acredito que isto resolva o problema.

Exemplo: (minOccurs="0" maxOccurs="1")

<xs:sequence>
<xs:element name="Code" type="xs:int"> </xs:element>
<xs:element name="Value" type="xs:string" minOccurs="0" maxOccurs="1"> </xs:element>
<xs:element name="ped" type="tns:array_filho"> </xs:element>
</xs:sequence>


 

Share this post


Link to post
Share on other sites
  • 0

A construção do webservice que não está correta.

o webservice é seu ou de terceiros ... se é seu basta alterar o código para funcionar como voce precisa, mas se não foi voce que o construiu, então  não dá para fazer nada.

Tem idéia de como criar um webservice ?

https://www.google.com.br/search?source=hp&ei=nIKnXpa4EcXI5OUP5o6a0Ao&q=criar+webservice+delphi&o que=criar+webservice&gs_lcp=CgZwc3ktYWIQARgEMgIIADICCAAyAggAMgIIADICCAAyAggAMgIIADICCAAyAggAMgQIABAKOgUIABCDAVD0CViOJGCsOGgAcAB4AYABlASIAcojkgEMMC4xMC4wLjEuMy4zmAEAoAEBqgEHZ3dzLXdperABAA&sclient=psy-ab

, onde um nodo possua limite?

o limite é voce quem define no código ....

pode me mostrar como é que voce cria o xml para envio ?

voce tem um ambiente ( endereço ) para testes ?

 

 

Share this post


Link to post
Share on other sites
  • 0

Bom, é como eu disse acima. Eu que estou fazendo o WebService. 

Se fizer um Webservice no Delphi, você cria as classes e ele cria o WSDL para publicação. Disse também que até mesmo o exemplo que o próprio delphi monta, não gera o wsdl corretamente. Não é possível ou pelo menos em nenhuma documentação embarcadero demonstra como colocar limites, conforme coloquei acima. 

Quando falo que ele não gera corretamente, é porque qualquer ferramenta que faz uso de um WSDL nativamente (SAP/SOAP), não conseguem interpretar o WSDL gerado pelo delphi, justamente pelo fato de não ser possível colocar limites (minOccurs="0" maxOccurs="1"), bem como a maneira como ele representa array.

Share this post


Link to post
Share on other sites
  • 0

experimente:

minOccurs="0" maxOccurs="unbounded"

Isso é especificado configurando o atributo maxOccurs do elemento "item" como "ilimitado", o que significa que pode haver tantas ocorrências do elemento "item" quanto o autor desejar.

ou pode limitar o numero de ocorrencias

exemplo:


<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
elementFormDefault="qualified">

<xs:element name="persons">
  <xs:complexType>
    <xs:sequence>
      <xs:element name="person" maxOccurs="unbounded">
        <xs:complexType>
          <xs:sequence>
            <xs:element name="full_name" type="xs:string"/>
            <xs:element name="child_name" type="xs:string"
            minOccurs="0" maxOccurs="5"/>
          </xs:sequence>
        </xs:complexType>
      </xs:element>
    </xs:sequence>
  </xs:complexType>
</xs:element>

</xs:schema> 

 

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Answer this question...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Sign in to follow this  



  • Forum Statistics

    • Total Topics
      148594
    • Total Posts
      644163
×
×
  • Create New...