Comunidad Delphiaccess

Por favor ingresa o regístrate.

Ingresar con nombre de usuario, contraseña y duración de la sesión

Noticias y Eventos:




Autor Tema: Consumir WebService con acceso a Base de Datos  (Leído 4966 veces)

0 Usuarios y 1 Visitante están viendo este tema.

« en: 21 de Mayo de 2009, 13:26:29 »
En línea

egostar

  • Administrador
  • ******
  • Calificaciones: +186/-6
  • Desconectado Desconectado
  • Sexo: Masculino
  • Mensajes: 5,415
  • Gracias
  • -Dados: 255
  • -Recibidos: 153
Consumir WebService con acceso a Base de Datos
« en: 21 de Mayo de 2009, 13:26:29 »
Índice

Introducción
Capítulo 1. Crear nuestra base de datos
Capítulo 2. Crear el Web Service
Capítulo 2.1 Creamos un Nuevo Proyecto
Capítulo 2.2 Creamos la Conectividad con la Base de Datos
Capítulo 2.3 La Clase TRemotable
Capítulo 2.4 Creando las funciones del ABM
Capítulo 3. Registrar el Web Service en el IIS
Capítulo 4. Crear la aplicación Cliente
Apéndice I


Introducción
Regresar al Índice

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.

« última modificación: 18 de Febrero de 2010, 10:20:29 por egostar »

"Nunca interrumpas a tu enemigo cuando está cometiendo un error."

- Napoleon Bonaparte


 

«Responder #1 en: 21 de Mayo de 2009, 13:28:03 »
En línea

egostar

  • Administrador
  • ******
  • Calificaciones: +186/-6
  • Desconectado Desconectado
  • Sexo: Masculino
  • Mensajes: 5,415
  • Gracias
  • -Dados: 255
  • -Recibidos: 153
Capítulo 1. Crear nuestra base de datos
« Respuesta #1 en: 21 de Mayo de 2009, 13:28:03 »

Capítulo 1. Crear nuestra base de datos
Regresar al índice

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:

Código: [Seleccionar]
/******************************************************************************/
/***               Generated by IBExpert 20/05/2009 15:13:56                ***/
/******************************************************************************/
 
SET SQL DIALECT 3;
 
SET NAMES NONE;
 
 
 
/******************************************************************************/
/***                                 Tables                                 ***/
/******************************************************************************/
 
 
CREATE GENERATOR GEN_CLIENTES_ID;
 
CREATE TABLE CLIENTES (
   CLIENTE_ID          INTEGER NOT NULL,
   TITULO_CLIENTE      VARCHAR(10),
   NOMBRE              VARCHAR(50),
   APELLIDOS           VARCHAR(50),
   FECHA_NACIMIENTO    DATE,
   DIRECCION           VARCHAR(100),
   CIUDAD              VARCHAR(50),
   PAIS                VARCHAR(50),
   CODIGO_POSTAL       VARCHAR(5),
   TELEFONO_CASA       VARCHAR(20),
   TELEFONO_TRABAJO    VARCHAR(20),
   TELEFONO_CELULAR    VARCHAR(20),
   CORREO_ELECTRONICO  VARCHAR(100)
);
 
 
 
 
/******************************************************************************/
/***                              Primary Keys                              ***/
/******************************************************************************/
 
ALTER TABLE CLIENTES ADD CONSTRAINT PK_CLIENTES PRIMARY KEY (CLIENTE_ID);
 
 
/******************************************************************************/
/***                                Triggers                                ***/
/******************************************************************************/
 
 
SET TERM ^ ;
 
 
/******************************************************************************/
/***                          Triggers for tables                           ***/
/******************************************************************************/
 
 
 
/* Trigger: CLIENTES_BI */
CREATE TRIGGER CLIENTES_BI FOR CLIENTES
ACTIVE BEFORE INSERT POSITION 0
AS
BEGIN
 IF (NEW.CLIENTE_ID IS NULL) THEN
   NEW.CLIENTE_ID = GEN_ID(GEN_CLIENTES_ID,1);
END
^
 
 
SET TERM ; ^
 
 
 
/******************************************************************************/
/***                               Privileges                               ***/
/******************************************************************************/
 


« última modificación: 18 de Febrero de 2010, 20:23:03 por egostar »

"Nunca interrumpas a tu enemigo cuando está cometiendo un error."

- Napoleon Bonaparte


 

«Responder #2 en: 21 de Mayo de 2009, 13:32:28 »
En línea

egostar

  • Administrador
  • ******
  • Calificaciones: +186/-6
  • Desconectado Desconectado
  • Sexo: Masculino
  • Mensajes: 5,415
  • Gracias
  • -Dados: 255
  • -Recibidos: 153
Capí­tulo 2. Crear el Web Service
« Respuesta #2 en: 21 de Mayo de 2009, 13:32:28 »

Capítulo 2. Crear el Web Service
Regresar al índice

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.


Capítulo 2.1 Creamos un Nuevo Proyecto
Regresar al índice

Comenzaremos por crear un nuevo proyecto desde el menú de Delphi:
 
File --> New --> Other --> WebService --> SOAP Server Application


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


Aceptamos crear la interfaz del Módulo SOAP.


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


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


WSdbAccess.bdsproj

Código: [Seleccionar]
library WSdbAccess;
 
uses
 ActiveX,
 ComObj,
 WebBroker,
 ISAPIApp,
 ISAPIThreadPool,
 uWSdbAccess in 'uWSdbAccess.pas' {WebModule2: TWebModule},
 WSdbAccessImpl in 'WSdbAccessImpl.pas',
 WSdbAccessIntf in 'WSdbAccessIntf.pas';
 
{$R *.res}
 
exports
 GetExtensionVersion,
 HttpExtensionProc,
 TerminateExtension;
 
begin
 CoInitFlags := COINIT_MULTITHREADED;
 Application.Initialize;
 Application.CreateForm(TWebModule2, WebModule2);
 Application.Run;
end.
 

uWSdbAccess.pas

Código: [Seleccionar]
unit uWSdbAccess;
 
interface
 
uses
 SysUtils, Classes, HTTPApp, InvokeRegistry, WSDLIntf, TypInfo, WebServExp,
 WSDLBind, XMLSchema, WSDLPub, SOAPPasInv, SOAPHTTPPasInv, SOAPHTTPDisp,
 WebBrokerSOAP;
 
