Ir al contenido



Foto

Consumir WebService con acceso a Base de Datos


  • Por favor identifícate para responder
74 respuestas en este tema

#1 egostar

egostar

    missing my father, I love my mother.

  • Administrador
  • 13.658 mensajes
  • LocationMéxico

Escrito 21 mayo 2009 - 12:26

Índice

 

 

  • Introducción
  • [swurl=#indice1]Capítulo 1. Crear nuestra base de datos[/swurl]
  • [swurl=#indice2]Capítulo 2. Crear el Web Service[/swurl]
  • [swurl=#indice21]    Capítulo 2.1 Creamos un Nuevo Proyecto[/swurl]
  • [swurl=#indice22]    Capítulo 2.2 Creamos la Conectividad con la Base de Datos[/swurl]
  • [swurl=#indice23]    Capítulo 2.3 La Clase TRemotable[/swurl]
  • [swurl=#indice24]    Capítulo 2.4 Creando las funciones del ABM[/swurl]
  • [swurl=#indice3]Capítulo 3. Registrar el Web Service en el IIS[/swurl]
  • [swurl=#indice4]Capítulo 4. Crear la aplicación Cliente[/swurl]
  • [swurl=#indice5]Apéndice I[/swurl]

 

Introducción
 

En el tutorial anterior vimos como Crear y Consumir un WebService con las 4 funciones aritméticas bsicas (suma, resta, multiplicación y división).

En este tutorial intentaré mostrar (paso a paso) como acceder a una base de datos a través de un WebService creando el famoso ABM (Altas, Bajas, Modificaciones).

Nota: Les pido una disculpa anticipada por mis limitantes y los invito a mejorar el código expuesto.

Comenzaré con dar algunos conceptos básicos.

Ambiente utilizado en el desarrollo de esta aplicación:
 

  • Windows XP Profesional SP3
  • Internet Information Services (IIS) 5.1
  • Firebird 2.0
  • Turbo Delphi Profesional
  • IBExpert Personal Edition

WebService:

Es definido por la W3C como: "un sistema diseñado para soportar interoperabilidad máquina a máquina a través de una red" y que se comunican a través del protocolo HTTP utilizada en la Web.

ISAPI:

Internet Server Application Programming Interface por sus siglas en inglés, consta de dos componentes (Extensiones y Filtros) los cuales son compilados en una DLL y que se registra en el IIS para ser ejecutados en el Servidor Web.

SOAP:

Simple Object Access Protocol por sus siglas en inglés es un protocolo para el intercambio de información estructurada en la ejecución de Web Services, Se basa en lenguaje XML para la negociación y la transmisión de mensajes.

Regresar al Índice
 


  • 0

#2 egostar

egostar

    missing my father, I love my mother.

  • Administrador
  • 13.658 mensajes
  • LocationMéxico

Escrito 21 mayo 2009 - 12:28

 
[swname=indice1]Capítulo 1. Crear nuestra base de datos[/swname]
[swurl=#inicio]Regresar al Índice[/swurl]
 

Para efectos de nuestro ejemplo vamos a crear la tabla Clientes en nuestra base de datos, esto lo he hecho con IBExpert y con Firebird 2.0

Nuestra tabla incluye un campo alfanumérico que servirá de Llave primaria.

DDL:



sql
  1. /******************************************************************************/
  2. /***              Generated by IBExpert 20/05/2009 15:13:56                ***/
  3. /******************************************************************************/
  4.  
  5. SET SQL DIALECT 3;
  6.  
  7. SET NAMES NONE;
  8.  
  9.  
  10.  
  11. /******************************************************************************/
  12. /***                                Tables                                ***/
  13. /******************************************************************************/
  14.  
  15.  
  16. CREATE GENERATOR GEN_CLIENTES_ID;
  17.  
  18. CREATE TABLE CLIENTES (
  19.     CLIENTE_ID          INTEGER NOT NULL,
  20.     TITULO_CLIENTE      VARCHAR(10),
  21.     NOMBRE              VARCHAR(50),
  22.     APELLIDOS          VARCHAR(50),
  23.     FECHA_NACIMIENTO    DATE,
  24.     DIRECCION          VARCHAR(100),
  25.     CIUDAD              VARCHAR(50),
  26.     PAIS                VARCHAR(50),
  27.     CODIGO_POSTAL      VARCHAR(5),
  28.     TELEFONO_CASA      VARCHAR(20),
  29.     TELEFONO_TRABAJO    VARCHAR(20),
  30.     TELEFONO_CELULAR    VARCHAR(20),
  31.     CORREO_ELECTRONICO  VARCHAR(100)
  32. );
  33.  
  34.  
  35.  
  36.  
  37. /******************************************************************************/
  38. /***                              Primary Keys                              ***/
  39. /******************************************************************************/
  40.  
  41. ALTER TABLE CLIENTES ADD CONSTRAINT PK_CLIENTES PRIMARY KEY (CLIENTE_ID);
  42.  
  43.  
  44. /******************************************************************************/
  45. /***                                Triggers                                ***/
  46. /******************************************************************************/
  47.  
  48.  
  49. SET TERM ^ ;
  50.  
  51.  
  52. /******************************************************************************/
  53. /***                          Triggers for tables                          ***/
  54. /******************************************************************************/
  55.  
  56.  
  57.  
  58. /* Trigger: CLIENTES_BI */
  59. CREATE TRIGGER CLIENTES_BI FOR CLIENTES
  60. ACTIVE BEFORE INSERT POSITION 0
  61. AS
  62. BEGIN
  63.   IF (NEW.CLIENTE_ID IS NULL) THEN
  64.     NEW.CLIENTE_ID = GEN_ID(GEN_CLIENTES_ID,1);
  65. END
  66. ^
  67.  
  68.  
  69. SET TERM ; ^
  70.  
  71.  
  72.  
  73. /******************************************************************************/
  74. /***                              Privileges                              ***/
  75. /******************************************************************************/



[swurl=#inicio]Regresar al Índice[/swurl]


  • 0

#3 egostar

egostar

    missing my father, I love my mother.

  • Administrador
  • 13.658 mensajes
  • LocationMéxico

Escrito 21 mayo 2009 - 12:32

 
[swname=indice2]Capítulo 2. Crear el Web Service[/swname]
[swurl=#inicio]Regresar al Índice[/swurl]
 

En este capítulo veremos como crear nuestro Web Service implementando la conectividad con la base de datos utilizando un SOAP Server Data Module, agregaremos componentes dbExpress para el acceso y escritura de los datos, utilizaremos la clase TRemotable (algo nuevo para mi y creo que para varios de nosotros) para la recepción de algunos parámetros desde nuestra aplicación cliente y escribiremos las funciones para acceder a la base de datos que serán consumidas desde la aplicación Cliente.

Nota: He decidido usar dbExpress debido a que se comenta que en la nueva versión de Delphi se pretende tener soporte a Firebird.

En los siguientes capítulos les mostrará a detalle cada uno de estos pasos.

 
[swname=indice21]Capítulo 2.1 Creamos un Nuevo Proyecto[/swname]
[swurl=#inicio]Regresar al Índice[/swurl]
 

Comenzaremos por crear un nuevo proyecto desde el menú de Delphi:

File --> New --> Other --> WebService --> SOAP Server Application

Imagen Enviada

Seleccionamos el Tipo ISAPI para la Aplicación del Servidor Web la cual nos generá una DLL al compilar nuestro Web Service.

Imagen Enviada

Aceptamos crear la interfaz del Módulo SOAP.

Imagen Enviada

Y finalmente agregamos un nuevo Web Service al que nombraremos WSdbAccess con el modelo de activacion del Servicio Per Request que significa que cada petición entrante se creará una nueva instancia del objeto SOAP (y destruida después de ser usada).

[img width=400 height=193]http://egostar.delphiaccess.com/tutoriales/webservice/Add_New_WebService.PNG[/img]

Una vez completado estos pasos, Delphi nos generará la estructura básica de nuestro Web Service


WSdbAccess.bdsproj



delphi
  1. library WSdbAccess;
  2.  
  3. uses
  4.   ActiveX,
  5.   ComObj,
  6.   WebBroker,
  7.   ISAPIApp,
  8.   ISAPIThreadPool,
  9.   uWSdbAccess in 'uWSdbAccess.pas' {WebModule2: TWebModule},
  10.   WSdbAccessImpl in 'WSdbAccessImpl.pas',
  11.   WSdbAccessIntf in 'WSdbAccessIntf.pas';
  12.  
  13. {$R *.res}
  14.  
  15. exports
  16.   GetExtensionVersion,
  17.   HttpExtensionProc,
  18.   TerminateExtension;
  19.  
  20. begin
  21.   CoInitFlags := COINIT_MULTITHREADED;
  22.   Application.Initialize;
  23.   Application.CreateForm(TWebModule2, WebModule2);
  24.   Application.Run;
  25. end.



uWSdbAccess.pas



delphi
  1. unit uWSdbAccess;
  2.  
  3. interface
  4.  
  5. uses
  6.   SysUtils, Classes, HTTPApp, InvokeRegistry, WSDLIntf, TypInfo, WebServExp,
  7.   WSDLBind, XMLSchema, WSDLPub, SOAPPasInv, SOAPHTTPPasInv, SOAPHTTPDisp,
  8.   WebBrokerSOAP;
  9.  
  10. type
  11.   TWebModule2 = class(TWebModule)
  12.     HTTPSoapDispatcher1: THTTPSoapDispatcher;
  13.     HTTPSoapPascalInvoker1: THTTPSoapPascalInvoker;
  14.     WSDLHTMLPublish1: TWSDLHTMLPublish;
  15.     procedure WebModule2DefaultHandlerAction(Sender: TObject;
  16.       Request: TWebRequest; Response: TWebResponse; var Handled: Boolean);
  17.   private
  18.     { Private declarations }
  19.   public
  20.     { Public declarations }
  21.   end;
  22.  
  23. var
  24.   WebModule2: TWebModule2;
  25.  
  26. implementation
  27.  
  28. {$R *.dfm}
  29.  
  30. procedure TWebModule2.WebModule2DefaultHandlerAction(Sender: TObject;
  31.   Request: TWebRequest; Response: TWebResponse; var Handled: Boolean);
  32. begin
  33.   WSDLHTMLPublish1.ServiceInfo(Sender, Request, Response, Handled);
  34. end;
  35.  
  36. end.



WSdbAccessImpl.pas



delphi
  1. { Invokable implementation File for TWSdbAccess which implements IWSdbAccess }
  2.  
  3. unit WSdbAccessImpl;
  4.  
  5. interface
  6.  
  7. uses InvokeRegistry, Types, XSBuiltIns, WSdbAccessIntf;
  8.  
  9. type
  10.  
  11.   { TWSdbAccess }
  12.   TWSdbAccess = class(TInvokableClass, IWSdbAccess)
  13.   public
  14.   end;
  15.  
  16. implementation
  17.  
  18.  
  19. initialization
  20. { Invokable classes must be registered }
  21.   InvRegistry.RegisterInvokableClass(TWSdbAccess);
  22. end.




WSdbAccessIntf.pas



delphi
  1. { Invokable interface IWSdbAccess }
  2.  
  3. unit WSdbAccessIntf;
  4.  
  5. interface
  6.  
  7. uses InvokeRegistry, Types, XSBuiltIns;
  8.  
  9. type
  10.  
  11.   { Invokable interfaces must derive from IInvokable }
  12.   IWSdbAccess = interface(IInvokable)
  13.   ['{7923453C-068B-4CE6-A012-D6C3AC837B8E}']
  14.  
  15.     { Methods of Invokable interface must not use the default }
  16.     { calling convention; stdcall is recommended }
  17.   end;
  18.  
  19. implementation
  20.  
  21. initialization
  22.   { Invokable interfaces must be registered }
  23.   InvRegistry.RegisterInterface(TypeInfo(IWSdbAccess));
  24.  
  25. end.



En este momento ya podemos comenzar a agregar todo lo necesario para desarrollar nuestro Web Service.


 
[swname=indice22]Capítulo 2.2 Creamos la Conectividad con la Base de Datos[/swname]
[swurl=#inicio]Regresar al Índice[/swurl]
 

Para crear la conectividad con la base de datos usaremos un Módulo de Datos SOAP el cual se agregará desde el menú de Delphi:

File --> New --> Other --> WebService --> SOAP Server Data Module

[img width=400 height=302]http://egostar.delphiaccess.com/tutoriales/webservice/SOAP_DM.PNG[/img]

Asignamos frmDataModule al nombre del Módulo de Datos.

Imagen Enviada

En este momento veremos el típico Módulo de Datos pero con la estructura invocable requerida. Guardamos nuestra unidad como uDataModule.


Ahora vamos a crear una nueva conexión a nuestra base de datos que como ya he mencionado usaremos dbExpress pensando en que Firebird está soportado en la siguiente versión de Delphi.

Abrimos el Data Explorer de Delphi (recuerden que estoy usando Turbo Delphi) y realizamos lo siguiente:

INTERBASE --> dbExpress --> botón derecho del mouse Add New Connection --> Provider Name = INTERBASE, Connection Name = CLIENTES

Imagen Enviada

Posteriormente editamos las propiedades de la conexión y configuramos las propiedades DataBase y HostName, DecimalSeparator y PrepareSQL como se muestra en la siguiente image, la ubicación de la base de datos depende donde la han colocado ustedes.

[img width=400 height=251]http://egostar.delphiaccess.com/tutoriales/webservice/Connection_Editor.PNG[/img]

Ya tenemos nuestra conexión, la seleccionamos y la arrastramos al Módulo de Datos.

[img width=400 height=151]http://egostar.delphiaccess.com/tutoriales/webservice/SQLConnection.PNG[/img]

Ahora vamos a agregar 5 SQLDataSet para escribir las sentencias SQL correspondientes al acceso de datos, he decidido hacerlo por separado para ser mas claro en los procesos.

Cambiamos el nombre de cada uno de los SQLDataSet de acuerdo al siguiente esquema:

dsClientList:

Nos regresará una lista de los clientes únicamente con los Campos CLIENTE_ID, NOMBRE y APELLIDOS



sql
  1. SELECT CLIENTE_ID, NOMBRE, APELLIDOS  FROM CLIENTES



dsClientData:

Nos regresará el detalle del cliente para ser mostrado.



sql
  1. SELECT * FROM CLIENTES WHERE CLIENTE_ID = :ID



dsAddClient:

Nos permitirá agregar registros a la tabla CLIENTES



sql
  1. INSERT INTO CLIENTES
  2.   (CLIENTE_ID, TITULO_CLIENTE, NOMBRE, APELLIDOS, FECHA_NACIMIENTO, DIRECCION, CIUDAD, PAIS,
  3. CODIGO_POSTAL,  TELEFONO_CASA, TELEFONO_CELULAR, TELEFONO_TRABAJO, CORREO_ELECTRONICO)
  4. VALUES
  5.   (NULL, :TITULO_CLIENTE, :NOMBRE, :APELLIDOS, :FECHA_NACIMIENTO, :DIRECCION, :CIUDAD,
  6. :PAIS, :CODIGO_POSTAL,  :TELEFONO_CASA, :TELEFONO_CELULAR, :TELEFONO_TRABAJO,
  7. :CORREO_ELECTRONICO)



dsDeleteClient:

Nos permitirá borrar un registro de la tabla CLIENTES



sql
  1. DELETE FROM CLIENTES WHERE CLIENTE_ID = :ID



dsUpdateClient:

Nos permitirá modificar el detalle de los clientes.



sql
  1. UPDATE CLIENTES
  2. SET
  3.   TITULO_CLIENTE = :TITULO_CLIENTE,
  4.   NOMBRE = :NOMBRE,
  5.   APELLIDOS = :APELLIDOS,
  6.   FECHA_NACIMIENTO = :FECHA_NACIMIENTO,
  7.   DIRECCION = :DIRECCION,
  8.   CIUDAD = :CIUDAD,
  9.   PAIS = :PAIS,
  10.   CODIGO_POSTAL = :CODIGO_POSTAL,
  11.   TELEFONO_CASA = :TELEFONO_CASA,
  12.   TELEFONO_CELULAR = :TELEFONO_CELULAR,
  13.   TELEFONO_TRABAJO = :TELEFONO_TRABAJO,
  14.   CORREO_ELECTRONICO = :CORREO_ELECTRONICO
  15. WHERE
  16.   CLIENTE_ID = :ID

[img width=400 height=294]http://egostar.delphiaccess.com/tutoriales/webservice/SQLDataSet.PNG[/img]

Ya estamos listos para comenzar a codificar nuestro Web Service.


 
[swname=indice23]Capítulo 2.3 La Clase TRemotable[/swname]
[swurl=#inicio]Regresar al Índice[/swurl]
 

Antes de comenzar a escribir código les voy a mostrar una clase especial que nos será de mucha utilidad para nuestros procesos.

TRemotable es la Clase Base para las clases que se pueden pasar como parámetros o valores de retorno a una solicitud en un servicio Web, dicho en otras palabras, esta clase nos permitirá transportar desde y hacia nuestra Aplicación Cliente un conjunto de elementos que no sería posible si pretendemos trasportarlos usando el tipo record tradicional.

Vamos a crear dos clases trParams y trRetorno de tipo TRemotable en la unidad WSdbAccessIntf.pas. La primera nos servirá para recibir los parámetros que serán ingresados y/o actualizados a la tabla CLIENTES y la segunda nos servirá para regresar a la aplicación Cliente el resultado de las transacciones.

A continuación mostrará la estructura de cada una de las clases.



delphi
  1. type
  2.  
  3.   trRetorno = class(TRemotable)
  4.     private
  5.       FID: integer;
  6.       FDescripcion: widestring;
  7.     published
  8.       property ID: integer read FID write FID;
  9.       property Descripcion: widestring read FDescripcion write FDescripcion;
  10.   end;
  11.  
  12.   trParams = class(TRemotable)
  13.     private
  14.       FTitulo: widestring;
  15.       FNombre: widestring;
  16.       FApellidos: widestring;
  17.       FFecha: widestring;
  18.       FDireccion: widestring;
  19.       FCiudad: wideString;
  20.       FPais: wideString;
  21.       FCodPostal: wideString;
  22.       FTelCasa: wideString;
  23.       FTelOficina: wideString;
  24.       FCelular: wideString;
  25.       FCorreo: wideString;
  26.     published
  27.       property Titulo: widestring read FTitulo write FTitulo;
  28.       property Nombre: widestring read FNombre write FNombre;
  29.       property Apellidos: widestring read FApellidos write FApellidos;
  30.       property Fecha: widestring read FFecha write FFecha;
  31.       property Direccion: widestring read FDireccion write FDireccion;
  32.       property Ciudad: widestring read FCiudad write FCiudad;
  33.       property Pais: widestring read FPais write FPais;
  34.       property CodPostal: widestring read FCodPostal write FCodPostal;
  35.       property TelCasa: widestring read FTelCasa write FTelCasa;
  36.       property TelOficina: widestring read FTelOficina write FTelOficina;
  37.       property Celular: widestring read FCelular write FCelular;
  38.       property Correo: widestring read FCorreo write FCorreo;
  39.   end;
  40.  
  41.   { Invokable interfaces must derive from IInvokable }
  42.   IWSdbAccess = interface(IInvokable)
  43.   ['{7923453C-068B-4CE6-A012-D6C3AC837B8E}']
  44.  
  45.     { Methods of Invokable interface must not use the default }
  46.     { calling convention; stdcall is recommended }
  47.   end;



Con esto ya tenemos la base para escribir nuestro código lo cual veremos en el siguiente capítulo.


 
[swname=indice24]Capítulo 2.4 Creando las funciones del ABM[/swname]
[swurl=#inicio]Regresar al Índice[/swurl]
 

Ya estamos listos para escribir nuestro código, comenzaremos por "diseñar" 5 funciones en la unidad WSdbAccessIntf.pas dentro de la interfaz invocable IWSdbAccess.



delphi
  1.   { Invokable interfaces must derive from IInvokable }
  2.   IWSdbAccess = interface(IInvokable)
  3.   ['{7923453C-068B-4CE6-A012-D6C3AC837B8E}']
  4.     function GetClientNames: widestring; stdcall;
  5.     function GetClientsData(EmpID: integer): widestring; stdcall;
  6.     function AddClient(ParamsStr:trParams): trRetorno; stdcall;
  7.     function DeleteClient(EmpID: integer): trRetorno; stdcall;
  8.     function UpdateClient(EmpID:integer; ParamsStr:trParams): trRetorno; stdcall;
  9.     { Methods of Invokable interface must not use the default }
  10.     { calling convention; stdcall is recommended }
  11.   end;



Ahora, debemos copiar estas funciones a la unidad WSdbAccessImpl.pas en la clase TWSdbAccess donde haremos la implementación de dichas funciones.



delphi
  1. { Invokable implementation File for TWSdbAccess which implements IWSdbAccess }
  2.  
  3. unit WSdbAccessImpl;
  4.  
  5. interface
  6.  
  7. uses InvokeRegistry, Types, XSBuiltIns, WSdbAccessIntf;
  8.  
  9. type
  10.  
  11.   { TWSdbAccess }
  12.   TWSdbAccess = class(TInvokableClass, IWSdbAccess)
  13.   public
  14.     function GetClientNames: widestring; stdcall;
  15.     function GetClientsData(EmpID: integer): widestring; stdcall;
  16.     function AddClient(ParamsStr:trParams): trRetorno; stdcall;
  17.     function DeleteClient(EmpID: integer): trRetorno; stdcall;
  18.     function UpdateClient(EmpID:integer; ParamsStr:trParams): trRetorno; stdcall;
  19.   end;
  20.  
  21. implementation
  22.  
  23.  
  24. initialization
  25. { Invokable classes must be registered }
  26.   InvRegistry.RegisterInvokableClass(TWSdbAccess);
  27. end.



Nos posicionamos en cualquiera de estas funciones y presionamos Ctrl + Shift + C, Delphi nos generará las funciones en la sección de implementación automáticamente.



delphi
  1. implementation
  2.  
  3.  
  4. { TWSdbAccess }
  5.  
  6. function TWSdbAccess.GetClientNames: widestring;
  7. begin
  8.  
  9. end;
  10.  
  11. function TWSdbAccess.GetClientsData(EmpID: string): widestring;
  12. begin
  13.  
  14. end;
  15.  
  16. function TWSdbAccess.AddClient(ParamsStr:trParams): trRetorno;
  17. begin
  18.  
  19. end;
  20.  
  21. function TWSdbAccess.DeleteClient(EmpID: integer): trRetorno; stdcall;
  22. begin
  23.  
  24. end;
  25.  
  26. function TWSdbAccess.UpdateClient(EmpID:integer; ParamsStr:trParams): trRetorno; stdcall;
  27. begin
  28.  
  29. end;



Antes de comenzar a codificar nuestras funciones crearemos dos funciones que generarán la estructura XML de los campos de los DataSet, dichas funciones por lo que estuve investigando son autoría de Marco Cantú si alguien tiene otra referencia me gustaría que lo hicieran notar para dar crédito a quien lo merece.



delphi
  1. function MakeXmlStr (node, value: string): string;
  2. begin
  3.   Result := '<' + node + '>' + value + '</' + node + '>';
  4. end;
  5.  
  6. function FieldsToXml (rootName: string; data: TSQLDataSet): string;
  7. var
  8.   i: Integer;
  9. begin
  10.   Result := '<' + rootName + '>' + sLineBreak;;
  11.   for i := 0 to data.FieldCount - 1 do
  12.       Result := Result + '  ' + MakeXmlStr (
  13.                 LowerCase (data.Fields[i].FieldName),
  14.                 data.Fields[i].AsString) + sLineBreak;
  15.   Result := Result + '</' + rootName + '>' + sLineBreak;;
  16. end;



Ahora agregamos las unidades uDataModule, sysUtils y sqlExpr además de una variable de tipo TfrmDataModule.



delphi
  1. implementation
  2.  
  3. uses uDataModule, sysUtils, sqlExpr;
  4.  
  5. var
  6.   dm: TfrmDataModule;



Ahora si, comencemos con la implementación de nuestras funciones.

Función GetClientNames: widestring;

Esta función nos regresará un listado de los clientes que se tengan en la base de datos en formato XML dentro de una variable widestring.



delphi
  1. function TWSdbAccess.GetClientNames: widestring;
  2. begin
  3.   dm := TfrmDataModule.Create (nil);
  4.   try
  5.     dm.dsClientList.Open;
  6.     if dm.dsClientList.RecordCount > 0 then begin
  7.       Result := FieldsToXml ('ClientList', dm.dsClientList);
  8.     end
  9.     else begin
  10.           Result := '<ClientList>' + sLineBreak +
  11.                     '</ClientList>' + sLineBreak;
  12.     end;
  13.   finally
  14.     dm.dsClientList.Close;
  15.     dm.CLIENTES.Close;
  16.     dm.Free;
  17.   end;
  18. end;



Este código creará una estructura XML con el listado de clientes con el siguiente formato:



delphi
  1. <ClientList>
  2.   <cliente_id>1</cliente_id>
  3.   <nombre>JUAN</nombre>
  4.   <apellidos>PEREZ</apellidos>
  5.   <cliente_id>2</cliente_id>
  6.   <nombre>REMEDIOS</nombre>
  7.   <apellidos>CASEROS</apellidos>
  8.   <cliente_id>3</cliente_id>
  9.   <nombre>ALMA MARIA</nombre>
  10.   <apellidos>RICO</apellidos>
  11. </ClientList>



Función GetClientsData(EmpID: integer): widestring;

Esta función nos regresará el detalle del cliente solicitado en el parámetro EmpID en formato XML dentro de una variable widestring.



delphi
  1. function TWSdbAccess.GetClientsData(EmpID: integer): widestring;
  2. begin
  3.   dm := TfrmDataModule.Create (nil);
  4.   try
  5.     dm.dsClientData.Params.ParamByName('ID').Value := EmpID;
  6.     dm.dsClientData.Open;
  7.     Result := FieldsToXml ('ClientData', dm.dsClientData);
  8.   finally
  9.     dm.dsClientData.Close;
  10.     dm.CLIENTES.Close;
  11.     dm.Free;
  12.   end;
  13. end;



Este código creará una estructura XML con el detalle del cliente solicitado con el siguiente formato:



delphi
  1. <Clientes>
  2.   <cliente_id>2</cliente_id>
  3.   <titulo_cliente>SRA.</titulo_cliente>
  4.   <nombre>REMEDIOS</nombre>
  5.   <apellidos>CASEROS</apellidos>
  6.   <fecha_nacimiento>01/11/1956</fecha_nacimiento>
  7.   <direccion>CALLE DE LA AMARGURA 69</direccion>
  8.   <ciudad>DE LA INFLUENZA</ciudad>
  9.   <pais>TUMBUCTU</pais>
  10.   <codigo_postal>12345</codigo_postal>
  11.   <telefono_casa>111-111-1111</telefono_casa>
  12.   <telefono_trabajo>111-212-1122</telefono_trabajo>
  13.   <telefono_celular>222-123-1234</telefono_celular>
  14.   <correo_electronico>remedios.caseros@gmail.com</correo_electronico>
  15. </Clientes>



function AddClient(ParamsStr: trParams): trRetorno;

Esta función agregará el registro del cliente con los parámetros recibidos en la clase trParams y nos regresará un aviso para determinar si la transacción fue satisfactoria o no en la clase trRetorno



delphi
  1. function TWSdbAccess.AddClient(ParamsStr: trParams): trRetorno;
  2. begin
  3.   Result := trRetorno.Create;
  4.   dm := TfrmDataModule.Create(nil);
  5.   try
  6.     with dm.dsAddClient do begin
  7.       ParamByName('TITULO_CLIENTE').value    := ParamsStr.Titulo;
  8.       ParamByName('NOMBRE').value            := ParamsStr.Nombre;
  9.       ParamByName('APELLIDOS').value          := ParamsStr.Apellidos;
  10.       ParamByName('FECHA_NACIMIENTO').value  := strtodate(ParamsStr.Fecha);
  11.       ParamByName('DIRECCION').Value          := ParamsStr.Direccion;
  12.       ParamByName('CIUDAD').Value            := ParamsStr.Ciudad;
  13.       ParamByName('PAIS').Value              := ParamsStr.Pais;
  14.       ParamByName('CODIGO_POSTAL').Value      := ParamsStr.CodPostal;
  15.       ParamByName('TELEFONO_CASA').Value      := ParamsStr.TelCasa;
  16.       ParamByName('TELEFONO_TRABAJO').Value  := ParamsStr.TelOficina;
  17.       ParamByName('TELEFONO_CELULAR').Value  := ParamsStr.Celular;
  18.       ParamByName('CORREO_ELECTRONICO').Value := ParamsStr.Correo;
  19.     end;
  20.     dm.dsAddClient.ExecSQL();
  21.     Result.ID := 0;
  22.     Result.Descripcion := 'El cliente fuá agregado correctamente';
  23.   except
  24.     Result.ID := -1;
  25.     Result.Descripcion := 'Error al agregar un nuevo Cliente';
  26.   end;
  27.   dm.CLIENTES.Close;
  28.   dm.Free;
  29. end;



Función DeleteClient(EmpID: integer): trRetorno;

En esta función solo recibiremos el identificador del cliente que se desea borrar y la funcion retornará un aviso si fue satisfactoria o no la transacción dentro de la clase trRetorno.



delphi
  1. function TWSdbAccess.DeleteClient(EmpID: integer): trRetorno;
  2. begin
  3.   Result := trRetorno.Create;
  4.   dm := TfrmDataModule.Create(nil);
  5.   try
  6.     dm.dsDeleteClient.paramByName('ID').Value := EmpID;
  7.     dm.dsDeleteClient.ExecSQL();
  8.     Result.ID := 0;
  9.     Result.Descripcion := 'El cliente solicitado fué borrado correctamente';
  10.   except
  11.     Result.ID := -1;
  12.     Result.Descripcion := 'Error al borrar el cliente solicitado';
  13.   end;
  14.   dm.CLIENTES.Close;
  15.   dm.Free;
  16. end;



Función UpdateClient(EmpID: integer; ParamsStr: trParams): trRetorno;

En esta función recibiremos el identificador del cliente que deseamos modificar/actualizar y los parámetros con los cuales se modificará el registro dentro de la clase trParams y regresará si la transacción fuá satisfactoria o no dentro de la clase trRetorno.



delphi
  1. function TWSdbAccess.UpdateClient(EmpID: integer; ParamsStr: trParams): trRetorno;
  2. begin
  3.   Result := trRetorno.Create;
  4.   dm := TfrmDataModule.Create(nil);
  5.   try
  6.     with dm.dsUpdateClient do begin
  7.       ParamByName('TITULO_CLIENTE').value    := ParamsStr.Titulo;
  8.       ParamByName('NOMBRE').value            := ParamsStr.Nombre;
  9.       ParamByName('APELLIDOS').value          := ParamsStr.Apellidos;
  10.       ParamByName('FECHA_NACIMIENTO').value  := strtodate(ParamsStr.Fecha);
  11.       ParamByName('DIRECCION').Value          := ParamsStr.Direccion;
  12.       ParamByName('CIUDAD').Value            := ParamsStr.Ciudad;
  13.       ParamByName('PAIS').Value              := ParamsStr.Pais;
  14.       ParamByName('CODIGO_POSTAL').Value      := ParamsStr.CodPostal;
  15.       ParamByName('TELEFONO_CASA').Value      := ParamsStr.TelCasa;
  16.       ParamByName('TELEFONO_TRABAJO').Value  := ParamsStr.TelOficina;
  17.       ParamByName('TELEFONO_CELULAR').Value  := ParamsStr.Celular;
  18.       ParamByName('CORREO_ELECTRONICO').Value := ParamsStr.Correo;
  19.       ParamByName('ID').Value                := EmpID;
  20.     end;
  21.     dm.dsUpdateClient.ExecSQL();
  22.     Result.ID := 0;
  23.     Result.Descripcion := 'El cliente fuá modificado correctamente';
  24.   except
  25.     Result.ID := -1;
  26.     Result.Descripcion := 'Error al modificar el Cliente';
  27.   end;
  28.   dm.CLIENTES.Close;
  29.   dm.Free;
  30. end;



Ahora solo nos resta generar el código para que nuestro Web Service pueda obtener los parámetros de conexión a una base de datos en tiempo de ejecución leyendo un archivo INI.

Para realizar esto usaremos el evento OnCreate del frmDataModule para realizar dicha lectura. Debemos agregar las unidades IniFiles y windows en el uses.



delphi
  1. procedure TfrmDataModule.SoapDataModuleCreate(Sender: TObject);
  2. var
  3.   IniFile: TIniFile;
  4.   DATABASE,SERVER: string;
  5.   S: array[0..MAX_PATH] of Char;
  6. begin
  7.   windows.GetModuleFileName(hInstance, S, SizeOf(S));
  8.   IniFile  := TIniFile.Create(ExtractFileDir(S)+'\params.ini');
  9.   DATABASE := IniFile.ReadString('PARAMETERS','Path','');
  10.   SERVER  := IniFile.ReadString('PARAMETERS','Host','');
  11.   IniFile.Free;
  12.  
  13.   Clientes.Params.Values['HOSTNAME'] := SERVER;
  14.   Clientes.Params.Values['DATABASE'] := SERVER+':'+DATABASE;
  15. end;



El archivo params.ini debe estár en el mismo directorio de nuestro Web Service y deberá contener lo siguiente:

[PARAMETERS]
path="DRIVE:\RUTA\DBCLIENTES.FDB"
host="LOCALHOST"


Con esto hemos terminado nuestro Web Service, compilamos y si todo está correctamente nos creará el archivo WSdbAccess.dll el cual debemos registrar en el IIS, el proceso de registrar el Web Service lo veremos en el siguiente capítulo.

[swurl=#inicio]Regresar al Índice[/swurl]


  • 0

#4 egostar

egostar

    missing my father, I love my mother.

  • Administrador
  • 13.658 mensajes
  • LocationMéxico

Escrito 21 mayo 2009 - 12:33

 
[swname=indice3]Capí­tulo 3. Registrar el Web Service en el IIS[/swname]
[swurl=#inicio]Regresar al Índice[/swurl]
 

Para poder consumir el Web Service necesitamos registrarlo en el IIS de nuestra máquina y en este capí­tulo veremos como registrarlo.

Como les comente al inicio de este tutorial estoy usando lo siguiente :

  • Windows XP Profesional SP3
  • Internet Information Services (IIS) 5.1
Nota: Si alguno de ustedes cuenta con otro windows (Vista, Server 2000, Server 2003) estarí­a agradecido de que nos mostrara la forma de registrarlo en esos sistemas.

Comenzamos por abrir nuestro administrador de IIS y agregamos un nuevo directorio virtual como lo muestro en la siguiente imagen.

Imagen Enviada


Asignamos el Alias del Directorio Virtual que se va a crear, en este caso le he llamado simplemente WSClientes.

[img width=400 height=316]http://egostar.delphiaccess.com/tutoriales/webservice/VD_Alias.PNG[/img]

Capturamos la Ruta donde se localiza nuestra DLL.

[img width=400 height=316]http://egostar.delphiaccess.com/tutoriales/webservice/Directory.PNG[/img]

Y finalmente asignamos los permisos de acceso al Web Service teniendo cuidado de marcar la opción Ejecutar (aplicaciones ISAPI o CGI).

[img width=400 height=316]http://egostar.delphiaccess.com/tutoriales/webservice/Access_Permissions.PNG[/img]

En este momento ya se registró nuestra aplicación para ser consumida a través de protocolo HTTP, para continuar con el siguiente capí­tulo verificamos que nuestro Web Service ya esté disponible usando cualquier explorador de internet y escribiendo la URL correspondiente, en este caso fué la siguente:

http://localhost/WSC.../wsClientes.dll

Si todo está correcto veremos la página de información de nuestro Web Service como lo pueden ver en la siguiente imagen en caso contario deberá revisar la configuración del directorio virtual.

[img width=400 height=240]http://egostar.delphiaccess.com/tutoriales/webservice/wsdbaccess.PNG[/img]

En el siguiente capí­tulo veremos como crear la aplicación cliente que va a consumir nuestro Web Service.

[swurl=#inicio]Regresar al Índice[/swurl]


  • 0

#5 egostar

egostar

    missing my father, I love my mother.

  • Administrador
  • 13.658 mensajes
  • LocationMéxico

Escrito 21 mayo 2009 - 12:59

 
[swname=indice4]Capí­tulo 4. Crear la aplicación Cliente[/swname]
[swurl=#inicio]Regresar al Índice[/swurl]
 

Para comenzar a desarrollar nuestra aplicación cliente, vamos a crear un nuevo proyecto e incluir los siguientes componentes:

  • 4 TLabel (Contacto, Dirección, Teléfonos, email)
  • 3 TButton (Agrega Cliente, Borra Cliente, Actualiza Cliente)
  • 1 TTreeView

Imagen Enviada

Nota: Cabe mencionar que harémos una aplicación muy básica ya que solo es a manera de ejemplo, ustedes podrán generar una interfáz gráfica más robusta si así­ lo desean

El siguiente paso es obtener la URL del WSDL dando clic en IWSdbAccess [WSDL] en la página de información de nuestro Web Service, veremos la definición en formato XML de nuestro Web Service.

[img width=400 height=240]http://egostar.delphiaccess.com/tutoriales/webservice/WSDL.PNG[/img]

Esta dirección (URL) es la que nos va a servir para crear nuestra aplicación cliente a través del WSDL Importer que nos proporciona Delphi, para ello vamos al menu de Delphi:

File --> New --> Other --> WebService --> WSDL Importer

[img width=400 height=302]http://egostar.delphiaccess.com/tutoriales/webservice/WSDL_Importer.PNG[/img]

Clic en el boton OK y nos mostrará una ventana donde debemos de asignar la URL de nuestro WSDL, damos clic en el botón Finish.

[img width=400 height=281]http://egostar.delphiaccess.com/tutoriales/webservice/WSDL_Wizard.PNG[/img]

En seguida nos mostrará otra ventana con la vista previa de nuestra unidad WSDL, damos clic en el botón Finish para terminar.

[img width=400 height=281]http://egostar.delphiaccess.com/tutoriales/webservice/WSDL_Wizard1.PNG[/img]

En este momento Delphi ya creo la unidad IWSdbAccess1.pas la cual contiene los datos del archivo WSDL. Guardamos nuestra unidad y continuamos con el desarrollo de nuestra aplicación.

Lo primero que vamos a hacer antes de implementar nuestras funciones es obtener la estructura de las cadenas XML que nos regresa el WebService en las funciones:



delphi
  1.     function  GetClientNames: WideString; stdcall;
  2.     function  GetClientsData(const EmpID: Integer): WideString; stdcall;



Para ello vamos a generar dos archivos con fomato XML como se ve a continuación:

ClientList.xml



delphi
  1. <ClientList>
  2.       <cliente_id>1</cliente_id>
  3.       <nombre>JUAN</nombre>
  4.       <apellidos>PEREZ</apellidos>
  5.       <cliente_id>2</cliente_id>
  6.       <nombre>ROSA</nombre>
  7.       <apellidos>MARTINEZ</apellidos>
  8. </ClientList>



ClientData.xml



delphi
  1. <ClientData>
  2.       <cliente_id>1</cliente_id>
  3.       <titulo_cliente>SRA.</titulo_cliente>
  4.       <nombre>REMEDIOS</nombre>
  5.       <apellidos>CASEROS</apellidos>
  6.       <fecha_nacimiento>01/01/1980</fecha_nacimiento>
  7.       <direccion>CALLE DE LA AMARGURA</direccion>
  8.       <ciudad>DE LA INFLUENZA</ciudad>
  9.       <pais>MEXICO</pais>
  10.       <codigo_postal>1111_</codigo_postal>
  11.       <telefono_casa>55-5122-4354</telefono_casa>
  12.       <telefono_trabajo>55-5431-1767</telefono_trabajo>
  13.       <telefono_celular>55-2342-7879</telefono_celular>
  14.       <correo_electronico>usuario@delphiaccess.com</correo_electronico>
  15. </ClientData>



Te estarás preguntando para que hacemos esto, bueno, vamos a crear dos clase con la estructura de los archivos XML anteriores utilizando el XML Data Binding el cual nos permitirá acceder a los datos como si se tratara de un objeto.

Para hacer esto desde el menú de Delphi:

File --> New --> Other --> XML --> XML Data Binding

[img width=400 height=302]http://egostar.delphiaccess.com/tutoriales/webservice/XML_Data_Binding.PNG[/img]

Presionamos OK y nos pedirá el archivo XML que vamos a representar como un objeto.

[img width=400 height=263]http://egostar.delphiaccess.com/tutoriales/webservice/XML_Data_File.PNG[/img]

Presionamos Next y nos mostrará la estructura del archivo XML en forma de objeto. Presionamos Next para continuar.

[img width=400 height=263]http://egostar.delphiaccess.com/tutoriales/webservice/Schema_Component.PNG[/img]

Finalmente nos muestra la Interfaz generada y la vista previa del código de la clase, presionamos Finish para terminar.

[img width=400 height=263]http://egostar.delphiaccess.com/tutoriales/webservice/Binding_Summary.PNG[/img]

Nota: Esto deberá realizarse para cada uno de los archivos XML generados ClientList.XML y ClientData.XML.

Este proceso nos generará dos unidades con la definición de los objetos y su implementación la cual usaremos en nuestro código.

ClientList.pas



delphi
  1. type
  2.  
  3. { Forward Decls }
  4.  
  5.   IXMLClientListType = interface;
  6.  
  7. { IXMLClientListType }
  8.  
  9.   IXMLClientListType = interface(IXMLNode)
  10.     ['{9F055206-DF3E-4BA2-BE35-E1C26BD6CF35}']
  11.     { Property Accessors }
  12.     function Get_Cliente_id: Integer;
  13.     function Get_Nombre: WideString;
  14.     function Get_Apellidos: WideString;
  15.     procedure Set_Cliente_id(Value: Integer);
  16.     procedure Set_Nombre(Value: WideString);
  17.     procedure Set_Apellidos(Value: WideString);
  18.     { Methods & Properties }
  19.     property Cliente_id: Integer read Get_Cliente_id write Set_Cliente_id;
  20.     property Nombre: WideString read Get_Nombre write Set_Nombre;
  21.     property Apellidos: WideString read Get_Apellidos write Set_Apellidos;
  22.   end;



ClientData.pas



delphi
  1. type
  2.  
  3. { Forward Decls }
  4.  
  5.   IXMLClientDataType = interface;
  6.  
  7. { IXMLClientDataType }
  8.  
  9.   IXMLClientDataType = interface(IXMLNode)
  10.     ['{35537620-0491-4F50-8C11-E359974601C7}']
  11.     { Property Accessors }
  12.     function Get_Cliente_id: Integer;
  13.     function Get_Titulo_cliente: WideString;
  14.     function Get_Nombre: WideString;
  15.     function Get_Apellidos: WideString;
  16.     function Get_Fecha_nacimiento: WideString;
  17.     function Get_Direccion: WideString;
  18.     function Get_Ciudad: WideString;
  19.     function Get_Pais: WideString;
  20.     function Get_Codigo_postal: Integer;
  21.     function Get_Telefono_casa: Integer;
  22.     function Get_Telefono_trabajo: Integer;
  23.     function Get_Telefono_celular: Integer;
  24.     function Get_Correo_electronico: WideString;
  25.     procedure Set_Cliente_id(Value: Integer);
  26.     procedure Set_Titulo_cliente(Value: WideString);
  27.     procedure Set_Nombre(Value: WideString);
  28.     procedure Set_Apellidos(Value: WideString);
  29.     procedure Set_Fecha_nacimiento(Value: WideString);
  30.     procedure Set_Direccion(Value: WideString);
  31.     procedure Set_Ciudad(Value: WideString);
  32.     procedure Set_Pais(Value: WideString);
  33.     procedure Set_Codigo_postal(Value: Integer);
  34.     procedure Set_Telefono_casa(Value: Integer);
  35.     procedure Set_Telefono_trabajo(Value: Integer);
  36.     procedure Set_Telefono_celular(Value: Integer);
  37.     procedure Set_Correo_electronico(Value: WideString);
  38.     { Methods & Properties }
  39.     property Cliente_id: Integer read Get_Cliente_id write Set_Cliente_id;
  40.     property Titulo_cliente: WideString read Get_Titulo_cliente write Set_Titulo_cliente;
  41.     property Nombre: WideString read Get_Nombre write Set_Nombre;
  42.     property Apellidos: WideString read Get_Apellidos write Set_Apellidos;
  43.     property Fecha_nacimiento: WideString read Get_Fecha_nacimiento write Set_Fecha_nacimiento;
  44.     property Direccion: WideString read Get_Direccion write Set_Direccion;
  45.     property Ciudad: WideString read Get_Ciudad write Set_Ciudad;
  46.     property Pais: WideString read Get_Pais write Set_Pais;
  47.     property Codigo_postal: Integer read Get_Codigo_postal write Set_Codigo_postal;
  48.     property Telefono_casa: Integer read Get_Telefono_casa write Set_Telefono_casa;
  49.     property Telefono_trabajo: Integer read Get_Telefono_trabajo write Set_Telefono_trabajo;
  50.     property Telefono_celular: Integer read Get_Telefono_celular write Set_Telefono_celular;
  51.     property Correo_electronico: WideString read Get_Correo_electronico write Set_Correo_electronico;
  52.   end;



Ahora si ya estamos listos para implementar nuestras funciones que consumirán el Web Service

Agregamos las unidades ClientList.pas y ClientData.pas y las siguientes variables a nuestro proyecto.



delphi
  1. uses 
  2.   Windows, Messages, SysUtils, ..........., IwsClientes1, ClientData, ClientList;
  3.  
  4.   TfrmAppCliente = class(TForm)
  5.   private
  6.     { Private declarations }
  7.   public
  8.     { Public declarations }
  9.     Resultado: trRetorno;
  10.   end;
  11.  
  12. var
  13.   XMLString: widestring;
  14.   Archivo: textFile;
  15.   Indice: integer;
  16.   Lista: IXMLClientListType;
  17.   Detalle: IXMLClientDataType;



Lo primero que vamos a hacer es recuperar la información que se tenga en la base de datos usando el evento OnShow de nuestra forma y mostrando la lista de clientes dentro del TreeView.

Para ello colocamos el siguiente código en dicho evento.



delphi
  1. procedure TfrmAppCliente.FormShow(Sender: TObject);
  2. var
  3.   I: Integer;
  4. begin
  5.   XMLString := GetIwsClientes.GetClientNames;
  6.   CreaXML('Names.XML',XMLString);
  7.   Lista := ClientList.LoadClientList('Names.XML');
  8.   TreeView1.Items.Clear;
  9.   with Lista do begin
  10.     if Cliente_id.Count > 0 then begin
  11.         for I := 0 to Cliente_id.Count - 1 do begin
  12.             TreeView1.Items.Add(nil,format('%.*d',[3,Cliente_id[i]])+' '+
  13.                                                     Nombre[i]+' '+
  14.                                                     Apellidos[i]);
  15.       end;
  16.     end;
  17.   end;
  18.   TreeView1.SetFocus;
  19. end;



XMLString := GetIwsClientes.GetClientNames;

En este código lo que estamos haciendo es hacer la llamada a la función GetClientNames de nuestro WebService.

CreaXML('Names.XML',XMLString);

En esta lí­nea creamos un archivo con la información obtenida en la variable XMLString con la función CreaXML que contiene un código muy simple.



delphi
  1. procedure CreaXML(Nombre:string;textXML:WideString);
  2. begin
  3.   assignFile(Archivo,Nombre);
  4.   Rewrite(Archivo);
  5.   Write(Archivo,textXML);
  6.   closeFile(Archivo);
  7. end;



Lista := ClientList.LoadClientList('Names.XML');

En esta lí­nea cargamos desde el archivo creado la lista de clientes dentro del objeto Lista del tipo IXMLClientListType que fué creado con el XML Data Binding.

Agregamos los datos dentro del TreeView y le asignamos el foco.

En este momento ya tenemos preparada la primera fase, ahora vamos a mostrar (si se tiene) el detalle del primer cliente mostrado en el TreeView y utilizaremos el evento OnChange del TreeView.

Este es el código que usaremos.



delphi
  1. procedure TfrmAppCliente.TreeView1Change(Sender: TObject; Node: TTreeNode);
  2. begin
  3.   Indice := strtoint(Copy(TreeView1.Selected.Text,1,3));
  4.   XMLString := GetIwsClientes.GetClientsData(Indice);
  5.   CreaXML('Data.XML',XMLString);
  6.   Detalle := LoadClientData('Data.XML');
  7.   MuestraDatos;
  8. end;



Como podemos observar, en este código estamos recuperando la información del Item seleccionado y creando dentro del objeto Detalle de tipo IXMLClientDataType que se generó con el XML Data Binding y al final ejecuta un procedimiento llamado MuestraDatos el cual debemos agregar en la sección Private de nuestra forma.



delphi
  1.   private
  2.     { Private declarations }
  3.     procedure MuestraDatos;



La implementación de este procedimiento es el siguiente:



delphi
  1. procedure TfrmAppCliente.MuestraDatos;
  2. begin
  3.   label1.Caption := 'Contacto: ' + #9 + Detalle.Titulo_cliente + ' ' +
  4.                     Detalle.Nombre + ' ' +
  5.                     Detalle.Apellidos;
  6.   label2.Caption := 'Dirección: ' + #9 + Detalle.Direccion + #13#9#9 +
  7.                     Detalle.Ciudad + #13#9#9 +Detalle.Pais + #13#9#9 +
  8.                     'CP ' + Detalle.Codigo_postal;
  9.   label3.Caption := 'Telefonos: '+#9+'['+ Detalle.Telefono_casa + ']'+#13#9#9+'[' +
  10.                     Detalle.Telefono_trabajo + ']'+#13#9#9+'[' +
  11.                     Detalle.Telefono_celular + ']';
  12.   label4.Caption := 'email: ' + #9#9 + Detalle.Correo_electronico;
  13. end;



Lo que hace este código es concatenar dentro de los Label los datos contenidos en el objeto Detalle mostrando la iniformación completa del cliente seleccionado.

La siguiente fase es crear una ventana que nos permita agregar y/o modificar los datos del cliente.

Para ellos agregamos una nueva forma y agregamos los siguientes componentes:

  • 12 TLabel
  • 9 TEdit
  • 1 TComboBox
  • 1 TDateTimePicker
  • 1 TMaskEdit
  • 2 TButton
Acomodamos dichos componentes de la siguiente forma:

[img width=400 height=261]http://egostar.delphiaccess.com/tutoriales/webservice/Movs_Cliente.PNG[/img]

Nota: Los botones deberán configurarse en su propiedad ModalResult, a la ejecución de la función asignando mrOK y a la cancelación mrCancel. Esto es muy importante como se verá mas adelante.

Esta forma nos será útil para dos propósitos, para Agregar y para Modificar los datos del cliente, veamos como hacer esto.

Agregamos dos variables públicas y agregamos las unidades IwsClientes1, uAppCliente en el uses de la forma.



delphi
  1.   public
  2.     { Public declarations }
  3.     Proceso: integer;
  4.     EmpID: integer;
  5.   end;
  6.  
  7. implementation
  8.  
  9. uses IwsClientes1, uAppCliente;



La variable Proceso nos servirá para saber que función vamos a ejecutar en nuestro Web Service y la variable EmpID nos servirá para la función UpdateCient de nuestro Web Service

El botón Agrega Cliente que mostrará la leyenda dependiendo del proceso que se esté ejecutando contendrá el siguiente código:



delphi
  1. procedure TfrmProcClient.Button1Click(Sender: TObject);
  2. var
  3.   Params: trParams;
  4. begin
  5.   params := trParams.Create;
  6.   with params do begin
  7.     Titulo    := comboBox1.Text;
  8.     Nombre    := edit2.Text;
  9.     Apellidos  := edit3.Text;
  10.     Fecha      := datetostr(DatetimePicker1.Date);
  11.     Direccion  := edit5.Text;
  12.     Ciudad    := edit6.Text;
  13.     Pais      := edit7.Text;
  14.     CodPostal  := maskedit1.Text;
  15.     TelCasa    := edit9.Text;
  16.     TelOficina := edit10.Text;
  17.     Celular    := edit11.Text;
  18.     Correo    := edit12.Text;
  19.   end;
  20.   with frmAppCliente do begin
  21.     case proceso of
  22.       1: Resultado := GetIwsClientes.AddClient(params);
  23.       2: Resultado := GetIwsClientes.UpdateClient(EmpID,params)
  24.     end;
  25.     ShowMessage(inttostr(Resultado.ID)+': '+Resultado.Descripcion);
  26.   end;
  27.   params.Free;
  28. end;



El botón Cancelar contendrá el siguiente código:



delphi
  1. procedure TfrmProcClient.Button2Click(Sender: TObject);
  2. begin
  3.   ShowMessage('Proceso Cancelado');
  4.   Close;
  5. end;



Con esto hemos terminado la configuración de esta ventana  y continuamos con nuestro proyecto.

Regresamos a la unidad principal e implementaremos las funciones de Agregar, Borrar y Modificar clientes.

Función Agregar Clientes

Antes de continuar debemos "mover" en las opciones de nuestro proyecto la Form de Procesos como se muestra en la siguiente imagen:

[img width=400 height=280]http://egostar.delphiaccess.com/tutoriales/webservice/Project_Options.PNG[/img]

Con el siguiente código se ejecutará el proceso de agregar un cliente a nuestra base de datos configurando las opciones de Caption tanto de la forma como del botón de ejecutar proceso y asignando el proceso que se va a ejecutar en la variable pública proceso validando si se ha ejecutado el botón de Agrega Cliente en la forma creada y actuando en consecuencia.



delphi
  1. procedure TfrmAppCliente.Button1Click(Sender: TObject);
  2. var
  3.   FAddClient : TfrmProcClient;
  4.   I: integer;
  5. begin
  6.   FAddClient := TfrmProcClient.Create(nil);
  7.   FAddClient.Caption := 'Agrega Cliente consumiendo Web Service';
  8.   FAddClient.Button2.Caption := 'Agrega Cliente';
  9.   FAddClient.Proceso := 1;
  10.   FAddClient.ShowModal;
  11.   if FAddClient.ModalResult = mrOK then begin
  12.     XMLString := GetIwsClientes.GetClientNames;
  13.     CreaXML('Names.XML',XMLString);
  14.     Lista := ClientList.LoadClientList('Names.XML');
  15.     TreeView1.Items.Clear;
  16.     with Lista do begin
  17.         if Cliente_id.Count > 0 then begin
  18.           for I := 0 to Cliente_id.Count - 1 do begin
  19.               TreeView1.Items.Add(nil,format('%.*d',[3,Cliente_id[i]])+' '+
  20.                                                         Nombre[i]+' '+
  21.                                                         Apellidos[i]);
  22.           end;
  23.         end;
  24.     end;
  25.     TreeView1.SetFocus;
  26.   end;
  27.   FAddClient.Free;
  28. end;



Función Actualiza Cliente

El siguiente código ejecutará el proceso de actualizar un cliente en nuestra base de datos configurando las opciones de Caption tanto de la forma como del botón de ejecutar proceso, asignando el proceso que se va a ejecutar en la variable pública proceso y asignando el ID del cliente que se va a modificar vaidando si se ha seleccionado algún cliente de la lista y validando si se ejecutó el proceso de Actualiza Cliente de la forma creada y actuando en consecuencia.



delphi
  1. procedure TfrmAppCliente.Button2Click(Sender: TObject);
  2. var
  3.   FUpdateClient: TfrmProcClient;
  4.   I: integer;
  5. begin
  6.   if TreeView1.Items.Count > 0 then begin
  7.     if trystrtoint(Copy(TreeView1.Selected.Text,1,3), Indice) then begin
  8.       FUpdateClient := TfrmProcClient.Create(nil);
  9.       XMLString := GetIwsClientes.GetClientsData(Indice);
  10.       CreaXML('Data.XML',XMLString);
  11.       Detalle := ClientData.LoadClientData('Data.XML');
  12.       with FUpdateClient do begin
  13.           ComboBox1.Text := Detalle.Titulo_cliente;
  14.           edit2.Text := Detalle.Nombre;
  15.           edit3.Text := Detalle.Apellidos;
  16.           DatetimePicker1.Date := strtodate(Detalle.Fecha_nacimiento);
  17.           edit5.Text := Detalle.Direccion;
  18.           edit6.Text := Detalle.Ciudad;
  19.           edit7.Text := Detalle.Pais;
  20.           maskedit1.Text := Detalle.Codigo_postal;
  21.           edit9.Text := Detalle.Telefono_casa;
  22.           edit10.Text := Detalle.Telefono_trabajo;
  23.           edit11.Text := Detalle.Telefono_celular;
  24.           edit12.Text := Detalle.Correo_electronico;
  25.       end;
  26.       FUpdateClient.Caption := 'Modifica Cliente consumiendo Web Service';
  27.       FUpdateClient.Button2.Caption := 'Modifica Cliente';
  28.       FUpdateClient.EmpID := Indice;
  29.       FUpdateClient.Proceso := 2;
  30.       FUpdateClient.ShowModal;
  31.       FUpdateClient.Free;
  32.       XMLString := GetIwsClientes.GetClientNames;
  33.       CreaXML('Names.XML',XMLString);
  34.       Lista := ClientList.LoadClientList('Names.XML');
  35.       TreeView1.Items.Clear;
  36.       with Lista do begin
  37.         if Cliente_id.Count > 0 then begin
  38.             for I := 0 to Cliente_id.Count - 1 do begin
  39.                 TreeView1.Items.Add(nil,format('%.*d',[3,Cliente_id[i]])+' '+
  40.                                                         Nombre[i]+' '+
  41.                                                         Apellidos[i]);
  42.             end;
  43.         end;
  44.     end;
  45.     TreeView1.SetFocus;
  46.     end;
  47.   end
  48.   else begin
  49.         ShowMessage('No se ha seleccionado ningún registro');
  50.   end;
  51. end;



Función Borra Cliente

Ahora implementaremos el código de Borrar Cliente validando si se ha seleccionado algún cliente de la lista y actuando en consecuencia.



delphi
  1. procedure TfrmAppCliente.Button3Click(Sender: TObject);
  2. var
  3.   I: integer;
  4.  
  5.   procedure Limpia_Detalle;
  6.   begin
  7.     label1.Caption := 'Contacto: ';
  8.     label2.Caption := 'Dirección: ';
  9.     label3.Caption := 'Telefonos: ';
  10.     label4.Caption := 'email: ';
  11.   end;
  12.  
  13. begin
  14.   Resultado := trRetorno.Create;
  15.   if TreeView1.Items.Count > 0 then begin
  16.     if trystrtoint(Copy(TreeView1.Selected.Text,1,3), Indice) then begin
  17.         Resultado := GetIwsClientes.DeleteClient(Indice);
  18.         ShowMessage(inttostr(Resultado.ID)+': '+Resultado.Descripcion);
  19.         XMLString := GetIwsClientes.GetClientNames;
  20.         CreaXML('Names.XML',XMLString);
  21.         Lista := ClientList.LoadClientList('Names.XML');
  22.         TreeView1.Items.Clear;
  23.         Limpia_Detalle;
  24.         with Lista do begin
  25.           if Cliente_id.Count > 0 then begin
  26.             for I := 0 to Cliente_id.Count - 1 do begin
  27.                 TreeView1.Items.Add(nil,format('%.*d',[3,Cliente_id[i]])+' '+
  28.                                                           Nombre[i]+' '+
  29.                                                           Apellidos[i]);
  30.             end;
  31.           end;
  32.         end;
  33.     end;
  34.   end
  35.   else begin
  36.         ShowMessage('No se ha seleccionado ningún registro');
  37.   end;
  38.   Resultado.Free;
  39.   TreeView1.SetFocus;
  40. end;



Por último vamos a modificar nuestra unidad IwsClientes1 para que podamos modificar en tiempo de ejecución los valores de nuestro WSDL y la URL de nuestro Web Service lo cual nos será muy útil para ejecutar nuestra aplicación cliente desde otras computadoras ya sea en la Red Local o en Internet.

Cuando nuestra unidad IwsClientes1 nos generó las constantes mencionadas de esta forma:



delphi
  1. function GetIwsClientes(UseWSDL: Boolean; Addr: string; HTTPRIO: THTTPRIO): IwsClientes;
  2. const
  3.   defWSDL = '[url]http://localhost/WSClientes/wsClientes.dll/wsdl/IwsClientes';[/url]
  4.   defURL  = '[url]http://localhost/WSClientes/wsClientes.dll/soap/IwsClientes';[/url]
  5.   defSvc  = 'IwsClientesservice';
  6.   defPrt  = 'IwsClientesPort';



Lo que vamos a hacer es "convertir" las constantes defWSDL y defURL a variables para poder modificarlas en tiempo de ejecución y asignarlas a través de la lectura de un archivo INI y agregar varias unidades en el uses



delphi
  1. uses SysUtils, IniFiles, Forms;
  2.  
  3. var
  4.   IniFile: TIniFile;
  5.   defWSDL,defURL : widestring; //Extraemos estas constantes para convertirlas
  6.                               //en variables y poder manipularlas en tiempo de ejecución



Agregamos el código necesario para leer el archivo INI y para asignar los valores a dichas variables como se indica a continuación:



delphi
  1.   IniFile := TIniFile.Create(ExtractFilePath(Application.ExeName)+'conf.ini');
  2.   defWSDL := IniFile.ReadString('CONFIGURACION','WSDL','');
  3.   defURL  := IniFile.ReadString('CONFIGURACION','URL','');
  4.   IniFile.Free;



Esto deberá agregarse a la función:



delphi
  1. function GetIwsClientes(UseWSDL: Boolean; Addr: string; HTTPRIO: THTTPRIO): IwsClientes;



Y finalmente la función deberá quedar de la siguiente forma:



delphi
  1. implementation
  2.  
  3. uses SysUtils, IniFiles, Forms;
  4.  
  5. var
  6.   IniFile: TIniFile;
  7.   defWSDL,defURL : widestring; //Extraemos estas constantes para convertirlas
  8.                               //en variables y poder manipularlas en "runtime"
  9.  
  10. function GetIwsClientes(UseWSDL: Boolean; Addr: string; HTTPRIO: THTTPRIO): IwsClientes;
  11. const
  12.   defSvc  = 'IwsClientesservice';
  13.   defPrt  = 'IwsClientesPort';
  14. var
  15.   RIO: THTTPRIO;
  16. begin
  17.   IniFile := TIniFile.Create(ExtractFilePath(Application.ExeName)+'conf.ini');
  18.   defWSDL := IniFile.ReadString('CONFIGURACION','WSDL','');
  19.   defURL  := IniFile.ReadString('CONFIGURACION','URL','');
  20.   IniFile.Free;
  21.   Result := nil;
  22.   if (Addr = '') then
  23.   begin
  24.     if UseWSDL then
  25.       Addr := defWSDL
  26.     else
  27.       Addr := defURL;
  28.   end;
  29.   if HTTPRIO = nil then
  30.     RIO := THTTPRIO.Create(nil)
  31.   else
  32.     RIO := HTTPRIO;
  33.   try
  34.     Result := (RIO as IwsClientes);
  35.     if UseWSDL then
  36.     begin
  37.       RIO.WSDLLocation := Addr;
  38.       RIO.Service := defSvc;
  39.       RIO.Port := defPrt;
  40.     end else
  41.       RIO.URL := Addr;
  42.   finally
  43.     if (Result = nil) and (HTTPRIO = nil) then
  44.       RIO.Free;
  45.   end;
  46. end;



Para que esto funcione correctamente necesitaremos crear un Archivo INI de nombre conf.ini en el directorio de nuestra aplicación y deberá contener lo siguiente:



delphi
  1. [CONFIGURACION]
  2. WSDL="http://localhost/WSClientes/WSClientes.dll/wsdl/IwsClientes"
  3. URL="http://localhost/WSClientes/WSClientes.dll/soap/IwsClientes"



Compilamos y ejecutamos nuestra aplicación cliente y si todo se ha realizado correctamente ya tenemos nuestra aplicación funcionando y consumiendo las funciones del Web Service.


[swurl=#inicio]Regresar al Índice[/swurl]


  • 0

#6 egostar

egostar

    missing my father, I love my mother.

  • Administrador
  • 13.658 mensajes
  • LocationMéxico

Escrito 21 mayo 2009 - 01:11

 
[swname=indice5]Apéndice I[/swname]
[swurl=#inicio]Regresar al Índice[/swurl]
 

Una vez que hemos probado la aplicación en nuestra maquina, nos enfrentamos al reto de ejecutarla en un ambiente real, es decir, consumir nuestro Web Service desde la Red Local (Intranet) y desde Internet.

Consumir nuestro Web Service en la Red Local:

Para las pruebas en la Red Local tuve que abrir el puerto 80 de la computadora donde reside la DLL y la base de datos del Web Service y en otra máquina de la Red Local, ejecuté la aplicación Cliente que consumirí­a el Web Service modificando el archivo Conf.Ini asignado los valores del WSDL y el URL de la maquina donde corre el Web Service.

[CONFIGURACION]
WSDL="http://NombreServido...sdl/IwsClientes"
URL="http://NombreServido...oap/IwsClientes"

Imagen Enviada

Consumir nuestro Web Service desde Internet:

Para la prueba en Internet, tuve que abrir mi firewall para que pudieran entrar las peticiones desde Internet realizando un NAT de la IP Pública a la IP Privada de la máquina donde corre el Web Service

Envié la Aplicación Cliente a mis buenos amigos cHackAll y enecumene (gracias por ayudarme a hacer estas pruebas) y modificamos el archivo Config.Ini asignado los valores del WSDL y el URL como se muestra a continuación.

[CONFIGURACION]
WSDL="http://minombre.no-i...sdl/IwsClientes"
URL="http://minombre.no-i...oap/IwsClientes"


Nota: Cabe mencionar que mi IP es dinámica y utilizo NO-IP DUC para que mi IP sea alcanzada desde Internet.

El acceso a mi Web Service se hizo desde dos paises diferentes y sin ningún problema (lo que me lleno de gran entusiasmo  )

Imagen Enviada

Prueba superada

Con esto doy por terminado este Tutorial esperando que sea de utilidad y sobre todo que les ayude a crear aplicaciones realmente robustas.


[swurl=#inicio]Regresar al Índice[/swurl]


Solo quiero agregar que el código expuesto puede tener algunas "carencias" sobre todo por mi limitado conocimiento (como dicen algunos Know-How)  y por la poca información que pude encontrar para la realización del mismo por lo que los invito a mejorar este código a fin de que sea una gran referencia para los que buscamos esta información.

Salud OS


  • 0

#7 cHackAll

cHackAll

    Advanced Member

  • Administrador
  • 598 mensajes

Escrito 21 mayo 2009 - 01:40

Aunque ya he tenido un preview de este tema gracias a ti, debo decir que hiciste un excelente trabajo eliseo, gracias por el aporte y a estudiarlo se dijo!
  • 0

#8 Caral

Caral

    Advanced Member

  • Administrador
  • 4.218 mensajes
  • LocationCosta Rica

Escrito 21 mayo 2009 - 01:44

Hola
Amigo, esto no era un tutorial??, esto es todo un libro. :D
Impresionante trabajo amigo.
Saludos
  • 0

#9 enecumene

enecumene

    Webmaster

  • Administrador
  • 7.239 mensajes
  • LocationRepública Dominicana

Escrito 21 mayo 2009 - 02:05

Tremenda calidad, dudo que aparezca otro tutorial de esta magnitud, felicidades amigo ;).

Saludos.
  • 0

#10 Kipow

Kipow

    Advanced Member

  • Miembro Platino
  • PipPipPip
  • 228 mensajes
  • LocationGuatemala

Escrito 21 mayo 2009 - 02:31

Excelente tutorial yo nunca he hecho un Webservice, pero con esto creo que tengo idea de por donde empezar. muchas gracias.
  • 0

#11 poliburro

poliburro

    Advanced Member

  • Administrador
  • 4.937 mensajes
  • LocationMéxico

Escrito 21 mayo 2009 - 03:57

Excelente trabajo, se nota el esfuerzo por hacer algo bien y con calidad, coincido en que será dificilmente igualable.

Saludos.
  • 0

#12 egostar

egostar

    missing my father, I love my mother.

  • Administrador
  • 13.658 mensajes
  • LocationMéxico

Escrito 21 mayo 2009 - 04:53

Gracias amigos, la verdad que si me costo mucho desarrollar este material, obviamente porque me hace falta conocimiento y experiencia. Lo mejor de todo es que he aprendido mucho haciendolo.

Espero que lo sigan paso a paso y lo retroalimenten con las mejoras al código que seguro son muchas o casi todo y así­ poder tener un documento digno de ser referenciado en la web.

Salud OS
  • 0

#13 axesys

axesys

    Advanced Member

  • Moderadores
  • PipPipPip
  • 620 mensajes
  • LocationLos Mochis

Escrito 21 mayo 2009 - 11:55

Esta muy bueno el tutorial, haber si luego puedes hacer uno usando glassfish para los webservices y con hibernate para modificar cualquier base de datos, así­ ya se simplificarí­a mucho el código en el lado del servidor y el cliente igual en delphi pero sin eso de crear xmls.


Saludos
  • 0

#14 escafandra

escafandra

    Advanced Member

  • Moderadores
  • PipPipPip
  • 3.691 mensajes
  • LocationMadrid - España

Escrito 22 mayo 2009 - 12:15

Sólo una palabra, tremendo. Tremendo en contenido y tremendo en calidad.

Sabemos la ilusión y el esfuerzo que has puesto en este trabajo. Enhorabuena, amigo.  (y)

Saludos.
  • 0

#15 Delphius

Delphius

    Advanced Member

  • Administrador
  • 5.991 mensajes
  • LocationArgentina

Escrito 22 mayo 2009 - 10:59

He estado leyendo este tutorial desde que estuvo en borrador... y debo decir amigo ¡que pedazo de tutorial! (y) :D Muy bueno.

Ahora será cosa de leerlo mucho más tranquilo y pausado para poder estudiar bien y llevarlo a la práctica. Hay cosas interesantes que se pueden llevar a cabo, algunas ideas pueden rondar... pero serán en un momento a futuro.

Saludos,
  • 0

#16 egostar

egostar

    missing my father, I love my mother.

  • Administrador
  • 13.658 mensajes
  • LocationMéxico

Escrito 22 mayo 2009 - 11:14

Hola

haber si luego puedes hacer uno usando glassfish para los webservices y con hibernate para modificar cualquier base de datos


Muchas gracias amigo axesys, primero dejame saber que es glassfish e hibernate y después vemos :)

Sabemos la ilusión y el esfuerzo que has puesto en este trabajo. Enhorabuena, amigo.



Gracias amigo escafandra, espero que al menos a un lector le sea útil :)

Hay cosas interesantes que se pueden llevar a cabo, algunas ideas pueden rondar... pero serán en un momento a futuro.


Eso precisamente es lo que me gustarí­a amigo Delphius, que los que si saben, nutran con su calidad este tutorial ya que como podrás ver, tiene muchas carencias propias de mis limitaciones.

Salud OS

  • 0

#17 markdelphi

markdelphi

    Advanced Member

  • Moderadores
  • PipPipPip
  • 97 mensajes
  • LocationMéxico

Escrito 22 mayo 2009 - 11:16

Muchas felicidades Eliseo, me parece un estupendo tutorial voy a tener que leerlo detenidamente y a profundidad y ponerlo en practica. Ya vez y dices que no eres bueno para la redacción.  (y) 
  • 0

#18 egostar

egostar

    missing my father, I love my mother.

  • Administrador
  • 13.658 mensajes
  • LocationMéxico

Escrito 22 mayo 2009 - 11:28

Muchas felicidades Eliseo, me parece un estupendo tutorial voy a tener que leerlo detenidamente y a profundidad y ponerlo en practica. Ya vez y dices que no eres bueno para la redacción.  (y)


Pues sigo diciendolo amigo, nadamas de ver tu redacción, la de Delphius, de Al, etc... pues nada que ver :)

Muchas gracias,

Salud OS
  • 0

#19 Delphius

Delphius

    Advanced Member

  • Administrador
  • 5.991 mensajes
  • LocationArgentina

Escrito 22 mayo 2009 - 12:07

Eso precisamente es lo que me gustarí­a amigo Delphius, que los que si saben, nutran con su calidad este tutorial ya que como podrás ver, tiene muchas carencias propias de mis limitaciones.

Salud OS

Pues amigo, yo de WebServices no tengo ni la más remota idea :s. Este hermoso y bien elaborado tutorial puede ayudar a comprender mejor, y eso llevará a nuevas ideas.


Pues sigo diciendolo amigo, nadamas de ver tu redacción, la de Delphius, de Al, etc... pues nada que ver :)

Muchas gracias,

Salud OS

Pues, creo que tienes razón. Nada que ver... que se puede esperar de un gallego cuadrado :p... el resto con una sobriedad y delicadeza al elegir las mejores palabras. :D

Saludos,

  • 0

#20 Wilson

Wilson

    Advanced Member

  • Moderadores
  • PipPipPip
  • 2.135 mensajes

Escrito 23 mayo 2009 - 12:28

Egostar, Felicitaciones es un excelente trabajo que sin duda nos va servir mucho; aportes como este y el de otros compañeros del foro van colocando a DELPHIACCESS a la cabeza de los sitios Delphi en español.

Muchas gracias a todos por compartir.

Saludos
  • 0