[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
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:
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
<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
<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
[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
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
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.
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.
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.
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.
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.
private
{ Private declarations }
procedure MuestraDatos;
La implementación de este procedimiento es el siguiente:
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:
[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.
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:
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:
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:
[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.
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.
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.
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:
function GetIwsClientes(UseWSDL: Boolean; Addr: string; HTTPRIO: THTTPRIO): IwsClientes;
const
defWSDL = '[url]http://localhost/WSClientes/wsClientes.dll/wsdl/IwsClientes';[/url]
defURL = '[url]http://localhost/WSClientes/wsClientes.dll/soap/IwsClientes';[/url]
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
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:
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:
function GetIwsClientes(UseWSDL: Boolean; Addr: string; HTTPRIO: THTTPRIO): IwsClientes;
Y finalmente la función deberá quedar de la siguiente forma:
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:
[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.
[swurl=#inicio]Regresar al Índice[/swurl]