type
 TWebModule2 = class(TWebModule)
   HTTPSoapDispatcher1: THTTPSoapDispatcher;
   HTTPSoapPascalInvoker1: THTTPSoapPascalInvoker;
   WSDLHTMLPublish1: TWSDLHTMLPublish;
   procedure WebModule2DefaultHandlerAction(Sender: TObject;
     Request: TWebRequest; Response: TWebResponse; var Handled: Boolean);
 private
   { Private declarations }
 public
   { Public declarations }
 end;
 
var
 WebModule2: TWebModule2;
 
implementation
 
{$R *.dfm}
 
procedure TWebModule2.WebModule2DefaultHandlerAction(Sender: TObject;
 Request: TWebRequest; Response: TWebResponse; var Handled: Boolean);
begin
 WSDLHTMLPublish1.ServiceInfo(Sender, Request, Response, Handled);
end;
 
end.
 

WSdbAccessImpl.pas

Código: [Seleccionar]
{ Invokable implementation File for TWSdbAccess which implements IWSdbAccess }
 
unit WSdbAccessImpl;
 
interface
 
uses InvokeRegistry, Types, XSBuiltIns, WSdbAccessIntf;
 
type
 
 { TWSdbAccess }
 TWSdbAccess = class(TInvokableClass, IWSdbAccess)
 public
 end;
 
implementation
 
 
initialization
{ Invokable classes must be registered }
  InvRegistry.RegisterInvokableClass(TWSdbAccess);
end.
 


WSdbAccessIntf.pas

Código: [Seleccionar]
{ Invokable interface IWSdbAccess }
 
unit WSdbAccessIntf;
 
interface
 
uses InvokeRegistry, Types, XSBuiltIns;
 
type
 
 { Invokable interfaces must derive from IInvokable }
 IWSdbAccess = interface(IInvokable)
 ['{7923453C-068B-4CE6-A012-D6C3AC837B8E}']
 
   { Methods of Invokable interface must not use the default }
   { calling convention; stdcall is recommended }
 end;
 
implementation
 
initialization
 { Invokable interfaces must be registered }
 InvRegistry.RegisterInterface(TypeInfo(IWSdbAccess));
 
end.
 

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



Capítulo 2.2 Creamos la Conectividad con la Base de Datos
Regresar al índice

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


Asignamos frmDataModule al nombre del Módulo de Datos.


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


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.


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


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

Código: [Seleccionar]
SELECT CLIENTE_ID, NOMBRE, APELLIDOS  FROM CLIENTES

dsClientData:

Nos regresará el detalle del cliente para ser mostrado.

Código: [Seleccionar]
SELECT * FROM CLIENTES WHERE CLIENTE_ID = :ID

dsAddClient:

Nos permitirá agregar registros a la tabla CLIENTES

Código: [Seleccionar]
INSERT INTO CLIENTES
 (CLIENTE_ID, TITULO_CLIENTE, NOMBRE, APELLIDOS, FECHA_NACIMIENTO, DIRECCION, CIUDAD, PAIS,
CODIGO_POSTAL,  TELEFONO_CASA, TELEFONO_CELULAR, TELEFONO_TRABAJO, CORREO_ELECTRONICO)
VALUES
 (NULL, :TITULO_CLIENTE, :NOMBRE, :APELLIDOS, :FECHA_NACIMIENTO, :DIRECCION, :CIUDAD,
:PAIS, :CODIGO_POSTAL,  :TELEFONO_CASA, :TELEFONO_CELULAR, :TELEFONO_TRABAJO,
:CORREO_ELECTRONICO)
 

dsDeleteClient:

Nos permitirá borrar un registro de la tabla CLIENTES

Código: [Seleccionar]
DELETE FROM CLIENTES WHERE CLIENTE_ID = :ID

dsUpdateClient:

Nos permitirá modificar el detalle de los clientes.

Código: [Seleccionar]
UPDATE CLIENTES
SET
 TITULO_CLIENTE = :TITULO_CLIENTE,
 NOMBRE = :NOMBRE,
 APELLIDOS = :APELLIDOS,
 FECHA_NACIMIENTO = :FECHA_NACIMIENTO,
 DIRECCION = :DIRECCION,
 CIUDAD = :CIUDAD,
 PAIS = :PAIS,
 CODIGO_POSTAL = :CODIGO_POSTAL,
 TELEFONO_CASA = :TELEFONO_CASA,
 TELEFONO_CELULAR = :TELEFONO_CELULAR,
 TELEFONO_TRABAJO = :TELEFONO_TRABAJO,
 CORREO_ELECTRONICO = :CORREO_ELECTRONICO
WHERE
 CLIENTE_ID = :ID


Ya estamos listos para comenzar a codificar nuestro Web Service.



Capítulo 2.3 La Clase TRemotable
Regresar al índice

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.

Código: [Seleccionar]
type
 
 trRetorno = class(TRemotable)
   private
      FID: integer;
      FDescripcion: widestring;
   published
     property ID: integer read FID write FID;
     property Descripcion: widestring read FDescripcion write FDescripcion;
 end;
 
 trParams = class(TRemotable)
   private
     FTitulo: widestring;
     FNombre: widestring;
     FApellidos: widestring;
     FFecha: widestring;
     FDireccion: widestring;
     FCiudad: wideString;
     FPais: wideString;
     FCodPostal: wideString;
     FTelCasa: wideString;
     FTelOficina: wideString;
     FCelular: wideString;
     FCorreo: wideString;
   published
     property Titulo: widestring read FTitulo write FTitulo;
     property Nombre: widestring read FNombre write FNombre;
     property Apellidos: widestring read FApellidos write FApellidos;
     property Fecha: widestring read FFecha write FFecha;
     property Direccion: widestring read FDireccion write FDireccion;
     property Ciudad: widestring read FCiudad write FCiudad;
     property Pais: widestring read FPais write FPais;
     property CodPostal: widestring read FCodPostal write FCodPostal;
     property TelCasa: widestring read FTelCasa write FTelCasa;
     property TelOficina: widestring read FTelOficina write FTelOficina;
     property Celular: widestring read FCelular write FCelular;
     property Correo: widestring read FCorreo write FCorreo;
 end;
 
 { Invokable interfaces must derive from IInvokable }
 IWSdbAccess = interface(IInvokable)
 ['{7923453C-068B-4CE6-A012-D6C3AC837B8E}']
 
   { Methods of Invokable interface must not use the default }
   { calling convention; stdcall is recommended }
 end;
 

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



