!" # $ !"# $ % & !" ' "() "# $ *() " ! $ ' + ) , - ./ #" # $ $ + % & $ ' 0 0 ( $ - 0 1 0 2 / 0 + ) , 0 ""(# $ - ' ' / 3 - 4 - 5 ' + !" "() "5*() " 6 - 7 8 - 0 2 / ' 0 0 -7 8 + 0 / 3 1 0 ' - 1 0 ' - - 7 8 + 0 ' - 0 0 0 * 0 " " ( + 2 / "() "*() " ' !"
%
&
" 1 0 0 0 0 ' 0 0 + 0 9 0 : - : 0 !" - + 0 !" - 0 8 !" 0 ' 0 % & !" -!" 0 0 0 % 1 - 0 + -3 "() " *() " " " ( * ; < ( 0 ) "() "5*() " !" 9 !" 0 ( - "() "5*() " 0 0 0-'
+ 0 3 - 0 3 - 0 = ; > ; ? /-Web Server Application " ) * * + , @0 - - 0 + "() " *() " + 6 ' 0 - 8 - 0 !" % & !" 0 0 - 3 -TWebModule ' TWebActionItem - ' ( 0 - - TWebModule - TForm1
TForm TWebModule1 TWebModule + 6 0 TWebModule 0 TWebActionItem - 0 0 - - 7 8
(
'
" - TWebModule + - / 0 0 TWebModule 0 Actions " 0 0 / A 0 -- -: " 0 -TWebActionItem -; 4 0 0 Name 0-Name TButton 0 0 - Enabled
- Default -- 3 PathInfo 0 6 -MethodType -- . / MethodType mtAny - ( -+ + mtPost
+ -mtGet mtHead ( - 1 0 PathInfo = - 0 TWebActionItem - ( /Portada - % 0 % - 0+ 9B8http://miservidor/WebPCWorld.dll/Portada @0 miservidor + 0 ) - 0 -8 + - 0 - - -- 0 6 true Default 6
-!
' ) *
'
3 - # ; ?$ - 0 + - - 0 0 + 0 -0 0 ' ( 0 % 1 CD % 0 ( 0 -InetPub\Scripts 9 - : 0 0 + 8 -- 0 * * " 6 0 0 -2 / - 1 0 ' - % 1 0 - @7 6 )( ' - " " ( 3(
+
&
'
8- --OnAction 3 0 Response Content -( - - ; 4 - 0 Events " 0 0 0 OnAction " ' - A Response.Content :=
'Hola desde PC World';
Ahora compile el proyecto y aloje la librería o ejecutable en la carpeta que proceda, según la configuración de su servidor web. En este momento ya puede ejecutar su cliente habitual e introducir la URL apropiada para ver el resultado. En la Figura 4 puede ver el resultado obtenido usando Netscape Navigator.
Figura 4. Resultado que genera la primera acción implementada por nuestra aplicación de servidor.
Uso de documentos prediseñados
Desde el código de nuestra aplicación podemos asignar a la propiedad Content
documento HTML completo. No obstante, suele ser más sencillo diseñar dicho documento con una herramienta externa guardándolo en un archivo, de tal forma que posteriormente nuestra aplicación lo recupere y use.
Para poder realizar esta tarea lo primero que necesitamos es un documento HTML ya almacenado en un archivo. Supongamos que ya lo tenemos. Para leerlo y poder usarlo desde la aplicación insertaremos en el módulo web un componente TPageProducer. Encontrará este componente en la página Internet de la Paleta de componentes de Delphi.
Las dos propiedades fundamentales del componente TPageProducer son HTMLDoc y HTMLFile. La primera es una lista de cadenas de caracteres a la que
se puede asignar el documento, mientras que la segunda se utiliza para mantener una referencia al documento HTML almacenado en un archivo. La primera cuenta con el habitual editor de las propiedades de tipo TStrings, de
tal forma que es posible componer el documento simplemente introduciendo las etiquetas HTML.
Figura 5. Utilizaremos un componente TPageProducer para poder enviar al
cliente un documento HTML prediseñado y almacenado en un archivo. Suponiendo que tengamos un documento almacenado en un archivo con el nombre Portada.htm, estableceríamos las propiedades que pueden verse en la
Figura 5. Tenemos un TPageProducer llamado Portada cuya propiedad HTMLFile contiene el camino y nombre del documento. Acto seguido
tendríamos que modificar el código que habíamos escrito, sustituyendo la sentencia existente por esta:
Response.Content := Portada.Content;
Portada es el nombre del componente TPageProducer, componente que cuenta
con una función llamada Content() que se encarga de recuperar el documento
y devolver su contenido. Es este contenido el que asignamos al objeto
Response, de tal forma que sea la información enviada al cliente. El resultado
obtenido será idéntico al que veríamos al abrir el documento HTML original directamente.
Figura 6. La función 0 del componente TPageProducer se encarga de
recuperar el documento, permitiendo su visualización desde el cliente que ha enviado la solicitud.
Sustitución de etiquetas
Obviamente no es preciso crear una aplicación de servidor web para poder recuperar una página con contenido estático, ya que es mucho más sencillo y eficiente poner el documento original directamente accesible para los clientes. Utilizar el componente TPageProducer, sin embargo, tiene algunas ventajas,
entre ellas la posibilidad de sustituir ciertas etiquetas durante el proceso de composición de la respuesta.
Cada vez que al procesar el código HTML se encuentra una etiqueta que comienza con la pareja de caracteres <# el componente TPageProducer genera
un evento OnHTMLTag, facilitando todos los parámetros necesarios para poder
realizar la sustitución por el contenido que convenga. De los parámetros recibidos los dos más interesantes son TagString y ReplaceText. El primero
mencionados, mientras que el segundo será el destinatario del contenido que hay que insertar.
Para ver en la práctica cómo se codifican estas etiquetas sustituibles y cuál es el proceso a seguir, vamos a modificar el documento usado como portada añadiendo un contador, la fecha y la hora locales. Para ello abriremos el documento original y añadiremos al final las dos líneas siguientes:
<p align="center">Es el visitante número <#CONTADOR></p> <p align="right"><#FECHAHORA></p>
Tras guardar esta modificación seleccione el componente TPageProducer, abra
la página Events del Inspector de objetos y haga doble clic sobre el evento OnHTMLTag. El texto a introducir es el mostrado en el Listado 1. Observe que se
ha codificado una función independiente que se encarga de devolver el valor actual del contador actualizándolo.
procedure TWebModule1.PortadaHTMLTag(Sender: TObject; Tag: TTag;
const TagString: String; TagParams: TStrings; var ReplaceText:
String);
begin
Case TagString[1] Of // Nos guiamos por el primer carácter de la marca
'C': // si es el contador
ReplaceText := IntToStr(Contador); 'F': // si es la fecha y hora
ReplaceText := DateToStr(Date) + ' - ' + TimeToStr(Time); End;
end;
// Este método se encarga de devolver el valor del contador
Function TWebModule1.Contador: Integer;
Var
ArchivoContador: File of Integer; ValorContador: Integer;
Begin
// Asignamos el archivo
AssignFile(ArchivoContador, 'ContadorVisitas.DAT');
Try // intentamos abrirlos para lectura
Begin
Reset(ArchivoContador); // para leer el valor actual
Read(ArchivoContador, ValorContador); CloseFile(ArchivoContador);
End;
Except On Exception Do // si no es posible
ValorContador := 1; // inicializamos el contador
End;
Result := ValorContador; // lo devolvemos
Inc(ValorContador); // incrementamos
Rewrite(ArchivoContador); // y guardamos de nuevo
Write(ArchivoContador, ValorContador); // en el archivo
CloseFile(ArchivoContador);
End;
A pesar de que las etiquetas introducidas en el código HTML tienen un nombre completo, como CONTADOR y FECHAHORA, a la hora de comprobar cuál es la que
hay que sustituir tan sólo se ha tenido en cuenta el primer carácter. Esto se ha hecho por simple comodidad, con el fin de poder usar la sentencia Case de
Pascal. Podríamos haber comparado las cadenas completas usando la sentencia If.
Tras volver a compilar la aplicación, al ejecutarla podrá ver que el documento ahora cuenta con un contador que se incrementa y que, además, se muestran la fecha y hora actuales. Éstos son elementos que no pueden introducirse en un documento estático, siendo las aplicaciones de servidor una de las técnicas que pueden generarlos.
Figura 7. El documento ahora cuenta con algunos elementos dinámicos, como un contador, la fecha y hora.
Generar HTML a partir de tablas de
datos
En la mayoría de las ocasiones las aplicaciones de servidor web componen los documentos, total o parcialmente, a partir de información almacenada en bases de datos. En estos casos, y según se vio en el artículo Aplicaciones Web con Visual Basic 6, suele ser necesario obtener los datos, abriendo una tabla o ejecutando una consulta, recorrerlos y generar el código HTML.
Con Delphi este proceso es más simple, puesto que existen varios componentes que facilitan la creación de código HTML a partir de datos obtenidos de una tabla o consulta. Concretamente son tres los componentes disponibles: TDataSetPageProducer, TDataSetTableProducer y
TQueryTableProducer. Los dos últimos generan una tabla HTML que, como
veremos, puede ser personalizada completamente durante la fase de diseño. Supongamos que al pulsar el enlace Entrada existente en la página de
portada, enlace que tendríamos que definir apropiadamente, deseásemos mostrar una lista con todos los artículos existentes en una tabla alojada en una base de datos Microsoft Access. Se trata de la misma base de datos empleada en el artículo antes citado.
El primer paso será crear un alias para poder acceder a dicha base de datos mediante un componente TTable. Es posible realizar esta tarea desde el
Explorador SQL, tal y como se muestra en la Figura 8. Disponiendo de este alias ya podemos insertar en el TWebModule un componente TTable asignando
los valores apropiados a DatabaseName y TableName.
Figura 8. Mediante el Explorador SQL creamos un alias que nos permita acceder a la base de datos que contiene la tabla de artículos.
A continuación se insertará en el módulo un componente
TDataSetTableProducer, asignando a la propiedad DataSet una referencia
al TTable anterior según se ve en la Figura 9. Haciendo doble clic sobre
TDataSetTableProducer se abrirá un editor que permite establecer las columnas
que serán visibles en la tabla HTML, así como sus atributos particulares y las propiedades generales de la tabla. Usando este editor configuramos la tabla de tal forma que quede según puede ver en la Figura 10.
Figura 9. Asociamos el componente TDataSetTableProducer con el TTable, de
tal forma que pueda obtener todas las filas de la tabla y generar el código HTML.
Figura 10. Usando el editor asociado al TDataSetTableProducer es posible
establecer la mayoría de las propiedades de la tabla HTML a generar.
Lo único que queda por hacer para que el cliente pueda acceder a esta tabla de artículos es facilitar una opción para ello. Con este fin se facilitará un enlace en la página de portada que ejecutará la acción ListaArticulos. Esta acción,
que habrá que añadir al TWebModule, tendrá asociado el código siguiente en el
evento OnAction.
tblArticulos.Open; // abrimos la tabla // enviamos al cliente el contenido Response.Content :=
ListaArticulos.Content;
tblArticulos.Close; // y la cerramos
Tras recompilar el proyecto podrá acceder desde su cliente web y ver el resultado. Si está usando la misma base de datos facilitada como ejemplo, la información mostrada por el cliente será similar a la de la Figura 11.
Figura 11. Al solicitar la lista de artículos el servidor abre la tabla, genera el código y lo devuelve al cliente.
Personalizar la generación de código
Aparte de establecer una serie de atributos para la tabla y las columnas, nuestra aplicación también puede controlar individualmente el contenido de cada una de las celdas. Para ello el componente TDataSetTableProducer
genera un evento OnFormatCell por cada una de las celdillas, facilitando sus
coordenadas, alineación, color y contenido.
Las coordenadas de las celdillas se inician en la columna cero y fila cero, correspondientes a la esquina superior izquierda de la tabla. El contenido se recibe en una variable llamada 3 y es posible modificarla directamente,
al igual que el color, alineación y atributos.
En teoría es posible usar el evento OnFormatCell para realizar cualquier
operación que afecte a los atributos o contenido de una celdilla de la tabla. Para verlo en la práctica seleccione el componente TDataSetTableProducer que
hay en el módulo web, haga doble clic sobre el citado evento e inserte el código siguiente:
If (CellColumn=1) And (CellRow<>0) Then CellData := '<a href="ConsultaAutor?Autor=' +
CellData + '">' + CellData + '</a>';
Lo que se hace, como puede ver, es comprobar si la celdilla corresponde a la primera columna de una fila que no sea la de títulos. Dicha columna contiene el nombre del autor del artículo, nombre que convertimos en un enlace que
ejecutará una acción llamada ConsultaAutory que contará con una parámetro
llamado Autor. El valor de este parámetro será el propio nombre del autor.
Si tras hacer estos cambios vuelve a compilar e instalar la aplicación, al obtener la lista de artículos podrá ver, como en la Figura 12, que todos los nombres de autor actúan ahora como enlaces. Al pulsar sobre ellos,
lógicamente, no se obtiene documento alguno puesto que no se ha codificado la acción ConsultaAutor.
Figura 12. La tabla que genera ahora la aplicación genera un enlace por cada autor.
Para que los enlaces asociados a los nombres de autor sirvan para algo, aparte de aparecer en un bonito color y subrayados, será preciso codificar una nueva acción en el TWebModule. Ésta se encargaría de recuperar el parámetro
facilitado, el nombre del autor, ejecutando una consulta para obtener los artículos que correspondan y generar una nueva tabla. Este proceso puede realizarse, en su mayor parte, tan sólo con dos componentes.
El primer componente a añadir al módulo será un TQuery que, mediante la
propiedad DatabaseName, asociaremos al alias que habíamos creado y usado
previamente. La consulta que ejecutará este componente, y que deberemos introducir en la propiedad SQL, será tan simple como esta:
SELECT *
FROM Articulos WHERE Autor=:Autor
Observe que la cláusula WHERE tiene asociado un parámetro, llamado :Autor,
que coincide en nombre con el parámetro que facilita el enlace de la tabla HTML. Esto permitirá una sustitución automática del parámetro en la consulta por el valor obtenido de la petición del cliente, sin necesidad de ninguna intervención por nuestra parte.
Para generar la tabla HTML a partir del resultado que se produzca en el TQuery
precisaremos un nuevo componente: TQueryTableProducer. Éste estará
asociado al primero mediante la propiedad Query. Al igual que
TDataSetTableProducer, el componente TQueryTableProducer cuenta con un
editor que facilita la configuración de la mayoría de los atributos de la tabla. Usaremos este editor, como puede verse en la Figura 13, para fijar las columnas que se mostrarán, el tipo de borde y los colores.
Figura 13. Usamos el editor del componente TQueryTableProducer para
establecer las columnas visibles y los atributos de la tabla HTML. El último paso será definir la nueva acción en el TWebModule. El camino
asociado a esta acción será ConsultaAutor, tal y como se estableció al generar
los enlaces anteriormente. El código asociado al evento OnAction de esta
acción será una simple sentencia:
// Enviamos el resultado Response.Content :=
TablaArticulosAutor.Content;
Ahora ya podemos compilar e instalar de nuevo la aplicación. Pulsando sobre cualquier autor de la tabla de artículos obtendremos otra nueva, más reducida, que contendrá tan sólo los artículos del autor seleccionado.
Figura 14. La consulta genera una nueva tabla que contiene sólo los artículos del autor seleccionado.
Resumen
Como se ha demostrado en este artículo, la creación de aplicaciones de servidor web con Borland Delphi es una tarea realmente sencilla, incluso más que con Visual Basic si comparamos la cantidad de código escrita en el artículo Aplicaciones Web con Visual Basic 6 con la escrita en éste. Esto se debe, principalmente, a la existencia de componentes como TDataSetTableProducer y TQueryTableProducer, capaces de interactuar directamente con una tabla de
datos o una consulta.
Gracias a la existencia de estos componentes no hay que preocuparse por tareas como obtener los parámetros de un enlace o un formulario, ya que estos parámetros son recuperados automáticamente y usados, como se ha visto, para ejecutar las consultas codificadas en la fase de diseño. Lo único a tener en cuenta es que hay que seguir unas ciertas reglas, de tal forma que los nombres de los parámetros coincidan en el código HTML y las consultas. © 1997-2001 Francisco Charte Ojeda