Ir para conteúdo
Fórum Script Brasil
  • 0

(Resolvido) WebService


kartter

Pergunta

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

 

Link para o comentário
Compartilhar em outros sites

16 respostass a esta questão

Posts Recomendados

  • 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

 

Link para o comentário
Compartilhar em outros 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

Editado por kartter
Link para o comentário
Compartilhar em outros 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

Link para o comentário
Compartilhar em outros 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;

 

Link para o comentário
Compartilhar em outros 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.

Link para o comentário
Compartilhar em outros 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>


 

Link para o comentário
Compartilhar em outros 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 ?

 

 

Link para o comentário
Compartilhar em outros 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.

Link para o comentário
Compartilhar em outros 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> 

 

Link para o comentário
Compartilhar em outros sites

  • 0

Boa noite Kartter, estou enfrentando o mesmo problema que você relatou.

Gostaria de saber se você conseguiu encontrar alguma solução para o problema.

Agradeço se puder compartilhar alguma informação, já virei a internet e não consegui nada que indique uma possível solução.

Editado por Carlos Giovani Deitos
Link para o comentário
Compartilhar em outros sites

Participe da discussão

Você pode postar agora e se registrar depois. Se você já tem uma conta, acesse agora para postar com sua conta.

Visitante
Responder esta pergunta...

×   Você colou conteúdo com formatação.   Remover formatação

  Apenas 75 emoticons são permitidos.

×   Seu link foi incorporado automaticamente.   Exibir como um link em vez disso

×   Seu conteúdo anterior foi restaurado.   Limpar Editor

×   Você não pode colar imagens diretamente. Carregar ou inserir imagens do URL.



  • Estatísticas dos Fóruns

    • Tópicos
      152,3k
    • Posts
      652,3k
×
×
  • Criar Novo...