Capítulo 2.4 Creando las funciones del ABM
Regresar al índice

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.

Código: [Seleccionar]
  { Invokable interfaces must derive from IInvokable }
 IWSdbAccess = interface(IInvokable)
 ['{7923453C-068B-4CE6-A012-D6C3AC837B8E}']
   function GetClientNames: widestring; stdcall;
   function GetClientsData(EmpID: integer): widestring; stdcall;
   function AddClient(ParamsStr:trParams): trRetorno; stdcall;
   function DeleteClient(EmpID: integer): trRetorno; stdcall;
   function UpdateClient(EmpID:integer; ParamsStr:trParams): trRetorno; stdcall;
   { Methods of Invokable interface must not use the default }
   { calling convention; stdcall is recommended }
 end;
 

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

Código: [Seleccionar]
{ Invokable implementation File for TWSdbAccess which implements IWSdbAccess }
 
unit WSdbAccessImpl;
 
interface
 
uses InvokeRegistry, Types, XSBuiltIns, WSdbAccessIntf;
 
type
 
 { TWSdbAccess }
 TWSdbAccess = class(TInvokableClass, IWSdbAccess)
 public
   function GetClientNames: widestring; stdcall;
   function GetClientsData(EmpID: integer): widestring; stdcall;
   function AddClient(ParamsStr:trParams): trRetorno; stdcall;
   function DeleteClient(EmpID: integer): trRetorno; stdcall;
   function UpdateClient(EmpID:integer; ParamsStr:trParams): trRetorno; stdcall;
 end;
 
implementation
 
 
initialization
{ Invokable classes must be registered }
  InvRegistry.RegisterInvokableClass(TWSdbAccess);
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.

Código: [Seleccionar]
implementation
 
 
{ TWSdbAccess }
 
function TWSdbAccess.GetClientNames: widestring;
begin
 
end;
 
function TWSdbAccess.GetClientsData(EmpID: string): widestring;
begin
 
end;
 
function TWSdbAccess.AddClient(ParamsStr:trParams): trRetorno;
begin
 
end;
 
function TWSdbAccess.DeleteClient(EmpID: integer): trRetorno; stdcall;
begin
 
end;
 
function TWSdbAccess.UpdateClient(EmpID:integer; ParamsStr:trParams): trRetorno; stdcall;
begin
 
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.

Código: [Seleccionar]
function MakeXmlStr (node, value: string): string;
begin
 Result := '<' + node + '>' + value + '</' + node + '>';
end;
 
function FieldsToXml (rootName: string; data: TSQLDataSet): string;
var
 i: Integer;
begin
 Result := '<' + rootName + '>' + sLineBreak;;
 for i := 0 to data.FieldCount - 1 do
     Result := Result + '  ' + MakeXmlStr (
               LowerCase (data.Fields[i].FieldName),
               data.Fields[i].AsString) + sLineBreak;
 Result := Result + '</' + rootName + '>' + sLineBreak;;
end;
 

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

Código: [Seleccionar]
implementation
 
uses uDataModule, sysUtils, sqlExpr;
 
var
 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.

Código: [Seleccionar]
function TWSdbAccess.GetClientNames: widestring;
begin
 dm := TfrmDataModule.Create (nil);
 try
   dm.dsClientList.Open;
   if dm.dsClientList.RecordCount > 0 then begin
      Result := FieldsToXml ('ClientList', dm.dsClientList);
   end
   else begin
          Result := '<ClientList>' + sLineBreak +
                    '</ClientList>' + sLineBreak;
   end;
 finally
   dm.dsClientList.Close;
   dm.CLIENTES.Close;
   dm.Free;
 end;
end;
 

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

Código: [Seleccionar]
<ClientList>
 <cliente_id>1</cliente_id>
 <nombre>JUAN</nombre>
 <apellidos>PEREZ</apellidos>
 <cliente_id>2</cliente_id>
 <nombre>REMEDIOS</nombre>
 <apellidos>CASEROS</apellidos>
 <cliente_id>3</cliente_id>
 <nombre>ALMA MARIA</nombre>
 <apellidos>RICO</apellidos>
</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.

Código: [Seleccionar]
function TWSdbAccess.GetClientsData(EmpID: integer): widestring;
begin
 dm := TfrmDataModule.Create (nil);
 try
   dm.dsClientData.Params.ParamByName('ID').Value := EmpID;
   dm.dsClientData.Open;
   Result := FieldsToXml ('ClientData', dm.dsClientData);
 finally
   dm.dsClientData.Close;
   dm.CLIENTES.Close;
   dm.Free;
 end;
end;
 

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

Código: [Seleccionar]
<Clientes>
 <cliente_id>2</cliente_id>
 <titulo_cliente>SRA.</titulo_cliente>
 <nombre>REMEDIOS</nombre>
 <apellidos>CASEROS</apellidos>
 <fecha_nacimiento>01/11/1956</fecha_nacimiento>
 <direccion>CALLE DE LA AMARGURA 69</direccion>
 <ciudad>DE LA INFLUENZA</ciudad>
 <pais>TUMBUCTU</pais>
 <codigo_postal>12345</codigo_postal>
 <telefono_casa>111-111-1111</telefono_casa>
 <telefono_trabajo>111-212-1122</telefono_trabajo>
 <telefono_celular>222-123-1234</telefono_celular>
 <correo_electronico>remedios.caseros@gmail.com</correo_electronico>
</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

Código: [Seleccionar]
function TWSdbAccess.AddClient(ParamsStr: trParams): trRetorno;
begin
 Result := trRetorno.Create;
 dm := TfrmDataModule.Create(nil);
 try
   with dm.dsAddClient do begin
      ParamByName('TITULO_CLIENTE').value     := ParamsStr.Titulo;
      ParamByName('NOMBRE').value             := ParamsStr.Nombre;
      ParamByName('APELLIDOS').value          := ParamsStr.Apellidos;
      ParamByName('FECHA_NACIMIENTO').value   := strtodate(ParamsStr.Fecha);
      ParamByName('DIRECCION').Value          := ParamsStr.Direccion;
      ParamByName('CIUDAD').Value             := ParamsStr.Ciudad;
      ParamByName('PAIS').Value               := ParamsStr.Pais;
      ParamByName('CODIGO_POSTAL').Value      := ParamsStr.CodPostal;
      ParamByName('TELEFONO_CASA').Value      := ParamsStr.TelCasa;
      ParamByName('TELEFONO_TRABAJO').Value   := ParamsStr.TelOficina;
      ParamByName('TELEFONO_CELULAR').Value   := ParamsStr.Celular;
      ParamByName('CORREO_ELECTRONICO').Value := ParamsStr.Correo;
   end;
   dm.dsAddClient.ExecSQL();
   Result.ID := 0;
   Result.Descripcion := 'El cliente fuá agregado correctamente';
 except
   Result.ID := -1;
   Result.Descripcion := 'Error al agregar un nuevo Cliente';
 end;
 dm.CLIENTES.Close;
 dm.Free;
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.

