Wednesday, 19 August 2009

Creando un Cliente Web Service en Delphi

En éste artículo os propongo un pequeño ejercicio sobre la creación de un cliente web Service para utilizar un servicio y que nos devuelva información sobre la tabla periódica. Si consultamos la web de xMethods, veréis una lista de servicios web activos, los cuales podemos utilizar para obtener los datos remotos a través de Internet. Por lo tanto, podemos crear diversas aplicaciones y utilizar éstos servicios externos. El servicio que voy a utilizar es el siguiente: Periodic Table de Walter Vijaykumar Jones. Mediante éste servicio, podremos solicitar la información de uno de los elementos de la tabla periódica y obtener diferente información sobre su peso atómico, símbolo, etc.

Desde Delphi, crearemos una nueva VCL application, y luego seleccionamos -> New -> Other -> WSDL importer. Y añadimos el WSDL que nos devuelve la información de la SOAP.

Periodic Table : http://www.webservicex.com/periodictable.asmx?wsdl

Una vez hecho ésto, se crea un fichero PeriodicTable.pas que contiene toda la información de la SOAP.

Aquí os dejo el fichero .pas que nos ha generado el Delphi:

// ************************************************************************ //
// The types declared in this file were generated from data read from the
// WSDL File described below:
// WSDL     : http://www.webservicex.com/periodictable.asmx?wsdl
//  >Import : http://www.webservicex.com/periodictable.asmx?wsdl:0
// Encoding : utf-8
// Version  : 1.0
// (19/08/2009 16:07:16 - - $Rev: 10138 $)
// ************************************************************************ //

unit periodictable;

interface

uses InvokeRegistry, SOAPHTTPClient, Types, XSBuiltIns;

const
  IS_OPTN = $0001;
  IS_REF  = $0080;


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"[Gbl]



  // ************************************************************************ //
  // Namespace : http://www.webserviceX.NET
  // soapAction: http://www.webserviceX.NET/%operationName%
  // transport : http://schemas.xmlsoap.org/soap/http
  // style     : document
  // binding   : periodictableSoap
  // service   : periodictable
  // port      : periodictableSoap
  // URL       : http://www.webservicex.com/periodictable.asmx
  // ************************************************************************ //
  periodictableSoap = interface(IInvokable)
  ['{46CA9F35-B502-F19B-1A59-767555223F6A}']
    function  GetAtoms: WideString; stdcall;
    function  GetAtomicWeight(const ElementName: WideString): WideString; stdcall;
    function  GetAtomicNumber(const ElementName: WideString): WideString; stdcall;
    function  GetElementSymbol(const ElementName: WideString): WideString; stdcall;
  end;

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


implementation
  uses SysUtils;

function GetperiodictableSoap(UseWSDL: Boolean; Addr: string; HTTPRIO: THTTPRIO): periodictableSoap;
const
  defWSDL = 'http://www.webservicex.com/periodictable.asmx?wsdl';
  defURL  = 'http://www.webservicex.com/periodictable.asmx';
  defSvc  = 'periodictable';
  defPrt  = 'periodictableSoap';
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 periodictableSoap);
    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;


initialization
  InvRegistry.RegisterInterface(TypeInfo(periodictableSoap), 'http://www.webserviceX.NET', 'utf-8');
  InvRegistry.RegisterDefaultSOAPAction(TypeInfo(periodictableSoap), 'http://www.webserviceX.NET/%operationName%');
  InvRegistry.RegisterInvokeOptions(TypeInfo(periodictableSoap), ioDocument);

end.



Una vez hecho ésto, ya podemos utilizar la SOAP. Para ello, tenemos que añadir un componente THTTPRIO a nuestro formulario, y añadir la información necesaria a éste:

Una vez tenemos insertado el componente, su utilización es bien simple, solo tenemos que añadir lo siguiente:

uses
    Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
    Dialogs, periodicTable, StdCtrls, InvokeRegistry, Rio, SOAPHTTPClient, StrUtils;

type
    TForm3 = class(TForm)
        Button1: TButton;
        Memo1: TMemo;
        HTTPRIO1: THTTPRIO;
        Edit1: TEdit;
        procedure Button1Click(Sender: TObject);
    private
        { Private declarations }
    public
        { Public declarations }
    end;

var
    Form3: TForm3;

implementation

{$R *.dfm}

procedure TForm3.Button1Click(Sender: TObject);
var
    wf: string;
    i: integer;
begin
    if Edit1.text = '' then
        Exit;
    memo1.Lines.clear;
    wf := (HTTPRIO1 as periodictableSoap).GetAtomicNumber(Edit1.text);
    wf := AnsiReplaceStr(wf, chr(10), chr(13) + chr(10));
    memo1.Lines.Add(wf);
    wf := (HTTPRIO1 as periodictableSoap).GetAtomicWeight(Edit1.text);
    wf := AnsiReplaceStr(wf, chr(10), chr(13) + chr(10));
    memo1.Lines.Add(wf);
    wf := (HTTPRIO1 as periodictableSoap).GetElementSymbol(Edit1.text);
    wf := AnsiReplaceStr(wf, chr(10), chr(13) + chr(10));
    memo1.Lines.Add(wf);
end;


Et voilà!, ya tenemos nuestra aplicación utilizando un servicio externo. Aquí os dejo mi aplicación Thundax Periodic Table, que utiliza el Servicio Web de Walter Vijaykumar Jones para mostrar información sobre la tabla periódica.

Aquí os dejo una imagen de mi aplicación:

Espero que os sirva de ayuda.

  • Enlaces de interés:
Creating web service client with delphi.

6 comments:

  1. im a delphi programmer, it was big help, thanks

    ReplyDelete
  2. Thank you Master!!

    ReplyDelete
  3. Buenisimo!! Muchas gracias :D

    ReplyDelete
  4. Buenisimo! Muchas Gracias :D

    ReplyDelete
  5. Hi. Nice example. I have problem with an endpoint and calling a procedure (Delphi 7):

    procedure Proce1(const HEADER_IN: HEADER_IN; var BODY_IN_PROC: BODY_IN_PROC; out HEADER_OUT: HEADER_OUT; out BODY_OUT_PROC: BODY_OUT_PROC); stdcall;

    BODY_IN_PROC is
    property NUM_PER: TXSDecimal ...
    property COD_PA: WideString ...
    property TIP_ID: WideString ...
    property NUM_ID: TXSDecimal ...

    TXSDecimal values never reach response, so the procedure always show the message 'invalid parameters ' because they are null or 0

    What can be wrong?

    Greetings.

    ReplyDelete