Código: [Seleccionar]
function TWSdbAccess.DeleteClient(EmpID: integer): trRetorno;
begin
 Result := trRetorno.Create;
 dm := TfrmDataModule.Create(nil);
 try
   dm.dsDeleteClient.paramByName('ID').Value := EmpID;
   dm.dsDeleteClient.ExecSQL();
   Result.ID := 0;
   Result.Descripcion := 'El cliente solicitado fué borrado correctamente';
 except
   Result.ID := -1;
   Result.Descripcion := 'Error al borrar el cliente solicitado';
 end;
 dm.CLIENTES.Close;
 dm.Free;
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.

Código: [Seleccionar]
function TWSdbAccess.UpdateClient(EmpID: integer; ParamsStr: trParams): trRetorno;
begin
 Result := trRetorno.Create;
 dm := TfrmDataModule.Create(nil);
 try
   with dm.dsUpdateClient do begin
      ParamByName('TITULO_CLIENTE').value     := ParamsStr.Titulo;
      ParamByName('NOMBRE').value             := ParamsStr.Nombre;
      ParamByName('APELLIDOS').value          := ParamsStr.Apellidos;
      ParamByName('FECHA_NACIMIENTO').value   := strtodate(ParamsStr.Fecha);
      ParamByName('DIRECCION').Value          := ParamsStr.Direccion;
      ParamByName('CIUDAD').Value             := ParamsStr.Ciudad;
      ParamByName('PAIS').Value               := ParamsStr.Pais;
      ParamByName('CODIGO_POSTAL').Value      := ParamsStr.CodPostal;
      ParamByName('TELEFONO_CASA').Value      := ParamsStr.TelCasa;
      ParamByName('TELEFONO_TRABAJO').Value   := ParamsStr.TelOficina;
      ParamByName('TELEFONO_CELULAR').Value   := ParamsStr.Celular;
      ParamByName('CORREO_ELECTRONICO').Value := ParamsStr.Correo;
      ParamByName('ID').Value                 := EmpID;
   end;
   dm.dsUpdateClient.ExecSQL();
   Result.ID := 0;
   Result.Descripcion := 'El cliente fuá modificado correctamente';
 except
   Result.ID := -1;
   Result.Descripcion := 'Error al modificar el Cliente';
 end;
 dm.CLIENTES.Close;
 dm.Free;
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.

Código: [Seleccionar]
procedure TfrmDataModule.SoapDataModuleCreate(Sender: TObject);
var
 IniFile: TIniFile;
 DATABASE,SERVER: string;
 S: array[0..MAX_PATH] of Char;
begin
 windows.GetModuleFileName(hInstance, S, SizeOf(S));
 IniFile  := TIniFile.Create(ExtractFileDir(S)+'\params.ini');
 DATABASE := IniFile.ReadString('PARAMETERS','Path','');
 SERVER   := IniFile.ReadString('PARAMETERS','Host','');
 IniFile.Free;
 
 Clientes.Params.Values['HOSTNAME'] := SERVER;
 Clientes.Params.Values['DATABASE'] := SERVER+':'+DATABASE;
end;
 

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

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


« última modificación: 18 de Febrero de 2010, 20:29:34 por egostar »

"Nunca interrumpas a tu enemigo cuando está cometiendo un error."

- Napoleon Bonaparte


 

«Responder #3 en: 21 de Mayo de 2009, 13:33:19 »
En línea

egostar

  • Administrador
  • ******
  • Calificaciones: +186/-6
  • Desconectado Desconectado
  • Sexo: Masculino
  • Mensajes: 5,415
  • Gracias
  • -Dados: 255
  • -Recibidos: 153
Capí­tulo 3. Registrar el Web Service en el IIS
« Respuesta #3 en: 21 de Mayo de 2009, 13:33:19 »


Capí­tulo 3. Registrar el Web Service en el IIS
Regresar al í­ndice

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.



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


Capturamos la Ruta donde se localiza nuestra DLL.


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


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


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



"Nunca interrumpas a tu enemigo cuando está cometiendo un error."

- Napoleon Bonaparte


 

«Responder #4 en: 21 de Mayo de 2009, 13:59:05 »
En línea

egostar

  • Administrador
  • ******
  • Calificaciones: +186/-6
  • Desconectado Desconectado
  • Sexo: Masculino
  • Mensajes: 5,415
  • Gracias
  • -Dados: 255
  • -Recibidos: 153
Capí­tulo 4. Crear la aplicación Cliente
« Respuesta #4 en: 21 de Mayo de 2009, 13:59:05 »

Capí­tulo 4. Crear la aplicación Cliente
Regresar al í­ndice

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


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.


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


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.


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


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:

Código: [Seleccionar]
    function  GetClientNames: WideString; stdcall;
   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

Código: [Seleccionar]
<ClientList>
     <cliente_id>1</cliente_id>
     <nombre>JUAN</nombre>
     <apellidos>PEREZ</apellidos>
     <cliente_id>2</cliente_id>
     <nombre>ROSA</nombre>
     <apellidos>MARTINEZ</apellidos>
</ClientList>
 

ClientData.xml

Código: [Seleccionar]
<ClientData>
     <cliente_id>1</cliente_id>
     <titulo_cliente>SRA.</titulo_cliente>
     <nombre>REMEDIOS</nombre>
     <apellidos>CASEROS</apellidos>
     <fecha_nacimiento>01/01/1980</fecha_nacimiento>
     <direccion>CALLE DE LA AMARGURA</direccion>
     <ciudad>DE LA INFLUENZA</ciudad>
     <pais>MEXICO</pais>
     <codigo_postal>1111_</codigo_postal>
     <telefono_casa>55-5122-4354</telefono_casa>
     <telefono_trabajo>55-5431-1767</telefono_trabajo>
     <telefono_celular>55-2342-7879</telefono_celular>
     <correo_electronico>usuario@delphiaccess.com</correo_electronico>
</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


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


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


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


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

Código: [Seleccionar]
type
 
{ Forward Decls }
 
 IXMLClientListType = interface;
 
{ IXMLClientListType }
 
 IXMLClientListType = interface(IXMLNode)
   ['{9F055206-DF3E-4BA2-BE35-E1C26BD6CF35}']
   { Property Accessors }
   function Get_Cliente_id: Integer;
   function Get_Nombre: WideString;
   function Get_Apellidos: WideString;
   procedure Set_Cliente_id(Value: Integer);
   procedure Set_Nombre(Value: WideString);
   procedure Set_Apellidos(Value: WideString);
   { Methods & Properties }
   property Cliente_id: Integer read Get_Cliente_id write Set_Cliente_id;
   property Nombre: WideString read Get_Nombre write Set_Nombre;
   property Apellidos: WideString read Get_Apellidos write Set_Apellidos;
 end;
 

ClientData.pas

Código: [Seleccionar]
type
 
{ Forward Decls }
 
 IXMLClientDataType = interface;
 
{ IXMLClientDataType }
 
 IXMLClientDataType = interface(IXMLNode)
   ['{35537620-0491-4F50-8C11-E359974601C7}']
   { Property Accessors }
   function Get_Cliente_id: Integer;
   function Get_Titulo_cliente: WideString;
   function Get_Nombre: WideString;
   function Get_Apellidos: WideString;
   function Get_Fecha_nacimiento: WideString;
   function Get_Direccion: WideString;
   function Get_Ciudad: WideString;
   function Get_Pais: WideString;
   function Get_Codigo_postal: Integer;
   function Get_Telefono_casa: Integer;
   function Get_Telefono_trabajo: Integer;
   function Get_Telefono_celular: Integer;
   function Get_Correo_electronico: WideString;
   procedure Set_Cliente_id(Value: Integer);
   procedure Set_Titulo_cliente(Value: WideString);
   procedure Set_Nombre(Value: WideString);
   procedure Set_Apellidos(Value: WideString);
   procedure Set_Fecha_nacimiento(Value: WideString);
   procedure Set_Direccion(Value: WideString);
   procedure Set_Ciudad(Value: WideString);
   procedure Set_Pais(Value: WideString);
   procedure Set_Codigo_postal(Value: Integer);
   procedure Set_Telefono_casa(Value: Integer);
   procedure Set_Telefono_trabajo(Value: Integer);
   procedure Set_Telefono_celular(Value: Integer);
   procedure Set_Correo_electronico(Value: WideString);
   { Methods & Properties }
   property Cliente_id: Integer read Get_Cliente_id write Set_Cliente_id;
   property Titulo_cliente: WideString read Get_Titulo_cliente write Set_Titulo_cliente;
   property Nombre: WideString read Get_Nombre write Set_Nombre;
   property Apellidos: WideString read Get_Apellidos write Set_Apellidos;
   property Fecha_nacimiento: WideString read Get_Fecha_nacimiento write Set_Fecha_nacimiento;
   property Direccion: WideString read Get_Direccion write Set_Direccion;
   property Ciudad: WideString read Get_Ciudad write Set_Ciudad;
   property Pais: WideString read Get_Pais write Set_Pais;
   property Codigo_postal: Integer read Get_Codigo_postal write Set_Codigo_postal;
   property Telefono_casa: Integer read Get_Telefono_casa write Set_Telefono_casa;
   property Telefono_trabajo: Integer read Get_Telefono_trabajo write Set_Telefono_trabajo;
   property Telefono_celular: Integer read Get_Telefono_celular write Set_Telefono_celular;
   property Correo_electronico: WideString read Get_Correo_electronico write Set_Correo_electronico;
 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.

Código: [Seleccionar]
 
uses  
  Windows, Messages, SysUtils, ..........., IwsClientes1, ClientData, ClientList;
 
 TfrmAppCliente = class(TForm)
 private
   { Private declarations }
 public
   { Public declarations }
    Resultado: trRetorno;
 end;
 
var
 XMLString: widestring;
 Archivo: textFile;
 Indice: integer;
 Lista: IXMLClientListType;
 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.

Código: [Seleccionar]
procedure TfrmAppCliente.FormShow(Sender: TObject);
var
 I: Integer;
begin
 XMLString := GetIwsClientes.GetClientNames;
 CreaXML('Names.XML',XMLString);
 Lista := ClientList.LoadClientList('Names.XML');
 TreeView1.Items.Clear;
 with Lista do begin
    if Cliente_id.Count > 0 then begin
       for I := 0 to Cliente_id.Count - 1 do begin
           TreeView1.Items.Add(nil,format('%.*d',[3,Cliente_id[i]])+' '+
                                                    Nombre[i]+' '+
                                                    Apellidos[i]);
      end;
    end;
 end;
 TreeView1.SetFocus;
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.

Código: [Seleccionar]
procedure CreaXML(Nombre:string;textXML:WideString);
begin
 assignFile(Archivo,Nombre);
 Rewrite(Archivo);
 Write(Archivo,textXML);
 closeFile(Archivo);
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.

Código: [Seleccionar]
procedure TfrmAppCliente.TreeView1Change(Sender: TObject; Node: TTreeNode);
begin
 Indice := strtoint(Copy(TreeView1.Selected.Text,1,3));
 XMLString := GetIwsClientes.GetClientsData(Indice);
 CreaXML('Data.XML',XMLString);
 Detalle := LoadClientData('Data.XML');
 MuestraDatos;
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.

Código: [Seleccionar]
  private
   { Private declarations }
    procedure MuestraDatos;
 

La implementación de este procedimiento es el siguiente:

Código: [Seleccionar]
procedure TfrmAppCliente.MuestraDatos;
begin
 label1.Caption := 'Contacto: ' + #9 + Detalle.Titulo_cliente + ' ' +
                   Detalle.Nombre + ' ' +
                   Detalle.Apellidos;
 label2.Caption := 'Dirección: ' + #9 + Detalle.Direccion + #13#9#9 +
                   Detalle.Ciudad + #13#9#9 +Detalle.Pais + #13#9#9 +
                   'CP ' + Detalle.Codigo_postal;
 label3.Caption := 'Telefonos: '+#9+'['+ Detalle.Telefono_casa + ']'+#13#9#9+'[' +
                   Detalle.Telefono_trabajo + ']'+#13#9#9+'[' +
                   Detalle.Telefono_celular + ']';
 label4.Caption := 'email: ' + #9#9 + Detalle.Correo_electronico;
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:


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.

Código: [Seleccionar]
  public
   { Public declarations }
   Proceso: integer;
   EmpID: integer;
 end;
 
implementation
 
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:

Código: [Seleccionar]
procedure TfrmProcClient.Button1Click(Sender: TObject);
var
 Params: trParams;
begin
 params := trParams.Create;
 with params do begin
    Titulo     := comboBox1.Text;
    Nombre     := edit2.Text;
    Apellidos  := edit3.Text;
    Fecha      := datetostr(DatetimePicker1.Date);
    Direccion  := edit5.Text;
    Ciudad     := edit6.Text;
    Pais       := edit7.Text;
    CodPostal  := maskedit1.Text;
    TelCasa    := edit9.Text;
    TelOficina := edit10.Text;
    Celular    := edit11.Text;
    Correo     := edit12.Text;
 end;
 with frmAppCliente do begin
   case proceso of
      1: Resultado := GetIwsClientes.AddClient(params);
      2: Resultado := GetIwsClientes.UpdateClient(EmpID,params)
   end;
   ShowMessage(inttostr(Resultado.ID)+': '+Resultado.Descripcion);
 end;
 params.Free;
end;
 

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

Código: [Seleccionar]
procedure TfrmProcClient.Button2Click(Sender: TObject);
begin
 ShowMessage('Proceso Cancelado');
 Close;
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:


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.

Código: [Seleccionar]
procedure TfrmAppCliente.Button1Click(Sender: TObject);
var
 FAddClient : TfrmProcClient;
 I: integer;
begin
 FAddClient := TfrmProcClient.Create(nil);
 FAddClient.Caption := 'Agrega Cliente consumiendo Web Service';
 FAddClient.Button2.Caption := 'Agrega Cliente';
 FAddClient.Proceso := 1;
 FAddClient.ShowModal;
 if FAddClient.ModalResult = mrOK then begin
    XMLString := GetIwsClientes.GetClientNames;
    CreaXML('Names.XML',XMLString);
    Lista := ClientList.LoadClientList('Names.XML');
    TreeView1.Items.Clear;
    with Lista do begin
       if Cliente_id.Count > 0 then begin
          for I := 0 to Cliente_id.Count - 1 do begin
              TreeView1.Items.Add(nil,format('%.*d',[3,Cliente_id[i]])+' '+
                                                       Nombre[i]+' '+
                                                       Apellidos[i]);
          end;
       end;
    end;
    TreeView1.SetFocus;
 end;
 FAddClient.Free;
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.

Código: [Seleccionar]
procedure TfrmAppCliente.Button2Click(Sender: TObject);
var
 FUpdateClient: TfrmProcClient;
 I: integer;
begin
 if TreeView1.Items.Count > 0 then begin
   if trystrtoint(Copy(TreeView1.Selected.Text,1,3), Indice) then begin
      FUpdateClient := TfrmProcClient.Create(nil);
      XMLString := GetIwsClientes.GetClientsData(Indice);
      CreaXML('Data.XML',XMLString);
      Detalle := ClientData.LoadClientData('Data.XML');
      with FUpdateClient do begin
         ComboBox1.Text := Detalle.Titulo_cliente;
         edit2.Text := Detalle.Nombre;
         edit3.Text := Detalle.Apellidos;
         DatetimePicker1.Date := strtodate(Detalle.Fecha_nacimiento);
         edit5.Text := Detalle.Direccion;
         edit6.Text := Detalle.Ciudad;
         edit7.Text := Detalle.Pais;
         maskedit1.Text := Detalle.Codigo_postal;
         edit9.Text := Detalle.Telefono_casa;
         edit10.Text := Detalle.Telefono_trabajo;
         edit11.Text := Detalle.Telefono_celular;
         edit12.Text := Detalle.Correo_electronico;
      end;
      FUpdateClient.Caption := 'Modifica Cliente consumiendo Web Service';
      FUpdateClient.Button2.Caption := 'Modifica Cliente';
      FUpdateClient.EmpID := Indice;
      FUpdateClient.Proceso := 2;
      FUpdateClient.ShowModal;
      FUpdateClient.Free;
      XMLString := GetIwsClientes.GetClientNames;
      CreaXML('Names.XML',XMLString);
      Lista := ClientList.LoadClientList('Names.XML');
      TreeView1.Items.Clear;
      with Lista do begin
        if Cliente_id.Count > 0 then begin
           for I := 0 to Cliente_id.Count - 1 do begin
               TreeView1.Items.Add(nil,format('%.*d',[3,Cliente_id[i]])+' '+
                                                        Nombre[i]+' '+
                                                        Apellidos[i]);
           end;
        end;
    end;
    TreeView1.SetFocus;
   end;
 end
 else begin
        ShowMessage('No se ha seleccionado ningún registro');
 end;
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.

Código: [Seleccionar]
procedure TfrmAppCliente.Button3Click(Sender: TObject);
var
 I: integer;
 
 procedure Limpia_Detalle;
 begin
   label1.Caption := 'Contacto: ';
   label2.Caption := 'Dirección: ';
   label3.Caption := 'Telefonos: ';
   label4.Caption := 'email: ';
 end;
 
begin
 Resultado := trRetorno.Create;
 if TreeView1.Items.Count > 0 then begin
    if trystrtoint(Copy(TreeView1.Selected.Text,1,3), Indice) then begin
       Resultado := GetIwsClientes.DeleteClient(Indice);
       ShowMessage(inttostr(Resultado.ID)+': '+Resultado.Descripcion);
       XMLString := GetIwsClientes.GetClientNames;
       CreaXML('Names.XML',XMLString);
       Lista := ClientList.LoadClientList('Names.XML');
       TreeView1.Items.Clear;
       Limpia_Detalle;
       with Lista do begin
         if Cliente_id.Count > 0 then begin
            for I := 0 to Cliente_id.Count - 1 do begin
                TreeView1.Items.Add(nil,format('%.*d',[3,Cliente_id[i]])+' '+
                                                         Nombre[i]+' '+
                                                         Apellidos[i]);
            end;
         end;
       end;
    end;
 end
 else begin
        ShowMessage('No se ha seleccionado ningún registro');
 end;
 Resultado.Free;
 TreeView1.SetFocus;
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:

Código: [Seleccionar]
function GetIwsClientes(UseWSDL: Boolean; Addr: string; HTTPRIO: THTTPRIO): IwsClientes;
const
 defWSDL = 'http://localhost/WSClientes/wsClientes.dll/wsdl/IwsClientes';
 defURL  = 'http://localhost/WSClientes/wsClientes.dll/soap/IwsClientes';
 defSvc  = 'IwsClientesservice';
 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

Código: [Seleccionar]
uses SysUtils, IniFiles, Forms;
 
var
 IniFile: TIniFile;
 defWSDL,defURL : widestring; //Extraemos estas constantes para convertirlas
                              //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:

Código: [Seleccionar]
  IniFile := TIniFile.Create(ExtractFilePath(Application.ExeName)+'conf.ini');
 defWSDL := IniFile.ReadString('CONFIGURACION','WSDL','');
 defURL  := IniFile.ReadString('CONFIGURACION','URL','');
 IniFile.Free;
 

Esto deberá agregarse a la función:

Código: [Seleccionar]
function GetIwsClientes(UseWSDL: Boolean; Addr: string; HTTPRIO: THTTPRIO): IwsClientes;
 

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

Código: [Seleccionar]
implementation
 
uses SysUtils, IniFiles, Forms;
 
var
 IniFile: TIniFile;
 defWSDL,defURL : widestring; //Extraemos estas constantes para convertirlas
                              //en variables y poder manipularlas en "runtime"
 
function GetIwsClientes(UseWSDL: Boolean; Addr: string; HTTPRIO: THTTPRIO): IwsClientes;
const
 defSvc  = 'IwsClientesservice';
 defPrt  = 'IwsClientesPort';
var
 RIO: THTTPRIO;
begin
 IniFile := TIniFile.Create(ExtractFilePath(Application.ExeName)+'conf.ini');
 defWSDL := IniFile.ReadString('CONFIGURACION','WSDL','');
 defURL  := IniFile.ReadString('CONFIGURACION','URL','');
 IniFile.Free;
 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 IwsClientes);
   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;
 

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:

Código: [Seleccionar]
[CONFIGURACION]
WSDL="http://localhost/WSClientes/WSClientes.dll/wsdl/IwsClientes"
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.

« última modificación: 22 de Mayo de 2009, 18:31:29 por egostar »

"Nunca interrumpas a tu enemigo cuando está cometiendo un error."

- Napoleon Bonaparte


 

«Responder #5 en: 21 de Mayo de 2009, 14:11:06 »
En línea

egostar

  • Administrador
  • ******
  • Calificaciones: +186/-6
  • Desconectado Desconectado
  • Sexo: Masculino
  • Mensajes: 5,415
  • Gracias
  • -Dados: 255
  • -Recibidos: 153
Consumir WebService con acceso a Base de Datos
« Respuesta #5 en: 21 de Mayo de 2009, 14:11:06 »

Apéndice I
Regresar al í­ndice

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.

Citar
[CONFIGURACION]
WSDL="http://NombreServidor/WSClientes/WSClientes.dll/wsdl/IwsClientes"
URL="http://NombreServidor/WSClientes/WSClientes.dll/soap/IwsClientes"



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.

Citar
[CONFIGURACION]
WSDL="http://minombre.no-ip.org/WSClientes/WSClientes.dll/wsdl/IwsClientes"
URL="http://minombre.no-ip.org/WSClientes/WSClientes.dll/soap/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 :) )


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.

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
« última modificación: 21 de Mayo de 2009, 14:18:44 por egostar »

"Nunca interrumpas a tu enemigo cuando está cometiendo un error."

- Napoleon Bonaparte


 

«Responder #6 en: 21 de Mayo de 2009, 14:40:09 »
En línea

cHackAll

  • Administrador
  • *******
  • Calificaciones: +2/-666
  • Desconectado Desconectado
  • Sexo: Masculino
  • Mensajes: 427
  • Gracias
  • -Dados: 0
  • -Recibidos: 3
  • Baneado?
Re:Consumir WebService con acceso a Base de Datos
« Respuesta #6 en: 21 de Mayo de 2009, 14:40:09 »
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!

«Responder #7 en: 21 de Mayo de 2009, 14:44:02 »
En línea

Caral

  • Administrador
  • *******
  • Calificaciones: +126/-4
  • Conectado Conectado
  • Sexo: Masculino
  • Mensajes: 2,171
  • Gracias
  • -Dados: 69
  • -Recibidos: 94
  • Siempre Novato
Re:Consumir WebService con acceso a Base de Datos
« Respuesta #7 en: 21 de Mayo de 2009, 14:44:02 »
Hola
Amigo, esto no era un tutorial??, esto es todo un libro. :D
Impresionante trabajo amigo.
Saludos

«Responder #8 en: 21 de Mayo de 2009, 15:05:44 »
En línea

enecumene

  • Administrador
  • *******
  • Calificaciones: +151/-1
  • Desconectado Desconectado
  • Sexo: Masculino
  • Mensajes: 3,750
  • Gracias
  • -Dados: 155
  • -Recibidos: 106
  • DA Webmaster
Re:Consumir WebService con acceso a Base de Datos
« Respuesta #8 en: 21 de Mayo de 2009, 15:05:44 »
Tremenda calidad, dudo que aparezca otro tutorial de esta magnitud, felicidades amigo ;).

Saludos.

«Responder #9 en: 21 de Mayo de 2009, 15:31:32 »
En línea

Kipow

  • Miembro Platino
  • *****
  • Calificaciones: +5/-0
  • Desconectado Desconectado
  • Sexo: Masculino
  • Mensajes: 172
  • Gracias
  • -Dados: 6
  • -Recibidos: 2
  • Knowledge Is POWer
Re:Consumir WebService con acceso a Base de Datos
« Respuesta #9 en: 21 de Mayo de 2009, 15:31:32 »
Excelente tutorial yo nunca he hecho un Webservice, pero con esto creo que tengo idea de por donde empezar. muchas gracias.

«Responder #10 en: 21 de Mayo de 2009, 16:57:28 »
En línea

poliburro

  • Administrador
  • *******
  • Calificaciones: +54/-0
  • Desconectado Desconectado
  • Sexo: Masculino
  • Mensajes: 1,360
  • Gracias
  • -Dados: 13
  • -Recibidos: 40
Re:Consumir WebService con acceso a Base de Datos
« Respuesta #10 en: 21 de Mayo de 2009, 16:57:28 »
Excelente trabajo, se nota el esfuerzo por hacer algo bien y con calidad, coincido en que será dificilmente igualable.

Saludos.
Mi corazón late a la izquierda

«Responder #11 en: 21 de Mayo de 2009, 17:53:03 »
En línea

egostar

  • Administrador
  • ******
  • Calificaciones: +186/-6
  • Desconectado Desconectado
  • Sexo: Masculino
  • Mensajes: 5,415
  • Gracias
  • -Dados: 255
  • -Recibidos: 153
Re:Consumir WebService con acceso a Base de Datos
« Respuesta #11 en: 21 de Mayo de 2009, 17:53:03 »
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

"Nunca interrumpas a tu enemigo cuando está cometiendo un error."

- Napoleon Bonaparte


 

«Responder #12 en: 22 de Mayo de 2009, 00:55:48 »
En línea

axesys

  • Moderadores
  • ******
  • Calificaciones: +54/-0
  • Desconectado Desconectado
  • Sexo: Masculino
  • Mensajes: 568
  • Gracias
  • -Dados: 86
  • -Recibidos: 39
  • Abelica
    • WWW
Re:Consumir WebService con acceso a Base de Datos
« Respuesta #12 en: 22 de Mayo de 2009, 00:55:48 »
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
"Cualquier tonto puede escribir código que un ordenador entiende. Los buenos programadores escriben código que los humanos pueden entender"

Martin Fowler

«Responder #13 en: 22 de Mayo de 2009, 01:15:00 »
En línea

escafandra

  • Moderadores
  • ******
  • Calificaciones: +204/-0
  • Desconectado Desconectado
  • Sexo: Masculino
  • Mensajes: 1,123
  • Gracias
  • -Dados: 22
  • -Recibidos: 182
Re:Consumir WebService con acceso a Base de Datos
« Respuesta #13 en: 22 de Mayo de 2009, 01:15:00 »
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.

«Responder #14 en: 22 de Mayo de 2009, 11:59:55 »
En línea

Delphius

  • Administrador
  • *******
  • Calificaciones: +87/-2
  • Desconectado Desconectado
  • Sexo: Masculino
  • Mensajes: 1,844
  • Gracias
  • -Dados: 61
  • -Recibidos: 65
  • ¿El polimorfismo seguirá siendo parte de mi vida?
Re:Consumir WebService con acceso a Base de Datos
« Respuesta #14 en: 22 de Mayo de 2009, 11:59:55 »
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,
Como redactar mensajes - Uso de etiquetas

Se enseña por amor a los demás, se aprende por amor a la verdad
Cuanto más se busca la verdad, sin llegar a la perfección, anhelamos saber lo que falta

San Agustín

«Responder #15 en: 22 de Mayo de 2009, 12:14:26 »
En línea

egostar

  • Administrador
  • ******
  • Calificaciones: +186/-6
  • Desconectado Desconectado
  • Sexo: Masculino
  • Mensajes: 5,415
  • Gracias
  • -Dados: 255
  • -Recibidos: 153
Re:Consumir WebService con acceso a Base de Datos
« Respuesta #15 en: 22 de Mayo de 2009, 12:14:26 »
Hola

Cita de: axesys
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 :)

Cita de: escafandra
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 :)

Cita de: Delphius
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

"Nunca interrumpas a tu enemigo cuando está cometiendo un error."

- Napoleon Bonaparte


 

«Responder #16 en: 22 de Mayo de 2009, 12:16:35 »
En línea

markdelphi

  • Moderadores
  • ******
  • Calificaciones: +11/-0
  • Desconectado Desconectado
  • Sexo: Masculino
  • Mensajes: 71
  • Gracias
  • -Dados: 1
  • -Recibidos: 8
Re:Consumir WebService con acceso a Base de Datos
« Respuesta #16 en: 22 de Mayo de 2009, 12:16:35 »
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) 

«Responder #17 en: 22 de Mayo de 2009, 12:28:43 »
En línea

egostar

  • Administrador
  • ******
  • Calificaciones: +186/-6
  • Desconectado Desconectado
  • Sexo: Masculino
  • Mensajes: 5,415
  • Gracias
  • -Dados: 255
  • -Recibidos: 153
Re:Consumir WebService con acceso a Base de Datos
« Respuesta #17 en: 22 de Mayo de 2009, 12:28:43 »
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

"Nunca interrumpas a tu enemigo cuando está cometiendo un error."

- Napoleon Bonaparte


 

«Responder #18 en: 22 de Mayo de 2009, 13:07:07 »
En línea

Delphius

  • Administrador
  • *******
  • Calificaciones: +87/-2
  • Desconectado Desconectado
  • Sexo: Masculino
  • Mensajes: 1,844
  • Gracias
  • -Dados: 61
  • -Recibidos: 65
  • ¿El polimorfismo seguirá siendo parte de mi vida?
Re:Consumir WebService con acceso a Base de Datos
« Respuesta #18 en: 22 de Mayo de 2009, 13:07: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,
Como redactar mensajes - Uso de etiquetas

Se enseña por amor a los demás, se aprende por amor a la verdad
Cuanto más se busca la verdad, sin llegar a la perfección, anhelamos saber lo que falta

San Agustín

«Responder #19 en: 23 de Mayo de 2009, 01:28:18 »
En línea

Wilson

  • Miembro Platino
  • *****
  • Calificaciones: +77/-0
  • Desconectado Desconectado
  • Sexo: Masculino
  • Mensajes: 471
  • Gracias
  • -Dados: 52
  • -Recibidos: 55
Re:Consumir WebService con acceso a Base de Datos
« Respuesta #19 en: 23 de Mayo de 2009, 01:28:18 »
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
Los libros son como semillas. Pueden estar siglos aletargados y luego florecer en el suelo menos prometedor.   Carl Sagan.

Cada compañero del foro es un libro en potencia.


 


Página generada en 3.428 segundos con 48 consultas.