Está en la página 1de 291

Desarrollo de software

Este texto est pensado para aquellos que, teniendo conocimientos de la tecnologa ASP, deseen aumentar la potencia y escalabilidad de sus aplicaciones mediante el uso de componentes compilados. La primera parte del libro consiste en un recordatorio de las caractersticas ms importantes de ASP, mientras que la segunda se centra en el diseo y uso de componentes. Se tratan temas como la creacin de libreras de enlace dinmico (DLLs), uso de componentes desde pginas ASP, modelo COM+, Servicios de Componentes, componentes de acceso a datos, componentes transaccionales, MSMQ y ADSI. Se requieren unos conocimientos bsicos de Windows, fundamentos de Internet/Intranet, lenguaje HTML y tecnologa ASP, as como ciertas nociones de programacin con Visual Basic.

PARA INTERNET/INTRANET CON ASP 3


VCTOR ARRONDO, NGEL ESTEBAN

DESARROLLO DE APLICACIONES COM+

ADVERTENCIA LEGAL
Todos los derechos de esta obra estn reservados a Grupo EIDOS Consultora y Documentacin Informtica, S.L. El editor prohbe cualquier tipo de fijacin, reproduccin, transformacin, distribucin, ya sea mediante venta y/o alquiler y/o prstamo y/o cualquier otra forma de cesin de uso, y/o comunicacin pblica de la misma, total o parcialmente, por cualquier sistema o en cualquier soporte, ya sea por fotocopia, medio mecnico o electrnico, incluido el tratamiento informtico de la misma, en cualquier lugar del universo. El almacenamiento o archivo de esta obra en un ordenador diferente al inicial est expresamente prohibido, as como cualquier otra forma de descarga (downloading), transmisin o puesta a disposicin (an en sistema streaming). La vulneracin de cualesquiera de estos derechos podr ser considerada como una actividad penal tipificada en los artculos 270 y siguientes del Cdigo Penal. La proteccin de esta obra se extiende al universo, de acuerdo con las leyes y convenios internacionales. Esta obra est destinada exclusivamente para el uso particular del usuario, quedando expresamente prohibido su uso profesional en empresas, centros docentes o cualquier otro, incluyendo a sus empleados de cualquier tipo, colaboradores y/o alumnos. Si Vd. desea autorizacin para el uso profesional, puede obtenerla enviando un e-mail fmarin@eidos.es o al fax (34)-91-5017824. Si piensa o tiene alguna duda sobre la legalidad de la autorizacin de la obra, o que la misma ha llegado hasta Vd. vulnerando lo anterior, le agradeceremos que nos lo comunique al e-mail fmarin@eidos.es o al fax (34)-91-5017824). Esta comunicacin ser absolutamente confidencial. Colabore contra el fraude. Si usted piensa que esta obra le ha sido de utilidad, pero no se han abonado los derechos correspondientes, no podremos hacer ms obras como sta. Victor Arrondo y ngel Esteban, 2000 Grupo EIDOS Consultara y Documentacin Informtica, S.L., 2000 ISBN 84-88457-20-0

Desarrollo de Aplicaciones COM+ para Internet/Intranet con ASP 3


Victor Arrondo y ngel Esteban
Responsable editorial Paco Marn (fmarin@eidos.es) Autoedicin Magdalena Marn (mmarin@eidos.es) Victor Arrondo (varrondo@eidos.es) ngel Esteban (aesteban@eidos.es) Grupo EIDOS C/ Tllez 30 Oficina 2 28007-Madrid (Espaa) Tel: 91 5013234 Fax: 91 (34) 5017824 www.grupoeidos.com/www.eidos.es www.LaLibreriaDigital.com Coordinacin de la edicin Antonio Quirs (aquiros@eidos.es)

ndice
NDICE................................................................................................................................................... 5 INTRODUCCIN A ASP................................................................................................................... 11 ANTECEDENTES DE ASP: LA ESPECIFICACIN CGI .......................................................................... 11 DEFINICIN DE ASP........................................................................................................................... 12 APLICACIONES ASP ........................................................................................................................... 13 APORTACIONES DE ASP..................................................................................................................... 14 SINTAXIS DE ASP............................................................................................................................... 15 OBJETOS INTEGRADOS EN ASP 3.0.................................................................................................... 17 COMPONENTES DE SERVIDOR ............................................................................................................ 18 NOVEDADES DE ASP 3.0 ................................................................................................................... 19 Mejoras generales en ASP 3.0....................................................................................................... 19 El objeto Response......................................................................................................................... 20 El objeto Server ............................................................................................................................. 20 El objeto ASPError........................................................................................................................ 24 Componente de registro de IIS (Logging Utility) .......................................................................... 26 Aplicaciones ASP con IIS 5.0 ........................................................................................................ 30 Otros cambios................................................................................................................................ 32 MODELO DE OBJETOS DE ASP. PARTE I .................................................................................. 35 INTRODUCCIN .................................................................................................................................. 35 EL OBJETO RESPONSE ........................................................................................................................ 36 Colecciones del objeto Response................................................................................................... 37 Propiedades del objeto Response .................................................................................................. 39 Mtodos del objeto Response......................................................................................................... 41 EL OBJETO REQUEST .......................................................................................................................... 44

Colecciones del objeto Request ..................................................................................................... 44 MODELO DE OBJETOS DE ASP. PARTE II ................................................................................ 49 EL OBJETO APPLICATION ................................................................................................................... 49 Colecciones del objeto Application ............................................................................................... 51 Mtodos del objeto Application ..................................................................................................... 52 Eventos del objeto Application. El GLOBAL.ASA......................................................................... 53 EL OBJETO SESSION ........................................................................................................................... 56 Colecciones del objeto Session...................................................................................................... 56 Propiedades del objeto Session ..................................................................................................... 58 Mtodos del objeto Session............................................................................................................ 60 Eventos del objeto Session............................................................................................................. 60 EL OBJETO SERVER ............................................................................................................................ 61 Propiedades del objeto Server....................................................................................................... 61 Mtodos del objeto Server ............................................................................................................. 62 EL OBJETO OBJECTCONTEXT ............................................................................................................. 64 Mtodos del objeto ObjectContext................................................................................................. 66 EVENTOS DEL OBJETO OBJECTCONTEXT ........................................................................................... 66 EL OBJETO ASPERROR ...................................................................................................................... 67 Propiedades del objeto ASPError ................................................................................................. 67 COMPONENTES DE SERVIDOR ................................................................................................... 69 INTRODUCCIN .................................................................................................................................. 69 COMPONENTE ADROTATOR .............................................................................................................. 71 COMPONENTE FUNCIONES DEL NAVEGADOR .................................................................................... 74 COMPONENTE NEXTLINK................................................................................................................... 77 COMPONENTE CONTENT ROTATOR ................................................................................................... 80 COMPONENTE PAGECOUNTER ........................................................................................................... 83 COMPONENTE COUNTERS .................................................................................................................. 86 COMPONENTE MYINFO ...................................................................................................................... 87 COMPONENTE TOOLS ......................................................................................................................... 88 COMPONENTE PERMISSIONCHECKER ................................................................................................ 91 COMPONENTES DE ACCESO A DATOS. ADO .......................................................................... 93 INTRODUCCIN .................................................................................................................................. 93 MODELO DE OBJETOS DE ADO .......................................................................................................... 96 EL OBJETO CONNECTION ................................................................................................................... 97 Abrir una conexin ........................................................................................................................ 98 Ejecutar comandos sobre una conexin ...................................................................................... 102 Cerrar la conexin....................................................................................................................... 104 EL OBJETO COMMAND ..................................................................................................................... 104 Crear un objeto Command .......................................................................................................... 105 La coleccin Parameters ............................................................................................................. 107 Ejecutar un comando................................................................................................................... 109 EL OBJETO RECORDSET ................................................................................................................... 111 Creacin y apertura de un objeto Recordset ............................................................................... 114 CDONTS Y ASP ................................................................................................................................ 119 INTRODUCCIN ................................................................................................................................ 119 MODELO DE OBJETOS DE CDONTS................................................................................................. 121 EL OBJETO NEWMAIL ....................................................................................................................... 122 EL OBJETO SESSION ......................................................................................................................... 127 EL OBJETO FOLDER .......................................................................................................................... 130 EL OBJETO MESSAGE ....................................................................................................................... 133 EL MODELO COM.......................................................................................................................... 143
6

INTRODUCCIN A LOS COMPONENTES ............................................................................................. 143 CONCEPTOS ...................................................................................................................................... 144 ESPECIFICACIN COM..................................................................................................................... 144 VENTAJAS DEL USO DE COMPONENTES............................................................................................ 145 LOS INTERFACES .............................................................................................................................. 146 IDENTIFICADORES NICOS GLOBALES (GUIDS)............................................................................. 147 ENLACE TEMPRANO Y TARDO ......................................................................................................... 148 ESPACIO DE PROCESO DE UN COMPONENTE ..................................................................................... 149 EL INTERFAZ IUNKNOWN ................................................................................................................ 150 WINDOWS DNA ............................................................................................................................... 150 COMPONENTES EN VISUAL BASIC .......................................................................................... 153 INTRODUCCIN ................................................................................................................................ 153 COMPONENTES EN VISUAL BASIC Y VISUAL C++........................................................................... 153 UN PRIMER EJEMPLO DE COMPONENTE............................................................................................ 154 Fases en el diseo del componente.............................................................................................. 154 Creacin del proyecto ActiveX DLL............................................................................................ 155 Diseo del interfaz....................................................................................................................... 156 Generacin de la DLL y registro del componente....................................................................... 159 Rediseo del componente ............................................................................................................ 161 Reutilizacin del componente ...................................................................................................... 164 TIPOS DE COMPONENTES.................................................................................................................. 167 MODELOS DE APLICACIONES CLIENTE/SERVIDOR.......................................................... 171 INTRODUCCIN ................................................................................................................................ 171 ARQUITECTURA CLIENTE/SERVIDOR EN DOS CAPAS........................................................................ 171 ARQUITECTURA CLIENTE/SERVIDOR EN TRES CAPAS ...................................................................... 172 EJEMPLO DE UNA APLICACIN ASP EN TRES CAPAS ....................................................................... 174 COMPONENTIZACIN DE LA CAPA INTERMEDIA .............................................................................. 175 Diseo de la capa intermedia con un componente ...................................................................... 175 Rediseo del componente de la capa intermedia......................................................................... 178 Un segundo rediseo del componente de la capa intermedia ..................................................... 178 ARQUITECTURA CLIENTE/SERVIDOR EN N CAPAS ............................................................................ 180 DISEO DE COMPONENTES PARA ASP................................................................................... 181 INTRODUCCIN ................................................................................................................................ 181 TIPOS VARIANT ................................................................................................................................ 181 ACCESO AL MODELO DE OBJETOS DE ASP DESDE UN COMPONENTE .............................................. 185 Acceso al objeto Application ....................................................................................................... 185 Acceso a los objetos Request y Response .................................................................................... 187 Recompilacin de componentes con enlace temprano ................................................................ 192 IMPLEMENTACIN DE INTERFACES EN VISUAL BASIC .................................................................... 193 SERVICIOS DE COMPONENTES ................................................................................................ 197 INTRODUCCIN ................................................................................................................................ 197 CARACTERSTICAS DEL MTS (MICROSOFT TRANSACTION SERVER).............................................. 197 SERVICIOS QUE APORTA EL MTS..................................................................................................... 198 Transacciones para componentes................................................................................................ 199 Comercio de objetos .................................................................................................................... 199 Independencia entre procesos ..................................................................................................... 199 Fondo comn de recursos............................................................................................................ 199 Activacin en el momento (Just-In-Time).................................................................................... 199 Seguridad..................................................................................................................................... 200 CONCEPTOS PRINCIPALES DEL MTS ................................................................................................ 200 La intercepcin ............................................................................................................................ 200
7

Propiedades declarativas. El catlogo del MTS.......................................................................... 200 FUNCIONAMIENTO DEL MTS ........................................................................................................... 201 El objeto Context Wrapper .......................................................................................................... 201 El objeto de contexto ................................................................................................................... 201 El interfaz ObjectContext ............................................................................................................ 202 El interfaz ObjectControl ............................................................................................................ 203 INSTANCIAR UN OBJETO A PARTIR DE UN COMPONENTE MTS ........................................................ 204 Instanciar un objeto desde otro objeto de Visual Basic .............................................................. 204 Instanciar un objeto desde una pgina ASP con VBScript.......................................................... 204 INTRODUCCIN A LAS TRANSACCIONES .......................................................................................... 205 Duracin y resultado de una transaccin.................................................................................... 206 ACTIVACIN EN EL MOMENTO ......................................................................................................... 206 ALMACENAR EL ESTADO DEL OBJETO ............................................................................................. 208 ADMINISTRADOR DE PROPIEDADES COMPARTIDAS (SPM)............................................................. 208 Obtener una referencia al SPM ................................................................................................... 209 Crear un grupo de propiedades compartidas.............................................................................. 210 Crear una propiedad compartida................................................................................................ 212 SERVICIOS DE COMPONENTES Y COM+ .......................................................................................... 213 La intercepcin en COM+........................................................................................................... 215 DISEO DE COMPONENTES COM+ .......................................................................................... 219 EL INTERFAZ OBJECTCONTROL ....................................................................................................... 219 ACTIVACIN JUST-IN-TIME (JIT) .................................................................................................... 227 INICIALIZACIN DEL COMPONENTE ................................................................................................. 229 ESTADO DE UN COMPONENTE .......................................................................................................... 232 CADENA DEL CONSTRUCTOR ........................................................................................................... 238 COMPONENTES TRANSACCIONALES..................................................................................... 241 INTRODUCCIN ................................................................................................................................ 241 EL CONTEXTO Y LAS TRANSACCIONES ............................................................................................ 242 PAUTAS PARA EL DESARROLLO DE COMPONENTES TRANSACCIONALES ......................................... 242 CASOS PRCTICOS ........................................................................................................................... 243 La pgina contiene todo el cdigo transaccional........................................................................ 243 PARTE DEL CDIGO TRANSACCIONAL EN UN COMPONENTE ............................................................ 245 VOTO TRANSACCIONAL DE UN COMPONENTE ................................................................................. 249 DOS COMPONENTES TRANSACCIONALES INVOCADOS DESDE ASP.................................................. 251 UN COMPONENTE TRANSACCIONAL INVOCA A OTRO ...................................................................... 253 ACCESO A MSMQ DESDE ASP .................................................................................................... 257 SERVICIOS DE MENSAJERA ENTRE APLICACIONES .......................................................................... 257 MSMQ (MESSAGE QUEUING SERVER)............................................................................................ 258 FUNCIONAMIENTO DEL MSMQ ....................................................................................................... 259 Creacin de una cola................................................................................................................... 260 Modelo de objetos de MSMQ....................................................................................................... 261 Envo de mensajes........................................................................................................................ 262 Prioridad de los mensajes ........................................................................................................... 265 Recepcin de mensajes ................................................................................................................ 266 Colas de diario ............................................................................................................................ 269 ENVO DE UN COMPONENTE COM+................................................................................................. 271 ACCESO A ADSI DESDE ASP ....................................................................................................... 277 DIRECTORIOS Y SERVICIOS DE DIRECTORIO .................................................................................... 277 ACTIVE DIRECTORY DE MICROSOFT ............................................................................................... 278 ADSI (ACTIVE DIRECTORY SERVICES INTERFACE) ........................................................................ 279 ESTRUCTURA DE ACTIVE DIRECTORY ............................................................................................. 280
8

PROVEEDOR ADSI PARA WINNT .................................................................................................... 281 CONTENEDORES ............................................................................................................................... 283 PROPIEDADES DE LOS OBJETOS DEL DIRECTORIO ............................................................................ 285 PROPIEDADES CON VALORES MLTIPLES ........................................................................................ 287 MODIFICACIN DE PROPIEDADES .................................................................................................... 288

Introduccin a ASP
Antecedentes de ASP: La especificacin CGI
ASP no es una idea realmente nueva, encontramos un antecedente muy importante y muy utilizado en Internet denominado comnmente scritps CGI. Las siglas CGI se corresponden en ingls a Common Gateway Interface, es decir, interfaz de pasarela comn. Vamos a ir viendo paso a paso que significan cada unas de estas palabras, que realmente son las que definen el concepto de CGI. La especificacin Common Gateway Interface permite a los servidores Web ejecutar y comunicarse con otros programas, llamados programas CGI, e incorporar la salida de los mismos a los grficos, texto o audio enviados a un navegador Web. La programacin en CGI implica disear programas que se ejecutarn en el entorno de Internet, y ms concretamente en el entorno World Wide Web. El programa CGI se ejecutar dentro del entorno ofrecido por el servidor Web que lo contiene. El servidor Web crear una informacin especial para el CGI cuando pasa a ejecutarlo, y el servidor esperar una respuesta del programa CGI como resultado de su ejecucin. Es esta comunicacin o interaccin entre el servidor Web y el programa CGI es lo que define realmente la especificacin CGI. Los programas CGI tambin se suelen denominar scripts CGI, esto es debido a que los primeros programas CGI fueron escritos utilizando scripts de la shell de UNIX y Perl. Antes de que el programa CGI se ejecute, el servidor Web que lo contiene se encargar de crear un entorno con el que podr interactuar el programa CGI. Este entorno comprende la traduccin de

Desarrollo de aplicaciones COM+ para Internet / Intranet con ASP 3.0

Grupo EIDOS

cabeceras de peticiones del protocolo HTTP (HyperText Transfer Protocol) en variables de entorno a las que podr acceder nuestro programa CGI. Estas variables de entorno contendrn una informacin muy variada acerca del cliente que ha realizado la peticin o del propio servidor Web en el que se ejecuta el programa CGI. Una vez que el servidor ha iniciado la ejecucin del programa CGI esperar un resultado de la ejecucin del mismo. Este resultado suele ser una serie de encabezados de respuesta del protocolo HTTP y cdigo HTML. Estos encabezados y cdigo HTML sern recogidos por el servidor Web y enviados al cliente que realiz la peticin, es decir, al navegador o cliente Web. Despus de ver esta pequea introduccin podemos definir un programa CGI como un programa que se encuentra en un servidor Web y que recibe peticiones desde un cliente Web travs del servidor Web. Y gracias al entorno que le ofrece el servidor Web el programa CGI puede obtener informacin sobre la peticin realizada, adems de otra informacin til, que le permitir procesar la peticin. La respuesta a esta peticin ser generada por el programa CGI en forma de cabeceras de respuesta del protocolo HTTP y etiquetas del lenguaje HTML (HyperText Markup Language), que sern enviadas por el servidor Web al navegador Web que realiz la peticin. CGI no es un lenguaje de programacin sino que es una especificacin. La especificacin CGI va a realizar la funcin de interfaz o pasarela entre el servidor Web y los programas CGI, haciendo uso del protocolo HTTP y el lenguaje de hipertexto HTML. Un programa CGI ser aquel que cumpla la especificacin CGI, es decir, interactuar con el servidor atendiendo a unos principios establecidos por la especificacin CGI. CGI ya lleva siendo utilizado muchos aos en la red y todava se sigue utilizando en muchos sitios Web a la hora de acceder a datos o construir pginas dinmicas, pero cada vez ms los sitios Web van adoptando la utilizacin de Active Server Pages. Active Server Pages (ASP) es el nombre que reciben las pginas activas de servidor, es decir, las pginas que se ejecutan en el servidor. ASP se basa en la especificacin CGI, podemos considerar que ASP es una evolucin de la especificacin CGI.

Definicin de ASP
La filosofa de ASP resulta muy sencilla, en pocas palabras se puede definir de la siguiente forma: las pginas ASP, tambin llamadas pginas activas, son pginas que contienen cdigo HTML, script de cliente y un script que se ejecuta en el servidor, dando como resultado cdigo HTML. Por lo tanto al cargar una pgina ASP en nuestro navegador, en realidad no estamos cargando la pgina ASP como tal, sino el resultado de la ejecucin de la pgina ASP, es decir la salida de la pgina ASP, y como se ha apuntado anteriormente se trata de cdigo HTML. Es decir, son pginas que se ejecutan en el servidor enviando como resultado al cliente cdigo HTML. Antes de seguir vamos a definir de forma sencilla lo que se considera un lenguaje de script o de secuencia de comandos. Un lenguaje de script es un subconjunto de otro lenguaje ms general y que se utiliza para un entorno muy determinado, en este caso el entorno es la Web. Una pgina ASP podr contener los siguientes elementos: texto, componentes ActiveX, cdigo HTML y comandos de script. Este script puede ser de dos tipos: script de cliente o script de servidor. El script de servidor es la nueva idea que introduce ASP, se debe tener en cuenta que en el script de servidor se tiene acceso a diferentes objetos y no est orientado a eventos.

12

Grupo EIDOS

1. Introduccin a ASP

El script de servidor utilizado en ASP utiliza la misma sintaxis que el script de cliente, la diferencia est en que con ASP el script de servidor es compilado y procesado por el servidor Web antes de que la pgina sea enviada al navegador. ASP no es un lenguaje de script, ASP ofrece un entorno para procesar scripts que se incorporan dentro de pginas HTML, es decir, un entorno de procesamiento de scripts de servidor. La propia Microsoft define ASP de la siguiente manera: "...es un entorno de secuencias de comandos en el lado del servidor que puede utilizar para crear y ejecutar aplicaciones de servidor Web dinmicas, interactivas y de alto rendimiento...". Realmente, ASP es un componente (asp.dll) que se instala en un servidor Web y cuya misin es la de procesar ficheros que terminan con la extensin .asp y transmitir el resultado al cliente que solicit la pgina ASP. El script de servidor incluido en una pgina ASP empieza a ejecutarse cuando un navegador solicita el archivo .asp al servidor Web. El servidor Web llama entonces a ASP, el cual lee el archivo solicitado de arriba a abajo, ejecuta los comandos y enva una pgina HTML al explorador. ASP incluye un motor de interpretacin de scripts del lado del servidor. Las pginas ASP son ficheros con la extensin asp. Crear un fichero .asp resulta muy sencillo, se puede crear a partir de una pgina HTML existente, simplemente renombrando el fichero .html o .htm a un fichero .asp. Para hacer esta pgina ASP disponible para los usuarios de la Web, el fichero .asp se debe almacenar en un directorio de publicacin en Internet, se debe tener en cuenta que el directorio virtual asociado debe tener permisos de ejecucin de secuencias de comandos. La ltima versin de la tecnologa ASP es la versin 3.0. Esta versin es muy similar a su predecesora, y todas las nuevas caractersticas que presenta se deben a que se utiliza una nueva versin del servidor Web (Internet Information Services 5.0), recordemos que las pginas ASP son procesadas por el servidor. En el tema siguiente se ofrece una comparativa de ASP 2.0 con ASP 3.0 comentando brevemente todas sus novedades, se recomienda la lectura del segundo captulo sobretodo a los alumnos que ya conozcan ASP 2.0.

Aplicaciones ASP
Una aplicacin basada en ASP consta de un directorio virtual en un servidor Web y de todos los subdirectorios y archivos contenidos en l. Una aplicacin puede ser una pgina principal sencilla, o bien puede estar formada por un conjunto completo de pginas interrelacionadas entre s. Al usar aplicaciones en ASP es posible mantener un estado, es decir, se tiene la capacidad de mantener informacin. Dentro de una aplicacin ASP se pueden mantener dos tipos de estado: Estado de la aplicacin, en la que toda la informacin relativa a una aplicacin est disponible para todos los usuarios de la misma. Estado de sesin, en la que la informacin slo est disponible para un usuario o sesin especficos. Una sesin por lo tanto, pertenece a un solo usuario.

Un ejemplo prctico de una aplicacin ASP puede ser este mismo sitio Web. Almagesto est completamente realizado con pginas ASP constituyendo por lo tanto una aplicacin ASP, este sitio

13

Desarrollo de aplicaciones COM+ para Internet / Intranet con ASP 3.0

Grupo EIDOS

Web demuestra los diferentes usos que puede tener la tecnologa ASP y las necesidades que puede cubrir. Las aplicaciones ASP no son aplicaciones al uso, ya que en realidad no se dispone de un ejecutable sino de un conjunto de pginas, imgenes y recursos, por lo tanto se trata de aplicaciones muy particulares que requieren para su ejecucin de un servidor Web que soporte las pginas ASP.

Aportaciones de ASP
En este apartado se comentan las aportaciones que ofrece ASP desde su primera versin, es decir, se trata de aportaciones muy genricas de la tecnologa ASP. Para entender las aportaciones que ofrecen las pginas ASP se deben tener en cuenta una serie de caractersticas del protocolo HTTP (HyperText Transfer Protocol). Se dice que le protocolo HTTP es un protocolo sin estado, es decir, no se puede mantener un estado entre diferentes peticiones. El protocolo HTTP se basa en el paradigma cliente/servidor o peticin/respuesta. Se deben tener en cuenta un par de puntos a la hora de establecer la comunicacin entre clientes (navegadores Web) y servidores (servidores Web) del protocolo HTTP: Despus de realizar una peticin el cliente se desconecta del servidor y espera una respuesta. El servidor debe restablecer la conexin despus de que haya procesado la peticin. El servidor y el cliente slo se tienen en cuenta durante la conexin, despus, se olvidan el uno del otro. Por esta razn, ni el cliente ni el servidor pueden retener informacin entre diferentes peticiones o a travs de diferentes pginas Web. Sin embargo, ASP permite al servidor almacenar informacin, o mantener el estado, entre las diferentes peticiones del cliente.

El cliente y el servidor Web se comunican utilizando cabeceras HTTP, estas cabeceras son colecciones de datos que intercambian el cliente y el servidor para asegurar que la transaccin es coherente y completa. Como peticin del usuario se enva una cabecera y el servidor interpreta esta cabecera y enva una respuesta HTTP cuyo cuerpo sera el contenido del recurso demandado por el cliente. ASP permite al desarrollador intervenir en todo el proceso de comunicacin del protocolo HTTP. Los objetos integrados dentro de ASP Request y Response interactan con las peticiones y respuestas del protocolo HTTP, respectivamente. Dentro de los objetos integrados de ASP podemos encontrar la forma de acceder al servidor, obtener informacin del mismo, as como del usuario. Y tambin se permite, como se haba comentado anteriormente, mantener el estado entre diferentes peticiones del cliente. Se puede considerar ASP como una nueva (aunque ya no tan nueva) aproximacin a la creacin de pginas web complejas que pueden acceder a bases de datos o a otros objetos del servidor. Ofrece lo siguiente:
14

Independencia del navegador, ASP puede ejecutar complejas operaciones en el servidor y enviar solamente los resultados al cliente. Construccin de pginas basadas en bases de datos que permiten realizar operaciones sobre las bases de datos del servidor de forma bastante sencilla. Es una de las soluciones ms verstiles para el desarrollo de aplicaciones en el entorno de Internet/Intranet.

Grupo EIDOS

1. Introduccin a ASP

Desarrollo de complejas aplicaciones Web. Facilidad de uso de componentes de terceras partes ejecutndose en el servidor, es decir, se pueden utilizar componentes para liberarnos de realizar tareas complejas. Estos componentes se deben registrar en el servidor y podrn ser utilizados desde el script correspondiente. Estos componentes se denominan componentes ActiveX de servidor. Posibilidad de definir pginas ASP transaccionales para realizar todas las operaciones contenidas en la misma dentro de una transaccin. Una tecnologa en constante evolucin y mejora.

A lo largo del curso se profundizar ms en todos estos puntos, aqu se han comentado simplemente los ms evidentes y tambin para poseer una visin general de lo que supone la tecnologa ASP.

Sintaxis de ASP
Como se ha comentado anteriormente ASP no es un lenguaje de script, sino que ofrece un entorno para la ejecucin de estos lenguajes que se encuentran dentro de pginas ASP. ASP posee una sintaxis para poder distinguir cada uno de los elementos que nos podemos encontrar dentro de una pgina ASP. Encerrado dentro de los delimitadores <%%> se va a encontrar todo el cdigo de script de servidor, de esta forma el comando <%nombre="Pepe"%> asigna el valor Pepe a la variable nombre; y dentro de los delimitadores <%=%> se encuentran expresiones de salida, as por ejemplo la expresin <%=nombre%> enviar al navegador el valor Pepe, es decir, el valor actual de la variable, ms adelante se ver una equivalencia de estos delimitadores con un mtodo de un objeto integrado de ASP. Entre los delimitadores <%%> se puede y debe incluir varias sentencias en distintas lneas de cdigo del lenguaje de secuencias de comandos, sin embargo los delimitadores <%=%> slo podemos encerrar una sentencia por lnea. Entre los delimitadores de ASP se puede incluir cualquier tipo de expresin vlida en el lenguaje de script principal. Por ejemplo el Cdigo fuente 1 genera un texto que contiene la hora actual del servidor.

Esta pgina se actualiz a las <%=Now%> Cdigo fuente 1

En este caso el servidor Web devuelve al navegador el valor de la funcin Now de VBScript junto con el texto. Dentro de los delimitadores de script de servidor se pueden encontrar tambin instrucciones del lenguaje de script correspondiente, as por ejemplo puede aparecer una instruccin If...Then...Else del lenguaje VBScript como se puede apreciar en el Cdigo fuente 2.

<% If nombre="" Then variable="Nombre desconocido"

15

Desarrollo de aplicaciones COM+ para Internet / Intranet con ASP 3.0

Grupo EIDOS

Else variable="Hola amigo "&nombre End If %> <FONT COLOR="GREEN"> <%=variable%> </FONT> Cdigo fuente 2

En el cdigo anterior se comprueba si la variable nombre tiene algn valor, si lo tiene saludamos con el valor de la variable, mostrando el saludo en color verde. Tambin se puede incluir cdigo HTML entre las instrucciones del script. Por ejemplo la secuencia de comandos del Cdigo fuente 3 mezcla HTML con una instruccin condicional y produce el mismo resultado que la secuencia anterior.

<FONT COLOR="GREEN"> <% If nombre="" Then%> Nombre desconocido <%Else%> Hola amigo <%=nombre%> <%End If%> </FONT> Cdigo fuente 3

Para poder realizar una lectura ms sencilla del cdigo ASP se recomienda utilizar los delimitadores de script de servidor encerrando varias lneas de cdigo en lugar de un par de delimitadores por cada lnea. As, en lugar de escribir lo que se muestra en el Cdigo fuente 4, se debera escribir lo que se muestra en el Cdigo fuente 5.

<%strNombre=Session("nombre")%> <%strApellidos=Session("apellidos")%> <%strEdad=Session("edad")%> Cdigo fuente 4

<% strNombre=Session("nombre") strApellidos=Session("apellidos") strEdad=Session("edad") %> Cdigo fuente 5

16

Grupo EIDOS

1. Introduccin a ASP

Objetos integrados en ASP 3.0


ASP en su versin 3.0 contiene siete objetos integrados que liberan al programador de la realizacin de tareas complejas. Estos seis objetos no requieren que sean instanciados siempre se encuentran disponibles en nuestras pginas ASP. Estos objetos son los siguientes: Application, Session, Request, Response, Server, ASPError y ObjectContext. Cada uno de estos objetos posee una serie de mtodos y propiedades para poder ser utilizados por el script de servidor, adems cada objeto posee una funcin determinada, bsicamente estas funciones son las siguientes: Request: obtencin de informacin del cliente. Response: envo de informacin al cliente. Server: acceso a los recursos del servidor, como puede ser la creacin de componentes . Session: almacena informacin sobre la sesin de un usuario. Application: almacena informacin comn para todos los usuarios de la aplicacin ASP. ObjectContext: gestin de transacciones en pginas ASP. ASPError: contiene informacin detallada acerca del ltimo error que se ha producido.

Cada uno de estos objetos se explicarn con una mayor profundidad ms adelante. La sintaxis utilizada para poder acceder a los mtodos y propiedades de los objetos depende del lenguaje de script que estemos utilizando. Debido que el lenguaje de script por defecto de ASP es VBScript (subconjunto de Visual Basic) en este curso nos vamos a centrar en este script. Los objetos Request y Response contienen colecciones. Una coleccin es un conjunto de elementos de informacin relacionados y que se accede a ellos de una misma forma. Se puede acceder a cada elemento de una coleccin mediante el bucle For...Each. La utilizacin de colecciones se ver en detenimiento en los captulos dedicados a estos dos objetos integrados. Un mtodo es un procedimiento que acta sobre un objeto, la sintaxis para poder invocar un mtodo de un objeto es la del Cdigo fuente 6.

Objeto.metodo parametros Cdigo fuente 6

Donde el tipo de parametros depender del mtodo invocado. Una propiedad es un atributo de un objeto. Las propiedades son caractersticas de un objeto que describen su estado, as por ejemplo un objeto podra tener las caractersticas tamao, nombre, color, etc. Para obtener el valor de una propiedad utilizamos la sintaxis del Cdigo fuente 7.
17

Desarrollo de aplicaciones COM+ para Internet / Intranet con ASP 3.0

Grupo EIDOS

Objeto.propiedad Cdigo fuente 7

Y para asignarle un valor a una propiedad de un objeto debemos utilizar la sintaxis del Cdigo fuente 8.

Objeto.propiedad=valor Cdigo fuente 8

Donde valor depende de la propiedad del objeto.

Componentes de servidor
ASP incluye una serie de componentes ActiveX de servidor (o componentes de servidor), llamados componentes ActiveX Server, anteriormente conocidos como servidores de Automatizacin. Estos componentes estn diseados para ejecutarse en un servidor Web y contienen una serie de funciones bastante tiles para que el programador no tenga que construirlas, una de estas funciones puede ser el acceso a bases de datos. Estos componentes los invocaremos desde nuestras pginas ASP. No se deben confundir los componentes de servidor con los objetos integrados en ASP. Para poder tener acceso a alguno de los componentes ActiveX de servidor primero se deber crear una instancia del componente correspondiente. Una vez creada la instancia, se pueden usar los mtodos asociados al componente o establecer y leer sus propiedades. Los componentes ActiveX Server que incluye ASP en su versin 3.0 son los siguientes: Componente de acceso a bases de datos, ADO (ActiveX Data Objects). A travs de la utilizacin de este componente se puede ofrecer acceso a bases de datos desde una pgina ASP, as por ejemplo, se puede mostrar el contenido de una tabla, permitir que los usuarios realicen consultas y otras operaciones sobre una base de datos. Componente Ad Rotator. Este componente permite mostrar una serie de imgenes alternativas con un vnculo a otra direccin desde la imagen presentada. Este componente se suele utilizar para mostrar diferentes anuncios de forma alternativa dentro de una pgina ASP. Componente Funciones del explorador. A travs de este componentes podemos recuperar datos acerca del tipo de navegador del cliente y que capacidades o funciones tiene. Componente vnculo de contenidos. Facilita el desplazamiento lgico entre las diferentes pginas ASP de una aplicacin ASP. Componente Content Rotator (rotador de contenidos). Este componente permite hacer rotaciones de cadenas de contenido HTML en una pgina.

18

Grupo EIDOS

1. Introduccin a ASP

Componente Page Counter (contador de pginas). Permite llevar una cuenta del nmero de veces que se ha accedido a una pgina determinada dentro de nuestro sitio Web. Componente Counters. A travs de este componente podremos almacenar, crear, incrementar y consultar cualquier contador. Componente MyInfo. Nos permite almacenar informacin personal que ser ofrecida por el administrador del sitio Web. Componente Tools. Es el denominado componente de utilidades. Ofrece una serie de funciones diversas, como la generacin de nmeros aleatorios o la comprobacin de la existencia de un fichero en el servidor. Componente Permission Checker. A travs de este componente podremos determinar si a un usuario se le ha dado permisos para acceder a un fichero determinado. Componente Status. Este componente, de momento, nicamente est disponible para el servidor Personal Web Server en plataformas Macintosh. Resulta extrao pero es as. Nos ofrece una informacin variada acerca del estado del servidor Web. Componente de registro de IIS. Mediante este componente tenemos acceso a la informacin y manipulacin de los ficheros de registro (log) generados por el servidor Web IIS 5.0.

Adems de todos estos componentes, el programador puede crear sus propios componentes ActiveX Server. Estos componentes se pueden desarrollar en lenguajes de programacin como Visual Basic, Java o C++, una vez creado el componente se transforma a una DLL que se registrar en el servidor. Todos los componentes de servidor que no es encuentran incluidos en ASP deben ser registrados. Una vez registrado el componente en el servidor Web lo podemos instanciar desde el lenguaje de secuencias de comandos de una pgina ASP, al igual que hacamos con los componentes que vienen por defecto con ASP. Tambin se puede adquirir estos componentes a terceros, existen empresas que se dedican al diseo de componentes para que sean utilizados desde pginas ASP.

Novedades de ASP 3.0


Aqu se pretende mostrar de forma muy general las mejoras y novedades que aporta ASP 3.0 sobre la versin anterior de las pginas activas ASP 2.0, no se va a entrar en detalles y se supone que el lector tiene ya algn conocimiento de ASP 2.0. A continuacin vamos a ir comentando en cada apartado cada uno de los cambios y mejoras que aporta ASP 3.0, para ello se apoya en Internet Information Server 5.0.

Mejoras generales en ASP 3.0


En este epgrafe se va a reunir una serie de cambios y novedades que ofrece ASP 3.0, que son de carcter general y que afectan al rendimiento y funcionamiento de las aplicaciones ASP. En esta nueva versin de ASP se ofrece un mejor funcionamiento y escalabilidad de la tecnologa ASP, basndose en las nuevas caractersticas y mejoras de Internet Information Server 5.0.
19

Desarrollo de aplicaciones COM+ para Internet / Intranet con ASP 3.0

Grupo EIDOS

Se ha producido una mejora en el procesamiento de las pginas ASP por parte de la librera ASP.DLL. Se ofrece lo que se denomina ajuste automtico, que consiste en detectar cundo una peticin est bloqueada por recursos externos, en ese caso se proporcionan automticamente ms subprocesos para ejecutar peticiones adicionales y continuar de esta forma con el procesamiento normal de forma simultnea. Los objetos COM se liberan ms rpidamente y por defecto los componentes COM se ejecutan out-of-process, es decir, en un espacio de memoria distinto al del servidor Web. Con ASP 3.0 se ofrecen los objetos COM que se ofrecan con ASP 2.0 (componentes de servidor, como Content Rotator) pero con su rendimiento mejorado, es decir, aparecen versiones mejoradas de los componentes anteriores. El servidor transaccional Microsoft Transaction Server (MTS) ya no existe como una entidad separada en Windows 2000, y pasa a formar parte de Servicios de componentes (Microsoft Component Services). IIS 5.0 y Servicios de componentes funcionan conjuntamente para formar la arquitectura bsica para la creacin de aplicaciones Web.

El objeto Response
Los nicos objetos integrados dentro de ASP que han sufrido alguna modificacin han sido el objeto Response, que vemos en este apartado, y el objeto Server. Por defecto la propiedad Buffer del objeto Response tiene el valor True (verdadero), en ASP 2.0 y 1.0 esta propiedad del objeto Response tena por defecto el valor de False (falso). Debido a esto, en ASP 3.0 el resultado de la ejecucin de una pgina ASP nicamente es enviado al cliente cuando se termina de procesar la pgina ASP correspondiente, o bien cuando se utilizan los mtodos Flush o End del objeto Response. Por lo tanto, a no ser que se indique otra cosa, de forma predeterminada el resultado de la ejecucin de la pgina ASP se enviar al bfer. Segn afirma Microsoft la tcnica del bfer ofrece una entrega de pginas ms eficiente al cliente. En el objeto Response tambin cambia la forma de utilizar la propiedad IsClientConnected, mediante esta propiedad podemos consultar si un cliente se encuentra todava conectado a nuestro servidor o por el contrario si ha finalizado su sesin con el mismo. En ASP 2.0 podamos consultar esta propiedad slo si antes habamos enviado ya alguna salida o contenido al cliente, ahora con ASP 3.0 podemos utilizar IsClientConnected antes de enviar cualquier contenido al navegador.

El objeto Server
Este es otro de los objetos de ASP que ha experimentado cambios. Presenta dos nuevos mtodos: Transfer y Execute, que permiten controlar el control de flujo del programa, ampliando las capacidades de control de flujo de las pginas ASP, anteriormente slo se dispona del mtodo Redirect del objeto Response. En ASP 2.0 si queramos transferir la ejecucin a otra pgina ASP tenamos que utilizar el mtodo Redirect del objeto Response, pero esto supona enviar una respuesta al cliente para indicarle la carga de una nueva pgina, que es la pgina a la que pasamos la ejecucin.
20

Grupo EIDOS

1. Introduccin a ASP

La utilizacin del mtodo Redirect es bastante costosa y problemtica ya supone un envo de informacin ms del servidor al cliente para indicarle mediante una cabecera HTTP de redireccin que la pgina ha cambiado de localizacin, siendo la nueva localizacin la pgina que deseamos cargar. Esto es problemtico ya que en algunos navegadores como Netscape Communicator aparace un mensaje del tipo El objeto requerido se ha movido y se puede encontrar aqu, esto tambin ocurre cuando la conexin la realiza el cliente a travs de proxy. Pero ahora con ASP 3.0 podemos evitar esta redireccin, que como hemos visto, tiene lugar en el cliente, mediante los mtodos Execute y Transfer del objeto Server que permiten que la redireccin tenga lugar en el servidor, quedando el cliente completamente ajeno. Ambos mtodos reciben como parmetro la ruta de la pgina a la que queremos redirigir al cliente. La utilizacin del mtodo Execute es muy similar a realizar una llamada a un procedimiento o funcin. Cuando lanzamos el mtodo Execute se empieza a ejecutar la pgina que indicamos por parmetro, y cuando termina la ejecucin de esta nueva pgina, el control pasa a la siguiente sentencia despus de la llamada al mtodo Execute en la pgina inicial, siguiendo a partir de aqu con la ejecucin de la pgina, es decir, el navegador del cliente recibe una salida formada por la combinacin de la ejecucin de ambas pginas. El mtodo Transfer se comporta de distinto modo, al lanzar este mtodo se pasa la ejecucin a la nueva pgina, pero una vez que finaliza la ejecucin de la misma no se vuelve a la pgina inicial, como ocurra con el mtodo Execute. En ambos mtodos se mantiene el contexto de la pgina inicial, es decir, en la nueva pgina tenemos acceso a las variables, objetos y a todos los objetos intrnsecos de ASP (Request, Session, Response...) de la pgina inicial o pgina de origen. Tambin se mantienen las transacciones entre distintas pginas, siempre que proceda, atendiendo a la directiva @TRANSACTION. De esta forma como la redireccin entre pginas se produce en el servidor, el navegador cree que sigue recibiendo todava la pgina original que habia demandado, incluso en la barra de direcciones del navegador sigue apareciendo la misma URL y los botones Atrs y Adelante funcionan correctamente. Vamos a ofrecer un sencillo cdigo de una pgina ASP que utiliza los mtodos Transfer y Execute para ejecutar otra pgina, y as se puede ver ms claramente la utilizacin de estos dos nuevos mtodos del objeto Server. Nuestra pgina, llamada PaginaInicial.asp, va a constar de un formulario con dos botones, y segn el botn que se pulse se lanzar el mtodo Execute o Transfer para ejecutar la pgina OtraPagina.asp. El cdigo de de la pgina PaginaInicial.asp se muestra en el Cdigo fuente 9, y el de OtraPagina.asp en el Cdigo fuente 10.

<%If Request.Form("Execute")<>"" Then Response.Write "Se est ejecutando la pgina "_ & Request.ServerVariables("SCRIPT_NAME") & "<br>" Server.Execute "OtraPagina.asp" Response.Write "Se est ejecutando de nuevo la pgina "_ & Request.ServerVariables("SCRIPT_NAME") & "<br>" ElseIf Request.Form("Transfer")<>"" Then Response.Write "Se est ejecutando la pgina "_ & Request.ServerVariables("SCRIPT_NAME") & "<br>" Server.Transfer "OtraPagina.asp" Response.Write "Se est ejecutando de nuevo la pgina "_ & Request.ServerVariables("SCRIPT_NAME") & "<br>" End if%> <FORM ACTION="PaginaInicial.asp" METHOD="POST"> <input type="submit" name="Execute" value="Lanza Server.Execute"><br>

21

Desarrollo de aplicaciones COM+ para Internet / Intranet con ASP 3.0

Grupo EIDOS

<input type="submit" name="Transfer" value="Lanza Server.Transfer"> </FORM> Cdigo fuente 9

<hr> Se est ejecutando la pgina OtraPagina.asp<br> Esta pgina se ha cargado con el mtodo <%If Request.Form("Execute")<>"" Then%> <b>EXECUTE</b> <%ElseIf Request.Form("Transfer")<>"" Then%> <b>TRANSFER</b> <%End If%> <br>La variable Request.ServerVariables("SCRIPT_NAME") sigue teniendo el valor: <%=Request.ServerVariables("SCRIPT_NAME")%><br> Termina la ejecucin de OtraPagina.asp<br> <hr> Cdigo fuente 10

Si ejecutamos la pgina PAGINAINICIAL.ASP y pulsamos cada uno de sus botones, vemos el distinto comportamiento de los mtodo Execute y Transfer, en el primer caso se intercala el resultado ejecucin de ambas pginas, y en el segundo paso una vez que se ha terminado de ejecutar la segunda pgina finaliza tambin la ejecucin de la secuencia de comandos, sin retornar a la pgina inicial. Las siguientes figuras muestran estas dos situaciones. La Figura 1 muestra la pgina PAGINAINICIO.ASP cuando todava no se ha pulsado ningn botn. En la Figura 2 se muestra cuando se ha pulsado el botn Execute. Y en la Figura 3 cuando se ha pulsado el botn Transfer.

Figura 1

22

Grupo EIDOS

1. Introduccin a ASP

Figura 2

Figura 3

Otro nuevo mtodo que ofrece el objeto Server, y que est relacionado con el tratamiento de errores, es el mtodo GetLastError. Mediante el uso del mtodo GetLastError podemos tener acceso a toda la informacin referente al ltimo error que se ha producido en la pgina ASP actual. Pero es necesario aclarar que su utilizacin no es similar al tratamiento de errores que realizbamos con la sentencia On Error Resume Next y el objeto Err de VBScritp, que preguntbamos por la propiedad Number del objeto Err para averiguar si se haba producido algn error, el mtodo GetLastError se puede utilizar
23

Desarrollo de aplicaciones COM+ para Internet / Intranet con ASP 3.0

Grupo EIDOS

nicamente dentro de una pgina de error personalizada, es decir, cuando el error ya se ha producido y lo ha detectado el servidor Web. Mediante Internet Information Services 5 podemos indicar las pginas de error personalizadas y es en estas pginas dnde podemos hacer uso de este mtodo. El mtodo GetLastError devuelve un nuevo objeto de ASP llamado ASPError, son las propiedades de este nuevo objeto las que nos permiten acceder de forma detallada a toda la informacin referente al error que se ha producido. Este nuevo objeto lo trataremos con ms detalle en el siguiente apartado.

El objeto ASPError
Como ya hemos visto en el apartado anterior, este es un nuevo objeto del modelo de objetos incluido dentro de ASP 3.0. Tendremos acceso al objeto ASPError a travs de la llamada al mtodo GetLastError del objeto Server. La funcin de este objeto es la de ofrecer de forma detallada toda la informacin disponible del ltimo error que se ha producido. El objeto ASPError nicamente dispone de una serie de propiedades de slo lectura, que contienen la informacin relativa al ltimo error que se ha producido. Estas propiedades se comentan de forma breve en la Tabla 1.

Propiedad ASPCode ASPDescription

Descripcin Un entero generado por IIS. Una cadena que es una descripcin detallada del error si est relacionado con ASP. Cadena que indica si se trata de una error interno de ASP, del lenguaje de secuencia de comandos o de un objeto. Entero que indica la posicin de la columna del archivo ASP que gener el error. Breve descripcin del error. Nombre del archivo ASP que se estaba procesando cuando se produjo el error. Lnea del archivo ASP que gener el error. Cdigo de error estndar de COM. Devuelve el cdigo fuente real, si est disponible, de la lnea que caus el error.
Tabla 1

Category

Column

Description File Line Number Source

24

Grupo EIDOS

1. Introduccin a ASP

En el Cdigo fuente 11 se muestra un sencillo cdigo de ejemplo que hace uso del objeto ASPError, y que podra pertenecer a una pgina de error personalizada de IIS 5.0. Primero se obtiene una referencia al objeto ASPError mediante el mtodo GetLastError del objeto Server, y a continuacin se muestra los valores de las propiedades del objeto ASPError para informar al cliente acerca del error que se ha producido.

<%@ language="VBScript" %> <html> <body> <head> <title>The page cannot be displayed</title> </head> <%Set objASPError=Server.GetLastError%> <b>Detalles del error que se ha producido</b><br> Cdigo de error ASP: <i><b><%=objASPError.ASPCode%></b></i><br> Nmero de error: <i><b><%=objASPError.Number%></b></i><br> Cdigo fuente que lo ha producido: <i><b><%=Server.HTMLEncode(objASPError.Source)%></b></i><br> Categora del error: <i><b><%=objASPError.Category%></b></i><br> Fichero en el que se producido el error: <i><b><%=objASPError.File%></b></i><br> Lnea y columna en la que se ha producido el error: <i><b><%=objASPError.Line%>, <%=objASPError.Column%></b></i><br> Descripcin del error: <i><b><%=objASPError.Description%></b></i><br> </body> </html> Cdigo fuente 11

Un ejemplo de la ejecucin del cdigo anterior se puede ver en la Figura 4, y se produce cuando hay un error de ASP, es decir un error interno de servidor del tipo 500;100.

Figura 4

25

Desarrollo de aplicaciones COM+ para Internet / Intranet con ASP 3.0

Grupo EIDOS

Componente de registro de IIS (Logging Utility)


Otras de las novedades de ASP 3.0, abandonado ya los objetos integrados en ASP, es que ofrece un nuevo componente de servidor (componente ActiveX de servidor). El nuevo componente de servidor es denominado componente de registro o programa de registro de IIS. Mediante este componente tenemos acceso a la informacin y manipulacin de los ficheros de registro (log) generados por el servidor Web IIS 5.0. Este componente, al igual que todos los existentes en ASP 2.0, se instala conjuntamente con el servidor Web Internet Information Server 5.0. El fichero DLL que contiene a este nuevo componente es LOGSCRPT.DLL. Para instanciar un componente de registro debemos utilizar la sentencia que muestra el Cdigo fuente 12.

Set objRegistro=Server.CreateObject("MSWC.IISLog") Cdigo fuente 12

Es importante sealar que el usuario que tiene acceso a la secuencia de comandos ASP que crea la instancia del componente de registro debe autenticarse como Administrador u Operador en el servidor donde se ejecuta IIS, si es un usuario annimo, el componente de registro de IIS no funcionar correctamente. Para manipular los ficheros de registro de IIS el componente IISLog ofrece una serie de mtodos que se muestran en la Tabla 2.

Mtodo AtEndOfLog CloseLogFiles OpenLogFile ReadFilter ReadLogRecord WriteLogRecord

Descripcin Indica si se leyeron o no todos los registros del archivo. Cierra todos los archivos de registro abiertos. Abre un archivo de registro para lectura o escritura. Filtra los registros del archivo segn la fecha y la hora. Lee el siguiente registro disponible del archivo de registro actual. Escribe un registro en el archivo actual.
Tabla 2

26

Grupo EIDOS

1. Introduccin a ASP

Para obtener la informacin del registro actual el componente IISLog ofrece veinte propiedades de slo lectura, como se muestra en la Tabla 3, que se corresponden con los distintos campos de un registro de un archivo de registro.

Propiedad BytesReceived BytesSent ClientIP Cookie CustomFields DateTime Method ProtocolStatus

Descripcin Nmero de bytes recibidos del navegador como una peticin. Nmero de bytes enviados al navegador como una respuesta. Direccin IP del cliente. Indica los contenidos de cualquier cookie enviada en la peticin. Un vector de cabeceras personalizadas que se aadieron a la peticin. La fecha y hora de la peticin en formato GMT. El tipo de operacin, tal como puede ser GET o POST. El mensaje de estado devuelto al cliente, por ejemplo 200 OK.

ProtocolVersion Una cadena con la versin del protocolo utilizado, por ejemplo HTTP/1.1. Referer ServerIP ServerName ServerPort ServiceName La URL de la pgina que contiene el enlace que inici la peticin, si est disponible. La direccin IP del servidor Web. El nombre del servidor Web. El nmero de puerto por el que se recibi la peticin. Nombre del servicio, como puede ser el servicio FTP (MSFTPSVC) o Web (W3SVC). El tiempo de procesamiento total para devolver y crear la pgina devuelta. Cualquier parmetro aadido a la cadena de consulta (QueryString) de la URL en la peticin.

TimeTaken URIQuery

27

Desarrollo de aplicaciones COM+ para Internet / Intranet con ASP 3.0

Grupo EIDOS

URIStem UserAgent UserName Win32Status

La URL que demand el cliente. La cadena de agente de usuario (tipo de navegador) enviada por el cliente. Nombre de inicio de sesin del usuario si no ha accedido de forma annima. Cdigo de estado Win32 despus de haber procesado la peticin.
Tabla 3

Se puede configurar el tipo de registro que queremos en nuestro servidor a travs de IIS 5.0, de esta forma podremos aadir o eliminar de nuestro fichero de registro los campos descritos anteriormente. Para ello acudiremos a las propiedades del sitio Web y en la pestaa sitio Web pulsaremos el botn Propiedades contenido en el epgrafe de Habilitar registro, como se ve en la Figura 5. Se debe seleccionar uno de los formatos de registro que se corresponden con un fichero de registro, por lo tanto la opcin registro ODBC no sera vlida.

Figura 5

28

Grupo EIDOS

1. Introduccin a ASP

En el Cdigo fuente 13 se muestra la utilizacin de este nuevo objeto ActiveX de servidor. En este sencillo cdigo se utiliza el componente de registro para mostrar algunos de los campos contenidos en el fichero de registro.

<html> <head> <!--METADATA TYPE="TypeLib" FILE="c:\winnt\system32\inetsrv\logscrpt.dll"--> </head> <body> <%Set objRegistro=Server.CreateObject("MSWC.IISLog") objRegistro.OpenLogFile "c:\winnt\system32\logfiles\w3svc1\ex000517.log"_ ,ForReading,"W3SVC",1,0 objRegistro.ReadFilter DateAdd("d",-1,Now),Now%> <table align="center" border="0" cellspacing="2" cellpadding="5"> <tr> <th>Fecha/Hora</th> <th>IP del cliente</th> <th>Mtodo</th> <th>URL</th> </tr> <%While Not objRegistro.AtEndOfLog objRegistro.ReadLogRecord%> <tr> <td><%=objRegistro.DateTime%></td> <td><%=objRegistro.ClientIP%></td> <td><%=objRegistro.Method%></td> <td><%=objRegistro.URIStem%></td> </tr> <%Wend objRegistro.CloseLogFiles(ForReading)%> </body> </html> Cdigo fuente 13

Se ha utilizado un filtro para recuperar la informacin del fichero de registro referente al servicio Web y nicamente de las ltimas 24 horas. Tambin se puede observar que se utiliza una directiva METADATA, ms tarde comentaremos su utilidad y sintaxis, de momento diremos nicamente que nos permite incluir las constantes definidas en la librera que contiene al componente de registro. La informacin que se va a mostrar del fichero de registro va a ser la fecha y hora de la peticin, la direccin IP del cliente que ha realizado la peticin, el mtodo que se ha utilizado y la URL correspondiente. En la Figura 6 se puede ver un ejemplo de ejecucin de la pgina anterior. El nombre del fichero de registro variar segn sea nuestra configuracin del registro en el sitio Web correspondiente, la ubicacin de estos ficheros de registro suele ser el directorio C:\WINNT \SYSTEM32\LOGFILES\W3SVc1 para el servicio Web. Esta pgina ASP que utiliza el componente de registro se puede utilizar nicamente restringiendo el acceso annimo a la propia pgina o al directorio que la contiene a nivel de permisos de NTFS, en caso contrario no podremos acceder al fichero de registro, ya sea para leer o escribir datos.

29

Desarrollo de aplicaciones COM+ para Internet / Intranet con ASP 3.0

Grupo EIDOS

Figura 6

Aplicaciones ASP con IIS 5.0


En IIS 4.0 ya podamos definir aplicaciones ASP y su directorio de inicio, tambin podamos indicar a travs de la configuracin de los directorios de un sitio Web si la aplicacin se ejecutaba en otro espacio de memoria como un proceso aislado. Con IIS 5.0 el concepto de aplicacin ASP no ha variado, es decir, una aplicacin es un conjunto de pginas ASP que se ejecutan en un conjunto de directorios definidos dentro de un sitio Web, tampoco ha variado excesivamente la forma de configurar las aplicaciones ASP. Lo ms destacable que ofrece IIS 5.0 con respecto a las aplicaciones ASP es la posibilidad de definir tres niveles de proteccin distintos para dichas aplicaciones. En IIS 4.0 podamos indicar que nuestra aplicacin se ejecutara en el mismo espacio de memoria que el servidor Web o que se ejecutara en un proceso aislado, pero con IIS 5.0 tenemos otra posibilidad intermedia, que consiste en que la aplicacin se ejecuta en un proceso agrupado con el resto de las aplicaciones ASP. Los tres grados de proteccin que ofrece IIS 5.0 para las aplicaciones ASP se denominan bajo, medio y alto, y se muestran en la Tabla 4.

Proteccin Baja (proceso IIS)

Descripcin Las aplicaciones ASP se ejecutan todas en el mismo espacio de memoria que el servidor Web IIS 5.0. Si una aplicacin ASP falla afectar a todo el servidor Web, poniendo en peligro la ejecucin de la aplicacion InetInfo.exe, que es el ejecutable del servidor Web. Ofrece la ejecucin ms rpida y eficiente de las aplicaciones ASP, pero tambines la que ofrece ms riesgos.

30

Grupo EIDOS

1. Introduccin a ASP

Media (agrupada)

Esta es la proteccin por defecto, todas las aplicaciones ASP se ejecutan agrupadas en un espacio de memoria distinto que el del servidor Web, en este caso todas las aplicaciones ASP del servidor Web utilizan una instancia compartida del ejecutable DLLHost.exe. De esta forma se proteje al ejecutable InetInfo.exe de los posibles fallos de las aplicaciones ASP. Si se produce un fallo en una aplicacin ASP no afecta al servidor Web, pero s a resto de las aplicaciones ASP. Cada aplicacin ASP se ejecuta en un espacio de memoria distinto, es decir, cada aplicacin se ejecuta en una instancia distinta y exclusiva del ejecutable DLLHost.exe. De esta forma si una aplicacin falla no afectar al resto de las aplicaciones ASP ni tampoco al servidor Web, ya que se ejecuta en su propio espacio de memoria. Microsoft recomienda que por cada servidor Web no se definan ms de diez aplicaciones aisladas. Este tipo de proteccin es recomendable para aplicaciones ASP de alto riesgo o crticas.
Tabla 4

Alta (aislada)

Por defecto el sitio Web predeterminado se define como una aplicacin ASP agrupada o con grado de proteccin medio, este es el modo de proteccin de la aplicacin ms usual y recomendable, ya que ofrece una buena relacin en lo que a rendimiento y seguridad se refiere, con el grado de proteccin alto comprometemos el rendimiento y con el grado de proteccin bajo se compromete la seguridad del funcionamiento del servidor Web. En la Figura 7 se puede ver la forma de configurar el grado de proteccin de una aplicacin.

Figura 7

31

Desarrollo de aplicaciones COM+ para Internet / Intranet con ASP 3.0

Grupo EIDOS

Otros cambios
En la versin anterior de ASP si necesitbamos utilizar las constantes definidas en una librera de componentes, como puede ser ADO, tenamos que incluir un fichero con la definicin de dichas constantes mediante la tambin conocida directiva INCLUDE de ASP, en el caso de ADO se trataba del famoso fichero ADOVBS.INC. Pero con ASP 3.0 esta situacin ha cambiado, podemos incluir las constantes definidas en una librera de forma directa desde la propia librera, sin tener que crear un fichero de definicin de constantes diferenciado. Para incluir una referencia a una librera un componentes utilizamos la nueva directiva METADATA, cuya sintaxis se muestra en el Cdigo fuente 14.

<!-- METADATA TYPE="TypeLib" FILE="camino y nombre del fichero" UUID="identificador de la librera" VERSION="numVersionMayor.numVersionMenor" LCID="identificador de localizacin" --> Cdigo fuente 14

Las propiedades que son obligatorias son FILE o UUID, siempre deberemos indicar uno u otro para identificar la librera, el resto de las propiedades son de tipo opcional De esta forma para incluir las constantes de ADO y poder utilizarlas, escribiremos lo que indica el Cdigo fuente 15.

<!-- METADATA TYPE="TypeLib" FILE="c:\Archivos de Programa\Archivos comunes\System\ado\msado15.dll"--> Cdigo fuente 15

Se debe sealar que o bien podemos utilizar la directiva METADATA en cada una de las pginas ASP en las que necesitemos incluir las constantes o tambin se puede incluir en el fichero GLOBAL.ASA y de esta forma estar disponible la definicin de constantes y la referencia a la librera para todas las pginas de la aplicacin ASP. Como curiosidad hago notar que le nombre de la librera de ADO sigue siendo MSADO15.DLL cuando lgicamente debera ser MSADO25.DLL, ya que ya nos encontramos en la versin 2.5 de ADO, aunque de todas formas esta librera contiene la ltima versin de ADO. Para incluir archivos en nuestras pginas ASP ya hemos visto que utilizamos la directiva INCLUDE, pero en ASP 3.0 hay otra alternativa que es la utilizacin de la etiqueta <SCRIPT> como muestra el Cdigo fuente 16.

<SCRIPT RUNAT="SERVER" SRC="ruta relativa, fsica o virtual al fichero de scrip"></SCRIPT> Cdigo fuente 16

32

Grupo EIDOS

1. Introduccin a ASP

El fichero que incluimos, a diferencia de la directiva INCLUDE, nicamente puede contener secuencias de comandos, no puede contener texto ni cdigo HTML, adems no debe existir ningn elemento entre las etiquetas <SCRIPT></SCRIPT>. Si un usuario accede a un sitio Web indicando nicamente el nombre del mismo, sin indicar ninguna pgina, se enviar al usuario el documento o pgina por defecto. Sin embargo, si se aada una cadena de consulta (QueryString) a esta URL en la versin anterior de ASP esta cadena era ignorada. Pero ahora con ASP 3.0 y combinacin con IIS 5 la cadena de consulta si es considerada por la pgina predeterminada. De esta forma en ASP 3.0 escribir http://www.eidos.es/?prueba=true es equivalente a escribir la URL http://www.eidos.es/default.asp?prueba=true, siendo default.asp la pgina predeterminada del sitio Web del Grupo EIDOS.

33

Modelo de objetos de ASP. Parte I


Introduccin
Este tema pretende ser un simple recordatorio de los objetos integrados de ASP, y sus principales colecciones, mtodos y propiedades. Slo se entrar en detalle en aqullos que sean ms utilizados. ASP nos proporciona una serie de objetos integrados, a los que siempre tenemos acceso sin necesidad de instanciarlos, son objetos que constituyen lo que se denomina el modelo de objetos de ASP. Estos objetos son bastante interesantes ya que gran parte de la programacin de aplicaciones ASP se basa en la utilizacin de los mismos. Estos objetos ponen a disposicin del programador una serie de mtodos y propiedades que pueden ser utilizados desde el script de servidor, es decir, son directamente accesibles y manipulables desde VBScript. Cada uno de estos objetos cubre unas funciones determinadas. Antes de comenzar a explicar cada unos de los objetos integrados se considera necesario repasar el concepto de objeto, mtodo y propiedad dentro del entorno de la programacin orientada a objetos y desde el punto de vista que nos interesa, es decir desde las pginas activas de servidor. Un objeto es un componente que posee una serie de comportamientos y que tiene un estado. El estado de un objeto se encuentra definido por sus propiedades y sus comportamientos a travs de los mtodos. Un objeto puede contener otros objetos. Cada objeto tiene unas propiedades que definen sus atributos. Las propiedades de un objeto nos indican algo sobre el objeto o sus contenidos. Las propiedades diferencian un objeto de otro y determinan su estado y caractersticas. Los mtodos que poseen los objetos definen su comportamiento interno y frente a otros objetos.

Desarrollo de aplicaciones COM+ para Internet / Intranet con ASP 3.0

Grupo EIDOS

Los objetos integrados adems de poseer mtodos y propiedades, tambin ofrecen colecciones. Una coleccin es un grupo de objetos del mismo tipo. Un objeto y una coleccin son ambos contenedores, pero de distinto tipo. Un objeto contendr cero o ms colecciones de diferente tipo, mientras que una coleccin contendr cero o ms objetos de naturaleza similar. Por ejemplo, ASP ofrece el objeto Request que contiene diferentes propiedades y colecciones de distinto tipo. Una de estas colecciones es la coleccin Form, esta coleccin contiene informacin sobre los elementos del formulario que se ha enviado. Aqu se puede observar la diferencia entre objetos y colecciones en ASP, un objeto puede siempre contener otro nivel de informacin variada pero las colecciones no. La mayora de los objetos integrados de ASP proporcionan colecciones. Una coleccin es una estructura de datos, similar a una matriz, que almacena cadenas, nmeros, objetos y otros valores. A diferencia de las matrices, las colecciones se amplan y reducen automticamente al recuperar o almacenar elementos. La posicin de un elemento tambin cambia al modificar la coleccin. Es posible tener acceso a un elemento de una coleccin por su clave de cadena nica, por su ndice (posicin) en la coleccin o si se iteran todos los elementos de la coleccin. El acceso a las colecciones, su sintaxis y utilizacin la veremos segn vayamos avanzando en el temario con distintos ejemplos. Todas las colecciones ofrecen una serie de mtodos comunes a todas ellas y son los siguientes: Count: devuelve nmero de elementos contenidos en la coleccin. Item: devuelve el elemento que se corresponde con el ndice o cadena clave que se pasa por parmetro. Key: devuelve el nombre de una clave dado su ndice.

Las colecciones que no son slo de lectura, sino tambin de escritura, permiten adems los mtodos: Remove: elimina un elemento determinado de la coleccin, del que indicamos su clave o ndice. La coleccin debe ser de escritura. RemoveAll: elimina todos los elementos presentes en una coleccin. Al igual que el mtodo anterior requiere que la coleccin sea de escritura.

Las colecciones comienzan en el ndice 1, a diferencia de los arrays que empiezan en el ndice cero. Antes de poder utilizar un objeto se debe instanciar, es decir, crear el objeto y asignrselo a una variable que va a representar una instancia de ese objeto, en realidad, hasta que no se instancia un objeto, el objeto no existe. Pero en el caso de los objetos integrados no hay que instanciarlos, se puede considerar que son creados al iniciar la ejecucin la aplicacin ASP.

El objeto Response
Este objeto integrado en el modelo de objetos de ASP tiene la funcin de enviar datos al cliente, es decir, al navegador que ha cargado la pgina ASP. A travs de este objeto podremos escribir en la pgina que visualizar el usuario e incluso podremos redirigir al usuario a otra direccin en Internet. Tambin a partir de este objeto podremos definir cookies para el usuario y asignarles un valor. En definitiva, representa la respuesta que el servidor web devuelve al navegador del cliente como resultado de su peticin.
36

Grupo EIDOS

2. Modelo de objetos de ASP. Parte I

Colecciones del objeto Response


El objeto Response posee una nica coleccin llamada Cookies, que le permite crear y asignar valores a una cookie. Una cookie, fsicamente, es un fichero que se escribe en la mquina local del cliente que se conecta a un sitio Web y que contiene informacin relativa a la conexin. Una cookie es utilizada para mantener informacin entre diferentes conexiones HTTP. Se debe recordar que el protocolo HTTP es un protocolo sin estado, es decir, no se retiene informacin entre las diferentes conexiones que se realicen. Por esta razn, ni el cliente ni el servidor pueden mantener informacin entre diferentes peticiones o a travs de diferentes pginas Web. Este mecanismo para mantener informacin entre diferentes conexiones HTTP fue propuesto e implementado en un principio por la compaa Netscape. Existen varios usos prcticos de las cookies, a continuacin se van a comentar los ms destacados: Para almacenar informacin acerca de las preferencias del cliente que se conecta a nuestro sitio Web, por ejemplo el color seleccionado de la pgina, el tipo de letra, etc. Para conservar informacin personal, no sensible, del usuario, como puede ser el nombre, el pas de origen, cdigo postal, el nmero de veces que ha accedido a nuestro sitio Web, etc.

Por lo tanto el uso de cookies nos puede permite personalizar las pginas ASP segn el cliente que se haya conectado atendiendo a sus preferencias y datos personales. Por ejemplo podemos saludar al usuario con su nombre y asignar al color de fondo de la pgina su color favorito o tambin podremos indicarle el nmero de veces que ha accedido a nuestro sitio Web. De esta forma podemos evitar preguntar al usuario sus preferencias o datos personales cada vez que entra en nuestro sitio Web. Siempre debe haber una primera ocasin en la que el cliente conectado especifique el valor de la cookie, una vez especificado este valor ya puede ser utilizada la cookie en las diferentes conexiones que realice ese cliente, ya que la informacin ha quedado almacenada en la cookie. Esta informacin se almacena fsicamente en un fichero del disco duro local del cliente. En el caso del navegador Internet Explorer de Microsoft cada cookie se corresponde con un fichero.txt que se encuentra en el directorio Documents and Settings (en el caso de Windows 2000) y en el subdirectorio Cookies, y en el caso del Communicator de Netscape las cookies se almacenan todas en un fichero llamado cookies.txt en el subdirectorio Netscape\User\usuario. Hay una serie de consideraciones que se deben tener en cuenta a la hora de utilizar cookies en nuestra aplicacin ASP: Las cookies se pueden perder, por lo tanto nunca se debe depender de las cookies para almacenar una informacin que no se pueda volver a generar. Este tipo de informacin se debera almacenar en una base de datos del servidor. No se debe olvidar que las cookies se almacenan en el disco local del cliente en ficheros, y por lo tanto estos ficheros se pueden daar, ser borrados o sobreescritos. Las cookies pueden ser modificadas por el cliente, por lo tanto nunca se debe considerar que la informacin ofrecida por una cookie es autntica. Si estamos usando una cookie para determinar la fecha de la ltima vez que un usuario visit nuestro sitio Web podemos considerar como autntica esta informacin sin ningn problema, pero sin embargo no es nada recomendable considerar autntica una cookie que posee el nmero de cuenta de un usuario. Como regla general nunca se debe utilizar una cookie para almacenar informacin
37

Desarrollo de aplicaciones COM+ para Internet / Intranet con ASP 3.0

Grupo EIDOS

confidencial, este tipo de informacin se debera almacenar en una base de datos en el servidor Web. Las cookies pueden ser copiadas sin el consentimiento del propietario, nunca se debera utilizar una cookie para identificar a un usuario, una solucin mejor es utilizar una contrasea y validarla con una base de datos del servidor. Algunos navegadores no reconocen las cookies. Incluso los ms populares como el Internet Explorer y el Communicator, se pueden configurar para no utilizar cookies.

Se debe sealar que ASP para mantener estados, es decir, valores de variables, objetos..., entre diferentes pginas de una aplicacin ASP utiliza cookies desde los objetos integrados Session y Application. El uso de estas cookies por parte de ASP, se oculta completamente al programador para que se abstraiga de la utilizacin lgica de las cookies, todo ello gracias a los objetos Session y Application que las gestionan internamente (estos dos objetos los trataremos en los captulos correspondientes). As por ejemplo, cuando se inicia una sesin se crea la cookie ASPSSESIONID, aunque esta cookie no se grabar en el disco duro del cliente, sino que permanecer en memoria, por lo tanto podemos asegurar al usuario que no vamos a acceder a su disco. De esta forma si un navegador no acepta cookies, la aplicacin ASP no podr mantener el estado entre diferentes pginas. Si tenemos configurado nuestro navegador para que nos avise cuando recibe una cookie, al iniciar una sesin con una aplicacin ASP aparecer una ventana similar a la que se muestra en la Figura 8.

Figura 8

La coleccin Cookies tambin aparece en el objeto Request, pero en el objeto Request la coleccin es slo de lectura, mientras que en el objeto Response es slo de escritura. De esta forma en el objeto Response la coleccin Cookies ser utilizada para crear las cookies o para modificar su valor, y en el objeto Request para recuperar el valor de las cookies.

38

Grupo EIDOS

2. Modelo de objetos de ASP. Parte I

Para crear una cookie se utiliza la sintaxis del Cdigo fuente 17.

Response.Cookies(NombredelaCookie)=ValordelaCookie Cdigo fuente 17

Si la cookie ya existe modifica su valor. La sintaxis general es Response.Cookies(cookie)[(clave)|atributo]=valor, donde cookie, es el nombre de la cookie a la que hacemos referencia, clave es un parmetro opcional que se utiliza cuando la cookie es un diccionario, es decir puede contener diferentes datos, y atributo especifica una propiedad de la cookie. Las propiedades que poseen las cookies son: Expires: slo de escritura, indica la fecha en la que caduca la cookie. Si no se especifica ningn valor, por defecto caduca cuando termina la sesin. Domain: slo de escritura, especifica a que dominio es enviada la cookie. Por defecto ser el nombre del dominio del servidor del que proviene la cookie. Path: slo de escritura, indica la ruta del servidor de la que proviene la cookie. Si no se especifica, por defecto se toma la ruta de la pgina ASP que gener la cookie. Secure: slo de escritura, para indicar si la cookie es segura. HasKeys: slo de lectura, especifica si la cookie tiene claves, es decir, si es un diccionario.

Si queremos crear una cookie que tenga claves, por ejemplo que contenga los datos nombre, apellidos y edad, y que caduque a finales del 2001 se debera escribir lo que indica el Cdigo fuente 18.

<% Response.Cookies("datosPersonales").Expires= #December 31, 2001# Response.Cookies("datosPersonales")("nombre")="Angel" Response.Cookies("datosPersonales")("apellidos")="Esteban Nez" Response.Cookies("datosPersonales")("edad")=25 %> Cdigo fuente 18

En el caso de que se quiera eliminar una cookie que ya exista, basta con cambiar el valor de su propiedad Expires, asignndole una fecha anterior a la actual. Las cookies se envan desde el servidor al navegador del cliente como un encabezado del protocolo HTTP.

Propiedades del objeto Response


En este apartado vamos a comentar cada una de las propiedades del objeto Response, y como podemos utilizar las ms comunes.

39

Desarrollo de aplicaciones COM+ para Internet / Intranet con ASP 3.0

Grupo EIDOS

El objeto Response posee las siguientes propiedades: Buffer: indica si los datos de la pgina se almacenan en un bfer. ContentType: especifica el tipo de contenido HTTP de la respuesta. Expires: especifica el intervalo de tiempo que debe transcurrir para que caduque una pgina almacenada en la cach del navegador. ExpiresAbsolute: tiene el mismo sentido que la propiedad anterior, pero aqu se especificar la hora y la fecha en la que caducar la pgina en la cach del navegador. Status: valor de la lnea de estado que devuelve el servidor. CacheControl: determinar si los servidores proxy van a almacenar o no en su cach la salida generada por una pgina ASP. CharSet: indicar el juego de caracteres que est utilizando la pgina ASP. PICS: mediante esta propiedad indicaremos el tipo de contenido que posee nuestra pgina ASP. IsClientConnected: propiedad de slo lectura con la que podremos averiguar si el cliente se ha desconectado del servidor.

Si utilizamos la propiedad Buffer del objeto Response asignndole el valor True, conseguiremos que ASP procese todo el script en el servidor antes de enviar algo al usuario, por defecto esta propiedad tiene el valor True. El contenido del bfer no es enviado al navegador hasta que no se haya terminado de procesar la pgina o hasta que los mtodos End o Flush del objeto Response no son invocados. Una vez activado el almacenamiento en bfer, es decir, la propiedad Buffer posee el valor True, y una vez que ya se ha enviado contenido al navegador del cliente, no se puede modificar su valor, tampoco se puede modificar ningn valor de las propiedades del objeto Response.As por ejemplo el Cdigo fuente 19 generara un error.

<%Response.Buffer=False%> <HTML> <HEAD> <%Response.Expires=10%> Cdigo fuente 19

El error devuelto por el navegador sera similar a Los encabezados HTTP ya estn escritos en el explorador cliente. Cualquier cambio en el encabezado HTTP se debe hacer antes de escribir el contenido de la pgina. En las versiones anteriores de ASP la propiedad Buffer tena por defecto la propiedad False, de esta forma segn se iba procesando la pgina ASP se enviaba el resultado de la ejecucin al cliente. Segn Microsoft con este cambio se obtiene un mejor rendimiento en la ejecucin de pginas ASP. En realidad lo que se tiene tambin es un mayor control sobre la salida que va a recibir el usuario.

40

Grupo EIDOS

2. Modelo de objetos de ASP. Parte I

El uso de este bfer puede ser til en el caso de que sea necesario procesar el contenido de una pgina ASP antes de enviar ningn contenido previo al navegador del cliente. De esta forma se puede redireccionar al navegador hacia otra pgina con el mtodo Redirect del objeto Response, este mtodo se comentar en su apartado correspondiente, pero se puede adelantar que una llamada a este mtodo producir un error en el caso de que se haya enviado anteriormente algn contenido al usuario. La propiedad Buffer tambin puede ser utilizada para verificar errores antes de enviar informacin al navegador, de esta forma si se detecta un error se puede detener el proceso de la pgina y redireccionar al navegador del cliente hacia una pgina determinada. Cuando la propiedad Buffer, tiene su valor por defecto, es decir, el valor True se pueden utilizar una serie de mtodos del objeto Response, estos mtodos, cuya funcin se ver en el apartado correspondiente, son: Clear, End y Flush y bsicamente lo que permiten es controlar el resultado o salida que se le enva al cliente.

Mtodos del objeto Response


A continuacin, de la misma forma que se ha hecho con las propiedades del objeto Response, se va a hacer una breve descripcin de los mtodos que nos ofrece este objeto. AddHeader: agrega un nuevo encabezado HTML a la respuesta. Este mtodo no es muy utilizado. Permite definir nuevos encabezados. Su sintaxis es: Response.AddHeader nombreEncabezado, valorEncabezado. AppendToLog: agrega una cadena al final de la entrada de registro del servidor Web para la peticin. IIS se puede configurar para registrar las peticiones de los clientes en una base de datos o en un fichero de log. Este mtodo permite agregar una cadena a la informacin que ser almacenada por el usuario acerca de una peticin de un cliente. BinaryWrite: este mtodo es utilizado para escribir informacin directamente en la salida HTTP, es decir, el navegador del cliente, sin ningn tipo de interpretacin. Este mtodo es til cuando se necesita enviar pequeos grficos, multimedia u otros componentes que no son texto. Clear: elimina el contenido del cdigo HTML del bfer. End: detiene el procesamiento de la pgina ASP y devuelve los resultados obtenidos hasta la llamada a End. Flush: enva al navegador el contenido del bfer antes de finalizar el procesamiento de la pgina ASP. Redirect: se redirecciona al navegador Web del cliente a la direccin que se le pasa como parmetro. Write: escribe en el navegador del cliente.

Los mtodos Clear, Flush y End, deben ser utilizados cuando la propiedad Buffer del objeto Response est activada, es decir, tiene como valor True, ya sabemos que este es el valor por defecto de esta propiedad. Cuando est activado el almacenamiento en el bfer existen varias formas de enviar la informacin del bfer al navegador del cliente:
41

Desarrollo de aplicaciones COM+ para Internet / Intranet con ASP 3.0

Grupo EIDOS

Llamando al mtodo Flush. Llamando al mtodo End. De esta forma tambin se detiene la ejecucin de la pgina ASP. Cuando finaliza le ejecucin de la pgina ASP, es decir, cuando se ejecuta la ltima lnea de las secuencias de comandos de servidor.

El mtodo Clear se utiliza cuando se quiere eliminar todo el contenido que posee el bfer, pero esto no implica que se borre el contenido que ya se ha enviado al cliente, a ese contenido ya no se tiene acceso, as por ejemplo el Cdigo fuente 20 producira un error.

<HTML> <HEAD> <META NAME="GENERATOR" Content="Microsoft Visual Studio 6.0"> </HEAD> <BODY> <b>Esto es contenido</b> <%Response.Flush Response.Clear Response.Redirect "pruebas.asp"%> </BODY> </HTML> Cdigo fuente 20

La utilizacin de estos mtodos junto con la propiedad Buffer nos permite controlar el procesamiento de la pgina ASP de una forma muy sencilla y eficaz. Para mostrar el uso de estos mtodos junto con el almacenamiento en bfer vamos a ver un sencillo ejemplo, en el Cdigo fuente 21, que va mostrando poco a poco un texto en pantalla.

<%strTexto="Texto que se va mostrando poco a poco en el navegador" For i=1 to Len(strTexto) 'se realiza una pausa For j=1 To 100000 Next Response.Write Mid(strTexto,i,1) 'se enva el contenido del bfer Response.Flush Next%> Cdigo fuente 21

El efecto de este cdigo es que se va enviando el texto caracter a caracter mediante el mtodo Flush, para que se produzca una pausa se realiza un bucle For adicional. Si situamos la sentencia Response.Flush al final del cdigo, aparecer todo el texto de una sola vez. A lo largo de los distintos ejemplos que hemos visto hasta ahora en el curso, en alguno de ellos hemos utilizado la sentencia Response.Write, por lo tanto ya sabemos exactamente la funcin de este mtodo del objeto Response. Pero tambin para escribir se han utilizado los delimitadores <%=%>. Estos delimitadores son equivalentes a escribir Response.Write, se pueden considerar como su abreviatura. El mtodo
42

Grupo EIDOS

2. Modelo de objetos de ASP. Parte I

Response.Write se utilizar dentro de una bloque de script de servidor, es decir, un bloque de cdigo encerrado por los delimitadores <%%>, y el uso de los delimitadores <%=%> ser adecuado cuando se necesite intercalar una lnea aislada entre cdigo HTML: Como ya se ha visto, el mtodo Write se puede utilizar para escribir texto en el navegador. Las llamadas a mtodos y las variables dentro del mtodo Write sern evaluadas y slo el resultado se escribir en el navegador del cliente. Por ejemplo, el Cdigo fuente 22 mostrar el valor de la variable contador en el navegador del cliente.

<%Response.Write("La variable contador contiene el valor: " & contador)%> Cdigo fuente 22

El uso de parntesis en el mtodo Write es opcional. Si tenemos en cuenta los delimitadores <%=%>, de forma equivalente podramos haber escrito lo que se muestra en el Cdigo fuente 23 o en el Cdigo fuente 24.

<%="La variable contador contiene el valor: "&contador%> Cdigo fuente 23

La variable contador contiene el valor: <%=contador%> Cdigo fuente 24

Si en nuestro cdigo tenemos diferentes lneas con los delimitadores <%=%> intercaladas dentro de cdigo HTML, para una mayor eficiencia es recomendable sustituirlos por una nica lnea mediante Response.Write. Adems se consigue un cdigo ms legible, se debe tender a bloques de HTML y de script de servidor bien diferenciados, siempre que sea posible. El mtodo Redirect recibe como parmetro una cadena de texto en forma de URL que especifica la nueva direccin a la que se va a redirigir el navegador del usuario. La URL puede ser absoluta, del tipo www.almagesto.com o del tipo /directorio/pagina.asp, o relativa del tipo pagina.asp. Al lanzar el mtodo Redirect en realidad lo que estamos haciendo es enviar una cabecera HTTP al navegador Web del cliente para indicarle que la pgina se ha movido y le indicamos la nueva localizacin, que es la URL que hemos indicado al mtodo Redirect. La informacin que se enva al navegador es HTTP/1.1 Object Moved Location /directorio/pagina.asp. Como se puede observar la redireccin se realiza en el cliente, indicndole que la pgina se ha movido a una nueva direccin, que en realidad es otra pgina completamente distinta. Aqu nos hemos centrado en redireccionar el navegador a otra pgina (HTML o ASP), pero se puede generalizar diciendo que podemos redireccionar al navegador a cualquier recurso, como puede ser una imagen, un fichero zip, un documento, etc.

43

Desarrollo de aplicaciones COM+ para Internet / Intranet con ASP 3.0

Grupo EIDOS

El objeto Request
Este objeto integrado es utilizado para obtener informacin del usuario, por lo tanto realiza las funciones contrarias al objeto Response. Cuando un navegador cliente se comunica con el servidor Web a travs del protocolo HTTP, el navegador manda un gran nmero de informacin adems de la pgina que se quiere cargar, esta informacin puede ser: variables de entorno, informacin sobre certificados, cookies, formularios, etc. Toda esta informacin es codificada y enviada a travs de cabeceras del protocolo HTTP y en muchos casos no es sencilla de extraer. ASP realiza las funciones de extraer, decodificar y organizar toda esta informacin a travs del objeto Request y sus diferentes colecciones. Esta informacin enviada por el navegador, se puede utilizar para: validar un usuario, obtener informacin sobre el usuario el navegador, almacenar informacin para su posterior uso, enviar informacin al servidor a travs de formularios, etc. ASP almacena toda esta informacin en colecciones del objeto Request. Mediante llamadas del tipo Request.coleccin se puede obtener de forma sencilla la informacin que sea necesaria. El objeto Request presenta cinco colecciones que veremos en el siguiente apartado

Colecciones del objeto Request


Las cinco colecciones que ofrece el el objeto Request del modelo de objetos de ASP contienen toda la informacin enviada por el navegador cliente al servidor Web. Estas colecciones se pasan a comentar de forma breve: ClientCertificate: contiene los valores de los campos de certificacin (especificados en el estndar X.509) de la peticin emitida por el navegador. Cookies: valores de las cookies del cliente. Form: valores de elementos de un formulario HTML. QueryString: valores de las variables de la cadena de consulta HTTP enviada. ServerVariables: esta coleccin almacena informacin sobre el navegador, el servidor y el usuario.

Para tener acceso a la informacin de las colecciones del objeto Request se puede utilizar la sintaxis general Request.NombreColeccion(variable), donde NombreColeccion es el nombre de la coleccin que se quiere consultar y variable es el nombre de la variable de la coleccin a la que se quiere tener acceso y recuperar su valor. Las variables contenidas en las colecciones del objeto Request son nicamente de lectura. Tambin se puede acceder a una variable de una coleccin sin especificar el nombre de la coleccin (Request(variable)). En este caso se realizar una bsqueda por todas las colecciones del objeto Request hasta que se obtenga la variable deseada. El orden de bsqueda entre las colecciones es el siguiente: QueryString, Form, Cookies, ServerVariables y por ltimo ClientCertificate. Se obtendr la primera variable que coincida con el parmetro variable. Esto no es muy recomendable ya que es ms lento y pueden existir variables con el mismo nombre en distintas colecciones.

44

Grupo EIDOS

2. Modelo de objetos de ASP. Parte I

Para obtener todos los valores de las variables de una coleccin se puede utilizar la instruccin For Each...in..., el Cdigo fuente 25 muestra como se obtendra el nombre y el valor de cada variable de la coleccin ServerVariables:

<%For each variable in Request.ServerVariables Response.Write("La variable: "&variable&" tiene el valor: "&_ Request.ServerVariables(variable)&"<br>") Next%> Cdigo fuente 25

El objeto Request mediante su coleccin Form permite acceder a los datos enviados a travs de un formulario mediante el mtodo POST. Para obtener los datos de un formulario, que por ejemplo tuviera los campos Nombre y Edad, se debera escribir el Cdigo fuente 26 dentro de la pgina ASP llamada PROCESAINFO.ASP.

Nombre usuario: <%=Request.Form("nombre")%><br> Edad usuario: <%=Request.Form("edad")%> Cdigo fuente 26

Si se quiere obtener los datos sin decodificar bastara con escribir el Cdigo fuente 27.

Datos: <%=Request.Form%> Cdigo fuente 27

En el navegador aparecera lo siguiente: Datos: nombre=Pepe&edad=30&boton=Enviar. Se puede observar que adems de los campos de texto del formulario tambin se enva el botn de Submit si a ste se le ha asignado un nombre en la etiqueta de HTML. En algunos casos los elementos de un formulario pueden ser un array, basta con, por ejemplo, dar a varias cajas de texto el mismo nombre, de esta forma para acceder a la informacin se deber utilizar un ndice. Por ejemplo si tenemos el formulario del Cdigo fuente 28.

<form action="procesaInfo.asp" method="POST"> Nombre: <input type="Text" name="datosPersonales" value=""> Apellidos: <input type="Text" name="datosPersonales" value=""> Edad: <input type="Text" name="datosPersonales" value=""> <input type="Submit" name="boton" value="Enviar"> </form> Cdigo fuente 28

45

Desarrollo de aplicaciones COM+ para Internet / Intranet con ASP 3.0

Grupo EIDOS

Para poder recuperar la informacin enviada se debera tratar como un array, y se realizara de la forma que se indica en el Cdigo fuente 29.

<%For i=1 To Request.QueryString("datosPersonales").Count Response.write(Request.Form("datosPersonales")(i)&"<br>") Next%> Cdigo fuente 29

Como se puede observar los ndices comienzan en 1, y para saber el nmero de elementos del array se utiliza el mtodo Count que devuelve el nmero de elementos de un array. Las pginas ASP se pueden utilizar para recoger y procesar valores de formularios HTML de varias maneras: Un archivo htm o html esttico puede contener un formulario que enve sus valores a una pgina ASP, como ha sido el caso de los ejemplos anteriores. Una pgina ASP puede contener un formulario que enve informacin a otra pgina ASP. Una pgina ASP puede contener un formulario que enve informacin as misma, es decir, a la pgina ASP que contiene el formulario.

La ltima opcin es la ms potente y la ms recomendable, de esta forma una pgina ASP se llama as misma. Para poder utilizar esta estrategia lo que se debe tener en cuenta es si la pgina ASP se carga por primera vez o se carga de nuevo porque ha sido llamada por s misma. Esto se puede conseguir preguntando si existe alguno de los campos del formulario, si existe es que se ha realizado la llamada desde la misma pgina y por lo tanto se validarn o mostrarn los datos; y si no existe, la pgina se est cargando por primera vez y se mostrar el formulario. En el Cdigo fuente 30 de ejemplo se puede observar esta tcnica.

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN"> <HTML> <HEAD> <TITLE>Misma pgina ASP</TITLE> </HEAD> <BODY> <%If Request.Form("botonEnviar")<>"" Then%> <u>Datos enviados</u><br> Nombre: <%=Request.Form("nombre")%><br> Edad: <%=Request.Form("edad")%> <%Else%> <form action="mismaPagina.asp" method="POST"> Nombre: <input type="Text" name="nombre" value=""> Edad: <input type="Text" name="edad" value=""> <input type="Submit" name="botonEnviar" value="Enviar"> </form> <%End If%> </BODY> </HTML> Cdigo fuente 30

46

Grupo EIDOS

2. Modelo de objetos de ASP. Parte I

En este caso se pregunta por el valor del botn de envo, ya que siempre que se enve el formularo se enviar tambin el botn de tipo submit. Adems se supone el cdigo mostrado pertenece a una pgina ASP llamada mismaPagina.asp tal como se indica en la propiedad ACTION de la etiqueta <FORM>. Si cargamos por primera vez esta pgina pasaremos por la rama de la instruccin Else y veramos el formulario en el navegador. Una vez cargada la pgina, si rellenamos los campos de texto y pulsamos sobre el botn etiquetado como Enviar, pasaramos por el primer bloque del If, ya que la pgina ASP se volvera a cargar as misma y la variable botonEnviar de la coleccin Form ya contendra un valor. Como se puede observar da la impresin que son dos pginas distintas, pero en realidad es la misma pgina ASP que genera diferente cdigo HTML segn la ejecucin del script de servidor. Para obtener los valores de un formulario que se ha enviado con el mtodo GET o para recuperar los valores de una cadena de consulta de un enlace, utilizaremos esta otra coleccin del objeto Request: QueryString. Todo lo visto para la coleccin Form es vlido para la coleccin QueryString. La nica diferencia es que los datos aparecen visibles en la barra de direcciones del navegador y existe un tamao mximo de 1024K. La decisin de utilizar una coleccin u otra depende del tamao de los datos a enviar y del nmero de ellos. Cuando el tamao es mayor de 1024K slo tendremos la opcin de usar la coleccin Form. Yo personalmente sigo la siguiente regla, para los formularios de HTML siempre utilizao el mtodo de envo POST y por lo tanto para recuperar los valores de los campos utilizo Form, y la coleccin QueryString la suelo utilizar para recuperar los valores de los datos facilitados desde un enlace. Se debe tener en cuenta que el usuario puede manipular la cadena de consulta enviada mediante un enlace, por lo tanto habr algunos datos que no podremos enviar desde una cadena de consulta, pero hay algunos casos en que no representa ningn problema que el usuario modifique la cadena de consulta.

47

Modelo de objetos de ASP. Parte II


El objeto Application
Un objeto Application representa una aplicacin ASP. Una aplicacin basada en ASP consta de un directorio en un servidor Web y de todos los subdirectorios y archivos contenidos en l. Una aplicacin puede ser una pgina principal sencilla, o bien puede estar formada por un conjunto completo de pginas interrelacionadas entre s. Se debe recordar que el protocolo HTTP es un protocolo sin estado, es decir, no se puede almacenar informacin entre diferentes conexiones HTTP. No se puede mantener el estado entre diferentes pginas Web a travs del protocolo HTTP, sino que se deben utilizar otros mecanismos como las cookies. Pero el objeto Application junto con el objeto Session (que se comentar en su captulo correspondiente) nos permite de forma sencilla y directa almacenar informacin abstrayndonos del uso de cookies y de encabezados HTTP. La informacin almacenada en los objetos Session y Application difieren en el mbito de la misma, una informacin tendr el mbito de la sesin de un usuario concreto y la otra el mbito de la aplicacin general, respectivamente. Las variables almacenadas dentro del objeto Application son visibles para todos los usuarios que estn utilizando la misma aplicacin ASP, es decir son compartidas por varios usuarios. En contraposicin al objeto Session, cuyas variables son para cada uno de los usuarios conectados, es decir, no se comparten y son propias de cada sesin. Podremos acceder a una variable a nivel de aplicacin en cualquiera de las pginas ASP contenidas en la aplicacin ASP actual.

Desarrollo de aplicaciones COM+ para Internet / Intranet con ASP 3.0

Grupo EIDOS

En este punto se debe sealar que una variable en una aplicacin ASP puede tener cuatro mbitos diferentes, se va a ir del ms global al ms particular. La creacin de una variable con un mbito u otro depender del uso que queramos hacer de ella. mbito de aplicacin: esta variable la podrn manipular todos los usuarios de la aplicacin ASP, es comn a todos ellos. Se almacena dentro del objeto Application. mbito de sesin: las variables con este mbito son propias de cada uno de los usuarios de la aplicacin, es decir, cada usuario tendr acceso a las variables de su sesin. Estas variables se almacenan dentro del objeto integrado Session. mbito de pgina: estas variables son las que se crean dentro del script de servidor de una pgina ASP, slo tienen vigencia dentro de la pgina en la que se declararon, al abandonar la pgina se destruirn. mbito de procedimiento: a este mbito pertenecen las variables declaradas dentro de un procedimiento (Sub o Function). Estas variables slo existirn dentro del procedimiento en el que son declaradas, se dice que son variables locales al procedimiento.

Para almacenar una variable dentro de un objeto Application, es decir, crear una variable cuyo mbito sea la aplicacin se debe utilizar la sintaxis del Cdigo fuente 31.

Application("NombreVariable")=valorVariable Cdigo fuente 31

Tambin se pueden almacenar objetos dentro del objeto Application. Hay una serie de consideraciones acerca de las variables que se pueden almacenar en el objeto Application y que pasamos a comentar a continuacin. En cuanto a tipos de variable se refiere, una variable de aplicacin puede contener cualquier tipo de valor Variant, y en cuanto a objetos, puede contener cualquier tipo de objeto o componente que se encuentre preparado para tener mbito de aplicacin, a excepcin de los objetos del modelo de objetos de ASP (ASPError, Request, Server, Response, Application, Session, ObjectConext) de esta forma la instruccin del Cdigo fuente 32 generara un error.

<%Set Application("objeto")=Request%> Cdigo fuente 32

Si almacenamos una variable array a nivel de aplicacin, para modificar sus valores no podremos hacerlo directamente, sino que se debe hacer a travs de una variable auxiliar, que ser la que se modificar y luego asignar a la variable de aplicacin correspondiente. En el Cdigo fuente 33 se muestra la utilizacin de una variable de aplicacin que es un array de cadenas.

<%Dim vector(3) vector(0)="Primer valor" vector(1)="Segundo"

50

Grupo EIDOS

3. Modelo de objetos de ASP. Parte II

vector(2)="Tercero" vector(3)="Ultimo Valor" Application("valores")=vector '---'---'Para modificar los valores recuperamos la variable vectorAux=Application("valores") vectorAux(2)="Elemento modificado" Application("valores")=vectorAux For i=0 to UBound(Application("valores")) Response.Write "Application('valores')("&i&")="&Application("valores")(i)&"<br>" Next%> Cdigo fuente 33

Sin embargo los valores de cada elemento de array si que se pueden recuperar directamente de la variable de aplicacin. No es recomendable almacenar objetos a nivel de aplicacin, ya que esto supone que el objeto va a existir durante toda la vida de la aplicacin ASP y puede ser accedido por distintos usuarios de manera concurrente. Lo ideal para almacenar en variables de aplicacin son variables de tipo entero, booleano o cadenas de caracteres.

Colecciones del objeto Application


En la versin 1.0 de ASP el objeto Application no posea ninguna coleccin, sin embargo en ASP 2.0 se aadieron dos colecciones, y son: Contents: contiene las variables a nivel de aplicacin a excepcin de los objetos creados con la etiqueta <OBJECT> StaticObjects: contiene nicamente los objetos a nivel de aplicacin creados con la etiqueta <OBJECT>.

Ambas colecciones nos van a permitir recuperar o acceder a las variables y objetos creados a nivel de aplicacin, aunque ya hemos visto en el apartado anterior que podemos acceder directamente a ellos. La coleccin Contents contiene todos los objetos y variables creados a nivel de aplicacin, excluyendo aquellos objetos que han sido creados utilizando la etiqueta de HTML <OBJECT>. Esta etiqueta se utiliza para la creacin de objetos, de todas formas veremos con detalle el uso de la etiqueta <OBJECT> en este mismo apartado a la hora de comentar la coleccin StaticObjects. En esta coleccin se incluirn, por tanto, los objetos creados a nivel de aplicacin con la sentencia Server.CreateObject y las variables creadas con Application("variable")=valor. La coleccin Contents del objeto Application permite utilizar un par de mtodos que son comunes a todas las colecciones de escritura y que son los siguientes: RemoveAll: elimina todas las variables de aplicacin, a excepcin de las creadas con la etiqueta <OBJECT>. Este mtodo carece de parmetros. Remove: elimina una variable de aplicacin determinada que est contenida en la coleccin Contents. Este mtodo recibe por parmetro el ndice o nombre de la variable correspondiente.
51

Desarrollo de aplicaciones COM+ para Internet / Intranet con ASP 3.0

Grupo EIDOS

La coleccin StaticObjects contiene todos los objetos a nivel de aplicacin que se han creado mediante la etiqueta <OBJECT>, por lo tanto la coleccin StaticObjects nicamente contendr variables que son referencias a objetos. De la misma forma que veamos en el ejemplo anterior, podremos recorrer la coleccin StaticObjects para acceder a los objetos estticos creados a nivel de aplicacin. La etiqueta <OBJECT> es una etiqueta de HTML que se suele utilizar para instanciar y crear objetos ActiveX en el navegador del cliente, sin embargo aqu su uso es muy distinto, ya que se utiliza para instanciar componentes del servidor, podemos decir que es equivalente a la sentencia Server.CreateObject. Pero esta etiqueta nicamente se puede utilizar en el fichero especial global.asa. La coleccin StaticObjects no ofrece ningn mtodo como los de la coleccin Contents, nicamente ofrece los mtodos que son comunes a todas las colecciones de lectura, que son Count, Key e Item. Veamos un ejemplo, suponiendo que tememos creados los objetos del ejemplo anterior.

Mtodos del objeto Application


Las variables almacenadas en el objeto Application son compartidas por todos los usuarios de la aplicacin ASP. Debido a esto se pueden dar problemas de concurrencia, es decir, cuando dos usuarios acceden a la misma informacin y la quieren modificar al mismo tiempo, por lo tanto se debe tener un acceso exclusivo a las variables del objeto Application cuando se quiera modificar su valor. Aqu entendemos por usuarios a sentencias del lenguaje de secuencias de comandos, es decir, seran dos sentencias en distintas pginas que intentaran modificar la misma variable de aplicacin al mismo tiempo. Para implementar este mecanismo de exclusin mutua el objeto Application ofrece dos mtodos: Lock y UnLock. Cuando se llama al mtodo Lock, ste impide que otros usuarios modifiquen el contenido de las variables de la aplicacin. Y cuando se llama al mtodo UnLock, se permite el acceso a las variables a todos los usuarios de la aplicacin. Es un mtodo de exclusin mutua, slo un usuario puede a la vez estar utilizando las variables del objeto Application, las variables quedarn libres para el resto de los usuarios cuando se lance sobre el objeto Application el mtodo UnLock. El Cdigo fuente 34 muestra un ejemplo de utilizacin de estos dos mtodos.

<%Application.Lock Application("NumVisitas")=Application("NumVisitas")+1 Application.UnLock%> Cdigo fuente 34

Este mecanismo puede ser ineficiente, ya que se bloquean todas las variables del objeto Application cuando, como en el ejemplo anterior, necesitamos que solamente se proteja una variable. No se debe utilizar demasiadas sentencias entre una llamada al mtodo Lock y la correspondiente llamada a UnLock, ya que las variables del objeto Application podran quedar bloqueadas demasiado tiempo afectando de esta forma al correcto funcionamiento de la aplicacin ASP correspondiente. Lock y UnLock se utilizarn normalmente en el momento en el que se vaya a modificar el valor de una variable de aplicacin.

52

Grupo EIDOS

3. Modelo de objetos de ASP. Parte II

Nunca se debe olvidar el corresponder cada llamada Lock con una llamada UnLock, ya que podramos caer en el error de dejar bloqueada las variables de la aplicacin de forma indefinida.

Eventos del objeto Application. El GLOBAL.ASA


El objeto Application posee dos eventos, cuando comienza la ejecucin de la aplicacin ASP y cuando finaliza la ejecucin de la aplicacin ASP, estos dos eventos se llaman, respectivamente Application_OnStart y Application_OnEnd. Estos dos eventos se corresponden con dos procedimientos del mismo nombre definidos en el fichero global.asa. Ya empezamos a ver una de las principales funciones del ya mencionado fichero global.asa. Dentro de estos eventos se puede situar un script que realice las tareas que consideremos necesarias. El script que se debe ejecutar en cada uno de estos eventos se deber indicar el fichero especial llamado GLOBAL.ASA (ASA, Active Server Application). El evento Application_OnStart se produce cuando entra el primer usuario en la aplicacin, es decir antes de producirse el primer inicio de sesin (Session_OnStart), por ejemplo, cuando el primer usuario carga una pgina ASP perteneciente a una aplicacin. Dentro de este evento se deber indicar el cdigo de inicializacin de la aplicacin ASP. Y el evento Application_OnEnd se produce cuando se apaga el servidor Web, se descarga la aplicacin ASP, finaliza la ltima de las sesiones de un usuario o se modifica el fichero GLOBAL.ASA, estas son las distintas formas que tiene de finalizar una sesin. Dentro de este evento se deber escribir el script que se desee que se ejecute antes de destruir la aplicacin. En los eventos Application_OnEnd y Application_OnStart nicamente se tiene acceso a dos de los objetos integrados de ASP, se trata de los objetos Server y Application, si intentamos utilizar algn otro objeto del modelo de objetos de ASP se producir un error. El fichero GLOBAL.ASA (ASA, Active Server Application, aplicacin activa de servidor o mejor aplicacin ASP), que tanto hemos mencionado hasta ahora en este captulo, es un fichero opcional que se encuentra en el directorio raz de la aplicacin ASP y que est relacionado de forma directa con los objetos integrados Application y Session. Este fichero, que debe ser nico para cada aplicacin ASP, tiene varias funciones: Definir como son tratados los eventos de los objetos Session y Application. Como hemos comentado en el apartado anterior. Permitir crear objetos con el mbito de aplicacin y sesin. Inicializar y crear variables en el mbito de la sesin y aplicacin. Informacin acerca del tratamiento de los eventos de los objetos Session y Application. Declaraciones de objetos mediante la etiqueta <OBJECT>.

Este fichero no es un fichero cuyo contenido se muestre al usuario, si un usuario intenta cargar el fichero global.asa en su navegador recibir un mensaje de error:. La estructura general del GLOBAL.ASA es la del Cdigo fuente 35.

53

Desarrollo de aplicaciones COM+ para Internet / Intranet con ASP 3.0

Grupo EIDOS

<SCRIPT LANGUAJE=VBScript RUNAT=Server> SUB Application_OnStart ...... END SUB SUB Session_OnStart ...... END SUB SUB Session_OnEnd ...... END SUB SUB Application_OnEnd ...... END SUB </SCRIPT> Cdigo fuente 35

Si se escribe script fuera de las etiquetas <SCRIPT></SCRIPT> o se declara un objeto que no tiene mbito de sesin o de aplicacin se producir un error. Tampoco se pueden incluir ficheros de ningn tipo mediante el uso de la directiva INCLUDE. El lenguaje de secuencias de comandos a utilizar se indica en el atributo LANGUAGE de la etiqueta <SCRIPT>, y tambin se debe indicar en que lugar se ejecutar el script, esto se consigue a travs del atributo RUNAT de la etiqueta <SCRIPT>, en realidad este atributo slo tiene un valor posible: Server, es decir, el script se ejecutar en el servidor. Para declarar objetos mediante la etiqueta <OBJECT>, para que tengan el mbito de sesin o aplicacin se deber seguir la sintaxis del Cdigo fuente 36.

<OBJECT RUNAT=Server SCOPE=Ambito ID=Identificador {PROGID="IDprog"|CLASSID="IDclase"}> ........ </OBJECT> Cdigo fuente 36

La declaracin de los objetos deber ir fuera de las etiquetas de script. Los objetos declarados de esta forma no se crearn hasta que el servidor procese una secuencia de comandos en el que se haga referencia a ellos. As se ahorran recursos, al crearse slo los objetos que son necesarios. Estos objetos pasaran a formar parte de la coleccin StaticObjects del objeto Application. El parmetro Ambito especifica el mbito del objeto, podr tener los valores Session o Application; Identificador especifica un nombre para la instancia del objeto; IDprog e IDclase para identificar la clase del objeto. La propiedad SCOPE de la etiqueta <OBJECT> de HTML, tiene un valor de mbito ms, adems de los de sesin y de aplicacin, y se trata del mbito de pgina SCOPE="PAGE". El mbito de pgina indica que el objeto que se instancie slo existir en el pgina actual, pero este mbito no se puede
54

Grupo EIDOS

3. Modelo de objetos de ASP. Parte II

utilizar en el fichero global.asa sino que se puede utilizar en cualquier pgina ASP. Sin embargo en las pginas ASP no se puede utilizar la etiqueta <OBJECT> con el mbito de aplicacin o de sesin, nicamente se pueden instanciar objetos con mbito de pgina. El Cdigo fuente 37 dentro del fichero global.asa creara un objeto Connection de ADO con mbito de sesin.

<OBJECT RUNAT=Server SCOPE=Session ID=conexion PROGID="ADODB.Connection"> </OBJECT> Cdigo fuente 37

Para utilizar este objeto posteriormente dentro de una pgina ASP, por ejemplo, para ejecutar una sentencia SQL sobre la conexin con la base de datos, bastara con escribir la lnea del Cdigo fuente 38.

<%conexion.Execute "DELETE FROM Usuarios WHERE id<10"%> Cdigo fuente 38

Es decir, accedemos directamente al nombre del objeto, que ser el indicado en la propiedad ID de la etiqueta <OBJECT>. El objeto Application se crea cuando el primer usuario se conecta a una aplicacin ASP y pide una sesin, es decir, carga la primera pgina de la aplicacin ASP. Cuando se crea el objeto Application, el servidor busca el fichero GLOBAL.ASA en el directorio raz de esa aplicacin ASP, si el fichero existe se ejecuta el script del evento Application_OnStart. A continuacin se crea el objeto Session. La creacin del objeto Session ejecuta el script que se encuentra en el evento Session_OnStart. El script asociado al tratamiento de este evento se ejecutar antes de cargar la pgina indicada por la peticin del navegador cliente. Cuando el objeto Session caduca o se lanza el mtodo Session.Abandon, se ejecutar el script que se corresponde con el evento Session_OnEnd, el cdigo de este evento se procesar antes de destruir la sesin. Cuando finaliza la ltima sesin de los usuarios, es decir, se ejecuta el cdigo del ltimo evento evento Session_OnEnd, se lanza el evento Application_OnEnd antes de que se destruya el objeto Application. Si se modifica el fichero GLOBAL.ASA, el servidor lo recompilar, para ello el servidor deber destruir el objeto Application actual y los objetos Session actuales. Primero, el servidor procesa todas las peticiones activas, el servidor no procesar ms peticiones hasta que no se procese el evento Application_OnEnd. Los usuarios que se intenten conectar durante este proceso recibirn un mensaje que le indica que la peticin no puede ser procesada mientras la aplicacin es reiniciada. Durante este proceso se dan los siguientes pasos: Las sesiones activas se destruyen, dando lugar al procesamiento del evento Session_OnEnd. La aplicacin se destruye, producindose el evento Application_OnEnd.

55

Desarrollo de aplicaciones COM+ para Internet / Intranet con ASP 3.0

Grupo EIDOS

La primera peticin reiniciar el objeto Application y crear un nuevo objeto Session, es decir, se darn los eventos Application_OnStart y Session_OnStart, respectivamente.

Tambin se ejecutar la el evento Application_OnEnd cuando se descargue la aplicacin ASP desde el Administrador de servicios de Internet o cuando se apague el servidor Web.

El objeto Session
Al igual que ocurra con el objeto Application, el objeto Session nos va a permitir almacenar informacin entre diferentes pginas ASP incluidas en una misma aplicacin ASP. La diferencia con el objeto Application se encuentra en el mbito de las variables, cada variable del objeto Session es particular a una sesin de un usuario determinado, no a toda la aplicacin. De esta forma, cada usuario tendr sus variables y sus valores, sin dar lugar a problemas de concurrencia, tampoco se podr acceder a distintas variables de sesin, cada usuario tiene su espacio de almacenamiento. Las variables de aplicacin son valores globales y comunes a toda la aplicacin, y las variables de sesin son particulares para cada usuario de la aplicacin. El servidor Web crea automticamente un objeto Session, cuando un usuario que an no estableci una sesin solicita una pgina ASP perteneciente a la aplicacin ASP actual. El servidor Web sabe si un navegador tiene ya una sesin debido a que la cookie ASPSESSIONID es enviada junto con la peticin de la pgina ASP. Un uso comn del objeto Session es almacenar las preferencias del usuario o informacin personal. Se debe sealar que se podrn almacenar variables dentro del objeto Session si el navegador acepta cookies, ya que el objeto Session para almacenar informacin se basa en la cookie ASPSESSIONID. Aunque la utilizacin de esta cookie es completamente transparente para el programador. Para una aplicacin ASP tendremos tantas sesiones como usuarios conectados a la aplicacin ASP. Las recomendaciones realizadas para el objeto Application en cuanto a utilizacin de objetos y variables de tipo array, son tambin vlidas para el objeto Session. La sintaxis para manipular variables del objeto Session es la misma que en el objeto Application. El Cdigo fuente 39 crea una variable del objeto Session con el nombre que el usuario facilita en un formulario.

<%Session("nombreUsuario")=Request.Form("nombre")%> Cdigo fuente 39

Colecciones del objeto Session


En la versin 1.0 de ASP el objeto Session ,al igual que ocurra con el objeto Application tampoco posea ninguna coleccin, apareciendo en la versin de 2.0 ASP con dos nuevas colecciones con las mismas funciones que las del objeto Application pero a nivel de sesin claro: Contents: contiene todas las variables a nivel de sesin menos las creadas con al etiqueta <OBJECT>.

56

Grupo EIDOS

3. Modelo de objetos de ASP. Parte II

StaticObjects: contiene las variables de la sesin creadas con la etiqueta <OBJECT>.

Ambas colecciones nos van a permitir recuperar o acceder a las variables y objetos creados, en este caso, a nivel de sesin. La coleccin Contents contiene todos los objetos y variables creados a nivel de sesin, excluyendo a los objetos que han sido creados utilizando la etiqueta <OBJECT>. En esta coleccin se incluirn, por tanto, los objetos creados a nivel de sesin con Server.CreateObject y las variables creadas con las sentencias del tipo Session("variable"). La coleccin StaticObjects contiene todos los objetos que se han creado mediante la etiqueta <OBJECT> dentro del alcance de la sesin. Si suponemos que tenemos el fichero GLOBAL.ASA que aparece en el Cdigo fuente 40.

<SCRIPT LANGUAGE="VBScript" RUNAT="Server"> Sub Session_OnStart Session("variableUno")="valor" Session("variableDos")=2 Session("variableTres")=True End Sub </SCRIPT> <OBJECT RUNAT="Server" SCOPE="Session" ID="conex" PROGID="ADODB.Connection"> </OBJECT> <OBJECT RUNAT="Server" SCOPE="Session" ID="recordset" PROGID="ADODB.RecordSet"> </OBJECT> Cdigo fuente 40

Si ahora se ejecuta una pgina con el Cdigo fuente 41.

<%@ Language=VBScript %> <HTML> <HEAD> <META NAME="GENERATOR" Content="Microsoft Visual Studio 6.0"> </HEAD> <BODY> Nmero de elementos de la coleccin Contents: <b><%=Session.Contents.Count%></b><br> <%For Each variable in Session.Contents Response.Write variable & " = "&Session.Contents(variable)&"<br>" Next%> <br> Nmero de elementos de la coleccin StaticObjects: <b><%=Session.StaticObjects.Count%></b><br> <%For Each objeto in Session.StaticObjects Response.Write objeto&"<br>" Next%> <br> <%'accedemos la variable de aplicacin definida con <OBJECT> conex.Open "DSN=BD;UID=sa;PWD=" Response.Write "Base de datos predeterminada: "&conex.DefaultDatabase conex.Close%> </BODY> </HTML> Cdigo fuente 41

57

Desarrollo de aplicaciones COM+ para Internet / Intranet con ASP 3.0

Grupo EIDOS

Se producir este resultado: Nmero de elementos de la coleccin Contents: 3 variableUno = valor variableDos = 2 variableTres = Verdadero Nmero de elementos de la coleccin StaticObjects: 2 conex recordset Base de datos predeterminada: Cursos

Propiedades del objeto Session


El objeto Session posee cuatro propiedades: SessionID: contiene la identificacin de la sesin para el usuario. Cada sesin tiene un identificador nico que genera el servidor al crearla. No se debe utilizar esta propiedad como clave de una tabla de una base de datos, ya que, al reiniciar el servidor Web, algunos de los valores de SessionID pueden coincidir con los generados antes de que se apagase el servidor. Es nicamente de lectura. Timeout: la propiedad Timeout especifica el intervalo de inactividad para el objeto Session en minutos. Si el usuario no actualiza o solicita una pgina durante ese intervalo, la sesin termina. El valor por defecto de esta propiedad es de 20 minutos, es decir, por defecto la sesin permanecer inactiva 20 minutos. Una sesin se dice que est inactiva mientras el navegador cliente no realice una peticin. El valor de esta propiedad se puede modificar dinmicamente a lo largo de la ejecucin de la aplicacin ASP. CodePage: indica la pgina de cdigos de caracteres que va a ser utilizado. A esta propiedad se le puede asignar un valor entero par especificar la pgina de cdigos que se va a utilizar. As si queremos utilizar el juego de caracteres del alfabeto turco le asignaremos a esta propiedad el valor 1254 ( <% Session.CodePage = 1254 %>). Esta propiedad es tambin de lectura/escritura. LCID (Locale Identifier): propiedad de lectura/escritura, es una abreviatura estndar e internacional que identifica de forma nica la localizacin de los sistemas. Esta localizacin determina la forma en la que se le da formato a las horas y fechas, como se tratan las cadenas de caracteres y los diferentes elementos del alfabeto. As si queremos establecer la propiedad LCID para la regin de Rusia, le debemos asignar a esta propiedad el valor 1049 ( <% Session.LCID = 1049 %> ).

Las ltimas dos propiedades han sido incluidas con la versin 2.0 de ASP. Se puede configurar si queremos utilizar el estado de sesin o no, mediante el Administrador de servicios de Internet. Pulsamos sobre la aplicacin con el botn derecho del ratn y seleccionamos la opcin de men propiedades, aparecern las hojas de propiedades del directorio como se ve en la Figura 9.

58

Grupo EIDOS

3. Modelo de objetos de ASP. Parte II

Figura 9

En el epgrafe denominado configuracin de aplicacin podemos observar un botn etiquetado como Configuracin, si lo pulsamos aparece una nueva ventana de la que elegiremos la pestaa etiquetada como opciones de aplicacin. Ver Figura 10. Desde esta hoja de propiedades podemos configurar algunos parmetros de nuestra aplicacin ASP, entre ellos el que nos interesa, es decir, la posibilidad de habilitar o deshabilitar el estado de la sesin.

Figura 10

59

Desarrollo de aplicaciones COM+ para Internet / Intranet con ASP 3.0

Grupo EIDOS

Adems podemos configurar la propiedad Timeout de la sesin y el lenguaje del intrprete de comandos por defecto. Tambin podemos habilitar o deshabilitar el almacenamiento en bfer. Los valores que especifiquemos en esta pantalla se pueden sobreescribir desde el cdigo ASP indicando los valores de las propiedades o directivas de procesamiento correspondientes

Mtodos del objeto Session


Este objeto posee un nico mtodo: el mtodo Abandon. Al lanzar sobre el objeto Session el mtodo Abandon, se destruyen todas las variables de la sesin y se liberan sus recursos, finalizando la misma. Si no se llama explcitamente al mtodo Abandon, el servidor destruir los objetos cuando la sesin caduque, atendiendo al valor de la propiedad Timeout. La destruccin del objeto Session no se har efectiva hasta que el servidor no haya terminado de ejecutar la pgina ASP. Por lo tanto las variables del objeto Session existirn mientras no se cargue otra pgina. El servidor crear un nuevo objeto Session al abrir una nueva pgina ASP despus de abandonar la sesin.

Eventos del objeto Session


Al igual que ocurra en el objeto Application, el objeto Session objeto posee dos eventos: el inicio de sesin, Session_OnStart, y el fin de sesin Session_OnEnd. El inicio de sesin se produce cuando el usuario carga la primera pgina se una aplicacin ASP. Dentro de este evento se debern indicar las acciones a llevar a cabo antes de que se cargue la primera pgina de una aplicacin ASP. Este evento se suele utilizar para inicializar las variables para toda la sesin, as por ejemplo, si la aplicacin ASP va a manipular una serie de tablas de una base de datos, se podr crear una conexin con la base de datos en el evento de inicio de sesin y almacenarla en el objeto Session para que est disponible para ese usuario mientras su sesin permanezca activa. Tambin se puede utilizar para cargar una serie de variables que definan el perfil del usuario que se acaba de conectar. El fin de la sesin, es decir, el evento Session_OnEnd, se puede producir porque se haya caducado la sesin al permanecer inactiva el tiempo indicado por su propiedad Timeout, o bien, se puede forzar mediante a una llamada al mtodo Abandon. Cuando el usuario cierra el navegador no se ejecuta el evento Session_OnEnd de forma inmediata, sino que se ejecutar cuando se cumpla el Timeout correspondiente, para la aplicacin ASP es igual que el usuario se encuentre con la pgina cargada en el navegador sin realizar ninguna peticin o que el usuario haya cerrado su sesin del navegador, lo que se tiene en cuenta es el tiempo de inactividad de la sesin del usuario. Sin embargo una llamada a Session.Abandon lanza el evento Session_OnEnd de manera inmediata. Al igual que ocurra con el objeto Application, los procedimientos para el tratamiento de estos eventos se deben incluir en el ya conocido fichero de aplicacin GLOBAL.ASA.

60

Grupo EIDOS

3. Modelo de objetos de ASP. Parte II

En el evento Session_OnEnd slo estn disponibles los objetos Application, Server y Session, y tampoco se puede utilizar el mtodo MapPath del objeto Server. En el evento Session_OnStart se tiene acceso a todos los objetos integrados de ASP.

El objeto Server
El objeto Server nos permite ampliar las capacidades de las pginas ASP mediante la posibilidad de la creacin y utilizacin de objetos externos y componentes en el lenguaje de secuencias de comandos. El objeto Server est diseado para realizar tareas especficas en el servidor. Adems de la posibilidad de instanciar componentes el objeto Server ofrece una serie de mtodos muy tiles como pueden se los que permiten dar formato URL o HTML a cadenas de caracteres, los que modifican la lnea de ejecucin de un script de una pgina con la posibilidad de ejecutar distintas pginas, y tambin existe un mtodo utilizado para el tratamiento de errores dentro de ASP, etc. Todos estos mtodos los veremos en el presente captulo. En algunas definiciones del objeto Server se suele indicar tambin que nos permite acceder a los recursos del servidor, en cierto modo esto es correcto ya que para poder instanciar un componente debe encontrarse registrado en el servidor Web.

Propiedades del objeto Server


El objeto Server posee una nica propiedad ScriptTimeout que es de lectura/escritura. La propiedad ScriptTimeOut expresa en segundos el periodo de tiempo durante el que puede ejecutarse una secuencia de comandos (script) antes de que termine su intervalo de espera. El intervalo de espera de la secuencia de comandos no tendr efecto mientras haya un componente del servidor en proceso. Las modificaciones sobre la propiedad ScriptTimeOut del objeto Server se aplican nicamente a la pgina actual. Puede ser interesante aumentar el valor de esta propiedad en el caso de pginas que tarden mucho tiempo en ejecutarse debido a su complejidad, ya que si las secuencias de comandos de una pgina tardan en ejecutarse ms tiempo que el especificado en la propiedad ScriptTomeOut se producir un error. La propiedad ScriptTimeOut es una forma de evitar que el servidor Web se sobrecargue son pginas ASP que presentan tiempo de ejecucin excesivo. El valor por defecto que posee esta propiedad es de 90 segundos, el valor por defecto se puede modificar a travs del Administrador de servicios de Internet para que sea aplicable a todas las pginas ASP que componen una aplicacin ASP determinada, es decir, se puede definir un valor por defecto de la propiedad ScriptTimeout para cada aplicacin ASP. La forma de modificar el valor por defecto de la propiedad ScriptTimeout es acudiendo a las propiedades de la carpeta que contiene la aplicacin ASP dentro del Administrador de servicios de Internet. Pulsamos el botn de Configuracin y accedemos a la pestaa Opciones de la aplicacin. En esta ventana podemos ver un parmetro denominado Tiempo de espera de archivo de comandos ASP, este ser el parmetro que defina el valor predeterminado de la propiedad ScriptTimeout.

61

Desarrollo de aplicaciones COM+ para Internet / Intranet con ASP 3.0

Grupo EIDOS

Mtodos del objeto Server


Tiene los siguientes mtodos: CreateObject: mtodo por excelencia del objeto Server, crea una instancia de un componente. Este componente debe estar registrado en el servidor Web. HTMLEncode: devuelve una cadena codificada en HTML a partir de la cadena que se le pasa como parmetro. MapPath: devuelve la ruta fsica de una ruta virtual dada a travs de una cadena en formato URL. URLEncode: devuelve una cadena a la que se le ha aplicado la codificacin URL correspondiente a las cadenas de consulta (QueryString). URLPathEncode: devuelve una cadena a la que se le ha aplicado la codificacin URL correspondiente a las cadenas de rutas. Execute: para la ejecucin de la pgina actual y transfiere la ejecucin a la pgina indicada. Una vez que ha finalizado la ejecucin de la nueva pgina, la ejecucin contina en la pgina inicial. Transfer: finaliza la ejecucin de la pgina actual y transfiere la ejecucin a la pgina indicada por parmetro. Sin volver en ningn caso a la pgina original. GetLastError: devuelve una referencia al objeto ASPError que contiene la informacin detallada del ltimo error que se ha producido.

Los cuatro ltimos mtodos han sido aadidos en la versin 3.0 de ASP. El mtodo ms utilizado del objeto Server es, posiblemente, el mtodo CreateObject. Este mtodo permite la instanciacin de componentes de servidor, para que a continuacin sean manipulados por las secuencias de comandos de nuestras pginas ASP. Para crear una instancia de un componente de servidor se debe utilizar la sintaxis general del Cdigo fuente 42.

Set nombreObjeto=Server.CreateObject(ProgID) Cdigo fuente 42

La palabra reservada Set siempre se debe utilizar en la instanciacin de un objeto y ProgID es el nombre con el que est registrado el objeto en el servidor, el formato para ProgID es: [Fabricante.]Componente[.Versin]. As por ejemplo el ProgID de el objeto Recordset del modelo de objetos de acceso a datos ActiveX Data Objects (ADO) es ADODB.Recordset. La variable nombreObjeto debe tener un nombre distinto de cualquiera de los objetos integrados de ASP. Se puede destruir un objeto asignndole Nothing, con el Cdigo fuente 43.De esta forma se libera la memoria ocupada por el objeto.

62

Grupo EIDOS

3. Modelo de objetos de ASP. Parte II

<%Set nombreObjeto=Nothing%> Cdigo fuente 43

Las instancias de un objeto, por defecto, se destruyen cuando la pgina ASP termina de ser procesada, aunque es ms seguro destruirlas mediante la palabra reservada Nothing. Para crear un objeto con mbito de sesin o de aplicacin se debe almacenar el objeto en una variable de sesin o de aplicacin, o bien utilizando la etiqueta de HTML <OBJECT> en el fichero global.asa y asignando al parmetro SCOPE los valores Session o Application, como vimos en el captulo anterior. De esta forma el objeto se destruir cuando haya finalizado la sesin o la aplicacin. No es demasiado recomendable utilizar objetos a nivel de sesin o aplicacin, y si se utilizan se deben destruir cuanto antes, ya que pueden suponer una gran carga para la memoria del servidor Web. Es preferible crear y destruir un objeto varias veces que llevar su referencia almacenada en una variable de sesin o de aplicacin. El mtodo MapPath devuelve la ruta fsica que se corresponde con el la ruta virtual que se le pasa por parmetro. El objeto Server posee informacin sobre los directorios fsicos, virtuales y relativos de la mquina servidor y sabe como debe realizar la traduccin de rutas virtuales a fsicas. Se puede necesitar obtener rutas fsicas cuando se quieran crear directorios o manipular ficheros en el servidor. La forma ms frecuente de utilizar este mtodo es la del Cdigo fuente 44, que devuelve la ruta fsica de la carpeta en que se encuentra la pigna ASP en ejecucin.

nombreVariable=Server.MapPath(rutaVirtual) Cdigo fuente 44

Se recomienda por eficiencia evitar el uso del mtodo MapPath, cada llamada a este mtodo supone una nueva conexin al servidor Web para que IIS devuelva la ruta actual del servidor. En su lugar es ms rpido utilizar la ruta literal, si se conoce. Cuando tratamos el objeto Response en su captulo correspondiente vimos que presentaba un mtodo llamado Redirect que nos permita pasar a ejecutar una pgina distinta, pero esto supona enviar una respuesta al cliente para indicarle la carga de una nueva pgina, que es la pgina a la que pasamos la ejecucin. La utilizacin del mtodo Redirect es bastante costosa y problemtica ya supone un envo de informacin ms del servidor al cliente para indicarle mediante una cabecera HTTP de redireccin que la pgina ha cambiado de localizacin, siendo la nueva localizacin la pgina que deseamos cargar. Esto es problemtico ya que en algunos navegadores como Netscape Communicator aparace un mensaje del tipo El objeto requerido se ha movido y se puede encontrar aqu, esto tambin ocurre cuando la conexin la realiza el cliente a travs de proxy. Pero mediante los mtodos Execute y Transfer podemos evitar esta redireccin, que como hemos visto, tiene lugar en el cliente. Estos dos mtodos permiten que la redireccin tenga lugar en el servidor, quedando el cliente completamente ajeno. Ambos mtodos reciben como parmetro la ruta de la pgina a la que queremos redirigir al cliente.

63

Desarrollo de aplicaciones COM+ para Internet / Intranet con ASP 3.0

Grupo EIDOS

La utilizacin del mtodo Execute es muy similar a realizar una llamada a un procedimiento o funcin. Cuando lanzamos el mtodo Execute se empieza a ejecutar la pgina que indicamos por parmetro, y cuando termina la ejecucin de esta nueva pgina, el control pasa a la siguiente sentencia despus de la llamada al mtodo Execute en la pgina inicial, siguiendo a partir de aqu con la ejecucin de la pgina, es decir, el navegador del cliente recibe una salida formada por la combinacin de la ejecucin de ambas pginas. El cliente ni siquiera observa la URL correspondiente a la segunda pgina, ya que la redireccin entre pginas se produce en el servidor. El navegador cree que sigue recibiendo todava la pgina original que habia demandado, incluso en la barra de direcciones del navegador sigue apareciendo la misma URL y los botones Atrs y Adelante funcionan correctamente. En ambos mtodos se mantiene el contexto de la pgina inicial, es decir, en la nueva pgina tenemos acceso a los mismos objetos intrnsecos de ASP (Request, Session, Response...) de la pgina inicial o pgina de origen. Es decir, la coleccin Request.Form de la segunda pgina coincide con la de la primera. El mtodo Transfer tambin permite la redireccin entre pginas en el servidor, pero este mtodo se comporta de distinto modo al mtodo Execute, al lanzar este mtodo se pasa la ejecucin a la nueva pgina, pero una vez que finaliza la ejecucin de la misma no se vuelve a la pgina inicial, como ocurra con el mtodo Execute. El mtodo Transfer es bastante ms parecido al mtodo Redirect que lo era el mtodo Execute, ya que con Transfer al igual que con Redirect no se regresa a la pgina original. Con el mtodo Transfer se sigue manteniendo el contexto de la pgina inicial entre las distintas pginas. La nica diferencia es que la ejecucin finaliza cuando termina la ejecucin de la segunda pgina, y no se vuelve a la inicial. Mediante el uso del mtodo GetLastError podemos tener acceso a toda la informacin referente al ltimo error que se ha producido en la pgina ASP actual. Pero es necesario aclarar que su utilizacin no es similar al tratamiento de errores que realizbamos con la sentencia On Error Resume Next y el objeto Err de VBScritp, que preguntbamos por la propiedad Number del objeto Err para averiguar si se haba producido algn error. El mtodo GetLastError se puede utilizar nicamente dentro de una pgina de error personalizada, es decir, cuando el error ya se ha producido y lo ha detectado el servidor Web. Mediante el servidor Web Internet Information Server 5 podemos indicar las pginas de error personalizadas y es en estas pginas dnde podemos hacer uso de este mtodo. El mtodo GetLastError devuelve un nuevo objeto del modelo de objetos de ASP llamado ASPError, son las propiedades de este nuevo objeto las que nos permiten acceder de forma detallada a toda la informacin referente al error que se ha producido.

El objeto ObjectContext
Este objeto integrado se incluy en la versin 2.0 de las pginas ASP. Este objeto se ofrece gracias a la integracin que presentaban dentro de Windows NT el servidor Web IIS4 (Internet Information Server 4) con el servidor de transacciones MTS 2.0 (Microsoft Transaction Server). A travs del objeto integrado ObjectConext podremos tratar y gestionar las transacciones que se realicen en nuestras pginas ASP, pudiendo construir, por tanto, pginas ASP transaccionales.

64

Grupo EIDOS

3. Modelo de objetos de ASP. Parte II

Esta integracin entre el servidor Web y el servidor de transacciones sigue existiendo, pero ahora el servidor Web se encuentra en su nueva versin IIS5 y el servidor de transacciones ya no se denomina MTS sino que se encuentra integrado en lo que en Windows 2000 se denomina Servicios de componentes, se puede decir que IIS y los Servicios de componentes funcionan conjuntamente para formar la arquitectura bsica para la creacin de aplicaciones Web y para coordinar el proceso de transacciones para las aplicaciones ASP transaccionales. A travs del objeto ObjectConext podremos deshacer o llevar a cabo las transacciones gestionadas por los Servicios de componentes. Recordemos que una transaccin es una operacin que se debe realizar de forma completa, es decir, si falla una parte de la transaccin se deben deshacer todos los cambios. Un ejemplo tpico de una transaccin es la transferencia de una cuenta bancaria a otra, las operaciones de que implican restar el capital de una cuenta y aadirlo a otra se deben ejecutar dentro de una transaccin, si falla alguna de las dos se debe devolver al sistema a su estado inicial. Las transacciones ofrecen una serie de caractersticas comunes conocidas como propiedades ACID (Atomicity, Consistency, Isolation, Durability). Para indicar la naturaleza transaccional de una pgina ASP debemos incluir, como primera lnea de la pgina, la directiva de procesamiento TRANSACTION, como en el Cdigo fuente 45.

<%@ TRANSACTION = valor %> Cdigo fuente 45

Donde el argumento valor define el comportamiento transaccional de la pgina ASP actual y puede tomar uno de los siguientes valores: Requires_New: se requiere una nueva transaccin, por lo que siempre se iniciar una nueva transaccin para las pginas ASP con este valor. Esta configuracin es recomendable para pginas que debe realizar transacciones pero que siempre deben estar separadas del resto. Required: se requiere una transaccin, si no hay una iniciada, se iniciar una nueva. La pgina ASP siempre se ejecutar en una transaccin ya sea iniciada por ella misma o bien aprovechando una transaccin ya existente. Supported: soporta transacciones, pero no iniciar ninguna en el caso de que no exista. En algunos casos la pgina ASP se ejecutar en una transaccin y en otros no, ya que slo utiliza transacciones existentes. Not_Supported: no soporta transacciones, es el valor por defecto. La pgina ASP nunca participar en ningn tipo de transaccin. Disabled: se ignorarn los requerimientos transaccionales de la pgina ASP. La diferencia con el caso anterior, es que con Not_Supported la pgina ASP siempre se ejecutar en un nuevo contexto, y con Disabled, si existe un contexto se utilizar el mismo.

A travs del objeto ObjectContext podremos construir pginas ASP transaccionales, pero evidentemente, cuando se realicen operaciones que puedan tener una naturaleza transaccional, como puede ser el acceso a bases de datos. Adems, una transaccin no puede abarcar varias pginas ASP, a no ser que hagamos uso de los mtodos Transfer o Execute del objeto Server, ya comentamos que con

65

Desarrollo de aplicaciones COM+ para Internet / Intranet con ASP 3.0

Grupo EIDOS

estos mtodos de ejecucin entre pginas se conserva el contexto de la pgina inicial, en este contexto se encuentra incluido las transacciones. Hay que tener en cuenta, adems, que la mayora de las aplicaciones ASP slo requieren hacer uso de un contexto transaccional en determinadas operaciones. As por ejemplo, una aplicacin de una Lnea de Autobuses podra hacer uso de pginas ASP transaccionales para la venta de billetes y la reserva de asientos, dejando el resto de tareas fuera del contexto transaccional.

Mtodos del objeto ObjectContext


Para gestionar la transaccin de una pgina ASP y poder indicar si se debe llevar a cabo la misma (commit) o bien se deben deshacer los cambios y volver al estado anterior (rollback) debemos hacer uso de los dos mtodos del objeto ObjectContext. En algn momento debemos determinar si las operaciones que deba realizar una pgina ASP se han realizado con xito, y por tanto, se puede llevar a cabo la transaccin correspondiente. Igualmente debemos disponer de algn mtodo que nos permita anular una transaccin en el caso de que falle alguna de las operaciones implicadas en la misma. Para ello disponemos de dos mtodos del objeto ObjectContext: SetComplete: indica que se puede llevar a cabo la transaccin correspondiente al realizarse con xito las operaciones que deba llevar a cabo la pgina ASP. Es decir, una llamada a este mtodo equivaldra a realizar un commit dentro de SQL Server o del gestor de bases de datos correspondiente. SetAbort: indica que algo ha fallado en las operaciones implicadas en la transaccin, una llamada a este mtodo cancela la transaccin y deshace los cambios que se hayan podido realizar. Sera equivalente a realizar una llamada a RollBack en SQL Server.

En el caso de que finalice el procesamiento de la pgina ASP y no se haya realizado ninguna llamada a alguno de los dos mtodos anteriores, se considerar que no se ha producido ningn problema en el procesamiento de la pgina y, por lo tanto, se llamar automticamente al mtodo SetComplete.

Eventos del objeto ObjectContext


El objeto ObjectContext ofrece dos eventos que indican la forma en la que ha finalizado la transaccin. Esto es bastante til para obrar en consecuencia, es decir, si se ha abortado una transaccin o se ha realizado con xito se debern hacer unas operaciones u otras. O si lo queremos podemos no utilizar estos eventos. Los eventos del objeto ObjectContext se describen a continuacin: OnTransactionCommit: este evento se dispara cuando se llev a cabo de una transaccin de manera satisfactoria con la llamada al mtodo SetComplete. OnTransactionAbort: este evento se disparar tras la cancelacin de una transaccin con el mtodo SetAbort.

El uso de estos dos eventos, nos permitir realizar diferentes tratamientos segn se haya finalizado la transaccin, es decir, si se ha producido con xito , o por el contrario se han producido errores y se ha tenido que deshacer.
66

Grupo EIDOS

3. Modelo de objetos de ASP. Parte II

El objeto ASPError
Este objeto es le nuevo objeto integrado que aparece en ASP 3.0. La funcin del objeto ASPError es la de ofrecer de forma detallada toda la informacin relativa al ltimo error que se ha producido dentro de una aplicacin ASP, describe el error que se ha producido, la naturaleza y fuente del mismo, y si es posible el cdigo fuente que caus el error. Para ello el objeto ASPError consta de nueve propiedades de slo lectura, y no ofrece ningn mtodo. Una referencia al objeto ASPError la obtenemos a travs de un nuevo mtodo del objeto Server, el mtodo GetLastError que ya comentamos en el captulo correspondiente, la sintaxis de este mtodo es la del Cdigo fuente 46.

Set objASPError=Server.GetLastError() Cdigo fuente 46

Ahora bien, el mtodo GetLastError del objeto Server no se puede utilizar de forma indiscriminada en cualquier lugar de nuestro cdigo para consultar si se ha producido un error, nicamente se puede utilizar de forma satisfactoria dentro de una pgina ASP de error personalizado. Si desactivamos el tratamiento de errores predeterminado que presenta ASP mediante la sentencia On Error Resume Next, al igual que se hacia anteriormente para consultar la propiedad Number del objeto Error, e intentamos lanzar el mtodo GetLastError para obtener una referencia al objeto ASPError, esta llamada fallar y el mtodo no podr acceder a los detalles del error que se ha producido.

Propiedades del objeto ASPError


El objeto ASPError no ofrece ni eventos ni mtodos nicamente ofrece propiedades y todas de lectura. Estas propiedades contienen la informacin detallada relativa al ltimo error de ASP que se ha producido en una aplicacin. Las propiedades del objeto ASPError las consultaremos cuando se haya producido un error, cada una de ellas tiene un significado determinado que se pasa a exponer a continuacin: ASPCode: un entero generado por IIS (Internet Information Server) y que representa un cdigo de error de ASP. ASPDescription: una cadena que es una descripcin detallada del error si est relacionado con ASP. Category: cadena que indica si se trata de una error interno de ASP, del lenguaje de secuencia de comandos o de un objeto. Column: entero que indica la posicin de la columna del archivo ASP que gener el error. Description: cadena que contiene una breve descripcin del error. Tiene el mismo significado que la propiedad Description del objeto Err. File: cadena que contiene el nombre del archivo ASP que se estaba procesando cuando se produjo el error.
67

Desarrollo de aplicaciones COM+ para Internet / Intranet con ASP 3.0

Grupo EIDOS

Line: entero que se corresponde con el nmero de lnea del archivo ASP que gener el error. Number: entero que representa un cdigo de error estndar de COM. Tiene el mismo significado que la propiedad Number del objeto Err. Source: cadena que contiene el cdigo fuente real, si est disponible, de la lnea que caus el error.

Como se puede observar podemos obtener una informacin bastante ms precisa que con el objeto Err de VBScript.

68

Componentes de Servidor
Introduccin
Hemos visto los componentes integrados dentro de ASP y que forman parte del modelo de objetos de ASP y los componentes que ofrece el motor de secuencias de comandos de ASP contiene una serie de componentes que ofrecen una serie de funciones que liberan al programador de implementarlas, estas funciones pueden ser tareas comunes que se deban realizar dentro de un desarrollo en el entorno Web. Estos componentes estn diseados para ejecutarse en el servidor Web como parte de una aplicacin basada en ASP. Estos componentes se denominan componentes ActiveX Server o componentes de servidor, y anteriormente eran conocidos como servidores de automatizacin. Los componentes ActiveX Server se invocan desde pginas ASP (en nuestro caso), pero tambin pueden ser llamados desde otros orgenes, como por ejemplo aplicaciones ISAPI, desde otro componente de servidor o desde otros lenguajes OLE compatibles. Los componentes de servidor son ficheros DLL que se ejecutan en el mismo espacio de direcciones de memoria que las pginas ASP y el servidor Web Internet Information Server. Los componentes ActiveX Server que se encuentran incluidos dentro de ASP en su versin 3.0 y que se van a comentar en este tema son: Componente de acceso a bases de datos, ADO (ActiveX Data Objects). A travs de la utilizacin de este componente se puede ofrecer acceso a bases de datos desde una pgina ASP, as por ejemplo, se puede mostrar el contenido de una tabla, permitir que los usuarios realicen consultas y otras operaciones sobre una base de datos.

Desarrollo de aplicaciones COM+ para Internet / Intranet con ASP 3.0

Grupo EIDOS

Componente Ad Rotator. Este componente permite mostrar una serie de imgenes alternativas con un vnculo a otra direccin desde la imagen presentada. Este componente se suele utilizar para mostrar diferentes anuncios de forma alternativa dentro de una pgina ASP. Componente Funciones del explorador. A travs de este componentes podemos recuperar datos acerca del tipo de navegador del cliente y que capacidades o funciones tiene. Componente vnculo de contenidos. Facilita el desplazamiento lgico entre las diferentes pginas ASP de una aplicacin ASP. Componente Content Rotator (rotador de contenidos). Este componente permite hacer rotaciones de cadenas de contenido HTML en una pgina. Componente Page Counter (contador de pginas). Permite llevar una cuenta del nmero de veces que se ha accedido a una pgina determinada dentro de nuestro sitio Web. Componente Counters. A travs de este componente podremos almacenar, crear, incrementar y consultar cualquier contador. Componente MyInfo. Nos permite almacenar informacin personal que ser ofrecida por el administrador del sitio Web. Componente Tools. Es el denominado componente de utilidades. Ofrece una serie de funciones diversas, como la generacin de nmeros aleatorios o la comprobacin de la existencia de un fichero en el servidor. Componente Permission Checker. A travs de este componente podremos determinar si a un usuario se le ha dado permisos para acceder a un fichero determinado. Componente Status. Este componente, de momento, nicamente est disponible para el servidor Personal Web Server en plataformas Macintosh, resulta extrao pero es as. Nos ofrece una informacin variada acerca del estado del servidor Web. Componente de registro de IIS. Mediante este componente tenemos acceso a la informacin y manipulacin de los ficheros de registro (log) generados por el servidor Web IIS 5.0.

Para poder utilizar un componente de servidor dentro de una pgina ASP debemos instanciarlo, para ello deberemos utilizar el mtodo CreateObject del objeto Server de la misma forma que lo hacamos con los componentes de VBScript. Tambin se puede crear una instancia de un componente de servidor a travs de la etiqueta <OBJECT> de HTML, como ya vimos en el tema anterior La diferencia entre los dos mecanismos es desde el punto de vista de la eficiencia. Cuando se instancia un objeto con el mtodo Server.CreateObject se crea inmediatamente el objeto, aunque no lo lleguemos a utilizar, sin embargo, si instanciamos el objeto con la etiqueta <OBJECT> el objeto slo se crear en el momento que lo vayamos a utilizar por primera vez. A lo largo de los siguientes apartados del presente captulo vamos a ir comentando los distintos componentes de servidor que se ofrecen junto con la instalacin de ASP.

70

Grupo EIDOS

4. Componentes de Servidor

Componente AdRotator
Este componente de servidor se encarga de rotar una serie de anuncios (imgenes) dentro de una pgina ASP. Cada vez que un usuario vuelva a cargar la pgina el componente AdRotator mostrar una imagen con una URL asociada, atendiendo a un fichero especial denominado fichero de planificacin. Una de las caractersticas de HTML es que permite la creacin de imgenes con vnculos. La etiqueta HTML que permite visualizar una imagen en una pgina es la etiqueta <IMG>. El componente AdRotator genera una etiqueta <IMG> a la que le asigna tambin una URL, al pulsar sobre la imagen se redireccionar al usuario hacia la URL asociada a esa imagen. Para llevar a cabo este proceso el componente AdRotator se sirve de dos ficheros: el fichero de redireccionamiento y el de planificacin. El fichero de redireccionamiento es una pgina ASP que debemos crear si queremos utilizar este componente. Este fichero suele incluir secuencias de comandos para analizar la cadena de consulta enviada por el componente AdRotator y para redirigir al usuario a al direccin URL asociada con el anuncio sobre el que se ha pulsado. En el Cdigo fuente 47,el fichero de redireccin simplemente redirige al usuario a la pgina del anunciante.

<%Response.Redirect(Request.QueryString("url"))%> Cdigo fuente 47

Dentro de la coleccin QueryString, en este caso, podemos encontrar dos variables: url, que indica la URL que tiene asociada la imagen e image, que indica el nombre de la imagen sobre la que se ha pulsado. Como ya se haba comentado con anterioridad, dentro del fichero de redireccionamiento tambin podemos realizar otras tareas adems de redireccionar al navegador a una direccin determinada. Con el Cdigo fuente 48 que se muestra a continuacin se consigue saber el nmero de usuarios que pulsan sobre un anuncio determinado. En este cdigo aparece un par de componentes de VBScript como son el objeto FileSystemObject y TextStream, que nos permiten leer y escribir en un fichero del servidor en el que vamos a almacenar el nmero de usuarios que han pulsado sobre el anuncio nmero dos.

<!--METADATA TYPE="typelib" FILE="C:\Winnt\system32\scrrun.dll"--> <%'Cuenta el nmero de usuarios que han pulsado sobre un anuncio determinado 'el fichero de pulsaciones est en este caso en el mismo directorio 'que la pgina ASP de redireccin nombreFichero=Server.MapPath("pulsaciones.txt") if Request.QueryString("image")="/cursoASP30/images/Anuncio2.gif" Then Set objFSO= Server.CreateObject("Scripting.FileSystemObject") If objFSO.FileExists(nombreFichero) Then 'Se abre el fichero para su lectura Set objTextStream=objFSO.OpenTextFile(nombreFichero) pulsaciones=CInt(objTextStream.ReadLine) pulsaciones=pulsaciones+1 objTextStream.Close Else pulsaciones=1 End If Set objTextStream=objFSO.OpenTextFile(nombreFichero,ForWriting,True) objTextStream.WriteLine pulsaciones objTextStream.Close Set objFSO=Nothing

71

Desarrollo de aplicaciones COM+ para Internet / Intranet con ASP 3.0

Grupo EIDOS

End if Response.Redirect(Request.QueryString("url"))%> Cdigo fuente 48

En la sentencia if...Then... se consulta la variable image de la coleccin QueryString del objeto Request, para comprobar si contiene el nombre del fichero de imagen del segundo anuncio. Si es el anuncio nmero dos, se lee del fichero el nmero actual de usuarios que lo han pulsado y se actualiza este nmero incrementndolo en uno. Este es un ejemplo muy bsico, por que si dos usuarios pulsan a la vez sobre el anuncio nmero dos uno de ellos no se contar. Para evitar este problema se debera guardar el objeto que representa al fichero dentro de una variable del objeto Application, y al ir a utilizar esta variable lanzar sobre el objeto Application los mtodos Lock y UnLock. El fichero de planificacin contiene informacin utilizada por el componente AdRotator para administrar y mostrar las diversas imgenes de los anuncios. En l se especifican los detalles de los anuncios como puede ser tamao, imagen a utilizar, URL asociada, frecuencia de aparicin de cada imagen. Este fichero tiene un formato determinado que se pasa a comentar a continuacin. Se encuentra dividido en dos secciones mediante un asterisco (*). La primera seccin establece los parmetros aplicables a todas la imgenes de los anuncios existentes, y la segunda seccin especifica la informacin de cada imagen individual y el porcentaje de tiempo de presentacin de cada anuncio. En la primera seccin hay cuatro parmetros opcionales y globales, si no se especifica ninguno de estos parmetros la primera lnea del archivo debera empezar por un asterisco. El formato general del fichero de planificacin es el siguiente: REDIRECT url WIDTH ancho HEIGHT alto BORDER borde * Fichero que contiene la imagen Url asociada Texto alternativo Nmero de impactos La primera lnea, REDIRECT url, indica el fichero (pgina ASP) que implementa el redireccionamiento, es decir, indica cual es el fichero de redireccionamiento. Las tres lneas siguientes, pertenecientes a la primera seccin del fichero de planificacin, hacen referencia al aspecto de la imagen: dimensiones y borde. En la segunda seccin tenemos la ubicacin del fichero grfico que representa la imagen a mostrar, a continuacin est la URL a la que ser enviado el navegador cuando el usuario pulse sobre la imagen, esta URL ser la direccin del anunciante, por ejemplo; si el anuncio no tiene ningn vinculo asociado se deber escribir un guin (-). La siguiente lnea contiene el texto alternativo que aparecer cuando el navegador no est habilitado para cargar imgenes o bien el texto que aparecer cuando el cursor del ratn se site sobre la imagen, el equivalente a la propiedad ALT de la etiqueta <IMG>. Por ltimo se debe indicar el nmero relativo de apariciones del anuncio.

72

Grupo EIDOS

4. Componentes de Servidor

En el Cdigo fuente 49 se va a mostrar y comentar un ejemplo de un fichero de planificacin para un componente Ad Rotator.

Redirect redirecciona.asp BORDER 0 * /cursoASP30/images/Anuncio1.gif http://www.almagesto.com Campus Virtual Almagesto 40 /cursoASP30/images/Anuncio2.gif http://www.eidos.es Sitio Web del Grupo EIDOS 30 /cursoASP30/images/Anuncio3.gif http://www.eidos.es/algoritmo Revista Algoritmo 30 Cdigo fuente 49

En este ejemplo el fichero encargado de redireccionar al navegador a la direccin asociada a la imagen que se ha pulsado es la pgina ASP redirecciona.asp. Al no especificarse las dimensiones de la imagen, se tomarn los valores por defecto: WIDTH=440 y HEIGHT=60. Se han utilizado tres imgenes, cuya frecuencia de aparicin ser: para la primera un 40% de las veces que se cargue la pgina, para la segunda un 30% y para la tercera otro 30%. El componente AdRotator adems de estos dos ficheros especiales que ya se han comentado, posee tambin tres propiedades y un mtodo. Sus propiedades son las siguientes: Border: indica el tamao del borde que rodea a la imagen del anuncio, cumple la misma funcin que la lnea BORDER del fichero de planificacin. Clickable: indica si el anuncio es un hipervnculo o no, tendr los valores True o False, respectivamente. TargetFrame: esta propiedad especifica el marco de destino en el que se debe cargar el vnculo. Esta propiedad realiza la misma funcin que el parmetro TARGET de una instruccin HTML de creacin de vnculos.

El nico mtodo que posee este componente ActiveX de servidor es el mtodo GetAdvertisement. A este mtodo se le debe pasar como parmetro el nombre del fichero de planificacin, y la funcin de este mtodo es la de obtener las especificaciones, a partir del fichero de planificacin, para el siguiente anuncio y le da formato de cdigo HTML. Para crear un componente AdRotator cuyo fichero de planificacin se llama planificacion.txt se deber escribir el Cdigo fuente 50.

<%Set anuncios=Server.CreateObject("MSWC.AdRotator")%> <%=anuncios.GetAdvertisement("planificacion.txt")%> Cdigo fuente 50

73

Desarrollo de aplicaciones COM+ para Internet / Intranet con ASP 3.0

Grupo EIDOS

Con el mtodo GetAdvertisement siempre debemos utilizar los delimitadores <%=%> o bien Response.Write, para enviar al navegador el cdigo HTML encargado de mostrar la imagen correspondiente con su vnculo asociado. Si tenemos en cuenta el cdigo anterior y su fichero de planificacin, una posible generacin de cdigo HTML por parte del mtodo GetAdvertisement, podra ser la que se muestra en el Cdigo fuente 51.

<A HREF="redirecciona.asp?url=http://www.eidos.es&image=images/Anuncio2.gif"> <IMG SRC="/cursoASP30/images/Anuncio2.gif" ALT="Sitio Web del Grupo EIDOS" WIDTH=440 HEIGHT=60 BORDER=0></A> Cdigo fuente 51

En la Figura 11 se puede observar como se relaciona el componente AdRotator con todos los ficheros que utiliza.

Figura 11

Componente Funciones del navegador


El componente de funciones del navegador (Browser Capabilities) permite consultar las funciones que posee el navegador Web que ha cargado la pgina ASP. Cuando un navegador se conecta a un servidor Web, le enva automticamente un encabezado HTTP llamado User Agent. Este encabezado es una cadena que identifica el explorador y su nmero de versin. El componente encargado de comprobar las funciones del navegador compara el encabezado User Agent con las entradas de un fichero especial llamado Browscap.ini. Para crear una instancia de este componente deberemos escribir lo que se muestra en el Cdigo fuente 52.

74

Grupo EIDOS

4. Componentes de Servidor

<%Set navegador=Server.CreateObject("MSWC.BrowserType")%> Cdigo fuente 52

El fichero Browscap.ini es un fichero de texto que asigna las propiedades del navegador atendiendo al encabezado HTTP User Agent, este fichero se debe encontrar en el mismo directorio que la librera que contiene al componente, es decir, el fichero BROWSCAP.DLL. Si se encuentra coincidencia entre el encabezado User Agent y una entrada del fichero BROWSCAP.INI, el componente asumir las propiedades del navegador de la lista que coincida con el el encabezado User Agent. Si el componente no encuentra una coincidencia entre el encabezado User Agent y una entrada del fichero BROWSCAP.INI, toma las propiedades predeterminadas del navegador Web. Pero si dentro de BROWSCAP.INI no se han especificado estas propiedades predeterminadas se establecer la cadena UNKNOWN para las propiedades del navegador. Dentro del fichero BROWSCAP.INI se pueden realizar definiciones de propiedades para diferentes navegadores, tambin se pueden establecer valores predeterminados para utilizarlos si el navegador no pertenece a ninguna de las definiciones existentes. Para cada definicin de navegador se debe proporcionar un valor del encabezado User Agent y las propiedades y valores que se desea asociar a ese encabezado. El formato general de este fichero es el siguiente: ;comentarios [EncabezadoHTTPUserAgent] parent = DefinicinExplorador propiedad1 = valor1 propiedadN = valorN [Default Browser Capability Settings] PropiedadPredeterminada1 = ValorPredeterminado1 PropiedadPredeterminadaN = ValorPredeterminadoN Dentro de este fichero los comentarios se indicarn con punto y coma. El encabezado User Agent puede contener comodines utilizando el carcter * para reemplazar cero o ms caracteres. Por ejemplo si escribimos el siguiente valor para el encabezado User Agent: [Mozilla/2.0 (compatible; MSIE 3.0;* Windows 95)] Coincidira con los siguientes encabezados User Agent: [Mozilla/2.0 [Mozilla/2.0 [Mozilla/2.0 [Mozilla/2.0 (compatible; (compatible; (compatible; (compatible; MSIE MSIE MSIE MSIE 3.0; 3.0; 3.0; 3.0; Windows 95)] AK; Windows 95)] SK; Windows 95)] AOL; Windows 95)]

Si se dan varias coincidencias, el componente devolver las propiedades de la primera definicin coincidente. Mediante la propiedad parent, podemos utilizar dentro de una definicin de un navegador todos los valores de las propiedades de otro navegador cuyo nombre se indica en DefinicionExplorador. La
75

Desarrollo de aplicaciones COM+ para Internet / Intranet con ASP 3.0

Grupo EIDOS

definicin del navegador actual heredar todas las propiedades declaradas en la definicin del navegador principal. Esto es til para definir propiedades de una nueva versin de un navegador, ya que las nuevas versiones suelen conservar la mayora de las propiedades de la versin anterior. Estos valores de propiedades heredados se pueden sobreescribir estableciendo un nuevo valor para esa propiedad. El nmero de propiedades a definir puede ser cualquiera, las nicas restricciones es que el nombre de la propiedad debe comenzar por un carcter alfabtico y no puede tener ms de 255 caracteres. Normalmente para cada tipo de navegador solamente se definirn las propiedades que vayan a ser utilizadas. El valor que se le asignar a la propiedad por defecto es una cadena, si se quiere asignar un entero se deber utilizar el signo de nmero (#) y para especificar un valor booleano se utilizar TRUE o FALSE. Con el valor de User Agent [Default Browser Capability Settings] se especifican las propiedades por defecto de un navegador cuya cabecera User Agent no ha coincidido con ninguna de las especificadas en el fichero BROWSCAP.INI. Se debe realizar un mantenimiento del fichero BROWSCAP.INI para tenerlo actualizado con las nuevas versiones de navegadores Web que van apareciendo. Existen un par de direcciones que ofrecen la ltima versin de este fichero: http://www.cyscape.com/browscap y http://www.asptracker.com. En el Cdigo fuente 53 se crea un componente defunciones del navegador y se muestran por pantalla algunas de las caractersticas del navegador del cliente. Si en el servidor Web tenemos el fichero BROWSCAP.INI como se ve en el Cdigo fuente 54.

<%Response.Write("La Cabecera USER_AGENT enviada por el navegador es: "&_ Request.ServerVariables("HTTP_USER_AGENT")&"<br>") Set navegador=Server.CreateObject("MSWC.BrowserType") if navegador.vbscript=TRUE Then Response.Write("Soporta VBScript<br>") if navegador.cookies=TRUE Then Response.Write("Soporta Cookies<br>") if navegador.beta=FALSE Then Response.Write("No es una beta<br>") if navegador.javaapplets=TRUE Then Response.Write("Soporta Java<br>") Response.Write("Plataforma: "&navegador.platform&"<br>") Response.Write("Navegador: "&navegador.browser&navegador.version&"<br>")%> Cdigo fuente 53

;Internet Explorer 4.0 [IE 4.0] browser=IE Version=4.0 cookies=TRUE vbscript=TRUE javascript=TRUE javaapplets=TRUE ActiveXControls=TRUE Win16=False beta=False [Mozilla/4.0 (compatible; MSIE 4.01; Windows 95)] parent=IE 4.0 Version=4.01 platform=Win95 Cdigo fuente 54

76

Grupo EIDOS

4. Componentes de Servidor

Si el navegador que se conecta es el Internet Explorer y enva la cabecera User Agent: Mozilla/4.0 (compatible; MSIE 4.01; Windows 95), el resultado de la ejecucin del Cdigo fuente 53 sera: La Cabecera USER_AGENT enviada por el navegador es: Mozilla/4.0 (compatible; MSIE 4.01; Windows 95) Soporta VBScript Soporta Cookies No es una beta Soporta Java Plataforma: Win95 Navegador: IE4.01 Pero si el navegador que se conecta enva otra cabecera diferente, el navegador no ser reconocido y por lo tanto todas las propiedades se establecern como UNKNOWN, y la salida que devolver la ejecucin del ejemplo anterior sera: La Cabecera USER_AGENT enviada por el navegador es: Mozilla/4.03 [es] (Win95; I) Plataforma: Unknown Navegador: UnknownUnknown

Componente Nextlink
Este componente llamado tambin componente de vinculacin de contenido, tiene como misin gestionar un conjunto de direcciones URL para poder utilizarlas dentro de pginas ASP de forma sencilla, permite tratar las pginas como las de un libro, es decir, ofrece la gestin de una navegacin entre las diferentes pginas ASP de una forma sencilla. Se debe tener en cuenta que el componente de Vinculacin de Contenido trata un sitio Web como si fuera un libro que debe ser ledo desde el principio al final. Sin embargo este no es el comportamiento natural de un sitio Web, ya que su distribucin no es lineal, por lo tanto esta herramienta puede ser necesaria para guiar al usuario a travs de un sitio Web, es decir es una herramienta lineal para un espacio no lineal. El componente Nextlink hace referencia a un fichero especial llamado lista de vnculos, este fichero contiene una lista de las direcciones de las pginas vinculadas, este fichero se debe encontrar en el servidor Web. El fichero de lista de vnculos contiene una lnea de texto por cada direccin URL de la lista. Cada lnea termina con un retorno de carro y cada elemento de una lnea se separa mediante un tabulador. Los vnculos a las pginas que aparece en este fichero deben estar en el orden deseado, como si fuera un libro. El formato de este fichero es el siguiente: URL-Pgina-Web descripcin

No se admiten URLs absolutas, es decir, las que comienzan con "http:","//" o \\. Las URLs utilizadas deben ser relativas con el formato nombreFichero o directorio/nombreFichero. Cuando se debe modificar el orden o el nmero de las pginas de contenido, slo es necesario actualizar la lista de URLs que se encuentra dentro del fichero lista de vnculos y no se tiene que actualizar los vnculos de exploracin de cada pgina. Una ejemplo de un fichero de lista de vnculos podra ser el siguiente:
77

Desarrollo de aplicaciones COM+ para Internet / Intranet con ASP 3.0

Grupo EIDOS

intro.asp cap1.asp cap2.asp cap3.asp

Introduccin a ASP VBScript Objetos Integrados Componentes ActiveX Server

Para tener acceso a las URLs que aparecen especificadas dentro del fichero lista de vnculos, el objeto Nextlink ofrece una serie de mtodos: GetListCount(fichero): devuelve el nmero de vnculos del fichero lista de vnculos. GetNextURL(fichero): obtiene la siguiente URL teniendo en cuenta la pgina actual. Si la pgina actual no est especificada en dicho fichero, GetNextURL devuelve la direccin URL de la ltima pgina de la lista. GetPreviousDescription(fichero): este mtodo devuelve la descripcin del elemento anterior del fichero lista de vnculos, atendiendo a la pgina actual. Si la pgina actual no est en el fichero, se devolver la descripcin del primer elemento de la lista. GetListIndex: devuelve el ndice que corresponde a la pgina actual dentro del fichero lista de vnculos. La primera pgina tendr el ndice 1. Si la pgina actual no existe dentro de la lista de vnculos se devolver 0. GetNthDescription(fichero, indice): devuelve la descripcin correspondiente al elemento de la lista de vnculos cuyo ndice coincide con el ndice que se le pasa como parmetro a este mtodo. GetPreviousURL(fichero): obtiene la URL anterior teniendo en cuenta ja pgina actual. Si la pgina actual no est especificada en dicho fichero, GetPreviousURL devuelve la direccin URL de la primera pgina de la lista de vnculos. GetNextDescription(fichero): este mtodo devuelve la descripcin del siguiente elemento del fichero lista de vnculos, atendiendo a la pgina actual. Si la pgina actual no est en el fichero, se devolver la descripcin del ltimo elemento de la lista de vnculos. GetNthUTL(fichero, indice): devuelve la direccin URL correspondiente al elemento de la lista de vnculos cuyo ndice coincide con el ndice que se le pasa como parmetro a este mtodo.

Todos estos mtodos poseen un parmetro comn que indica la ubicacin del fichero lista de vnculos con el que debe trabajar un componente de vinculacin de contenido. En el Cdigo fuente 55 se muestra como se utilizara este componente para indicar en un pgina un enlace a la pgina siguiente, anterior y para volver a la primera pgina:

<div align="center"> <hr> <%Set vinculos=Server.CreateObject("MSWC.NextLink") listaVinculos="vinculos.txt" If (vinculos.GetListIndex(listaVinculos) > 1) Then %> <a href="<%=vinculos.GetPreviousURL(listaVinculos)%>">Pgina anterior</a>&nbsp; <%End If%> <%If (vinculos.GetListIndex(listaVinculos)<vinculos.GetListCount(listaVinculos)) Then%> <a href="<%=vinculos.GetNextURL(listaVinculos)%>">Pgina siguiente</a>&nbsp;

78

Grupo EIDOS

4. Componentes de Servidor

<%End If%> <a href="<%=vinculos.GetNthURL(listaVinculos,1)%>">Volver Inicio</a> </div> Cdigo fuente 55

Para comprobar si es necesario crear un enlace a la pgina anterior se verifica que la pgina actual no es la primera, esta comprobacin se realiza en el primer If...Then..., y en el segundo If se comprueba si es necesario crear un enlace a la pgina siguiente, para ello se comprueba si la pgina actual es la ltima o no comparando el valor devuelto por el mtodo GetListIndex con el devuelto por GetListCount. Para realizar el enlace a la pgina anterior se utilizar el mtodo GetPreviousURL, para crear el enlace a la pgina siguiente se utiliza GetNextURL y para el enlace de la pgina de inicio se utiliza el mtodo GetNthURL pasndole como parmetro el ndice con valor 1. Este cdigo lo podemos escribir en una pgina llamada pie.asp y realizar un INCLUDE en las pginas correspondientes para que muestren en la parte inferior esta sencilla barra de navegacin. El aspecto sera el de la Figura 12.

Figura 12

En el captulo de introduccin de la lista de vnculos del ejemplo nos puede interesar mostrar un ndice de todo el curso. En el Cdigo fuente 56 se muestra como se creara una tabla de contenidos a partir del fichero lista de vnculos de un componente Nextlink.

<%Set vinculos=Server.CreateObject("MSWC.NextLink") listaVinculos="vinculos.txt" num=vinculos.GetListCount(listaVinculos) i=1 %> ndice: <ul> <%While (i<=num)%> <li> <a href="<%=vinculos.GetNthURL(listaVinculos,i)%>"> <%=vinculos.GetNthDescription(listaVinculos,i)%></a>

79

Desarrollo de aplicaciones COM+ para Internet / Intranet con ASP 3.0

Grupo EIDOS

</li> <%i=i+1%> <%Wend%> Cdigo fuente 56

Para recorrer el fichero lista de vnculos es necesario obtener el nmero de URLs que existen en el fichero, es decir, el nmero de enlaces, para ello utilizamos el mtodo GetListCount, para acceder a cada elemento del fichero deberemos utilizar un bucle While. Dentro de este bucle se lanza el mtodo GetNthURL, para obtener la URL cuyo ndice se corresponde con el valor del contador del bucle, tambin se lanza el mtodo GetNthDescription para obtener la descripcin correspondiente. El aspecto que se correspondera con el ejemplo de fichero de vnculos anterior sera el de la Figura 13.

Figura 13

Componente Content Rotator


Este es uno de los componentes de servidor que se incluy con la versin 2.0 de ASP. Su finalidad es similar al componente Ad Rotator (rotador de anuncios) que ya habamos comentado en este captulo. Pero este nuevo componente no permite slo alternar diferentes imgenes con enlaces atendiendo a una determinada frecuencia, sino que permite mostrar cualquier contenido HTML que ir apareciendo atendiendo a la frecuencia establecida en el fichero de planificacin correspondiente, al igual que ocurra con la frecuencia asignada a las imgenes del componente AdRotator.

80

Grupo EIDOS

4. Componentes de Servidor

El fichero de planificacin para este componente es un fichero de texto que debe estar disponible en una ruta virtual del servidor Web y puede incluir cualquier nmero de entradas de cadenas de contenido HTML, por ello tambin se le denomina fichero de contenido. Cada entrada se compone de dos partes: una lnea que empieza por dos signos de porcentaje (%%) seguida, de manera opcional, por un nmero entre 0 y 65.535 que indica el peso relativo de la cadena de contenido HTML y unos comentarios acerca de la entrada. La segunda parte de la entrada contiene la cadena de contenido HTML propiamente dicha (texto, imgenes, hipervnculos...). La sintaxis de estas entradas sera: %% [#Peso] [//Comentarios] CadenaContenido En el Cdigo fuente 57 se ofrece un ejemplo de fichero de planificacin para el componente Content Rotator.

%% 2 // Esta es la primera lnea del fichero de contenidos. <A HREF = "http://www.eidos.es"><img src="images/eidosportada.jpg"></A> %% 4 // Segunda Lnea. <B>Cursos - Internet</B> <UL> <LI>Programacin de aplicaciones para Internet con ASP. <LI>Lenguaje HTML. <LI>La Especificacin CGI. <LI>JavaScript. </UL> Cdigo fuente 57

La probabilidad de que el objeto presente una determinada cadena de contenido se expresa como el peso asociado a dicha cadena dividido por la suma de todos los pesos de las distintas entradas del fichero de contenido. As, para el fichero de ejemplo, el componente Content Rotator presentar la primera cadena de contenido una tercera parte del tiempo, y la segunda las dos terceras partes del tiempo. Un peso 0 har que se pase por alto la entrada, y si no se especifica peso para una entrada determinada se asume que su peso es 1. El componente Content Rotator, para recuperar las cadenas de contenido del fichero de planificacin, dispone de dos mtodos: ChooseContent(fichero): recupera una cadena de contenido HTML del archivo de contenidos y la presenta en la pgina actual. Este mtodo recuperar una nueva cadena de contenido cada vez que se cargue la pgina. GetAllContent(fichero): recupera todas las cadenas de contenido del archivo de contenidos y las escribe directamente en la pgina como una lista con una etiqueta <HR> despus de cada entrada.
81

Desarrollo de aplicaciones COM+ para Internet / Intranet con ASP 3.0

Grupo EIDOS

En el Cdigo fuente 58 vamos a ver un ejemplo de cmo se recuperara el contenido del fichero CONTENIDO.TXT, haciendo uso del mtodo ChooseContent().

<%Set objContenido = Server.CreateObject("MSWC.ContentRotator")%> <%=objContenido.ChooseContent("contenido.txt")%> Cdigo fuente 58

Cada vez que el usuario ejecute la secuencia de comandos anterior, se visualizar una de las dos cadenas de contenido HTML incluidas en el fichero de planificacin CONTENIDO.TXT, como se ve en la Figura 14.

Figura 14

En el Cdigo fuente 59 podemos ver otro ejemplo haciendo uso del mtodo GetAllContent para representar todas las cadenas de contenido incluidas en el fichero CONTENIDO.TXT.

<B>Cadenas de contenido HTML incluidas en "contenido.txt":</B> <%Set objContenido = Server.CreateObject("MSWC.ContentRotator")%> <%=objContenido.GetAllContent("contenido.txt")%> Cdigo fuente 59

El resultado de la ejecucin de la secuencia de comandos anterior sera el mostrado en la Figura 15.

82

Grupo EIDOS

4. Componentes de Servidor

Figura 15

Componente Pagecounter
Este componente nos permite llevar la cuenta del nmero de veces que una pgina Web ha sido abierta. El componente guarda el nmero de visitas que se han realizado en una pgina determinada y lo almacena peridicamente en un archivo de texto. Al guardarse la cuenta de visitas por pgina en un fichero de texto, si por ejemplo se resetea el servidor los datos no se perdern. Este fichero de texto se llama HITCNT.CNT y se encuentra en el directorio c:\winnt\system32\inetsrv\data, un ejemplo de contenido de este fichero es: 21 5 0 12 3 2 0 /cursoasp30/pagecounter.asp /cursoasp30/adrot.asp adrot.asp /cursoasp30/page/visitas.asp /cursoASP30/page/adrot.asp /cursoASP30/page/pagecounter.asp /cursoASP30/page/Rec.asp

El fichero HITCNT.CNT se crear o actualizar cuando se ejecute el evento Application_OnEnd del fichero GLOBAL.ASA de la aplicacin ASP correspondiente. Este componente tambin fue incluido con la versin 2.0 de ASP. El componente contador de pginas se instancia de la forma que indica el Cdigo fuente 60.
83

Desarrollo de aplicaciones COM+ para Internet / Intranet con ASP 3.0

Grupo EIDOS

<%Set ObjetoContador = Server.CreateObject("MSWC.PageCounter")%> Cdigo fuente 60

Los mtodos de los que dispone el objeto Page Counter son los que se comentan a continuacin: Hits(rutapagina): devuelve un valor LONG representado el nmero de veces que se ha abierto una pgina Web determinada. Este mtodo puede recibir como parmetro la ruta de la pgina a la que se le va a llevar la cuenta. Si se omite este parmetro el mtodo devolver el nmero de visitas de la pgina actual. PageHit(): Incrementa el nmero de visitas a la pgina actual. Sintaxis. Reset(rutapagina): Pone a 0 el nmero de visitas de la pgina cuya ruta se le pasa como parmetro. Si no se especifica ninguna pgina en el parmetro, se pondr a 0 el nmero de visitas de la pgina actual.

En el Cdigo fuente 61 un ejemplo del uso de este componente en el que nos vamos a fabricar un contador de visitas para la pgina actual. Guardaremos la pgina como CONTADOR.ASP:

<% Set Contador = Server.CreateObject("MSWC.PageCounter")%> <b>Nmero de visitas:<%=Contador.Hits%> <%Contador.PageHit 'incrementamos el contador en uno cada vez que se cargue la pgina%> Cdigo fuente 61

En cualquier momento, desde otra pgina podremos conocer el nmero de visitas de la pgina anterior. Suponiendo que dicha pgina se encuentra en la ruta virtual "/CursoASP30/pagecounter.asp", visualizaramos su nmero de visitas como se indica en el Cdigo fuente 62.

<b>El nmero de visitas de la pgina Contador.asp es: <%=Contador.Hits("/CursoASP30/pagecounter.asp")%> Cdigo fuente 62

La ruta que se indica en los mtodos Hits() y Reset() del objeto PageCounter debe iniciarse siempre con /, es decir, debe partir desde la raz del sitio Web. Si queremos registrar las visitas realizadas a todas las pginas ASP mediante este componente, podemos construirnos la pgina ASP que se muestra en el Cdigo fuente 63, que se utilizara como un INCLUDE en todas las pginas.

<%Set Contador=Server.CreateObject("MSWC.PageCounter") Contador.PageHit Set Contador=Nothing%> Cdigo fuente 63

84

Grupo EIDOS

4. Componentes de Servidor

Siguiendo este ejemplo vemos que sera muy fcil realizar una pgina ASP que contenga una tabla informativa de las visitas que han recibido todas las pginas del Web con contadores de un sitio Web determinado. En este nuevo ejemplo del objeto Page Counter vamos a mostrar el nmero de visitas que han tenido las pginas contenidas en un directorio determinado de nuestro sitio Web. Para ello vamos hacer uso de los ya conocidos componentes de acceso al sistema de ficheros. Veamos el Cdigo fuente 64 de este pgina.

<%strDirectorio="/cursoASP30/page" 'creamos un objeto PageCounter Set Contador = Server.CreateObject("MSWC.PageCounter") 'en esta mismo pgina tambin se registran sus visitas Contador.PageHit Set objFSO=Server.CreateObject("Scripting.FileSystemObject") 'obtnemos una refencia a la carpeta dnde estn las pginas Set objFolder=objFSO.GetFolder(Server.MapPath(strDirectorio)) 'obtenemos los ficheros de la carpeta Set colFiles=objFolder.Files 'se recorren los ficheros For each objFile in colFiles 'se recupera el nombre para obtener despus el n de visitas strNombreFichero=objFile.Name Response.Write strNombreFichero&" --nmero de visitas: "&_ Contador.Hits(strdirectorio&"/"&strNombreFichero)&"<br>" Next%> Cdigo fuente 64

Se supone que todas las pginas mostradas deben registrar mediante el mtodo PageHit() que un usuario a cargado la pgina, sino parecer siempre cero en su nmero de visitas. En la Figura 16 se puede observar la ejecucin del cdigo anterior.

Figura 16

85

Desarrollo de aplicaciones COM+ para Internet / Intranet con ASP 3.0

Grupo EIDOS

Componente Counters
Este componente nos permite crear, manipular y almacenar cualquier nmero de contadores individuales a travs de una instancia del mismo. Slo necesitamos crear un nico objeto Counters en el sitio Web, a travs del cual podremos crear los contadores individuales que queramos. Para ello debemos crear el objeto Counters en el archivo especial de aplicacin ASP llamado GLOBAL.ASA, como se ve en el Cdigo fuente 65, y guardarlo en una variable de aplicacin. Con lo cual dicho objeto persistir durante toda la vida de la aplicacin.

Sub Application_OnStart Set ObjContador = Server.CreateObject("MSWC.Counters") Set Application("Contador") = ObjContador End Sub Cdigo fuente 65

Tambin podemos crearlo con la etiqueta OBJECT, segn puede verse en el Cdigo fuente 66.

<object id="objContador" runat="server" scope="application" progid="MSWC.Counters"> Cdigo fuente 66

Los contadores que creemos a partir de este objeto Counters no se incrementan automticamente al cargar la pgina asp en la que han sido incluidos, sino que debemos hacerlo con el mtodo correspondiente, que en este caso es Increment. Todos los contadores se almacenan en un archivo de texto del servidor Web y se utilizan con valores enteros. Este fichero de texto se llama COUNTERS.TXT y se encuentra en el directorio c:\winnt\system32\inetsrv\Data, un ejemplo de contenido de este fichero es: contadorUno:16 contadorDos:0 Contador1:31 Contador2:1 Podremos manipular los contadores con los siguientes mtodos que ofrece el objeto Counters: Get: Devuelve el valor actual del contador cuyo nombre se le pasa como parmetro. Si el contador no existe, el mtodo lo crea y lo pone a 0. Increment: Incrementa en un 1 el valor actual del contador cuyo nombre se le pasa como parmetro, y devuelve el nuevo valor del contador. Si el contador no existe, el mtodo lo crea y lo pone a 1. Set: Recibe dos parmetros, el nombre del contador y un entero, asignando al contador el valor entero y devolviendo el nuevo valor. Si el contador no existe, el mtodo lo crea y le asigna el valor entero.

86

Grupo EIDOS

4. Componentes de Servidor

Remove: Elimina de la coleccin Counters y el contador cuyo nombre se le pasa como parmetro.

Veamos un ejemplo del uso de este componente en el que vamos a crear dos contadores "Contador1" y "Contador2" a partir del objeto de aplicacin Counters que anteriormente hemos creado en el archivo GLOBAL.ASA mediante la etiqueta <OBJECT>. Ambos contadores se incrementarn cada vez que se actualice la pgina. En el momento que el segundo contador alcance el valor 10 lo volvemos a poner a 0. Todo esto puede verse en el Cdigo fuente 67.

<b>"Contador1": <%= objCounter.Increment("Contador1") %> <br><b>"Contador2":<%=objCounter.Increment("Contador2")%> <%If CInt(objCounter.Get("Contador2"))=10 Then objCounter.Set "Contador2",0 End If%> Cdigo fuente 67

En cualquier momento, desde otra pgina ASP podremos conocer el valor de ambos contadores como puede verse en el Cdigo fuente 68.

<b>Valor del "Contador1": <%=objCounter.Get("Contador1") %> <br><b>Valor del "Contador2":<%=objCounter.Get("Contador2")%> Cdigo fuente 68

Componente MyInfo
Este componente, que tambin fue novedad en la versin 2.0 de ASP, nos permite almacenar informacin personal que ser ofrecida por el administrador del sitio Web. Esta informacin se cargar en las propiedades correspondientes del objeto MyInfo y podr ser recogida a travs de secuencias de script de la forma: <%=MyInfo.Propiedad%>. Todas las propiedades del objeto MyInfo devuelven una cadena. Con el componente MyInfo al igual que ocurra con Counters, nicamente se suele crear una instancia a nivel de aplicacin en el fichero GLOBAL.ASA, como vemos en el Cdigo fuente 69, o tambin como en el Cdigo fuente 70.

Sub Application_OnStart Set objMyInfo=Server.CreateObject("MSWC.MyInfo") Set Application("objMyInfo")=objMyInfo End Sub Cdigo fuente 69

<object id="objMyInfo" runat="server" scope="application" progid="MSWC.MyInfo"> Cdigo fuente 70

87

Desarrollo de aplicaciones COM+ para Internet / Intranet con ASP 3.0

Grupo EIDOS

En cualquier momento podremos crear nuevas propiedades para el objeto MyInfo y asignarles un valor. Por ejemplo, suponiendo que hemos creado el objeto con la etiqueta OBJECT, podramos utilizar el Cdigo fuente 71.

<%objMyInfo.Nombre = "Angel" objMyInfo.Apellidos = "Esteban Nez" objMyInfo.Correo = "aesteban@eidos.es"%> Nombre: <%=objMyInfo.Nombre%><br> Apellidos: <%=objMyInfo.Apellidos%><br> Correo: <%=objMyInfo.Correo%> Cdigo fuente 71

Las tres nuevas propiedades que acabamos de crear se almacenarn de forma persistente junto con las dems propiedades de MyInfo. Por lo que podemos hacer uso de las propiedades de este objeto para almacenar valores que permanezcan constantes en todo el sitio Web. Este objeto no tiene mtodos, y las propiedades son las que le indiquemos nosotros. La informacin que contiene el objeto MyInfo almacena en un fichero XML llamado myinfo.xml y se encuentra en el directorio c:\winnt\system32\inetsrv\data. Un ejemplo de contenido de este fichero podra ser el Cdigo fuente 72.

<XML> <Nombre>Angel</> <Apellidos>Esteban Nez</> <Correo>aesteban@eidos.es</> </XML> Cdigo fuente 72

Componente Tools
Este componente, componente de herramientas, proporciona una serie de utilidades a travs de sus mtodos. Estos mtodos son: FileExists, ProcessForm, Random, Owner y PluginExists. Hay que tener en cuenta que los dos ltimos mtodos (Owner y PluginExists) nicamente han sido implementados en Personal Web Server para Macintosh. Este componente, tambin fue novedad en la versin 2.0 de ASP. Vamos a describir los mtodos del componente Tools: FileExists: Este mtodo permite comprobar si el archivo cuya URL se le pasa como parmetro est publicado en el sitio Web. Por tanto, las URLs que recibe como parmetro son relativas y no absolutas. Si la URL existe dentro del directorio de publicacin devolver True, en caso contrario devolver False. ProcessForm: Este mtodo es el ms complejo del objeto Tools y procesa el contenido de un formulario enviado por un visitante del sitio Web. Su sintaxis es:

88

Grupo EIDOS

4. Componentes de Servidor

ObjetoTools.ProcessForm(URL_Archivo_Resultados, URL_Archivo_Plantilla, [PuntoInsercin]) Donde: URL_Archivo_Resultados: es la URL del archivo de salida en el que se han escrito los datos procesados; URL_Archivo_Plantilla: es la URL del archivo que contiene las instrucciones para procesar los datos y PuntoInsercin: es un parmetro opcional que indicar en qu lugar del archivo del resultados se han de insertar los datos procesados. El fichero de salida puede ser una pgina ASP que se ejecutar en un navegador, el fichero de plantilla puede ser tambin un pgina ASP pero no se ejecutar, sino que es copiado su cdigo ASP al fichero de salida, pero si utilizamos la sintaxis <%% %%>, al realizar la copia al fichero se salida si se ejecutar el cdigo ASP correspondiente. Random: Este mtodo devuelve un nmero entero aleatorio entre -32768 y 32767. Owner: Este mtodo devuelve True si el nombre y la contrasea enviados en el encabezado de la peticin coinciden con los del Administrador establecidos en la interfaz de Personal Web Server. En caso contrario devuelve False. Hay que tener en cuenta que este mtodo nicamente han sido implementado en Personal Web Server para Macintosh. PluginExists: Comprueba la existencia de un complemento de servidor. Devuelve True si el complemento est registrado y False en caso contrario. Igual que el mtodo anterior, slo ha sido implementado en Personal Web Server para Macintosh.

Los mtodos Random() y FileExists() son muy sencillos y los podemos observar en el Cdigo fuente 73.

<%Set objTools=Server.CreateObject("MSWC.Tools")%> <%=objTools.FileExists("versiones.asp")%><br> <%=objTools.Random()%> Cdigo fuente 73

El mtodo ProcessForm es algo ms complicado, si tenemos el fichero de plantilla mostrado en el Cdigo fuente 74.

Nombre: <%%=Request.Form("nombre")%%><br> Apellidos: <%%=Request.Form("apellidos")%%><br> Edad: <%%=Request.Form("edad")%%><br> Generado en: <%%=Now%%> Cdigo fuente 74

Al pasarle los datos de un formulario generar este otro fichero de salida: Nombre: Angel<br> Apellidos: Esteban Nez<br> Edad: 25<br> Generado en: 05/06/2000 17:18:01 Vemoslo con un sencillo ejemplo. Al pulsar el botn del formulario se ejecutar el mtodo ProcessForm y escribir los datos en el fichero de salida atendiendo al fichero que funciona como
89

Desarrollo de aplicaciones COM+ para Internet / Intranet con ASP 3.0

Grupo EIDOS

plantilla. Adems, en esta pgina a travs de un objeto TextStream se muestra el contenido del fichero de salida una vez ejecutado el mtodo ProcessForm. Ver el Cdigo fuente 75.

<%@ Language=VBScript %> <HTML> <HEAD> <META NAME="GENERATOR" Content="Microsoft Visual Studio 6.0"> </HEAD> <BODY> <%Set objTools=Server.CreateObject("MSWC.Tools")%> <form method="post" action="tools.asp"> Nombre:<input type="text" name="nombre" value="" size="20"><br> Apellidos:<input type="text" name="apellidos" value="" size="40"><br> Edad:<input type="text" name="edad" value="" size="2"><br> <input type="submit" name="enviar" value="Enviar"><br> </form> <%If Request.Form("enviar")<>"" Then objTools.ProcessForm "ficheroSalida.asp","plantilla.asp"%> Se ha generado el siguiente fichero de salida:<br> <%Set objFSO=Server.CreateObject("Scripting.FileSystemObject") Set objTextStream=objFSO.OpenTextFile(Server.MapPath("ficheroSalida.asp")) Response.Write(objTextStream.ReadAll) objTextStream.Close End if%> </BODY> </HTML> Cdigo fuente 75

Y en la Figura 17 se puede ver un ejemplo de ejecucin.

Figura 17

90

Grupo EIDOS

4. Componentes de Servidor

Si especificamos el parmetro punto de insercin se buscar la cadena especificada en el fichero de plantilla y aadir los datos a partir de esa coincidencia.

Componente PermissionChecker
Este componente nos va a permitir determinar si a un usuario se le ha dado permisos para acceder a un fichero determinado. Este componente se basa en los mecanismos de autenticacin de usuario de IIS, es decir, usuario annimo, autenticacin bsica y autenticacin desafo/respuesta de Windows NT. En el caso de que se encuentre activada la autenticacin annima, todos los usuarios iniciarn sus sesiones con la cuenta de usuario annimo de IIS. En este caso, al compartir todos los usuarios la misma cuenta, El componente PermissionChecker no podr autenticar usuarios de forma individual. En el caso de aplicaciones en las que todos los usuarios tengan cuentas individuales, como en los sitios Web dentro de una Intranet, es recomendable la desactivacin de la autenticacin annima para que PermissionChecker pueda identificar a cada usuario de forma individual. Para denegar el acceso annimo a una pgina Web, podemos usar uno de estos tres mtodos: En la lista de control de acceso al archivo, excluir la cuenta del usuario annimo a nivel de NTFS. Desde el Administrador de servicios de Internet, en la hoja de propiedades de la seguridad de directorio se desactiva el acceso annimo. En el captulo siguiente veremos en detenimiento la configuracin y administracin del servidor Web Internet Information Server. Mediante un script se servidor similar al del Cdigo fuente 76.

<%If Request.ServerVariables("LOGON_USER") = "" Then Response.Redirect("NoAutorizado.htm") End If%> Cdigo fuente 76

En este script comprobamos si la variable del servidor LOGON_USER de la coleccin ServerVariables est vaca, en tal caso se tratar de la cuenta de usuario annimo y le redireccionamos a una pgina que le indica al usuario que no est autorizado para el acceso. En el caso de sitios Web mixtos de Internet e Intranet, es recomendable activar la autenticacin annima y al menos uno de los dos mtodos de autenticacin por contrasea, autenticacin bsica o autenticacin desafo/respuesta de Windows NT. De esta forma, si se deniega a un usuario el acceso annimo a una pgina, el servidor intentar autenticar al usuario mediante alguno de dos mtodos antes comentados. A travs de este componente podremos, incluso, controlar la navegacin entre pginas. Es decir, para un hiperenlace determinado podramos comprobar si el usuario tiene permisos de acceso a la pgina direccionada, y en caso negativo desactivar el hiperenlace. La sintaxis de creacin de este componente es:

91

Desarrollo de aplicaciones COM+ para Internet / Intranet con ASP 3.0

Grupo EIDOS

Set Objeto = Server.CreateObject("MSWC.PermissionChecker") Este componente dispone de un solo mtodo, llamado HasAccess, a travs del cual vamos a poder realizar el chequeo del acceso al un archivo especificado. Su sintaxis es: objPermissionChecker.HasAccess("rutaArchivo") Donde rutaArchivo podr ser una ruta fsica o virtual a un archivo determinado. HasAccess() devolver un valor booleano indicando si el usuario Web tiene acceso al archivo. En el caso de que el archivo no exista, devolver False. Veamos en el Cdigo fuente 77 un ejemplo de utilizacin del componente, en el que chequeamos el acceso del usuario a un archivo del Web y en caso afirmativo le proporcionamos un enlace para que acceda al mismo.

<%Set objPermission=Server.CreateObject("MSWC.PermissionChecker") If objPermission.HasAccess("/MiWeb/Privado.htm") Then%> <A HREF= "/MiWeb/Privado.html"> Area Privada </A> <%Else%> Enlace no disponible. <%End If%> Cdigo fuente 77

Si el usuario no se ha autenticado para acceder a la pgina ASP del ejemplo, nunca tendr acceso al enlace, aunque el usuario annimo de Internet est autorizado el mtodo HasAccess() devolver False.

92

Componentes de acceso a datos. ADO


Introduccin
Los componentes de acceso a bases de datos son en realidad un conjunto de objetos que se agrupan dentro de la denominacin ActiveX Data Objects (ADO). Mediante el conjunto de objetos ActiveX Data Objects vamos a tener acceso a bases de datos, es decir, nos va a permitir realizar conexiones a bases de datos, ejecutar sobre ellas sentencias SQL, procedimientos almacenados, obtener resultados, etc. Es decir, nos va a ofrecer desde nuestras pginas ASP todas las operaciones que se suelen realizar sobre una base de datos. Antes en entrar en los detalles de ADO vamos a comentar el API (Application Program Interface) en el que se basa ADO. ActiveX Data Objects (ADO) nos permite desarrollar aplicaciones ASP para acceder y manipular bases de datos a travs de un proveedor OLE DB (Object Linking and Embedding para bases de datos). ADO es la primera tecnologa de Microsoft basada en OLE DB. OLE DB es una especificacin basada en un API construido con C++, por lo tanto se encuentra orientado a objetos. OLE DB consiste en consumidores de datos y proveedores de datos. Los consumidores toman los datos desde interfaces OLE DB, los proveedores ofrecen estos interfaces OLE DB. En algunos casos OLE DB puede acceder a los datos de forma ms rpida que DAO y RDO, esto es as debido a que DAO y RDO deben pasar a travs de la capa ODBC y OLE DB se puede conectar directamente a fuentes de datos relacionales con el proveedor correspondiente.

Desarrollo de aplicaciones COM+ para Internet / Intranet con ASP 3.0

Grupo EIDOS

Figura 18

OLE DB puede ser utilizado para extender la funcionalidad de proveedores de datos sencillos. Estos objetos ms especializados y sofisticados se denominan proveedores de servicio, permiten abstraer al consumidor de datos del tipo de datos al que se accede y su localizacin. Los proveedores de servicio son consumidores y proveedores, es decir, un proveedor de servicio puede consumir interfaces OLE DB y construir una tabla sencilla para ese entrada, y entonces puede ofrecer interfaces OLE DB para un aplicacin cliente para que construya su salida en HTML, este ejemplo sera nuestro caso, es decir una pgina ASP que usa ADO. Debemos tener en cuenta que OLE DB es una especificacin de bajo nivel. ADO encapsula el API de OLE DB en un API de ms alto nivel que proporciona dentro de su tecnologa de componentes un lenguaje neutral, que permite aprovechar todas las ventajas y caractersticas de OLE DB sin realizar una programacin a bajo nivel. Ya hemos introducido el concepto de proveedor y consumidor en el que se basa OLE DB, el consumidor es simplemente el que consume (utiliza) los datos y el proveedor el que ofrece esos datos. Para acceder a una base de datos determinada debemos tener el proveedor OLE DB correspondiente. De esta forma el acceso a una base de datos determinada viene condicionado por la existencia del proveedor OLE DB correspondiente. Para las bases de datos que no exista o no dispongamos de su proveedor OLE DB podemos utilizar el proveedor OLE DB para ODBC, ya que ODBC se encuentra ms difundido y es posible que exista el driver ODBC correspondiente. Es importante que no confundamos los proveedores con los drivers. En la Figura 19 se muestra un esquema dnde se pueden distinguir el lugar que ocupan los drivers y los proveedores OLE DB. Como se puede observar los proveedores se encuentran en la capa OLE DB y los drivers en la capa ODBC. ADO 2.5 ofrece varios proveedores OLE DB por defecto. De todas formas existen ms proveedores OLE DB que son ofrecidos por otras empresas. ADO permite crear aplicaciones ASP para acceder y manipular datos en una base de datos a travs de un proveedor OLE DB. Las principales ventajas de ADO son su velocidad, facilidad de uso, baja carga de memoria y requieren poco espacio en el disco duro.

94

Grupo EIDOS

5. Componentes de acceso a datos. ADO

Figura 19

Una ventaja de ADO es que si ya lo hemos utilizado en Visual Basic 6, veremos que ser prcticamente igual utilizarlo en ASP, aunque eso s, teniendo siempre en cuenta el entorno tan particular en el que nos encontramos. Las caractersticas que posee ADO para construir aplicaciones cliente/servidor y aplicaciones ASP son las siguientes: Sus objetos se pueden crear de forma independiente fuera de su jerarqua o modelo de objetos. No es necesario navegar a travs de una jerarqua para crear un objeto, la mayora de los objetos ADO se pueden instanciar de forma independiente. Esto nos permite crear nicamente los objetos que necesitamos. Ofrece soporte para realizar llamadas a procedimientos almacenados con parmetros de entrada/salida. Diferentes tipos de cursores. Soporta resultados mltiples devueltos desde procedimientos almacenados.

Se debe tener en cuenta que aunque ADO aporte todas estas caractersticas, los proveedores y drivers a los que llama ADO pueden no contemplar estas caractersticas. Por lo tanto antes debemos consultar la documentacin de los proveedores OLE DB que vamos a utilizar para informarnos de las caractersticas que ofrecen. ADO utiliza la caracterstica pooling de conexiones de ODBC 3.0 para efectuar el acceso a las bases de datos de forma ms eficiente. Esta caracterstica consiste en mantener abiertas conexiones de bases de datos y administrar la comparticin de conexiones entre diferentes solicitudes de usuarios para mantener el rendimiento y reducir el nmero de conexiones inactivas. En cada solicitud de conexin se determina si del grupo de conexiones hay una conexin inactiva, si la hay, el grupo de conexiones devuelve esa conexin en lugar de efectuar una nueva conexin a la base de datos. Por defecto el pooling de conexiones est activado en ASP. Para desactivar esta caracterstica se debe establecer a cero la entrada de registro llamada StartConnectionPool.
95

Desarrollo de aplicaciones COM+ para Internet / Intranet con ASP 3.0

Grupo EIDOS

Esta caracterstica es bastante til para ASP debido al entorno en el que nos encontramos. Las aplicaciones tradicionales de bases de datos suelen crear una nica conexin con la base de datos que se utiliza durante toda la duracin de la aplicacin. Sin embargo, debido a que en el entorno Web no se puede mantener la informacin entre diferentes peticiones de pginas, una aplicacin de bases de datos en el entorno Web debe abrir y cerrar una conexin en cada pgina. Adems no es recomendable almacenar referencias a objetos de ADO a nivel de variables del objeto Session o Application.

Modelo de objetos de ADO


Como se ha dicho anteriormente ADO es ms complejo que el resto de los componentes ActiveX Server que se incluyen con ASP. ADO presenta un completo modelo de objetos que se muestra en la Figura 20.

Figura 20

Como se puede observar en la figura hay tres objetos que se diferencian del resto, es decir, los objetos: Connection, Command y Recordset. Estos objetos son los principales dentro de ADO, y se pueden crear fuera de la jerarqua de la figura, y se pueden manejar sin tener que interactuar con un intermediario. Estos tres objetos se crearn mediante el mtodo CreateObject del objeto Server, al igual que hacamos con el resto de los componentes de servidor, el resto de los objetos de ADO se crean a partir de estos tres. Desde el punto de vista prctico el objeto Recordset es el ms importante, ya que es le que va a permitir acceder a los registros de la base de datos, pero los objetos Connection y Command permiten la creacin de un objeto Recordset. ASP 3.0 incluye la ltima versin de ADO, la versin 2.5, que incluye dos nuevos objetos: el objeto Record y el objeto Stream. De todas formas ya adelantamos que desde ASP 3.0 todava no se encuentra implementada de forma satisfactoria estos dos objetos.

96

Grupo EIDOS

5. Componentes de acceso a datos. ADO

El objeto Connection
Un objeto Connection representa una conexin a una base de datos. Los objetos Connection se pueden crear de forma independiente sin tener en cuenta ningn objeto definido previamente. Este objeto, al igual que los objetos Command y Recordset, es creado mediante el mtodo CreateObject del objeto Server. Las actividades que se pueden realizar con un objeto Connection son: creacin de conexiones con bases de datos, obtencin de objetos Recordset sencillos y tratamiento de errores. A continuacin se van a enumerar y comentar de forma breve las diferentes propiedades, mtodos y colecciones que posee este objeto. Despus se vern con ms detalle las propiedades, mtodos y colecciones ms importantes. Lo que se ofrece a continuacin no es una descripcin detallada del objeto Connection, sino que es una referencia rpida del mismo. Las propiedades del objeto Connection son: Attributes: indica distintas caractersticas de la conexin por ejemplo de que forma se puede iniciar una nueva transaccin. ConnectionTimeout: tiempo de espera mximo para la realizacin de una conexin antes de que se produzca un error. ConnectionString: cadena de conexin que identifica la base de datos a la que nos queremos conectar. CommandTimeout: tiempo mximo de espera en la ejecucin de un comando SQL que se ejecuta de forma directa sobre la conexin. CursorLocation: indica la localizacin de los cursores que se van a crear a partir de la conexin. pueden situarse en el cliente o en el servidor. DefaultDatabase: indica la base de datos por defecto con la que realizar la conexin. IsolationLevel: propiedad de slo lectura que indica el nivel de aislamiento de la conexin. Mode: modo de acceso a la conexin. Provider: proveedor OLE DB utilizado para establecer la conexin. Version: propiedad de slo lectura, indica la versin de ADO. State: propiedad de slo lectura que indica el estado de la conexin, es decir, si se encuentra abierta o cerrada.

Los mtodos del objeto Connection no son tan numerosos y son los siguientes: BeginTrans: indica el inicio de un transaccin. CommitTrans: almacena todos los cambios y finaliza la transaccin actual, representa el commit de una transaccin.
97

Desarrollo de aplicaciones COM+ para Internet / Intranet con ASP 3.0

Grupo EIDOS

RollbackTrans: cancela todos los cambios realizados durante la transaccin actual y finaliza la transaccin, representa el rollback de una transaccin. Close: cierra la conexin. Execute: ejecuta un comando SQL. Open: abre la conexin. Cancel: cancela la ejecucin de una operacin asncrona de ejecucin de una sentencia SQL o de una apertura de una conexin. OpenSchema: obtiene un objeto Recordset con el esquema de la base de datos.

El objeto Connection posee dos colecciones: Errors: coleccin de errores generados a travs del uso de ADO. Properties: una coleccin de objetos Property referentes al objeto Connection.

La funcin principal de un objeto Connection es la de especificar el origen de los datos, aunque tambin se puede utilizar a veces para ejecutar sentencias SQL sencillas.

Abrir una conexin


Una vez creado un objeto Connection mediante la siguiente lnea, podemos utilizarlo para establecer conexiones con un proveedor de datos. Decimos proveedor de datos porque la conexin no tiene que ser necesariamente a una base de datos, como vimos en el captulo anterior ADO forma parte de la estrategia universal de acceso a datos UDA, que permite acceder a diferentes tipos de datos. Para realizar la conexin utilizaremos el mtodo Open del objeto Connection, al que le podemos pasar como parmetro la cadena de conexin de la base de datos (o de forma ms general, del proveedor de datos u origen de los datos). Tambin es posible especificar la informacin de la conexin que se va a realizar a travs de la propiedad ConnectionString. La sintaxis general del mtodo Open es la siguiente: objConexion.Open [CadenaConexion], [IDusuario], [contrasea], [opciones] Donde CadenaConexion es la cadena de conexin del origen de los datos, IDusuario es el nombre del usuario que va a realizar la conexin, contrasea es la contrasea de ese usuario y opciones permite indicar informacin adicional acerca de la conexin. Vamos comentar estos parmetros de forma detallada. Como se puede observar en la sintaxis del mtodo Open todos los parmetros del mismo son opcionales, ya que esta misma informacin puede ser facilitado por la propiedad ConnectionString. Esta situacin la veremos en muchos casos al trabajar con ADO, es decir, los parmetros de los mtodos se corresponden con propiedades del objeto sobre el que se lanzan. El parmetro CadenaConexion puede contener los siguientes parmetros para la conexin:
98

Provider: proveedor OLE DB que se va a utilizar.

Grupo EIDOS

5. Componentes de acceso a datos. ADO

Data Source: el nombre del servidor dnde se encuentra la base de datos o del fichero fuente de datos. Initial Catalog: el nombre de la base de datos. User id: el nombre del usuario que va a establecer la conexin. Password: contrasea del usuario. File Name: nombre del fichero que contiene la informacin del proveedor de la conexin. URL: la URL absoluta que identifica la carpeta o fichero que se va a utilizar como origen de datos. DSN: nombre de la fuente de datos de ODBC que se va a utilizar.

Estos parmetros son exactos a los que puede contener la propiedad ConnectionString del objeto Connection. Adems se puede observar que el usuario y contrasea pueden estar contenidos en esta cadena de conexin. En el parmetro opciones se puede indicar una constante de ADO que aporta informacin adicional de la conexin, esta informacin indica si la conexin va a ser sncrona o asncrona, el valor de este parmetro es adASyncConnect, que indicar que la conexin es asncrona, sino se indica nada la conexin ser sncrona. En el entorno de ASP no tiene sentido declarar una conexin como asncrona, ya que ASP no puede recibir los eventos que genera ADO, por lo tanto en nuestras pginas ASP el mtodo Open nunca llevar el parmetro opciones. Para utilizar las constantes de ADO se debe incluir el fichero de constantes correspondiente. El fichero de constantes de ADO se llamada ADOVBS.INC y se encuentra en la ruta c:\Archivos de programa\archivos comunes\system\ado. Para incluir el fichero de constantes en nuestras pginas podemos copiarlo a nuestro sitio Web y realizar una referencia al mismo mediante la directiva INCLUDE, como se puede observar en el Cdigo fuente 78.

<!--#INCLUDE FILE="ADOVBS.INC"--> Cdigo fuente 78

Esta sentencia la deberemos repetir en todas las pginas en las que queramos utilizar las constantes de ADO. Una alternativa ms sencilla es hacer una referencia a la librera de tipos de ADO mediante la etiqueta METADATA dentro del fichero GLOBAL.ASA, como se ve en el Cdigo fuente 79. De esta forma las constantes se encontrarn accesibles desde cualquier pgina ASP de la aplicacin.

<!-- METADATA TYPE="typelib" FILE="c:\Archivos de programa\archivos comunes\system\ado\msado15.dll"--> Cdigo fuente 79

99

Desarrollo de aplicaciones COM+ para Internet / Intranet con ASP 3.0

Grupo EIDOS

Aunque el nombre de la librera de tipos termine en 15, pertenece a la versin 2.5 de ADO. A continuacin se va a mostrar una serie de ejemplos que realizan conexiones de distintas formas. En este primer ejemplo se realiza una conexin con el proveedor OLE DB de SQL Server. Adems de realizar la conexin se muestra el nombre del proveedor utilizado a travs de la coleccin Properties y la versin de ADO que se se ha utilizado para establecer la conexin. El cdigo necesario es el que aparece en el Cdigo fuente 80.

<%Set Conex=Server.CreateObject("ADODB.Connection") Conex.Open "Provider=SQLOLEDB;Data Source=aesteban2;Initial Catalog=pubs;User id=sa"%> <b>Versin de ADO: </b> <i><%=Conex.Version%></i><br> <b>Proveedor: </b><i><%=Conex.Properties("Provider Friendly Name")%> (<%=Conex.Properties("Provider Name")%>)</i><br> Cdigo fuente 80

Mediante esta cadena de conexin lo que se consigue es establecer una conexin con un servidor llamado aesteban2 que tiene instalado SQL Server, el usuario conectado es sa y se conecta a la base de datos pubs. El resultado que aparece en el navegador es: Versin de ADO: 2.5 Proveedor: Proveedor de Microsoft OLE DB para SQL Server (sqloledb.dll) Como se puede comprobar se muestra el nombre completo del proveedor (o nombre "amigable") y la librera en la que se encuentra. Si no indicamos ningn proveedor OLE DB a la hora de establecer la conexin por defecto se utiliza el proveedor de ODBC. La conexin del ejemplo anterior la podramos haber realizado de esta otra forma, como indica el Cdigo fuente 81. Y otra forma ms aparece en el Cdigo fuente 82.

Set Conex=Server.CreateObject("ADODB.Connection") Conex.ConnectionString="Provider=SQLOLEDB;Data Source=aesteban2;"&_ "Initial Catalog=pubs;User id=sa" Conex.Open Cdigo fuente 81

Conex.Open "Provider=SQLOLEDB;Data Source=aesteban2;Initial Catalog=pubs","sa" Cdigo fuente 82

Tambin podemos hacer uso de otras propiedades del objeto Connection, como se puede ver en el Cdigo fuente 83, que no es nada ms que otra versin distinta de nuestro ejemplo.

Conex.Provider="SQLOLEDB"

100

Grupo EIDOS

5. Componentes de acceso a datos. ADO

Conex.ConnectionString="Data Source=aesteban2;User id=sa" Conex.Open Conex.DefaultDatabase="pubs" Cdigo fuente 83

La propiedad DefaultDatabase, que indica la base de datos por defecto a la que nos conectamos, se puede utilizar una vez que ya est establecida la conexin. Como se puede comprobar, a la vista de las numerosas versiones de este ejemplo, el establecimiento de una conexin con ADO es muy flexible. Ahora se va a realizar una conexin utilizando el proveedor OLE DB de ODBC, como ya hemos dicho este es el proveedor por defecto que se utiliza para el objeto Connection. Se va actuar de la misma forma que para la conexin anterior, es decir, se van a mostrar distintas formas de establecer una misma conexin. Si suponemos que tenemos una fuente de datos ODBC (DSN de ODBC) de sistema definida en el servidor Web, podemos emplear el Cdigo fuente 84 para establecer la conexin.

<%Set Conex=Server.CreateObject("ADODB.Connection") Conex.ConnectionString="DSN=FuenteCursos;User id=cursos;Password=xxx" Conex.Open%> <b>Versin de ADO: </b> <i><%=Conex.Version%></i><br> <b>Proveedor: </b><i><%=Conex.Properties("Provider Friendly Name")%> (<%=Conex.Properties("Provider Name")%>)</i><br> Cdigo fuente 84

En esta caso nos conectamos a una DSN de ODBC de sistema llamada FuenteCursos con el usuario cursos que tiene la contrasea xxx. El resultado que se obtiene ahora es el siguiente: Versin de ADO: 2.5 Proveedor: Microsoft OLE DB Provider for ODBC Drivers (MSDASQL.DLL) Tambin disponemos de diversas formas de establecer una misma conexin, vamos a ver unas cuantas en el Cdigo fuente 85.

Set Conex=Server.CreateObject("ADODB.Connection") Conex.Open "DSN=FuenteCursos;User id=cursos;Password=xxx" Conex.Open "DSN=FuenteCursos;UID=cursos;PWD=xxx" Conex.Open "DSN=FuenteCursos","cursos","xxx" Cdigo fuente 85

Como se puede observar podemos utilizar indistintamente el parmetro PWD o Password para indicar la contrasea, y el parmetro User id y UID para indicar el usuario. Incluso se puede establecer la conexin a travs de el proveedor OLE DB de ODBC sin necesidad de crear la fuente de datos de ODBC en el servidor Web, es decir, se realiza la conexin con ODBC sin DSN. Vemoslo en el ejemplo del Cdigo fuente 86.
101

Desarrollo de aplicaciones COM+ para Internet / Intranet con ASP 3.0

Grupo EIDOS

Set Conex=Server.CreateObject("ADODB.Connection") Conex.Open "driver=SQL Server;server=aesteban2;uid=cursos;pwd=xxx;database=Cursos" Cdigo fuente 86

En este caso se ha establecido una conexin a la base de datos Cursos que se encuentra en el servidor aesteban2 y se ha utilizado el driver ODBC para SQL Server, ya que nuestra base de datos se encuentra en un servidor SQL Server. Como se puede comprobar debemos utlizar un parmetro driver para indicar el driver ODBC que se va a utilizar para establecer la conexin.

Ejecutar comandos sobre una conexin


Una vez establecida la conexin con un origen de datos determinados, ya podemos ejecutar consultas o sentencias sobre la conexin. Aunque ya hemos comentado en el tema anterior y en este mismo, que ADO permite manipular datos de cualquier tipo, vamos a centrarnos en el acceso a datos a un sistema gestor de bases de datos relacional, en mi caso he utilizado SQL Server 7, pero el lector puede utilizar el que estime conveniente. Esta no es la labor principal del objeto Connection, aunque se suelen ejecutar sentencias SQL sencillas directamente sobre la conexin para una mayor simplicidad del cdigo o por comodidad del programador. Una vez establecida la conexin, podremos ejecutar sobre ella comandos SQL (sentencias SQL, procedimientos almacenados, nombre de una tabla...), para ello utilizaremos el mtodo Execute, que posee la siguiente sintaxis general: Set resultado = conexion.Execute(CommandText[, RegistrosAfectados, Opciones]) connection.Execute CommandText[, RegistrosAfectados, Opciones] Como se puede observar existen dos formas distintas de utilizar el mtodo Execute. En la primera lnea se muestra de que forma se llamara al mtodo Execute cuando necesitamos almacenar su resultado en un objeto Recordset y en la segunda lnea cuando no es necesario almacenar su resultado. El parmetro CommandText es una cadena que representa el comando SQL que se debe ejecutar, es decir, esta cadena contendr: la sentencia SQL o procedimiento almacenado a ejecutar o el nombre de la tabla que se quiere recuperar. En el parmetro opcional RegistrosAfectados se devolver el nmero de registros a los que ha afectado la operacin. En el parmetro opcional Opciones se puede indicar mediante una constante de ADO el tipo de comando que se encuentra en el parmetro CommandText, es recomendable utilizar este parmetro para optimizar la evaluacin y ejecucin del comando correspondiente. Los valores que puede tomar este parmetro aparecen en la Tabla 5. Constante adCmdText Descripcin Evala el comando como una sentencia SQL.

102

Grupo EIDOS

5. Componentes de acceso a datos. ADO

adCmdTable adCmdStoredProc adCmdUnkown adCmdTableDirect adCmdFile

Evala el comando como el nombre de una tabla. Evala el comando como un procedimiento almacenado. El tipo del comando SQL es desconocido. Se evala como el nombre de una tabla Se trata como un fichero que contiene un objeto Recordset que se haba almacenado.

adExecuteNoRecords Se utiliza cuando los comandos no devuelven registros


Tabla 5

Por lo tanto, a travs del mtodo Execute podremos ejecutar diferentes tipo de comandos SQL, a continuacin se comentan mediante ejemplos algunos de los usos del mtodo Execute. En el Cdigo fuente 87 se muestra como se almacenara el contenido de una tabla en un objeto Recordset, indicando de forma explcita que el comando SQL es el nombre de una tabla.

<%Set objConexion=Server.CreateObject("ADODB.Connection") objConexion.Open "DSN=FuenteBD;UID=pepe;PWD=xxx" Set objRecordset=objConexion.Execute("provincias",,adCmdTable)%> Cdigo fuente 87

Un resultado equivalente lo obtendramos mediante la ejecucin de una sentencia SQL, como se muestra en el Cdigo fuente 88.

<%Set objConexion=Server.CreateObject("ADODB.Connection") objConexion.Open "DSN=FuenteBD;UID=pepe;PWD=xxx" Set objRecordset=objConexion.Execute("Select * from provincias",,adCmdText)%> Cdigo fuente 88

Para ejecutar un procedimiento almacenado llamado borraDatos, haramos lo del Cdigo fuente 89.

<%Set objConexion=Server.CreateObject("ADODB.Connection") objConexion.Open "DSN=FuenteBD;UID=pepe;PWD=xxx" objConexion.Execute "borraDatos",,adCmdStoredProc%> Cdigo fuente 89

103

Desarrollo de aplicaciones COM+ para Internet / Intranet con ASP 3.0

Grupo EIDOS

En el Cdigo fuente 90 se borran todas las provincias cuyo cdigo empiece por '8', el nmero de provincias borradas se recoge en el parmetro registrosBorrados:

<%Set objConexion=Server.CreateObject("ADODB.Connection") objConexion.Open "DSN=FuenteBD;UID=pepe;PWD=xxx" objConexion.Execute "DELETE FROM Provincias WHERE IDProvin LIKE '8%'"_ ,,registrosBorrados,adCmdText Response.write("Provincias borradas:"&registrosBorrados) %> Cdigo fuente 90

Cerrar la conexin
Una vez que hayamos terminado de trabajar con la conexin la deberemos cerrar mediante el mtodo Close. La llamada a Close liberar los recursos del sistema asociados a la conexin, pero no eliminar el objeto de la memoria, para eliminarlo de la memoria se deber asignar al objeto el valor Nothing. Cerrar una conexin mientras que existe una transaccin en progreso producir un error. Al lanzar el mtodo Close sobre una conexin tambin se cerrarn todos los objetos Recordset asociados a la conexin, y tambin se vaciarn las colecciones Parameters de los objetos Command asociados a la conexin y su propiedad ActiveConnection tendr el valor Nothing.

El objeto Command
Este es el segundo objeto que se poda crear de forma independiente a la jerarqua de objetos ADO, y adems era la segunda forma de obtener un objeto Recordset. Un objeto Command permite realizar la ejecucin de un procedimiento almacenado de una base de datos, por lo tanto para poder utilizar el objeto Command de esta forma, el proveedor de datos debe soportar procedimientos almacenados. A travs de este objeto podremos pasar parmetros a los procedimientos almacenados. Pero este objeto no slo permite realizar la ejecucin de procedimientos almacenados, tambin se puede utilizar para ejecutar sentencias SQL optimizadas. El objeto Command se va a comentar de la misma forma que el objeto Connection, primero se enumerarn todas su propiedades, mtodos y colecciones y luego detallaremos los ms importantes segn vayamos avanzando en la explicacin de este objeto de ADO. Las propiedades que posee este objeto son las que se enumeran a continuacin. ActiveConnection: conexin a la que se encuentra asociado el objeto Command. CommanText: comando que va a contener el objeto Command, puede ser una sentencia SQL, el nombre de una tabla o un procedimiento almacenado. CommandTimeout: tiempo mximo de espera para la finalizacin de la ejecucin de un objeto Command. Indica cuanto tiempo se esperar mientras se ejecuta un objeto Command antes de terminar su ejecucin y generar un error. Se expresa en segundos, su valor por defecto es de 30 segundos. CommandType: indica el tipo del objeto Command.

104

Grupo EIDOS

5. Componentes de acceso a datos. ADO

Prepared: indica si se va a crear un sentencia "preparada" (prepared statement), es decir, una sentencia precompilada, a partir del objeto Command antes de la ejecucin del mismo. State: propiedad de slo lectura que indica la situacin actual del comando, si se est ejecutando, si est cerrado o abierto. Name: permite identificar un objeto Command para luego ejecutarlo directamente desde el objeto Connection asociado.

Los mtodos del objeto Command son: CreateParameter: mediante este mtodo crearemos un parmetro para el comando SQL a ejecutar. Execute: ejecuta el objeto Command. Cancel: cancela la ejecucin asncrona de un comando. No es posible utilizarlo en pginas ASP ya que no est permitida la ejecucin asncrona.

A continuacin las colecciones del objeto Command: Parameters: esta coleccin contiene objetos Parameter que son cada uno de los parmetros que va a tener el objeto Command. Properties: coleccin de propiedades, objetos Property. Tiene la misma funcin que en el objeto Connection.

Crear un objeto Command


Como se ha dicho anteriormente, un objeto Command se puede crear de forma independiente, pero debemos indicarle sobre que conexin se va a realizar la ejecucin de ese comando. Para ello utilizaremos la propiedad ActiveConnection, el valor asignado a esta propiedad puede ser un objeto Connection ya creado o una cadena de conexin. En el Cdigo fuente 91 vemos varios ejemplos con las dos posibilidades.

<%Set objConexion=Server.CreateObject("ADODB.Connection") objConexion.Open "DSN=FuenteBD;UID=pepe;PWD=xxx" Set objComando=Server.CreateObject("ADODB.Command") objComando.ActiveConnection=objConexion%> <%Set objComando=Server.CreateObject("ADODB.Command") objComando.ActiveConnection="DSN=FuenteBD;UID=pepe;PWD=xxx"%> Cdigo fuente 91

Como se puede observar indicamos que el objeto Command va a utilizar una DSN de ODBC como origen de los datos, ya sea a travs de un objeto Connection ya creado y abierto o bien a travs de la cadena de conexin correspondiente. En el Cdigo fuente 92 se ofrece la creacin de un objeto Command pero que se conecta a travs del proveedor OLE DB de SQL Server.
105

Desarrollo de aplicaciones COM+ para Internet / Intranet con ASP 3.0

Grupo EIDOS

<%Set objConexion=Server.CreateObject("ADODB.Connection") objConexion.Open "Provider=SQLOLEDB;Data Source=aesteban2;Initial Catalog=pubs;User id=sa" Set objComando=Server.CreateObject("ADODB.Command") objComando.ActiveConnection=objConexion %> <%Set objComando=Server.CreateObject("ADODB.Command") objComando.ActiveConnection="Provider=SQLOLEDB;Data Source=aesteban2;"&_ "Initial Catalog=pubs;User id=sa" Cdigo fuente 92

Lo ms recomendable es utilizar en la propiedad ActiveConnection un objeto Connection, de esta forma distintos objetos Command pueden compartir una misma conexin. Si utilizamos una cadena de conexin en la propiedad ActiveConnection, cada objeto Command tendr su propia conexin (objeto Connection), lo que supondr una mayor carga para el servidor. Una vez que hemos indicado al objeto Command la conexin a la base de datos, le debemos indicar el comando que deseamos que contenga a travs de la propiedad CommandText, adems, podemos indicar el tipo de comando que se va a ejecutar a travs de la propiedad CommandType, los valores de esta propiedad son las constantes que ya vimos dentro del parmetro CommandText del mtodo Execute del objeto Connection. De esta forma si queremos crear un comando que ejecute una sentencia SQL INSERT deberemos escribir el Cdigo fuente 93.

<%Set objComando=Server.CreateObject("ADODB.Command") objComando.ActiveConnection="DSN=FuenteBD;UID=pepe;PWD=xxx" objComando.CommandType=adCmdText objComando.CommandText="INSERT INTO Provincias VALUES ('aa','Soria')"%> Cdigo fuente 93

El tiempo mximo que vamos a esperar a que un comando finalice su ejecucin se indica en segundos a travs de la propiedad CommandTimeout, cuando la ejecucin de un comando supera este tiempo, se abortar su ejecucin y se producir un error. El valor de CommandTimeout depender del trfico de la red, si es alto tendremos que aumentar el valor de esta propiedad. Esta propiedad del objeto Command permite sobreescribir el valor de la propiedad del objeto Connection para un objeto Command determinado. Mediante la propiedad Prepared indicaremos si el objeto Command contiene una sentencia SQL precompilada. Si esta propiedad tiene el valor True, antes de ejecutar el comando se enviar a la base de datos la sentencia para que sea compilada (sentencia preparada), esto podra ralentizar la primera ejecucin del objeto Command, pero una vez que el proveedor de datos a compilado el contenido del comando, el proveedor utilizar la versin compilada del comando en las sucesivas ejecuciones, por lo tanto ganaremos en eficiencia. Es recomendable asignar a Prepared el valor True cuando tengamos que ejecutar varias veces el objeto Command con una misma sentencia SQL.

106

Grupo EIDOS

5. Componentes de acceso a datos. ADO

La coleccin Parameters
Como se ha comentado al comienzo de este captulo, las funciones del objeto Command eran permitir la ejecucin de procedimientos almacenados y ejecucin se sentencias SQL optimizadas (precompiladas o preparadas), por lo tanto debe permitir realizar el paso de parmetros a la sentencia o procedimiento SQL que se vaya a ejecutar. Un objeto Command almacena los parmetros que va a necesitar para su ejecucin en una coleccin llamada Parameters, esta coleccin est constituida por objetos Parameter. Por lo tanto antes de ejecutar un comando deberemos crear sus parmetros y aadrselos a la coleccin Parameters. Para crear un parmetro utilizaremos el mtodo CreateParameter del objeto Command, al lanzar este mtodo obtenemos un objeto Parameter, la sintaxis general de este mtodo es la siguiente: Set parametro=objComando.CreateParameter([nombre][, tipo][, direccion][, tamao][, valor]) Donde parametro es un objeto Parameter en el que se va a almacenar el parmetro creado como resultado de lanzar este mtodo, objComando es el objeto Command al que se le ha asociado ese parmetro, los siguientes argumentos son todos opcionales: nombre es una cadena que va a representar el nombre del parmetro (a travs de este nombre se podr hacer referencia al parmetro dentro de la coleccin Parameters), tipo indica el tipo de dato del parmetro, direccion indica si el parmetro es de entrada o de salida, tamao indica el tamao mximo del parmetro y valor es el valor para ese objeto Parameter creado. Como se ha podido comprobar, podremos crear un objeto Parameter con todas sus propiedades especificadas en el mtodo CreateParameter, pero tambin podremos lanzar el mtodo CreateParameter sin especificar ninguna de estas propiedades (se debe recordar que todos los argumentos del mtodo CreateParameter eran opcionales) y luego, a partir del objeto Parameter creado podremos asignar valores a sus propiedades de forma directa. Las propiedades que posee el objeto Parameter son las siguientes: Name: nombre con el que se identifica al parmetro dentro de la coleccin Parameters. Este nombre no tiene porque coincidir con el nombre del parmetro correspondiente en el procedimiento almacenado de la base de datos. Type: tipo de dato del parmetro. Direction: indica la naturaleza (direccin) del parmetro. Size: es el tamao del parmetro. Value: valor que se asigna al parmetro. NumericScale: indica el nmero de decimales soportado por el parmetro. Precision: nmero mximo de dgitos del parmetro. Attributes: es una combinacin de ciertas constantes que indican otras caractersticas del parmetro. Estas constantes son adParamNullable (el parmetro acepta valores nulos), adParamSigned (el parmetro acepta valores con signo) y adParamLong (el parmetro acepta valores de datos grandes).

107

Desarrollo de aplicaciones COM+ para Internet / Intranet con ASP 3.0

Grupo EIDOS

En el Cdigo fuente 94 se muestran las dos posibilidades, es decir, se indican las caractersticas del parmetro a travs del mtodo CreateParameter y por otro lado se utilizan las propiedades del objeto Parameter para asignarles los valores correspondientes. En el ejemplo se pretende crear un parmetro de entrada llamado nombre de tipo char, de tamao mximo 20 y cuyo valor es "Pepe".

<%Set objComando=Server.CreateObject("ADODB.Command") objComando.ActiveConnection="DSN=FuenteBD;UID=jose;PWD=xxx" objComando.CommandType=adCmdText objComando.CommandText="INSERT INTO Usuarios VALUES (?)" Set parametro=objComando.CreateParameter("nombre",adChar,adParamInput,20,"Pepe")%> <%Set objComando=Server.CreateObject("ADODB.Command") objComando.ActiveConnection="DSN=FuenteBD;UID=jose;PWD=xxx" objComando.CommandType=adCmdText objComando.CommandText="INSERT INTO Usuarios VALUES (?)" Set parametro=objComando.CreateParameter parametro.Name="nombre" parametro.Type=adChar parametro.Direction=adParamInput parametro.Size=20 parametro.Value="Pepe" %> Cdigo fuente 94

Como se puede observar la primera forma de crear un parmetro y establecer sus propiedades es mucho ms cmoda. Tambin podemos apreciar que en la sentencia SQL que contiene el objeto Command, el parmetro se corresponde con el signo de interrogacin (?), este es el caracter especial que indica en que lugar se va a situar el parmetro. Una vez creado el parmetro y establecidas sus propiedades lo deberemos aadir a la coleccin Parameters del objeto Command correspondiente, para ello esta coleccin ofrece el mtodo Append. El orden en que se aaden los objeto Parameter a la coleccin Parameters es significativo, se irn sustituyendo los signos de interrogacin (?) de la sentencia o los parmetros del procedimiento almacenado segn se vayan aadiendo los parmetros a la coleccin. La sintaxis del mtodo Append es: objCommand.Parameters.Append objParametro La coleccin Parameters, adems del mtodo Append ofrece dos mtodos ms: Delete y Refresh. El mtodo Delete elimina el objeto Parameter de la coleccin Parameters, cuyo ndice o nombre se pasa como argumento, la sintaxis de este mtodo es: objCommand.Parameters.Delete {ndice|nombre} El mtodo Delete se suele utilizar para una vez ejecutado un objeto Command, eliminar sus parmetros para volver a utilizarlo con otros valores. El mtodo Refresh realiza una llamada al origen de los datos para obtener todos los datos correspondientes a los parmetros que necesita un objeto Command determinado. El mtodo Refresh obtiene los nombres, tipos de datos, naturaleza y longitud de los parmetros y con esta informacin rellena la coleccin Parameters por nosotros, nicamente deberemos indicar los valores de los parmetros, no deberemos utilizar el mtodo Append. Sin embargo es recomendable construir la coleccin Parameters de forma manual, sin realizar la llamada al mtodo Refesh, ya que esto ltimo resulta ms costoso para el origen de los datos.
108

Grupo EIDOS

5. Componentes de acceso a datos. ADO

La coleccin Parameters posee dos propiedades: Count: devuelve el nmero de objetos Parameters presentes en la coleccin Parameters. Item: es la propiedad por defecto de la coleccin Parameters y devuelve el objeto Parameters cuyo nombre o ndice se le pasa como argumento.

Ejecutar un comando
Cuando se hayan facilitado al objeto Command todos sus parmetros ya estaremos en disposicin de ejecutar el comando mediante el mtodo Execute. Una vez ejecutado el objeto Command, si deseamos volver a utilizarlo con otros parmetros ser necesario eliminar los parmetros existentes dentro de la coleccin Parameters, para ello se utiliza el mtodo Delete (como ya comentamos en el apartado anterior). Como se ha dicho con anterioridad para ejecutar un objeto Command se utiliza el mtodo Execute, que presenta la siguiente sintaxis: Set objRecordset=objComando.Execute(RegistrosAfectados, Parmetros, Opciones) objComando.Execute RegistrosAfectados, Parmetros, Opciones En el caso de que la ejecucin del objeto Command devuelva un conjunto de filas y columnas (resultado de una SELECT) lo podremos almacenar dentro de un objeto Recordset que podremos recorrer para mostrar la informacin. Como ya se coment anteriormente, el objeto Command ofreca el segundo mecanismo (el primer mecanismo lo ofreca el objeto Connection) para obtener un objeto Recordset. Los argumentos son todos opcionales, RegistrosAfectados es un entero que se devuelve y que indicar el nmero de registros que se han visto afectados por la ejecucin del comando, Parametros es un array de con los valores de los parmetros, se utiliza en el caso de que no hayamos aadido a la coleccin Parameters los parmetros correspondientes, Opciones indica que tipo de comando se quiere ejecutar, se utilizar si ya no lo hemos indicado en la propiedad CommandType del objeto Command, adems este parmetro si se especifica sobreescribe al valor indicado en la propiedad CommandType. En el Cdigo fuente 95 se muestra como se ejecutara una sentencia SQL que realiza una actualizacin sobre una tabla a partir de los parmetros que se le pasen.

<!--#INCLUDE VIRTUAL=/ADO/ADOVBS.INC--> <% Set objComando=Server.CreateObject("ADODB.Command") objComando.ActiveConnection="DSN=FuenteBD;UID=pepe;PWD=xxx" objComando.CommandType=adCmdText objComando.CommandText="UPDATE Provincias SET Provincia=?"&_ "WHERE IDProvin=?" Set parametro1=objComando.CreateParameter("nombre",adChar,adParamInput,20,"Cceres") Set parametro2=objComando.CreateParameter("clave",adChar,adParamInput,2,"10") objComando.Parameters.Append parametro1 objComando.Parameters.Append parametro2 objComando.Execute %> Cdigo fuente 95

109

Desarrollo de aplicaciones COM+ para Internet / Intranet con ASP 3.0

Grupo EIDOS

En el Cdigo fuente 96 se realiza una llamada a un procedimiento almacenado que realiza un alta sobre la tabla de provincias.

<!--#INCLUDE VIRTUAL=/ADO/ADOVBS.INC--> <% Set objComando=Server.CreateObject("ADODB.Command") objComando.ActiveConnection="DSN=FuenteBD;UID=pepe;PWD=xxx" objComando.CommandType=adCmdStoredProc objComando.CommandText="altaProvincia" Set parametro1=objComando.CreateParameter("clave",adChar,adParamInput,2,"90") Set parametro2=objComando.CreateParameter("nombre",adChar,adParamInput,20,"Santander") objComando.Parameters.Append parametro1 objComando.Parameters.Append parametro2 objComando.Execute %> Cdigo fuente 96

Como se puede apreciar, en el caso de realizar la ejecucin de un procedimiento almacenado, no se indican los parmetros con signos de interrogacin, nicamente se debe proporcionar el nombre del procedimiento almacenado que queremos utilizar, y los parmetros se situarn segn est definido el procedimiento en la base de datos. Es responsabilidad del programador conocer la definicin del procedimiento almacenado y por lo tanto proporcionar los parmetros de forma adecuada. La forma de obtener un objeto Recordset a partir de la ejecucin de un objeto Command es muy sencilla. A la hora de ejecutar el objeto Command con el mtodo Execute podremos guardar su resultado en un objeto Recordset, de la misma forma que ocurra al ejecutar un sentencia SQL sobre un objeto Connection. El Cdigo fuente 97 trata de una pgina ASP que realiza una SELECT sobre la tabla de provincias y guarda el resultado en un objeto Recordset para su futura inspeccin.

<%Set objConexion=Server.CreateObject("ADODB.Connection") objConexion.Open "DSN=FuenteBD;UID=pepe;PWD=xxx" Set objComando=Server.CreateObject("ADODB.Command") objComando.ActiveConnection=objConexion objComando.CommandType=adCmdText objComando.CommandText="SELECT * FROM Usuarios" Set objRecordset=objComando.Execute%> Cdigo fuente 97

En el Cdigo fuente 98 se crea un Recordset con la informacin devuelta por un procedimiento almacenado, en este caso, el procedimiento devuelveDomicilio devuelve una relacin de los nombres de usuario junto con su domicilio.

<%Set objConexion=Server.CreateObject("ADODB.Connection") objConexion.Open "DSN=FuenteBD;UID=pepe;PWD=xxx" Set objComando=Server.CreateObject("ADODB.Command") objComando.ActiveConnection=objConexion objComando.CommandType=adCmdStoredProc

110

Grupo EIDOS

5. Componentes de acceso a datos. ADO

objComando.CommandText="devuelveDomicilio" Set objRecordset=objComando.Execute%> Cdigo fuente 98

El objeto Recordset
Este es el tercero de los objetos principales del modelo de objetos de ADO. Como se ha visto anteriormente, un objeto de este tipo se obtiene de forma automtica a partir de la ejecucin de un objeto Connection o un objeto Command. Pero el objeto Recordset que se obtiene es muy sencillo y limitado, representa un cursor de slo lectura y que nicamente permite un desplazamiento hacia delante. Un objeto Recordset se puede crear de forma independiente, es decir, sin depender de ningn objeto Connection o Command. Un objeto Recordset es un objeto tabular que contiene datos. Los valores se encuentran en las filas y los nombres de los campos en las columnas. Cada fila es un registro completo. Es importante destacar que un objeto Recordset es una representacin de los datos, pero no son los datos almacenados. En un objeto Recordset se deben determinar tres cosas: el lugar en el que se encuentra, es decir, la fuente de los registros que contiene, las capacidades de navegacin y la conexin con los datos. Un cursor determina el comportamiento de un objeto Recordset. Por lo tanto, si queremos disponer de un cursor ms potente, deberemos crear un objeto Recordset. al igual que crebamos un objeto Connection o Command, y a travs de sus propiedades definir exactamente las caractersticas del Recorset. A continuacin se pasa a mostrar de forma resumida todas las propiedades, mtodos y colecciones que posee este objeto. El objeto Recordset posee un gran nmero de propiedades: PageSize: nmero de registros del Recordset que se van a encontrar dentro de una pgina lgica. AbsolutePage: nmero de pgina del registro actual. Para movernos a una pgina determinada le asignaremos a esta propiedad el nmero de pgina correspondiente. AbsolutePosition: especifica la posicin ordinal del registro actual dentro de un Recordset. PageCount: indica el nmero de pginas lgicas que posee un objeto Recordset. ActiveConnection: indica la conexin a la que esta asociado el objeto Recordset. Esta propiedad es slo de lectura en el caso de que la propiedad Source tenga un valor vlido. ActiveCommand: indica el objeto Command asociado con el objeto Recordset, si es que se ha utilizado uno para crear el Recordset. Esta propiedad es de slo lectura. Source: indica la procedencia de los datos que contiene el Recordset, puede ser un objeto Command, una sentencia SQL, un nombre de una tabla , un procedimiento almacenado, una direccin de Internet, etc. Esta propiedad es de lectura/escritura si el Recordset est cerrado, y slo de lectura si est abierto. DataMember: especifica el nombre de un miembro de datos del que obtener datos, este miembro de datos pertenece al origen de datos especificado en la propiedad DataSource.

111

Desarrollo de aplicaciones COM+ para Internet / Intranet con ASP 3.0

Grupo EIDOS

DataSource: especifica un objeto que contiene datos que pueden ser representados como un objeto Recordset. Index: devuelve en una cadena el nombre del ndice que se est utilizando actualmente. CursorLocation: indica la localizacin del motor del cursor, puede encontrarse en el cliente (adUseClient) o en el servidor (adUseServer). MarshalOptions: indica los registros que deben ser enviados al servidor. Sort: especifica el nombre del campo o campos por el que se encuentra ordenado el objeto Recordset, as como el orden. State: indica el estado del Recordset, si se encuentra abierto (adStateOpen) o cerrado (adStateClosed). LockType: indica el tipo de bloqueo que se aplicar al objeto Recordset. CursorType: indica el tipo de cursor que se utilizar en el Recordset. Bookmark: guarda una posicin determinada dentro de un Recordset para volver a ella en otro momento. Status: indica el estado del registro actual. Filter: indica que se va a realizar un filtro sobre el Recordset. CacheSize: indica el nmero de registros que se encuentran en la memoria. EditMode: indica el proceso de edicin del registro actual. Es de slo lectura. MaxRecords: indica el nmero mximo de registros que debe contener un Recordset como resultado de una consulta. Se utiliza esta propiedad para limitar el nmero de registros devueltos por el proveedor desde una fuente de datos. RecordCount: devuelve el nmero de registros de un objeto Recordset. BOF: indica si la posicin actual se encuentra antes del primer registro de un Recordset. EOF: indica si la posicin actual se encuentra despus del ltimo registro de un Recordset.

Los mtodos de estos objeto tambin son numerosos, y son los que aparecen a continuacin:
112

Open: este mtodo abre un cursor que va a representar los registros resultantes de la realizacin de un comando SQL. Close: cierra el cursor, perdiendo todos los datos asociados. CompareBookmarks: compara dos Bookmark y devuelve el resultado de la comparacin. Move: la posicin actual se desplaza a la posicin indicada. GetString: devuelve el Recordset completo dentro de una cadena.

Grupo EIDOS

5. Componentes de acceso a datos. ADO

MoveNext: el siguiente registro en un objeto Recordset pasa a ser el actual. MovePrevious: el registro anterior pasa a ser el registro actual. MoveFirst: el primer registro dentro de un objeto Recordset especificado, pasa a ser el registro actual. MoveLast: el ltimo registro dentro de un objeto Recordset especificado, pasa a ser el registro actual. NextRecordset: elimina el Recordset actual y se desplaza al siguiente. Esto tiene sentido cuando el comando SQL que se ha ejecutado, y cuyo resultado contiene el objeto Recordset, est compuesto de varios resultados. AddNew: crea un nuevo registro en un objeto Recordset actualizable. Delete: borra el registro actual o grupo de registros. Find: busca en el Recordset un registro que coincida con el criterio especificado. Update: almacena todos los cambios realizados sobre el registro actual. CancelUpdate: cancela los cambios realizados sobre el registro actual o sobre un nuevo registro sobre el que todava no se ha lanzado el mtodo Update. UpdateBatch: almacena todos los cambios pendientes de diferentes registros. CancelBatch: cancela todos los cambios pendientes de diferentes registros. GetRows: devuelve los registros de un Recordset dentro de un array de dos dimensiones. Supports: indica si el objeto Recordset soporta una funcin determinada. Clone: crea una copia de un objeto Recordset existente. Requery: actualiza los datos de un Recordset volviendo a ejecutar el comando correspondiente que cre el objeto. Resync: refresca los datos en el Recordset actual. Save: almacena el Recordset en un fichero. Seek: localiza un valor dentro del Recordset. Supports: indica si un objeto Recordset soporta la funcionalidad especfica que se le pasa como argumento a este mtodo.

El objeto Recordset posee dos colecciones: Fields: esta coleccin est formada por objetos Field. Cada objeto Field representa una columna del Recordset, es decir, un campo. Properties: esta coleccin es como la que posean los objetos Connection y Command.

113

Desarrollo de aplicaciones COM+ para Internet / Intranet con ASP 3.0

Grupo EIDOS

Creacin y apertura de un objeto Recordset


Debido a las enormes posibilidades de este objeto, slo se comentarn aqu las operaciones bsicas para abrir y cargar con datos un objeto recordset. Vamos a comenzar este apartado comentando el Cdigo fuente 99.

<HTML> <HEAD> <TITLE>Ejemplo objeto Recordset</TITLE> </HEAD> <BODY> <%Set objRecordset=Server.CreateObject("ADODB.Recordset") objRecordset.Source="SELECT * FROM Usuarios" objRecordset.CursorType=adOpenStatic objRecordset.ActiveConnection="DSN=FuenteBD;UID=pepe;PWD=xxx" objRecordset.Open%> <center><strong> Nmero de registros: <%=objRecordset.RecordCount%><br><br> </strong></center> <table border="1" align="center"> <tr> <th>DNI</th> <th>Nombre</th> <th>Domicilio</th> <th>Cdigo Postal</th> </tr> <%while not objRecordset.EOF%> <tr> <td><%=objRecordset("DNI")%></td> <td><%=objRecordset("Nombre")%></td> <td><%=objRecordset("Domicilio")%></td> <td align="right"><%=objRecordset("Codigo_Postal")%></td> </tr> <%objRecordset.MoveNext Wend objRecordset.Close Set objRecordset=Nothing%> </table> </body> </html> Cdigo fuente 99

En este ejemplo se ha creado un objeto Recordset y se han manipulado tres propiedades del mismo. A la propiedad CursorType, es decir, la propiedad que indica el tipo de cursor que va a poseer el Recordset, se le ha asignado el valor adOpenStatic. De esta forma podremos utilizar una serie de caractersticas del Recordset. En este caso se ha utilizado la propiedad RecordCount que devuelve el nmero de registros que existen dentro un Recordset, adems, este tipo de cursor permite un desplazamiento completamente libre sobre el Recordset. La propiedad Source indica la procedencia de los datos del Recordset, el valor de esta propiedad es un comando SQL vlido, como puede ser el nombre de una tabla, una sentencia SQL o el nombre de un procedimiento almacenado, tambin se le puede asignar un objeto Command. En este ejemplo a esta propiedad se le ha asignado una cadena que representa un sentencia SQL, en este caso una SELECT. En la propiedad ActiveConnection se le indica al Recordset la conexin a la que se encuentra asociado. A esta propiedad se le puede pasar un objeto Connection ya creado, o bien, una cadena de
114

Grupo EIDOS

5. Componentes de acceso a datos. ADO

conexin, como ocurre en este ejemplo. Lo normal es asignarle un objeto Connection, ya que de esta forma se puede reutilizar el mismo objeto Connection para distintos objetos Recordset, esto mismo ocurra con la propiedad ActiveConnection del objeto Command, que vimos anteriormente. Una vez definidas las propiedades del Recordset, nos disponemos a obtener los datos, para ello se utiliza el mtodo Open. Al lanzar este mtodo el Recordset pasar a contener los datos indicados por la propiedad Source. En este caso el mtodo Open se ha utilizado sin parmetros, ya que las caractersticas del objeto Recordset ya las hemos definido a travs de sus propiedades. La sintaxis general del mtodo Open es la siguiente: ObjetoRecordset.Open OrigenDatos, Conexion, TipoCursor, TipoBloqueo, Opciones Todos los parmetros son opcionales y se debern especificar si no hemos dado algn valor a alguna de las propiedades del Recordset que representa cada uno de ellos. De esta forma, OrigenDatos es el valor que se le asignara a la propiedad Source, Conexion representa el valor de la propiedad ActiveConnection, TipoCursor se corresponde con la propiedad CursorType, TipoBloqueo con la propiedad LockType y Opciones indica la naturaleza del origen de los datos. A continuacin se ofrecen varias formas que tenemos de obtener un objeto Recordset, en todos los casos se pretende que el contenido del objeto Recordset sea la tabla de autores (authors), y en todos los casos se va utilizar un cursor Forwar-only/Read-only. Lo podemos obtener a partir de la ejecucin directa sobre un objeto Connection, como se ve en el Cdigo fuente 100.

<%Set objConexion=Server.CreateObject("ADODB.Connection") objConexion.Open "Provider=SQLOLEDB;Data Source=aesteban2;Initial Catalog=pubs;User id=sa" Set objRecordSet=objConexion.Execute("Select * from authors",,adCmdText)%> Cdigo fuente 100

Tambin a partir de la ejecucin directa de un objeto Command, como en el Cdigo fuente 101.

<%Set objConexion=Server.CreateObject("ADODB.Connection") objConexion.Open "Provider=SQLOLEDB;Data Source=aesteban2;Initial Catalog=pubs;User id=sa" Set objComando=Server.CreateObject("ADODB.Command") objComando.ActiveConnection=objConexion objComando.CommandText="devuelveAutores" Set objRecordSet=objComando.Execute(,,adCmdStoredProc)%> Cdigo fuente 101

De momento no hemos utilizado el mtodo Open, pero en el Cdigo fuente 102 s que lo vamos a utilizar. Se trata de obtener el Recordset a partir del objeto Command, pero especificando nosotros mismos las propiedades de nuestro Recordset.

115

Desarrollo de aplicaciones COM+ para Internet / Intranet con ASP 3.0

Grupo EIDOS

<%Set objConexion=Server.CreateObject("ADODB.Connection") objConexion.Open "Provider=SQLOLEDB;Data Source=aesteban2;Initial Catalog=pubs;User id=sa" Set objComando=Server.CreateObject("ADODB.Command") objComando.ActiveConnection=objConexion objComando.CommandText="devuelveAutores" Set objRecordSet=Server.CreateObject("ADODB.Recordset") objRecordSet.Open objComando ,,adOpenForwardOnly,adLockReadOnly,adCmdStoredProc%> Cdigo fuente 102

Como se puede observar en el parmetro del mtodo Open correspondiente a la propiedad ActiveConnection del objeto Recordset no hemos indicado ninguna conexin, ya que se toma la conexin que se ha especificado para el objeto Command que utilizamos como origen de datos del objeto Recordset. Tambin podemos utilizar el mtodo Open especificando la tabla, como en el Cdigo fuente 103.

<%Set objConexion=Server.CreateObject("ADODB.Connection") objConexion.Open "Provider=SQLOLEDB;Data Source=aesteban2;Initial Catalog=pubs;User id=sa" Set objComando=Server.CreateObject("ADODB.Command") objComando.ActiveConnection=objConexion objComando.CommandText="devuelveAutores" Set objRecordSet=Server.CreateObject("ADODB.Recordset") objRecordSet.Open "authors",objConexion,adOpenForwardOnly,adLockReadOnly,adCmdTable%> Cdigo fuente 103

Y por ltimo podemos tener un objeto Recordset completamente independiente, que posea su propia conexin y recupere la informacin de la tabla a travs de una sentencia SQL. Ver el Cdigo fuente 104.

<%strConexion="Provider=SQLOLEDB;Data Source=aesteban2;Initial Catalog=pubs;User id=sa" strConsulta="select * from authors" Set objRecordSet=Server.CreateObject("ADODB.Recordset") objRecordSet.Open strConsulta,strConexion,adOpenForwardOnly,adLockReadOnly,adCmdText%> Cdigo fuente 104

Al igual que abrimos un Recordset, debmos cerrarlo con el mtodo Close, de esta forma liberaremos todos los recursos del sistema asociados a este objeto, pero no lo eliminaremos de la memoria, para ello deberemos asignarle al objeto Recordset el valor Nothing. En teora, si cerramos el objeto Connection al que est asociado una serie de objetos Recordset, se cerrarn todos estos objetos Recordset dependientes de forma automtica, pero es mejor, para liberar memoria y recursos de forma ms fiable e inmediata, cerrar cada uno de los Recordset mediante estas dos sencillas lneas de cdigo, como se muestra en el Cdigo fuente 105.
116

Grupo EIDOS

5. Componentes de acceso a datos. ADO

<%objRecordset.Close Set objRecordset=Nothing%> Cdigo fuente 105

117

CDONTS y ASP
Introduccin
En captulos anteriores hemos visto distintos tipos de componentes y objetos que se pueden utilizar en ASP: Objetos pertenecientes al modelo de objetos de ASP (Request, Server, Application, etc.). Componentes incluidos en el intrprete de secuencias de comandos de VBScript (Dictionary, FileSystemObject, TextStream, etc.). Componentes incluidos con la instalacin de ASP (AdRotator, MyInfo, ContentRotator, Tools, ADO, etc.).

En este captulo vamos a ver un conjunto de componentes agrupados todos ellos bajo el nombre de CDONTS (Collaboration Data Objects for NT Server). CDONTS es una librera de Microsoft que ofrece la posibilidad de utilizar sistemas de mensajera, basndose en servidores de correo como Microsoft Exchange Server o el servicio SMTP incluido en IIS 5.0. Como el propio nombre de estos componentes indica, son componentes para NT Server, en nuestro caso para 2000 Server. CDONTS se instala como parte del servicio de correo SMTP. Podremos acceder de igual forma a Microsoft Exchage Server 5.5 o superior y al servicio de correo SMTP incluido en IIS 5.0. En el presente captulo los ejemplos realizados con CDONTS han sido probados con el servicio de correo de IIS 5.0, para averiguar si tenemos instalado este servicio de IIS 5.0 debemos utilizar el

Desarrollo de aplicaciones COM+ para Internet / Intranet con ASP 3.0

Grupo EIDOS

Administrador de servicios de Internet y comprobar si existe el nodo llamado Servidor virtual SMTP predeterminado.

Figura 21. El servicio SMTP dentro de IIS 5.0

Si no se encuentra instalado este servicio acudiremos a la opcin Agregar o quitar programas del Panel de control. Dentro de esta opcin seleccionaremos Agregar o quitar componentes de Windows y de los componentes seleccionaremos Servicios de Internet Information Server (IIS). Si pulsamos el botn etiquetado como Detalles veremos los subcomponentes de IIS y seleccionaremos el componente Servicio SMTP.

Figura 22. Instalando el servicio SMTP

120

Grupo EIDOS

6. CDONTS y ASP

A lo largo de este captulo comentaremos cuando sea necesario algunos puntos relacionados con la configuracin del servicio SMTP de IIS 5.0. Antes de seguir con los distintos apartados que exponen el modelo de objetos de CDONTS, vamos a ver el Cdigo fuente 106 que utiliza un objeto de CDONTS llamado NewMail y que nos permite de manera muy sencilla enviar un mensaje de correo electrnico.

<%Set objMail=Server.CreateObject("CDONTS.NewMail") objMail.Send "pepe@trola.com","aesteban@mail.angel.es","Asunto","Hola que tal te va..."%> Cdigo fuente 106

Con este cdigo ya podramos enviar un mensaje de correo a travs de nuestro servicio SMTP. En siguientes apartados comentaremos detenidamente de nuevo este cdigo.

Modelo de objetos de CDONTS


La librera CDONTS se encuentra formada por un modelo de objetos que vamos a comentar es este captulo. Veamos grficamente este modelo con la Figura 23.

Figura 23. Modelo de objetos de CDONTS

Como se puede observar todos los objetos se encuentran relacionados a excepcin del objeto NewMail que aparece desconectado del resto. A continuacin se ofrece una breve descripcin de los objetos incluidos en CDONTS. NewMail: mediante este objeto podremos enviar nuevos mensajes de correo.

121

Desarrollo de aplicaciones COM+ para Internet / Intranet con ASP 3.0

Grupo EIDOS

Session: este objeto contiene toda la informacin necesaria para manipular mensajes y tambin las carpetas de entrada (inbox) y de salida de mensajes (outbox), es decir, podremos leer los mensajes revibidos y enviar nuevos mensajes. Mediante este objeto podremos acceder a los mensajes almacenados de un usuario determinado. El resto de los objetos de CDONTS tienen como referencia el objeto Session. Folder: representa una carpeta o contenedor que contiene los mensajes almacenados correspondientes a la sesin actual. Vamos a poder acceder a los mensajes recibidos y a los mensajes pendientes de enviar. Message: se corresponde con un mensaje de un objeto Folder, el objeto Folder ofrece una propiedad llamada Messages que contiene una coleccin de objetos Message. AddressEntry: este objeto contiene informacin relativa al remitente de un mensaje determinado, se obtiene a partir de la propiedad Sender del objeto Message. Attachments: coleccin perteneciente al objeto Message que contiene objetos Attachment, y que representa todos los adjuntos de un mensaje de correo determinado. Attachment: objeto que representa un fichero adjunto de un mensaje. Recipients: coleccin perteneciente al objeto Message que contiene objetos Recipient, y que representa todos los destinatarios de un mensaje determinado. Recipient: objeto que representa un destinatario de un mensaje.

En los distintos apartados de este tema veremos cada uno de los objetos del modelo de objetos de CDONTS.

El objeto Newmail
Como ya hemos dicho anteriormente, este objeto que se encuentra fuera de la jerarqua del objeto Session nos va a permitir enviar mensajes de correo electrnico. Los mtodos que ofrece este objeto son: Send(remitente, destinatario, asunto, mensaje, importancia): mediante este mtodo enviaremos un mensaje al destinatario que indiquemos. Todos los parmetros son opcionales, pudiendo aplicar el mtodo Send() sin parmetros, ya que el objeto NewMail ofrece una serie de propiedades que permiten configurar el mensaje antes de enviarlo. En el parmetro destinatario podemos expresar distintos destinatarios separados con comas. Tanto destinatario como remitente son direcciones de correo electrnico. En el asunto especificaremos el asunto del mensaje y en mensaje el cuerpo del mensaje, es decir, el mensaje en s. Y mediante el parmetro importancia indicamos si es alta (cdoHigh), normal (cdoNormal) o baja (cdoLow), por defecto este parmetro tiene el valor cdoNormal. Todos estos parmetros se corresponden con propiedades del objeto NewMail que veremos a continuacin. AttachFile(fuente, nombreFichero, codificacin): permite adjuntar el fichero especificado en el parmetro fuente a un mensaje de correo, se debe indicar una ruta fsica completa, el resto de los parmetros son opcionales. En nombreFichero indicamos el nombre con el que aparece el fichero adjunto en el cliente de correo, y en codificacin indicamos el mtodo de

122

Grupo EIDOS

6. CDONTS y ASP

codificacin empleado para enviar el fichero adjunto, esta parmetro tiene dos posibles valores cdoEncodingUUencode y cdoEncodingBase64, por defecto presenta el primero de ellos. En el ejemplo del Cdigo fuente 107 se trata de enviar un correo a aesteban@mail.angel.es, que es de prioridad baja y que posee dos ficheros adjuntos.

<!--METADATA TYPE="typelib" FILE="C:\Winnt\system32\cdonts.dll"--> <%Set objMail=Server.CreateObject("CDONTS.NewMail") objMail.AttachFile "c:\tmp\imagen.png","Figura" objMail.AttachFile "c:\tmp\tema30.html","Tema en HTML" objMail.Send "pepe@trola.com","aesteban@mail.angel.es"_ ,"Asunto","Hola que tal te va...",cdoLow%> Cdigo fuente 107

Como se puede observar se ha realizado una referencia a la librera de CDONTS, para as poder utilizar las constantes definidas en ella. En este caso se ha utilizado la constante para establecer la prioridad el mensaje. Si todo ha funcionado correctamente el mensaje habr llegado a su destinatario. Si el destinatario abre el mensaje de correo con el cliente de correo Microsoft Outlook Express tendr el aspecto que muestra la Figura 24.

Figura 24. El mensaje en Outlook Express

123

Desarrollo de aplicaciones COM+ para Internet / Intranet con ASP 3.0

Grupo EIDOS

Las propiedades que posee el objeto NewMail son las siguientes, y como ya hemos dicho algunas de ellas se corresponden con los parmetros del mtodo Send(): From: en esta propiedad indicamos el remitente del mensaje de correo. Se asigna una cadena que representa una direccin de correo, no es posible utilizar nombres. To: destinatario del mensaje, si existen varios destinatarios se deben separar mediante comas. CC: indicamos las direcciones de correo a las que deseamos enviar copia del mensaje. BCC: tiene la misma funcin que el caso anterior, pero en este caso se oculta la lista de destinatarios que reciben copia. Importance: es la importancia o prioridad del mensaje, se le puede asignar los valores cdoHigh(alta), cdoNormal(normal) o cdoLow(baja). Por defecto tiene el valor de prioridad normal. Body: representa el cuerpo del mensaje, es decir, el texto del mensaje. Puede contener texto plano o en HTML. BodyFormat: mediante este propiedad indicamos el formato del cuerpo del mensaje, puede aceptar los valores cdoBodyFormatHTML, para indica que el formato del cuerpo del mensaje es HTML o cdoBodyFormatText para indicar que el formato del cuerpo del mensaje es texto plano, por defecto el valor de esta propiedad es cdoBodyFormatText. Para poder utilizar el valor cdoBodyFormatHTML se debe utilizar el formato de correo MIME, indicndolo en la propiedad MailFormat. MailFormat: indica el formato con el que se crean los mensajes de correo, puede tener dos valores posibles, formato de texto plano (cdoMailFormatText), que es el valor por defecto, y formato MIME (cdoMailFormatMIME). Con el formato MIME podemos enviar contenidos ms elaborados en nuestros mensajes de correo. Version: esta propiedad de slo lectura devuelve la versin de la librera CDONTS que estamos utilizando, la versin actual es la 1.2. ContentLocation: permite especificar un camino relativo o absoluto para todas las URLs contenidas en el cuerpo del mensaje, esta propiedad tiene sentido cuando estamos enviando mensajes en formato HTML. ContentBase: propiedad relacionada con la anterior, ya que nos permite especificar la ruta base para todas URLs contendidas en el cuerpo del mensaje. Los valores de ContentLocation se consideran relativos a los valores de ContentBase. As si la propiedad ContentBase tiene el valor "http://www.almagesto.com" y ContentLocation tiene el valor "images/", para las URLs presentes en el cuerpo del mensaje se construir la ruta http://www.almagesto.com/images/. Esto sera equivalente a asignar a la propiedad ContentBase el valor "http://www.almagesto.com/images/".

Veamos un ejemplo que muestra la utilizacin de las propiedades del objeto NewMail. En este caso se definen algunas de las propiedades y luego se enva el correo mediante el mtodo Send() sin parmetros.

<!--METADATA TYPE="typelib" FILE="C:\Winnt\system32\cdonts.dll"-->

124

Grupo EIDOS

6. CDONTS y ASP

<%Set objMail=Server.CreateObject("CDONTS.NewMail") objMail.From="pepe@trola.com" objMail.To="aesteban@mail.angel.es" objMail.Importance=cdoLow objMail.MailFormat=cdoMailFormatMIME objMail.Subject="Asunto" objMail.BodyFormat=cdoBodyFormatHTML objMail.ContentBase="http://aesteban/images/" strTexto="<html><body><b><i>Hola que tal te va...</i></b><br>" strTexto=strTexto&"<div align='center'><img src='almagesto.gif'></div>" strTexto=strTexto&"</body></html>" objMail.Body=strTexto objMail.Send%> Cdigo fuente 108

En este ejemplo se ha dado el formato MIME al mensaje y al cuerpo el formato HTML, el resultado de visualizar este correo mediante el cliente de correo Outlook Express es el que muestra la Figura 25.

Figura 25. Mensaje de correo con formato

A travs del objeto NewMail tambin podemos tener acceso y manipular las cabeceras del mensaje de correo, que normalmente en los clientes de correo permanecen ocultas. Parte de la informacin contenida en las cabeceras se genera a partir de las propiedades del objeto NewMail y otra parte las genera el servidor de correo de forma automtica al enviar el mensaje. Estas cabeceras las podemos ver con el cliente de correo Outlook Express si en el men de el mensaje acudimos a la opcin Archivo|Propiedades, y luego elegimos la pestaa Detalles. Mediante la coleccin Value del objeto NewMail podemos aadir nuevas cabeceras a los mensajes o modificar las existentes. En el Cdigo fuente 109 se aade una nueva cabecera y se modifica la cabecera Subject.
125

Desarrollo de aplicaciones COM+ para Internet / Intranet con ASP 3.0

Grupo EIDOS

<!--METADATA TYPE="typelib" FILE="C:\Winnt\system32\cdonts.dll"--> <%Set objMail=Server.CreateObject("CDONTS.NewMail") objMail.From="pepe@trola.com" objMail.To="aesteban@mail.angel.es" objMail.Importance=cdoLow objMail.MailFormat=cdoMailFormatMIME objMail.Subject="Asunto" objMail.BodyFormat=cdoBodyFormatHTML objMail.ContentBase="http://aesteban/images/" strTexto="<html><body><b><i>Hola que tal te va...</i></b><br>" strTexto=strTexto&"<div align='center'><img src='imagen.gif'></div>" strTexto=strTexto&"</body></html>" objMail.Body=strTexto objMail.Value("Subject")="Modifico el asunto" objMail.Value("NuevaCabecera")="Nuevo valor" objMail.Send%> Cdigo fuente 109

Los detalles del mensaje en Outlook Express tienen el aspecto que nos muestra la

Figura 26. Cabeceras del mensaje

Hemos visto lo sencillo que resulta enviar un mensaje mediante el objeto NewMail de la librea CDONTS, ahora vamos a seguir viendo los distintos objetos que proporciona esta librera. Los siguientes objetos permiten acceder a los mensajes que se encuentran almacenados en el servidor de correo.

126

Grupo EIDOS

6. CDONTS y ASP

El objeto Session
Del objeto Session dependen el resto de los objetos de la librera CDONTS, a travs del objeto Session iniciamos una sesin con el servidor de correo mediante un usuario determinado. El servidor con el que iniciamos la sesin ser el servidor de correo que se encuentre instalado en el servidor Web en el que se ejecutan las pginas ASP, como ya hemos dicho este servidor puede ser el servicio SMTP incluido en IIS 5.0 o Exchange Server 5.5 o superior. Para realizar las pruebas con los distintos objetos de CDONTS se ha utilizado el servicio SMTP de IIS 5.0. Para indicar una direccin de correo dentro de este servidor utilizaremos la siguiente sintaxis: cuenta@nombreServidor, siendo nombreServidor el nombre del dominio por defecto del servidor SMTP. Aunque desde el Administrador de servicios de Internet podemos definir alias para el dominio por defecto. Para ello acudiremos dentro del Administrador de servicios de Internet al nodo llamado Servidor virtual SMTP predeterminado, y en la rama Dominios pulsando con el botn derecho del ratn seleccionamos la opcin Nuevo|Dominio, en ese momento se lanza el asistente para la creacin de nuevos dominios. Dentro del asistente seleccionamos la opcin de Alias y pulsamos el botn Siguiente. A continuacin se debe indicar el nombre que vamos a dar al alias de nuestro dominio, yo en mi caso le he llamado mail.angel.es, siendo mi dominio por defecto aesteban, es decir, el nombre de mi servidor. Pulsamos el botn Finalizar. Si todo ha sido correcto veremos una pantalla similar a la de la Figura 27.

Figura 27. Creando dominios alias

Despus de este pequeo comentario acerca de la creacin de dominios, volvamos al tema principal que nos ocupa dentro de este apartado. El objeto Session presenta los siguientes mtodos: LogonSMTP(nombre, direccion): mediante este mtodo se inicia una sesin con el servidor de correo. En el parmetro nombre se indica el nombre que se desea que se muestre al usuario, y en direccin la direccin completa del usuario que se desea conectar al servidor de correo. Este mtodo no realiza ningn tipo de validacin, si la conexin no se ha podido establecer no recibimos ningn mensaje de error. Cada usuario conectado tendr acceso a su propio buzn, pudiendo leer el correo de su "bandeja de entrada" (inbox) y enviar correo a travs de su "bandeja de salida" (outbox).

127

Desarrollo de aplicaciones COM+ para Internet / Intranet con ASP 3.0

Grupo EIDOS

LogOff(): este mtodo finalizar la sesin actual con el servidor de correo. Podremos reutilizar el objeto Session si deseamos realizar una nueva sesin llamando de nuevo al mtodo LogonSMTP. GetDefaultFolder(tipoCarpeta): mediante este mtodo se obtiene un objeto Folder que representa la bandeja o carpeta de entrada o la de salida del usuario conectado. El parmetro de este mtodo puede tener dos valores cdoDefaultFolderInbox(1) para obtener la bandeja de entrada y poder leer los mensajes recibidos o cdoDefaultFolderOutbox(2) para obtener la bandeja de salida y poder enviar mensajes. SetLocaleID(codigo): este mtodo permite establecer un cdigo de localizacin que afectar al entorno del lenguaje, formatos horarios, fechas, valores monetarios, etc. El parametro tiene los mismos valores que vimos para la propiedad LCID del objeto integrado Session de ASP. Este mtodo si se utiliza se debe lanzar antes de establecer la sesin con el servidor de correo mediante el mtodo LogonSMTP().

Ahora vamos a pasar a comentar las propiedades del objeto Session: Inbox: propiedad de slo lectura que devuelve un objeto Folder que representa la bandeja de entrada de la sesin actual. Outbox: propiedad de slo lectura que devuelve un objeto Folder que representa la bandeja de salida de la sesin actual. MessageFormat: propiedad de lectura y escritura que permite obtener e indicar el formato de codificacin de los mensajes. Tiene dos valores posibles CDOMime, para mensajes de tipo MIME, y CDOText para mensajes de tipo texto plano. Name: propiedad de slo lectura que contiene el nombre del usuario conectado y que se ha especificado en el mtodo LogonSMTP(). Version: propiedad de slo lectura que indica la versin de la librera CDONTS.

El objeto Session adems de estas propiedades ofrece otras tres que son comunes a todos los objetos de su jerarqua, y son las siguientes: Session: esta propiedad devuelve el objeto Session que representa la raz de la jerarqua de un objeto determinado. Class: esta propiedad devuelve un entero que nos indica el tipo de objeto: Session(0), Folder(2), Message(3), Recipient(4), Attachment(5), AddressEntry(8), Messages(16), Recipients(17) y Attachments(18). Parent: devuelve un objeto que representa el padre del objeto especificado. La propiedad Parent del objeto Session devuelve Nothing y la del objeto AddressEntry devuelve un objeto Message.

Una vez comentados los mtodos y propiedades del objeto Session vamos a mostrar un ejemplo que hace uso de algunos de ellos. Este ejemplo consiste en un formulario que nos permite conectarnos al servicio SMTP de IIS 5.0. El formulario permite especificar el nombre del usuario y la cuenta de correo del usuario que se va a conectar. Una vez que se ha establecido la conexin con el servidor SMTP se muestran algunos de los valores de las propiedades de la sesin actual. Tambin existe la posibilidad de desconectarnos para
128

Grupo EIDOS

6. CDONTS y ASP

iniciar una nueva sesin, la sesin se debe almacenar en una variable a nivel de sesin, ya que ms tarde deberemos utilizarla para realizar la desconexin. Veamos el Cdigo fuente 110. Y en la Figura 28 se puede ver un ejemplo de la ejecucin del cdigo anterior.

<!--METADATA TYPE="typelib" FILE="C:\Winnt\system32\cdonts.dll"--> <HTML> <HEAD> <META NAME="GENERATOR" Content="Microsoft Visual Studio 6.0"> </HEAD> <BODY> <%If Request.Form("Desconectar")<>"" Then 'se realiza la desconexin Set objSession=Session("oSession") objSession.LogOff End if If Request.Form("Conectar")="" Then%> <form action="<%=Request.ServerVariables("SCRIPT_NAME")%>" method="post"> Nombre:<input type="text" name="nombre" size="20" value=""><br> Cuenta de correo:<input type="text" name="cuenta" size="20" value=""><br> <input type="submit" name="conectar" value="Conectar"> </form> <%Else 'se realiza la conexin Set objSession=Server.CreateObject("CDONTS.Session") objSession.LogonSMTP Request.Form("nombre"),Request.Form("cuenta") Set Session("oSession")=objSession%> Usuario conectado: <%=objSession.Name%><br> <%If objSession.MessageFormat=CDOMime Then strFormato="CDOMime" Else strFormato="CDOText" End if%> Formato de los mensajes: <%=strFormato%><br> Versin de CDONTS: <%=objSession.Version%><br> <form action="<%=Request.ServerVariables("SCRIPT_NAME")%>" method="post"> <input type="submit" name="desconectar" value="Desconectar"> </form> <%End if%> </BODY> </HTML> Cdigo fuente 110

Figura 28. Utilizando el objeto Session de CDONTS

129

Desarrollo de aplicaciones COM+ para Internet / Intranet con ASP 3.0

Grupo EIDOS

El objeto Folder
Este objeto representa una carpeta o contenedor que se va a corresponder con las bandejas de entrada y de salida de los mensajes de correo de la sesin actual. Un objeto Folder lo obtenemos a partir de la propiedades Inbox y Outbox de un objeto Session que representa una sesin ya establecida con el servicio SMTP. Tambin lo podemos obtener a travs del mtodo GetDefaultFolder(). El objeto Folder suele representar las siguientes carpetas estndar: Bandeja de entrada (inbox): es la localizacin que tiene el correo recibido. Bandeja de salida (outbox): es la localizacin temporal que tiene el correo antes de proceder a su envo.

Mediante el objeto Folder vamos a tener acceso a los contenidos de la carpeta indicada. Aunque tenemos acceso a los mensajes este acceso es algo restrictivo, podremos eliminar mensajes existentes, leer mensajes existentes y enviar mensajes nuevos, sin embargo no podemos cambiar las propiedades de los mensajes ya existentes. En este punto se debe hacer una aclaracin acerca del servidor SMTP de IIS y los objetos de la librera CDONTS. El servidor de correo SMTP de IIS 5.0 a diferencia del servidor Exchange Server, no posee buzones individuales, es decir, no existe una bandeja para cada usuario sino que todos los mensajes recibidos se almacenan en una misma localizacin y todos los mensajes enviados en otra. Si hemos aceptado las configuraciones por defecto al instalar el servicio SMTP de IIS, la bandeja de entrada se corresponde con el directorio c:\inetpub\mailroot\Drop y la de salida con el directorio c:\inetpub\mailroot\Pickup. Sin embargo aunque los buzones sean globales, cuando iniciamos la sesin con el servidor SMTP, a travs de los objetos de CDONTS nicamente tendremos acceso a los mensajes que se corresponden con los del cliente que se a conectado, de esta forma se intenta simular los buzones personales. Debido a esto para utilizar el servicio SMTP no es necesario configurar buzones ni definir cuentas de correo de usuarios, de todas formas en los siguientes ejemplos todo esto se ver ms claro. Hecha esta aclaracin volvemos a tratar el objeto Folder, empezando ahora a comentar las propiedades que nos ofrece. Name: propiedad de slo lectura que contiene el nombre de la carpeta a la que representa el objeto Folder. Normalmente tiene los valores "Inbox" y "Outbox". Messages: esta propiedad devuelve una coleccin de objetos Message, que representar los mensajes presentes en la carpeta.

Veamos el tratamiento que tiene la coleccin Messages. La coleccin Messages posee las siguientes propiedades: Count: nmero de objetos Message contenidos en la misma. Item(indice): devuelve un objeto Message de la coleccin cuyo ndice coincide con el parmetro indicado. El primer ndice es 1.

130

Grupo EIDOS

6. CDONTS y ASP

Y los siguientes mtodos: Add(asunto, texto, importancia): permite aadir un nuevo mensaje a la coleccin. Todos los parmetros son opcionales, y cuando se ejecuta este mtodo se devuelve un objeto Message para poder manipularlo. Este mtodo nicamente se puede aplicar a una coleccin Messages que pertenece a la bandeja de salida. Delete(): elimina todos lo mensajes de la coleccin. Para borrar un mensaje en concreto debemos utilizar el mtodo Delete del objeto Message, pero eso lo veremos en el siguiente apartado. GetFirst(): mtodo que devuelve el primer objeto Message de la coleccin Messages. Si el objeto no existe devuelve Nothing. GetLast(): mtodo que devuelve el ltimo objeto Message de la coleccin Messages. Si el objeto no existe devuelve Nothing. GetNext(): mtodo que devuelve el siguiente objeto Message de la coleccin Messages. Si el objeto no existe devuelve Nothing. GetPrevious(): mtodo que devuelve el anterior objeto Message de la coleccin Messages. Si el objeto no existe devuelve Nothing.

Vamos a ampliar y modificar el ejemplo del apartado anterior que utilizaba el objeto Session de CDONTS para establecer una conexin, para mostrar la utilizacin prctica del objeto Folder. En este nuevo ejemplo vamos a establecer la sesin con el servicio SMTP con el mismo formulario y vamos a indicar el nmero de mensajes que posee el usuario conectado en ese momento en cada una de sus bandejas. Tambin aparece un nuevo botn que permite eliminar al usuario todos los mensajes de su bandeja de entrada. El Cdigo fuente 111.

<!--METADATA TYPE="typelib" FILE="C:\Winnt\system32\cdonts.dll"--> <HTML> <HEAD> <META NAME="GENERATOR" Content="Microsoft Visual Studio 6.0"> </HEAD> <BODY> <%If Request.Form("Desconectar")<>"" AND Session("oSession")<>"" Then 'se realiza la desconexin Set objSession=Session("oSession") objSession.LogOff Session("oSession")="" Elseif Request.Form("EliminarInbox")<>"" Then 'se eliminan todos los mensajes de Inbox Set objSession=Session("oSession") Set objFolderInbox=objSession.Inbox objFolderInbox.Messages.Delete End if If Request.Form("Conectar")="" AND Session("oSession")="" Then%> <form action="<%=Request.ServerVariables("SCRIPT_NAME")%>" method="post"> Nombre:<input type="text" name="nombre" size="20" value=""><br> Cuenta de correo:<input type="text" name="cuenta" size="20" value=""><br> <input type="submit" name="conectar" value="Conectar"> </form>

131

Desarrollo de aplicaciones COM+ para Internet / Intranet con ASP 3.0

Grupo EIDOS

<%Elseif Request.Form("Conectar")<>"" Then 'se realiza la conexin Set objSession=Server.CreateObject("CDONTS.Session") objSession.LogonSMTP Request.Form("nombre"),Request.Form("cuenta") 'se guarda a nivel se sesin la referencia a la sesin establecida 'con el servicio SMTP Set Session("oSession")=objSession End if If Session("oSession")<>"" Then 'se recupera la sesin con SMTP Set objSession=Session("oSession")%> Usuario conectado: <b><%=objSession.Name%></b><br> <form action="<%=Request.ServerVariables("SCRIPT_NAME")%>" method="post"> <input type="submit" name="desconectar" value="Desconectar"> <input type="submit" name="EliminarInbox" value="Vaciar Inbox"> </form> <%Set objFolderInbox=objSession.GetDefaultFolder(cdoDefaultFolderInbox)%> El nmero de mensajes en <%=objFolderInbox.Name%> es <%=objFolderInbox.Messages.Count%><br> <%Set objFolderOutbox=objSession.Outbox%> El nmero de mensajes en <%=objFolderOutbox.Name%> es <%=objFolderOutbox.Messages.Count%> <%End if%> </BODY> </HTML> Cdigo fuente 111

Y en la Figura 29 se muestra un ejemplo de un usuario conectado.

Figura 29. Utilizando el objeto Folder

En el siguiente apartado veremos como mostrar los datos de los mensajes contenidos en las bandejas y tambin como eliminar mensajes determinados y enviar nuevos.

132

Grupo EIDOS

6. CDONTS y ASP

El objeto Message
Este objeto representa un mensaje contenido en un objeto Folder, es decir, en una carpeta. Una referencia a un objeto Message la obtenemos a travs de la coleccin Messages del objeto Folder correspondiente. En este apartado adems de comentar el objeto Message vamos a tratar las dos colecciones que contiene: Recipients y Attachments, y tambin veremos el objeto AddressEntry, que permite especificar los datos del remitente. El objeto Message lo utilizaremos para manipular los mensajes de correo, y para ello este objeto ofrece las siguientes propiedades: Attachments: una coleccin de objetos Attachment que contiene los ficheros adjuntos de un mensaje. ContentBase: URL base para los contenidos del mensaje. ContentID: identificador del tipo de contenido MIME del mensaje. ContentLocation: URL relativa para los contenidos del mensaje. HTMLText: cuerpo del mensaje en formato HTML. Importance: prioridad del mensaje. MessageFormat: formato de codificacin del mensaje. Recipients: coleccin de objetos Recipient que representa a cada uno de los destinatarios del mensaje. Sender: devuelve un objeto AddressEntry que representa al remitente del mensaje. Size: tamao en bytes del mensaje. Subject: asunto del mensaje. Text: cuerpo del mensaje en formato de texto plano. TimeReceived: fecha y hora de recepcin del mensaje. TimeSent: fecha y hora de envo del mensaje.

Muchas de estas propiedades son comunes a las del objeto NewMail. El objeto Message ofrece los siguientes mtodos: Send(): este mtodo enva el mensaje a los destinatarios indicados. Delete(): elimina el mensaje de forma permanente.

Vamos a seguir utilizando el mismo ejemplo que el de los apartados anteriores para mostrar la utilizacin del objeto Message. En este caso se trata de mostrar el contenido de la bandeja de entrada
133

Desarrollo de aplicaciones COM+ para Internet / Intranet con ASP 3.0

Grupo EIDOS

del usuario que se ha conectado. La informacin que se va a mostrar de cada mensaje es la prioridad, remitente, asunto y fecha de recepcin. Para mostrar el contenido de la bandeja de entrada simplemente recorreremos la coleccin Messages de objeto Folder que se corresponde con inbox. Y utilizaremos las propiedades correspondientes de cada objeto Message para mostrar la informacin deseada. El cdigo que se debe aadir al ejemplo anterior, despus de haber obtenido una referencia a la carpeta Inbox, es el Cdigo fuente 112.

<%If objFolderInbox.Messages.Count>0 Then%> <table border="0"> <tr><th>Prioridad</td> <th>De</th> <th>Asunto</th> <th>Recibido</th> </tr> <%For Each objMessage In objFolderInbox.Messages%> <tr> <td><%=Prioridad(objMessage.Importance)%></td> <td><%=objMessage.Sender%></td> <td><%=objMessage.Subject%></td> <td><%=objMessage.TimeSent%></td> </tr> <%Next%> </table> <%End if%> Cdigo fuente 112

Se utiliza una funcin llamada Prioridad, cuya funcin es la de devolver una cadena con el texto que representa a la prioridad correspondiente, su cdigo es el Cdigo fuente 113.

<%Function Prioridad(prio) Select Case prio Case cdoLow: Prioridad="Baja" Case cdoNormal: Prioridad="Normal" Case cdoHigh: Prioridad="Alta" End Select End Function%> Cdigo fuente 113

Y un ejemplo de la ejecucin del Cdigo fuente 113 lo tenemos en la Figura 30. Como ya hemos comentado al principio el objeto Message ofrece dos colecciones a travs de de sus propiedades Recipients y Attachments. La coleccin Recipients contiene objetos Recipient que representan a cada uno de los destinatarios de un mensaje. Para aadir un nuevo destinatario utilizamos el mtodo Add() sobre la coleccin Recipients, que adems nos devolver un objeto Recipient por si deseamos manipularlo. La sintaxis del mtodo Add() es la siguiente: Set objRecipient=colRecipients.Add(nombre, direccin, tipo)
134

Grupo EIDOS

6. CDONTS y ASP

Figura 30. Mensajes de la bandeja de entrada

Todos los parmetros de este mtodo son opcionales. En nombre indicamos el nombre del destinatario que se va a mostrar, en direccin se indica la direccin de correo del destinatario y en tipo una constante que indica si es un destinatario de copia o no. Los valores de tipo pueden ser CdoTO (es el destinatario sin copia), CdoCC (se le enva copia) o CdoBCC (se le enva copia pero no aparece en la lista de los dems destinatarios. Los mensajes contenidos en la bandeja de entra no se pueden modificar, slo son de lectura, por lo tanto si lanzamos el mtodo Add() sobre una coleccin Recipients de un objeto Message que pertenezca al objeto Folder Inbox, se producir un error. El mtodo Delete de la coleccin Recipients elimina todos los objetos Recipient de la coleccin. Los parmetros que aparecan en el mtodo Add() de la coleccin Recipients se corresponden con las propiedades del objeto Recipient, y son las siguientes: Name: nombre del destinatario. Es el nombre que se va a mostrar. Address: direccin de correo del destinatario. Type: tipo de destinatario, puede tener uno de los siguientes valores: CdoTO, CdoCC, CdoBCC.

La otra coleccin que podemos encontrar en el objeto Message es la coleccin Attachments que se encuentra formada por objetos Attachment y que representa los ficheros adjuntos de un mensaje determinado. Mediante el mtodo Delete() de la coleccin Attachments eliminamos todos los ficheros adjuntos de un mensaje, y mediante el mtodo Add() se aade un nuevo fichero adjunto.
135

Desarrollo de aplicaciones COM+ para Internet / Intranet con ASP 3.0

Grupo EIDOS

Al igual que ocurra con la coleccin Recipients, al mtodo Add() devuelve un objeto Attachment para poder manipularlo, la sintaxis de este mtodo es: Set objAttachment=colAttachments.Add(nombre, tipo, fuente, localizacin, base) Todos los parmetros de este mtodo son opcionales. El parmetro nombre indica el nombre con el que se va a mostrar el adjunto, el tipo de adjunto puede ser cdoFileData(1) para indicar un fichero y cdoEmbeddedMessage(4) para indicar que el adjunto es otro mensaje. En fuente se indica la ruta completa del fichero adjunto o bien un objeto Message en el caso de ser el adjunto de tipo cdoEmbeddedMessage. Localizacin y base son dos parmetros que especifican cabeceras para ficheros adjuntos de tipo MIME. El mtodo Add() no se puede utilizar con mensajes que se encuentren en la bandeja de entrada, ya que estos mensajes son nicamente de lectura. El objeto Attachment ofrece una serie de propiedades que se corresponden con los parmetros del mtodo Add() de la coleccin Attachments, y son las siguientes: ContentBase: cabecera para un adjunto MIME que especifica la direccin URL base. ContentID: identificador nico para un adjunto MIME. ContentLocation: URL relativa para un adjunto MIME. Name: nombre con el que se va a mostrar el fichero adjunto. Source: ruta o localizacin del adjunto. Type: tipo de adjunto, puede presentar las siguientes constantes cdoFileData o cdoEmbeddedMessage.

Adems el objeto Attachment ofrece los siguientes mtodos: Delete(): para eliminar un adjunto determinado. ReadFromFile(nombreFichero): carga el adjunto desde el fichero indicado por parmetro. Se debe indicar la ruta completa del fichero. WriteToFile(nombreFichero): escribe en el fichero indicado el contenido del adjunto.

Relacionado con el objeto Message tambin encontramos el objeto AddressEntry. El objeto AddressEntry se obtiene a travs de la propiedad Sender del objeto Message y representa al remitente del mensaje. Este objeto ofrece las siguientes propiedades: Name: nombre del remitente o alias, es el nombre que se muestra. Address: direccin de correo electrnico del remitente. Type: tipo de direccin. Para CDONTS siempre es "SMTP".

Ahora vamos a mostrar un ejemplo que utiliza todos estos nuevos objetos. Para ello vamos a retomar el ejemplo visto con el objeto NewMail, y lo que vamos a hacer es la misma operacin, es decir,
136

Grupo EIDOS

6. CDONTS y ASP

enviar un correo nuevo, pero utilizando algunos de los objetos vistos hasta ahora que dependen del objeto Session inicial de la librera CDONTS.

<!--METADATA TYPE="typelib" FILE="C:\Winnt\system32\cdonts.dll"--> <%'se realiza la conexin Set objSession=Server.CreateObject("CDONTS.Session") objSession.LogonSMTP "Angel","aesteban@mail.angel.es" 'se obtiene la bandeja de salida Set objFolderOutbox=objSession.Outbox 'se obtiene la coleccin de mensajes Set colMensajes=objFolderOutbox.Messages strTexto="Mensaje enviado con los objetos de CDONTS" 'se aade un mensaje nuevo y se obtiene la referencia al mismo Set objMensaje=colMensajes.Add("Prueba de CDONTS",strTexto,cdoNormal) 'aadimos un adjunto al mensaje objMensaje.Attachments.Add "Fichero Adjunto",cdoFileData,"c:\tmp\imagen.png" 'aadimos un destinatario al mensaje objMensaje.Recipients.Add "Jose Mara","chema@mail.angel.es",cdoTO 'aadimos un destinatario al que se enva una copia objMensaje.Recipients.Add "Pepe","pepe@mail.angel.es",cdoCC 'se enva el mensaje objMensaje.Send%> Cdigo fuente 114

Como podemos comprobar es mucho ms sencillo y recomendable utilizar el objeto NewMail a la hora de enviar correo. El mensaje se ha enviado con el remitente que corresponde a la sesin actual, en este caso aesteban@mail.angel.es. Si abrimos el mensaje que hemos creado con el cliente de correo Outlook Express, vemos que tiene el aspecto que nos muestra la Figura 31.

Figura 31. Mensaje ledo con Outlook Express

137

Desarrollo de aplicaciones COM+ para Internet / Intranet con ASP 3.0

Grupo EIDOS

Y si queremos podemos ver los detalles del mismo(Figura 32).

Figura 32. Detalles del mensaje

Antes de terminar este tema vamos aadir una mayor funcionalidad al ejemplo en el que mostrbamos el contenido de la bandeja de entrada de un usuario conectado a una sesin de nuestro servidor SMTP. La nueva funcionalidad consiste en poder visualizar el contenido de cada uno de los mensajes que se encuentran en la bandeja de entrada del usuario conectado actualmente. Para ello vamos a situar en un enlace los asuntos de cada uno de los mensajes y para identificar cada uno de ellos utilizar una variable del QueryString que va a contener un entero para cada mensaje. En la pgina de lectura del mensaje adems vamos a permitir la opcin de borrar el mensaje que estamos leyendo. Veamos el Cdigo fuente 115 que debemos modificar en la pgina que muestra el contenido de la bandeja de entrada. Se debe aadir la creacin de los enlaces para cada asunto en el bucle For Each que recorre todos los mensajes.

<%i=0 For Each objMessage In objFolderInbox.Messages i=i+1%> <tr> <td><%=Prioridad(objMessage.Importance)%></td> <td><%=objMessage.Sender%></td>

138

Grupo EIDOS

6. CDONTS y ASP

<td><a href="LeerMensaje.asp?idmensaje=<%=i%>"><%=objMessage.Subject%></a></td> <td><%=objMessage.TimeSent%></td> </tr> <%Next%> Cdigo fuente 115

Como se puede comprobar en los enlaces se hace referencia a una pgina llamada LeerMensaje.asp, es en esta pgina dnde se encuentra el cdigo necesario para mostrar el contenido del mensaje solicidado. La pgina de lectura de mensajes va a tener un rea de texto para mostrar el contenido del mensaje, y tambin dos botones: uno para volver a la pgina anterior, y otro para eliminar el mensaje que estamos leyendo. La pgina encargada de borrar el mensaje no es la de lectura de los mimos, sino que el mensaje ser borrado en la pgina que muestra el contenido de al bandeja de entrada. Antes de nada veamos el Cdigo fuente 116 de la pgina de lectura de mensajes.

<%'recuperamos la sesin con el servidor SMTP Set objSession=Session("oSession") Set colMensajes=objSession.Inbox.Messages 'recuperamos el identificador del mensaje idmensaje=Request.QueryString("idmensaje") 'se recupera el mensaje correspondiente de la coleccin Set objMensaje=colMensajes.Item(idmensaje)%> <HTML> <HEAD> <META NAME="GENERATOR" Content="Microsoft Visual Studio 6.0"> </HEAD> <BODY> <%'se obtiene el objeto que representa al remitente Set objAddressEntry=objMensaje.Sender%> <b>De:</b> <%=objAddressEntry.Name%> (<%=objAddressEntry.Address%>)<br> <b>Asunto:</b> <%=objMensaje.Subject%><br> <form action="ListadoMensajes.asp" method="post"> <textarea rows="10" cols="50"> <%=objMensaje.Text%> </textarea><br> <input type="submit" name="Volver" value="Volver"> <input type="hidden" name="idmensaje" value="<%=idmensaje%>"> <input type="submit" name="Eliminar" value="Eliminar"> </form> <%'si existen adjuntos en el mensaje se muestran enlaces a los mismos If objMensaje.Attachments.Count>0 then%> <b>Adjuntos:</b><br> <ul> <%For Each objAdjunto in objMensaje.Attachments 'se almacena el adjunto en un directorio del servidor Web objAdjunto.WriteToFile(Server.MapPath("/cursoasp30")&"\"&objAdjunto.Name) 'se construye el enlace al adjunto%> <li><a href="<%=objAdjunto.Name%>"><%=objAdjunto.Name%></a><br></li> <%Next%> </ul> <%End if%> </BODY> </HTML> Cdigo fuente 116

139

Desarrollo de aplicaciones COM+ para Internet / Intranet con ASP 3.0

Grupo EIDOS

Como se puede ver tambin se crean enlaces para los adjuntos del mensaje si los tiene. Los ficheros adjuntos se graban en el servidor Web con el mtodo WrietToFile() del objeto Attachment, para que los pueda recupera el destinatario del mensaje. La forma de grabar el adjunto en una misma carpeta y aprovechando el valor de su propiedad Name, no demasiado adecuado, ya que si existe un fichero adjunto con ese mismo nombre se sobreescribir. Veamos, en la Figura 33, el aspecto que ofrece esta nueva pgina.

Figura 33. Pgina de lectura del mensaje

La pgina LISTADOMENSAJES.ASP le pasa a LEERMENSAJE.ASP a travs del QueryString un parmetro para identificar el mensaje que deseamos leer. Igualmente la pgina LEERMENSAJE.ASP le devuelve a la pgina LISTADOMENSAJES.ASP este mismo identificador de mensaje para que cuando sea demandando la pgina LISTADOMENSAJES.ASP pueda eliminar el mensaje deseado. Para que la pgina LISTADOMENSAJES.ASP pueda eliminar el mensaje solicitado, deberemos aadir el Cdigo fuente 117 justo antes de empezar a recorrer la coleccin de mensajes presentes en la bandeja de entrada..

<%If Request.Form("Eliminar")<>"" Then 'se obtiene el mensaje que se desea borrar Response.Write "paso: "& Request.Form("idmensaje")

140

Grupo EIDOS

6. CDONTS y ASP

Set objMensaje=objFolderInbox.Messages.Item(Request.Form("idmensaje")) 'se borra objMensaje.Delete End if%> Cdigo fuente 117

Simplemente se obtiene el objeto Message correspondiente de la coleccin Messages y se le lanza el mtodo Delete(). En el siguiente enlace se encuentra el cdigo completo de este ejemplo.

141

El modelo COM
Introduccin a los componentes
Los componentes de software son unidades de cdigo ejecutable que proporcionan una funcionalidad especfica para una aplicacin. A la aplicacin que utiliza cdigo de un componente, creando objetos y llamando a sus propiedades y mtodos, se denomina cliente o contenedora. Las ventajas derivadas de la utilizacin de los componentes en el desarrollo de software pueden compararse a las de la produccin industrial en cadena: en vez de ser un nico fabricante el que se encargue, por ejemplo, de la construccin de todas y cada una de las piezas de un coche, existen varios fabricantes, cada uno de ellos especializado en una parte concreta (motor, amortiguadores, motores elctricos, chapa, caja de cambios, ...), que tienen funcionalidades diferentes. Cada uno de estos fabricantes trabaja de forma independiente a los dems, pero siguiendo unos estndares industriales para que luego las piezas encajen entre s para formar una nica unidad funcional: el coche. Del mismo modo, la utilizacin de los componentes en una aplicacin informtica permite que varias personas distintas, de la misma o distinta empresa, trabajando con distintos lenguajes de programacin, puedan crear pequeos bloques de cdigo con una funcionalidad especfica. Cada uno de estos componentes deben ajustarse a unos estndares o protocolos, para que luego puedan encajar entre s y formar una aplicacin con funcionalidad completa. Uno de estos protocolos para que los componentes puedan interaccionar entre s es el modelo COM que propone Microsoft. El modelo DCOM permite que componentes que se ejecutan en mquinas distintas puedan comunicarse a travs de la red. Otro de estos protocolos es el modelo CORBA. Cada uno de estos modelos tiene sus ventajas y sus inconvenientes. El modelo CORBA est respaldado por una coalicin de varios cientos de empresas,

Desarrollo de aplicaciones COM+ para Internet / Intranet con ASP 3.0

Grupo EIDOS

el OMG (Object Management Group), y lleva varios aos de ventaja respecto al modelo COM/DCOM de Microsoft. Los pasos para el diseo de componentes son los siguientes: Establecer qu servicios debe proporcionar el componente. Determinar qu objetos son necesarios para dividir la funcionalidad del componente de una manera lgica. Decidir cmo se ejecutarn mejor esos componentes en el mismo proceso o en un proceso aparte.

Conceptos
Objeto: Es la instancia de una clase. Clase: Plantilla que implementa los mtodos y propiedades para un objeto. Un solo componente COM puede contener varias clases. En tiempo de ejecucin, se crear un objeto creando una instancia de una clase. Interfaz: Grupos de funciones que exponen la funcionalidad del componente; a travs de este interfaz, los clientes y los componentes COM se comunican. Las interfaces proporcionan acceso estandarizado a los mtodos y propiedades (funcionalidad) disponibles en los componentes. Es ms, son el contrato entre el autor del componente y los desarrolladores de clientes que aseguran un acceso fiable a la funcionalidad aportada. Componente: Coleccin de clases COM empaquetadas en una unidad ejecutable, como puede ser una DLL o un EXE. Los componentes son independientes del lenguaje; es decir, no se definen sobre la base del lenguaje con que se construyeron, sino por las interfaces que soportan. El lenguaje usado para implementar un componente y sus clientes es irrelevante.

Especificacin COM
Las principales caractersticas del modelo COM son: Compatibilidad binaria: El modelo COM es una especificacin binaria. Esto significa que se pueden construir componentes COM con cualquier herramienta de desarrollo que soporte COM (Visual Basic, Visual C++, Visual J++, Delphi, etc), y esos mismos componentes pueden ser despus utilizados desde una aplicacin, o desde otro componente, escrito en cualquier lenguaje de programacin que soporte COM. Compatibilidad con sistemas operativos distintos: Los componentes COM deben desarrollarse para una plataforma especfica, como Windows NT o UNIX ya que no pueden ejecutarse en una plataforma que no sea para la que fueron escritos; sin embargo, s que pueden comunicarse con otros objetos COM situados en otras plataformas. Localizacin transparente: Permite usar un componente desde un cliente sin importar si ese componente pertenece al mismo proceso, a otro proceso en la misma mquina o a otro proceso en una mquina distinta.

144

Grupo EIDOS

7. El modelo COM

Reutilizacin del cdigo: Es la mayor ventaja de COM. Los componentes COM contienen clases que exponen grupos de mtodos, conocidos como interfaces, a travs de los cuales los clientes se comunican con objetos. Dado que estos interfaces estn bien documentados, el cdigo que implementan puede reutilizarse con facilidad.

El Modelo de Objetos Componentes (COM) es una especificacin de cmo estos objetos interactan con sus clientes. Como tal especificacin, COM define una funcionalidad estndar, pero no define cmo debe implementarse, sino qu es lo que debe tener. Entre lo que especifica COM se incluye lo siguiente: Cmo se crean las instancias de los objetos COM. Cmo acceden los clientes a las caractersticas de estos objetos La responsabilidad de su auto-destruccin cuando ya no quedan instancias suyas.

Adems de lo que es meramente la especificacin, existen "bibliotecas COM", su runtime, que contienen: Una reducida API para facilitar la creacin de aplicaciones COM, tanto clientes como servidoras. Esta API ofrece, por un lado, las funciones para trabajar con clientes y, por otro, las que permiten a los servidores proporcionar objetos COM. Servicios de localizacin, a travs de los cuales se averigua en qu servidor se encuentra el objeto y la ubicacin dentro de ste. Indirectamente esto incluye un soporte entre el identificador de objeto y el paquete en el que se encuentra su cdigo, que normalmente se obtiene a travs del Registro de Windows. De esta manera, los clientes quedan totalmente independientes de los posibles cambios de ubicacin de los objetos COM, ya sean cambios de paquete o -incluso- cambios de mquina servidora. Servicios para la transparencia en las llamadas a procedimientos remotos, es decir, cuando un objeto est ejecutndose en un proceso aparte o en una mquina distinta desde la que se usa.

Ventajas del uso de componentes


Veamos las ventajas del uso de componentes, en general, y en particular para las aplicaciones ASP: Se divide un problema en partes ms pequeas, ms fciles de entender y resolver, y luego se unen todas las partes. Reduce la complejidad, que queda oculta dentro del componente, disfrazada bajo un interfaz ms amigable. Reparto del trabajo entre distintos equipos de programadores, que pueden trabajar simultneamente en paralelo, disminuyendo el plazo de desarrollo de la aplicacin. Ms fcil mantenimiento y mejora de cada parte individualmente. Los componentes son reutilizables. Si queremos reutilizar el cdigo de una pgina ASP, hay que copiar las lneas de script, pero si hemos usado componentes, stos pueden reutilizarse en la nueva pgina.

145

Desarrollo de aplicaciones COM+ para Internet / Intranet con ASP 3.0

Grupo EIDOS

Pueden ser escritos es cualquier lenguaje, y luego utilizados en una aplicacin en otro lenguaje. Un componente escrito en C++ puedo ser usado en una aplicacin VB o, en nuestro caso, desde el script de una pgina ASP. Esto permite que el componente pueda ser desarrollado en el lenguaje en el que se encuentre ms cmodo el programador. Se pueden comprar a terceras partes, empresas especializadas en el desarrollo de componentes. Existen muchas empresas de este tipo especializadas en el desarrollo de componentes para uso en aplicaciones ASP. Ms rapidez de ejecucin: los componentes estn compilados, mientras que el script de una pgina ASP es interpretado. Adems, hay cierta funcionalidad que no podemos conseguir con un lenguaje de script, que no deja de tener sus limitaciones. Proteccin del cdigo: el script se puede ver y modificar; un componente compilado no. Es cierto que a partir del IIS 5.0 puede utilizarse la herramienta Windows Script Encoder para codificar el script de las pginas ASP, convirtindolas en caracteres ASCII ilegibles, pero esto no supone una solucin segura ni definitiva. Sin embargo, el cdigo de un componente compilado en una DLL es inaccesible. Los depuradores de VB y sobre todo VC++ son mejores que el script debugger de pginas ASP.

Los interfaces
Un interfaz representa un contrato entre un servidor y un cliente. Un objeto siempre implementar la funcin para un interfaz determinado y de una manera estndar. El contrato posibilita el desarrollo de objetos en cualquier lenguaje, mientras stos expongan sus interfaces acorde con el estndar COM. En virtud del contrato puede afirmarse que: El interfaz tiene un Identificador nico Global (IID). Las funciones tendrn siempre los mismos parmetros y conservarn sus tipos. Las funciones devolvern siempre el mismo tipo de valor. Las funciones se implementarn cada una siguiendo la semntica del interfaz. El interfaz tendr siempre el mismo conjunto de funciones. No se pueden aadir ni borrar funciones.

Un interfaz no puede instanciarse en un objeto. Las clases que implementen el interfaz s pueden ser instanciadas. Encapsular funcionalidades en los objetos a los que se acceder a travs de interfaces hacen de COM un sistema abierto y extensible; cualquiera puede proporcionar una implementacin de un interfaz definida y desarrollar aplicaciones que usen esos interfaces. Un desarrollador que use luego estos componentes no necesitar entender las implementaciones internas de los interfaces; tan slo necesitar entender las especificaciones del interfaz. El diseo y utilizacin de interfaces es mucho ms importante en grandes aplicaciones. En aplicaciones empresariales minimiza las interdependencias. As, el cambiar un componente no requiere redisear todos los dems. Un sistema bien diseado y construido con interfaces COM

146

Grupo EIDOS

7. El modelo COM

permite a los usuarios de los componentes trabajar independientemente de los desarrolladores de componentes y, tambin, hacer pruebas rpidamente. La mayora de las herramientas de desarrollo que soportan COM permiten la creacin de clases, objetos y componentes. Sin embargo, hay diferencias en cmo permiten a los programadores acceder a los interfaces en cada lenguaje. Para el programador de Visual Basic, los interfaces permanecen ocultos. Cada vez que se crea una nueva clase, se crea automticamente un interfaz por defecto. Este interfaz est compuesto por todos los mtodos pblicos de la clase. Visual Basic 6.0 permite que una clase implemente un interfaz COM previamente definido, por ejemplo, usando MIDL en una biblioteca de tipos. En C++ los interfaces se implementan como clases abstractas. El programador de C++ trabaja directamente con clases e interfaces. La biblioteca ATL proporciona un mecanismo simple para generar el cdigo necesario para usar e implementar interfaces. Por definicin, un interfaz COM no puede cambiar una vez haya sido utilizado. Se dice que el interfaz es inmutable. Aunque ni los mtodos ni la firma puedan cambiar, la implementacin de estos componentes s que puede variar. La interfaz contractual, entendida por el cliente y el componente, proporciona la base de unas actualizaciones de versiones seguras. Mientras las interfaces permanezcan inmutables, los componentes podrn intercambiarse. Los componentes con enlace temprano no pueden cambiar sus interfaces; sin embargo, los que usan enlace tardo tienen la capacidad de aadir, borrar y cambiar mtodos. Cuando se actualicen estos componentes, hay que asegurarse de que no se rompe el contrato de la interfaz. Dado que las funcionalidades estn agrupadas en interfaces del modelo de programacin COM, se pueden aadir nuevas funcionalidades aadiendo nuevas interfaces y manteniendo las anteriores, aunque como veremos, desde una pgina ASP slo podemos acceder a un interfaz.

Identificadores nicos Globales (GUIDs)


Cuando un cliente necesita de los servicios de un componente, realiza una peticin de la clase e interfaz deseada al sistema operativo. COM utiliza Identificadores Globales nicos (GUIDs) para identificar cada interfaz y clase. Un GUID es un nmero entero de 128 bits nico en el tiempo y espacio. A estos nmeros se les asigna tambin un texto legible slo por conveniencia y con un mbito ms local (el PROGID). Este GUID asegura que no se solicitar ningn componente COM ni interfaz ni mtodo accidentalmente, incluso en redes de miles de objetos componentes. Adems de las clases y los interfaces, COM utiliza GUIDs para identificar entidades que requieren valores nicos. As, los GUIDs reciben nombres distintos segn la entidad a la que se aplique: CLSID: para clases IID: para interfaces LIBID: para libreras de tipos CATID: para categoras (tipos enumerados)

147

Desarrollo de aplicaciones COM+ para Internet / Intranet con ASP 3.0

Grupo EIDOS

Los GUIDs pueden generarse utilizando las herramientas "guidgen" o "uuidgen", o realizando llamadas a la funcin del API Win32 CoCreateGuid. Guidgen.exe y uuidgen.exe se instalan con Visual Studio en el directorio de Visual Studio\Common\Tools. Estos generadores utilizan un complejo algoritmo definido por la Open Software Foundation DCE estndar. El GUID generado depende del instante en que se llam a la funcin y del nmero de su tarjeta de red (o de otra caracterstica nica en ordenadores sin tarjeta de red). Utilizar un ordenador con tarjeta de red para generar el GUID, garantiza que el nmero obtenido ser nico. Cuando se desarrollan componentes se trabaja con muchos CLSIDs. El teclear estos GUIDs directamente en el cdigo es engorroso y suelen cometerse errores. Para simplificar esta operacin, se utiliza un texto "legible" que sustituye a esos CLSIDs. Los PROGID, o identificadores de programas, son cadenas de caracteres que identifican una clase y que estn asociadas a un CLSID en el registro de Windows. Una vez establecida la relacin entre el CLSID y el PROGID se puede utilizar ste para crear componentes. Algunos lenguajes como Visual Basic, crean automticamente PROGID y GUID para cada clase. Visual Basic usa el esquema nombreproyecto.nombredeclase como el PROGID. El gran inconveniente que tiene el uso de los PROGID es que puede generar conflictos con otros nombres ya existentes en la red, ya que no est garantizada su unicidad, como sucede con los CLSIDs.

Enlace temprano y tardo


El enlace tardo (late binding) ocurre en cualquier lenguaje en el que se use un tipo de datos neutral para llamar a un objeto. En Visual Basic, esto se hace declarando una variable del tipo Object. En Visual C++ se hace utilizando el interfaz IDispatch para invocar los mtodos del objeto. El compilador o la herramienta de desarrollo no puede comprobar los mtodos, propiedades, tipo y sintaxis de ninguna llamada a los mtodos del objeto en tiempo de compilacin, ya que no se ha definido el tipo de objeto concreto. El Cdigo fuente 118 es un ejemplo de enlace tardo a un objeto Connection de ADO en Visual Basic.

Dim objCnx As Object Set objCnx = CreateObject(ADODB.Connection) objCnx.metodo Cdigo fuente 118

Una ventaja del enlace tardo es que no es necesario identificar el objeto que se quiere crear hasta el tiempo de ejecucin. Por otro lado, una desventaja es que el compilador no puede comprobar la sintaxis. Como resultado de ello, errores como el pasar un nmero incorrecto de parmetros o con tipos incorrectos no se detectarn hasta el tiempo de ejecucin. Aparte de esto, el enlace tardo es menos eficiente que el enlace temprano, ya que requiere un mayor nivel de comunicacin entre el cliente y el componente para cada operacin. Algunos entornos, tales como los motores de scripts, slo soportan el enlace tardo para llamar a los componentes. Este es el caso de las pginas ASP. Por el contrario, el enlace temprano (early binding) ocurre cuando se conoce el tipo del objeto en tiempo de compilacin. Se establece un enlace temprano cuando se declaran variables de un tipo especfico de datos. En ese caso el compilador puede contrastar todas las referencias del objeto con las
148

Grupo EIDOS

7. El modelo COM

que define el entorno del objeto (normalmente incluidas en bibliotecas de tipos). Las bibliotecas de tipos pueden ser ficheros *.TLB independientes o estar incorporadas en los componentes. En Visual Basic, los enlaces tempranos requieren que se haga una referencia al componente y a la clase especfica usada cuando se declaran variables de ese tipo de objeto. Visual C++ utiliza la clusula #import o cabeceras de interfaces para obtener la informacin de tipos de los componentes. El Cdigo fuente 119 es un ejemplo de enlace temprano a un objeto Connection de ADO en Visual Basic.

Dim objCnx As ADODB.Connection Set objCnx = New ADODB.Connection objCnx.metodo Cdigo fuente 119

Dado que el compilador tiene acceso a la biblioteca de tipos del objeto, puede comprobar la sintaxis de todas las llamadas que usan esa variable de objeto e informarle de cualquier error sintctico en tiempo de diseo. Los mtodos de los componentes que se llamen utilizando enlace temprano son los ms eficientes en trminos de rendimiento. Dado que se dispone de la informacin en tiempo de compilacin, el compilador puede generar un cdigo ms ptimo para las llamadas. Los entornos de programacin como Visual Basic y Visual C++ soportan la creacin de componentes que sern llamados con enlaces tempranos o tardos. No as los motores de script que utilicemos desde una pgina ASP, que slo permiten el enlace tardo.

Espacio de proceso de un componente


Un componente que se ejecuta en el mismo proceso que la aplicacin comparte el mismo espacio de memoria que la aplicacin contenedora; sta puede ser una aplicacin propiamente dicha u otro componente que se ejecuta en el mismo proceso. Los componentes que se ejecutan en el mismo proceso se denominan COM DLLs. Los componentes que se ejecutan en otro proceso aparte tienen su propio espacio de memoria separado del de la aplicacin contenedora. Estos componentes se denominan COM EXEs. Este curso se centra en la construccin de componentes COM DLLs, que son los que soportan los Servicios de Componentes (antes denominados MTS). Visual Basic 6.0 y Delphi (entre otros) utilizan el trmino "DLL ActiveX" para referirse a los COM DLLs y "EXE ActiveX" para los COM EXEs. Esta denominacin es equivalente a la de COM DLL y COM EXE, respectivamente. Los controles ActiveX son un tipo especial de COM DLL que proporciona un interfaz visual al usuario. Obviamente, este tipo de componentes no son de utilidad en el script de servidor de una aplicacin ASP, aunque s podran serlo como controles ActiveX que se ejecutaran el la mquina cliente. Cada tipo de componente tiene sus ventajas e inconvenientes:

149

Desarrollo de aplicaciones COM+ para Internet / Intranet con ASP 3.0

Grupo EIDOS

Un componente DLL proporciona un acceso al objeto ms rpido, pero es menos tolerante al fallo: si el componente DLL falla, lo har el proceso servidor completo. En un componente EXE, los fallos no afectan a todos los procesos del sistema, slo al proceso en el que se encuentra el componente EXE. Es ms lento porque las llamadas del mtodo han de ser reconfiguradas entre los procesos.

El interfaz IUnknown
Por convencin, el nombre de un interfaz siempre lleva el prefijo "I". Para poder utilizar un objeto, un cliente necesita conocer qu interfaces soporta ese objeto. Segn la especificacin COM, un objeto debe poder ser consultado por un cliente para averiguar esta informacin. Esto se consigue gracias al interfaz denominado IUnknown, que deben soportar todos los objetos. Es ms, cualquier otro interfaz en el proyecto debe incluir la funcionalidad proporcionada por el interfaz IUnknown. Aunque Visual Basic maneja muchas de estas cuestiones sin que nos demos cuenta, de forma transparente para nosotros. Tradicionalmente, los clientes destruyen los objetos cuando ya no los necesitan. Debido a que mltiples clientes de diferentes procesos, e incluso de diferentes ordenadores, pueden conectarse y utilizar un objeto, cuando un cliente destruye un objeto podra dejar a otros clientes "colgados". Por eso es conveniente mantener un contador, de forma que si el contador es mayor que "0", significa que el objeto sigue en activo; y si indica un nmero igual a "0", el objeto se autodestruye. Para llevar este recuento, el interfaz IUnknown tiene dos funciones: AddRef: Incrementa en uno el contador del objeto cuando ste asigna un puntero de interfaz Se llama a AddRef cuando utiliza una sentencia Set para inicializar una variable del objeto. Release: Disminuye en uno el contador cuando una variable que seala al objeto se sale del mbito. Se llama esta funcin cuando se asigna Nothing a una variable del objeto, o cuando la variable sobrepase el mbito de su definicin.

Adems, el interfaz IUnknown presenta la funcin QueryInterface, que permite a los clientes preguntar por otros interfaces proporcionados por el objeto. Si el objeto soporta ese interfaz, QueryInterface devolver un puntero a ese interfaz. Luego podr utilizar los mtodos que contiene ese interfaz para comunicarse con el objeto.

Windows DNA
Se agrupa bajo el nombre de Windows DNA (Windows Distributed InterNet Application Architecture) a un conjunto de tecnologas que permiten desarrollar aplicaciones distribuidas para internet/intranet usando el modelo de n capas. Los servicios DNA ofrecen interfaces COM para que otras aplicaciones puedan utilizarlos. Puedo usar cualquier herramienta de desarrollo que soporte COM para escribir componentes para el DNA. Windows DNA se compone de los siguientes servicios (todos ellos basados en COM): Componentes COM

150

Grupo EIDOS

7. El modelo COM

HTML dinmico (DHTML) Servidor IIS Pginas ASP Componentes de acceso a datos (MDAC) Servicios de componentes (antes MTS) Colas de mensajes (MSMQ) Active Directory (ADSI) Servicios de seguridad de Windows

151

Componentes en Visual Basic


Introduccin
En este tema vamos a empezar a construir nuestros propios componentes. El entorno de trabajo utilizado en este tema y en los posteriores ser un sistema operativo Windows 2000 Server, con el servidor web IIS 5, con Visual Basic 6 y Visual InterDev 6, y el Internet Explorer 5. Habr ocasiones en que existan diferencias en la funcionalidad de los componentes si stos se ejecutan en Windows 2000 o en Windows NT. En esos casos se har mencin de estas diferencias.

Componentes en Visual Basic y Visual C++


Despus de haber visto en temas anteriores que desde pginas ASP podemos utilizar un gran nmero de componentes ya escritos (componentes ActiveX de servidor, componentes ADO, componentes CDONTS, ), vamos a avanzar un paso ms. Escribiremos estos componentes nosotros mismos, y los utilizaremos despus desde las pginas ASP de nuestra aplicacin web. Al ser COM una especificacin binaria, podemos escribir los componentes en el lenguaje de programacin que nos resulte ms cmodo, y que ms se adapte a los resultados que queremos obtener. Por supuesto que el lenguaje de programacin elegido deber ser capaz de generar componentes que cumplan con la especificacin COM. Entre estos lenguajes estn Visual Basic, Visual C++, Delphi, etc. El lenguaje que vamos a emplear para los ejemplos va a ser el Visual Basic, y esto ser as por varios motivos.

Desarrollo de aplicaciones COM+ para Internet / Intranet con ASP 3.0

Grupo EIDOS

El primero, y ms importante, es que el Visual Basic es un lenguaje conocido, al menos a un nivel bsico, por la mayora de los programadores, y no habr necesidad de dedicar tiempo y esfuerzo al aprendizaje de un lenguaje de la complejidad de Visual C++. Adems el Visual Basic, a pesar de su facilidad de uso, nos permite hacer prcticamente lo mismo que podramos hacer con Visual C++. Es cierto que no podremos alcanzar el nivel de control que puede lograrse programando en Visual C++, pero esto es as porque el Visual Basic simplifica muchas de las operaciones que en Visual C++ tendramos que codificar nosotros. Por ejemplo, todos los componentes COM implementan el interfaz IUnknown, pero esto a m como programador me queda oculto por el Visual Basic. Tambin el Visual Basic crea automticamente el interfaz por defecto, agrupando en l todos los mtodos pblicos del componente. Ser a este interfaz por defecto al nico al que tengamos acceso desde el script de una pgina ASP. Por supuesto que programar los componentes en Visual C++ tiene una serie de ventajas, aparte de la desventaja principal de la mayor dificultad del lenguaje. Entre estas ventajas estn: El lenguaje Visual C++ tiene mayor potencia y flexibilidad que el Visual Basic, y puedo lograr un mayor control sobre la funcionalidad del componente. El rendimiento conseguido por un componente escrito en Visual C++ es mayor que el de uno escrito en Visual Basic. El depurador de Visual C++ es ms completo que el de Visual Basic. Los componentes escritos en Visual C++ pueden beneficiarse de algunos servicios COM+ a los que no tienen acceso (por el momento) los componentes escritos en Visual Basic. Entre estos servicios estn el pooling de objetos. Este concepto es parecido al del pooling de conexiones de una base de datos: cuando una aplicacin cliente ha acabado de utilizar una conexin con la base de datos, en vez de ser destruida, esta conexin se guarda en un pool (como si dijramos un almacn) de donde puede ser utilizada luego por otra aplicacin cliente que la necesite. De igual manera, en el pooling de objetos, cuando un cliente ha terminado de utilizar un objeto, ste no se destruye sino que se guarda en el pool, de donde puede ser recuperado y reutilizado por otro cliente

Un primer ejemplo de componente


Vamos a proceder a escribir nuestro primer componente. Este componente va a ser muy simple, pero de todas formas nos tomaremos un tiempo en pensar detenidamente cmo vamos a disearlo. La funcionalidad de este componente ser la de calcular el resultado de incrementar una cantidad en un 7 por ciento de su valor. Como se ve, no parece necesario crear un componente para esta operacin tan sencilla, pero nos vendr muy bien como primer ejemplo.

Fases en el diseo del componente


Lo primero en el diseo de un componente sera definir claramente qu funcionalidad espero que tenga. Recordemos que un componente puede compararse con una caja negra que tiene una funcionalidad, a la que yo puedo acceder a travs de un interfaz, sin preocuparme en absoluto de cmo
154

Grupo EIDOS

8. Componentes en Visual Basic

se lleva a cabo internamente esa funcionalidad, ni siquiera en qu lenguaje de programacin est escrito el componente. La funcionalidad del componente ser la de calcular la nueva cantidad, resultado de incrementar en un porcentaje del 7 por ciento. El lenguaje de programacin ya hemos dicho que va a ser el Visual Basic, que nos permite con relativa facilidad obtener unos resultados satisfactorios. Para acceder a la funcionalidad del componente, disearemos un interfaz formado por un nico mtodo, que recibe como parmetro la cantidad sobre la que queremos efectuar el clculo. Ms adelante construiremos componentes mucho ms complicados que requieran un anlisis ms completo, pero para ste no necesitamos ms que ponernos ya manos a la obra.

Creacin del proyecto ActiveX DLL


Arrancamos Visual Basic 6.0, y en la ventana de Nuevo Proyecto, elegimos la opcin ActiveX DLL, pulsando a continuacin el botn Abrir. Visual Basic pone por defecto el nombre de Proyecto1 para el proyecto y el nombre de Class1 para el mdulo de clase. Vamos a cambiarlos por otros ms descriptivos. Los nombres que elijamos sern los que luego formen el ProgId del componente, una vez compilado y registrado en el equipo.

Figura 34

Cada mdulo de clase de Visual Basic define un tipo de objeto. Es la plantilla que define los mtodos y propiedades para un objeto. Los objetos se crean, en tiempo de ejecucin, al crear una instancia de una clase. Un componente puede contener varios mdulos de clase, y servir por tanto de plantilla para la creacin de varios tipos de objeto. Es lo que se llama un COM Server. En este caso, nuestro componente slo contendr un mdulo de clase.

155

Desarrollo de aplicaciones COM+ para Internet / Intranet con ASP 3.0

Grupo EIDOS

Para cambiar el nombre del proyecto, seleccionarlo haciendo click sobre l en la ventana del Explorador de proyectos, y luego modificando su nombre en la ventana de Propiedades (cambiarlo a CompPorcentaje). Repetir la operacin seleccionando el mdulo de clase en la ventana del Explorador de proyectos y luego modificando el nombre en la ventana de Propiedades (cambiarlo a Porcentaje).

Diseo del interfaz


Para disear el interfaz que presentar el componente, puedo hacerlo codificando directamente los mtodos (en este caso slo uno) en la ventana de edicin de cdigo, pero es ms cmodo hacerlo usando el Generador de clases. Esta utilidad aparece en el men Complementos. De no ser as, pulsar dentro del men Complementos la opcin Administrador de complementos. En la ventana que aparece, seleccionar la utilidad Generador de clases de VB 6, y activar las casillas de verificacin Cargado/Descargado y Cargar al iniciar (si queremos que siempre que iniciemos el Visual Basic est disponible esta utilidad en el men de Complementos). Ahora la utilidad est disponible en el men Complementos, y no hemos de hacer ms que seleccionarla para que se inicie. Se muestra un mensaje de advertencia, debido a que el mdulo de clase no fue creado desde el Generador, sino al crear el nuevo proyecto; responder que S. Una vez abierta, seleccionar en el panel izquierdo el mdulo de clase (en este caso lo hemos llamado Porcentaje), y pulsando sobre l con el botn derecho seleccionar Nuevo mtodo.

Figura 35

En la ventana del Generador de mtodos que aparece, similar a la de la Figura 36, asignarle un nombre al mtodo. Le llamaremos calcular. En esta misma ventana, pulsar el botn que aparece etiquetado con un signo +, para definir el argumento que va a recibir este mtodo.

156

Grupo EIDOS

8. Componentes en Visual Basic

Figura 36

En la nueva ventana Agregar argumento que aparece, similar a la de la Figura 37, darle un nombre al argumento (por ejemplo cantidad), activar la casilla de verificacin de ByVal, y seleccionar Variant de la lista desplegable Tipo de dato. Ms adelante veremos los problemas que se nos pueden plantear al utilizar tipos de datos distintos de Variant dentro de un componente que luego usemos desde una pgina ASP; recordemos que el VBScript, como JavaScript, es un lenguaje de script dbilmente tipado, donde slo existe el tipo de dato Variant.

Figura 37

Al activar la casilla de verificacin de ByVal, estamos indicando que el parmetro se pasar por valor, es decir, el mtodo recibir internamente una copia del valor que se le pase, y trabajar con esa copia, y no con el valor original. La otra forma de pasar el valor sera ByRef, por referencia, que es la que se
157

Desarrollo de aplicaciones COM+ para Internet / Intranet con ASP 3.0

Grupo EIDOS

usa si usamos explcitamente la palabra ByRef o si no indicamos absolutamente nada, ya que es el valor por defecto. Despus de pulsar Aceptar, y ya de vuelta en la ventana del Generador de mtodos, seleccionaremos Variant de la lista desplegable de Tipo de datos de retorno (es decir, estamos definiendo un mtodo que ser una funcin de Visual Basic, en vez de un procedimiento). El resultado final ser el de la Figura 38. Pulsando Aceptar volvemos a la ventana del Generador de clases, donde ya podemos ver el mtodo que acabamos de declarar.

Figura 38

Es recomendable, antes de salir de la utilidad Generador de clases, seleccionar la opcin Actualizar proyecto del men Archivo, para asegurarnos de que los cambios que acabamos de introducir en el interfaz tienen efecto, y no los perdemos al salir. Incluso antes de cerrar la utilidad podemos ver, en la ventana de edicin de cdigo que queda debajo de la del Generador de clases, que se genera el Cdigo fuente 120, necesario para implementar el mtodo recin creado.

Public Function calcular(ByVal cantidad As Variant) As Variant End Function Cdigo fuente 120

Cerremos ya la utilidad sin miedo. Ya en la ventana de edicin de cdigo, escribamos las lneas necesarias para que el mtodo tenga la funcionalidad que queremos. Esto se reduce a la lnea que aparece en el Cdigo fuente 121.

158

Grupo EIDOS

8. Componentes en Visual Basic

Public Function calcular(ByVal cantidad As Variant) As Variant calcular = cantidad * 1.07 End Function Cdigo fuente 121

Guardemos el mdulo de clase (PORCENTAJE.CLS) y el proyecto (COMPPORCENTAJE.VBP) en la carpeta que queramos, y ya estamos en disposicin de generar la DLL.

Generacin de la DLL y registro del componente


Para generar la DLL, no tenemos ms que seleccionar la opcin Generar CompPorcentaje.dll dentro del men Archivo. Esto crear el fichero DLL en la ubicacin que hayamos elegido. Pero al mismo tiempo que se ha generado la dll, Visual Basic se ha encargado de registrar el componente en nuestro equipo. Comprobmoslo. Si en el men Inicio seleccionamos Ejecutar y tecleamos regedit, se inicia el editor del registro de Windows. Recordar siempre que no debemos modificar nada del registro a no ser que estemos completamente seguros de lo que estamos haciendo. En este caso nos limitaremos a comprobar que el componente est registrado, pero no modificaremos absolutamente nada. En el registro es posible buscar por el ProgId del componente y por el CLSID. Si expandimos, dentro del editor del registro, la carpeta etiquetada como HKEY_CLASSES_ROOT, podremos encontrar una carpeta denominada CompPorcentaje.Porcentaje, como se muestra en laFigura 39, que contiene la informacin del registro del componente que acabamos de generar. Como podemos ver, el ProgId que genera el Visual Basic para el componente est formado por el nombre del proyecto y el nombre del mdulo de clase, separados por un punto. Este ProgId ser el que utilicemos al instanciar el componente desde nuestra pgina ASP. Si expandimos esta carpeta, podemos seleccionar con un click la subcarpeta Clsid que aparece, y en el panel de la derecha aparecer el GUID asignado al componente.

Figura 39

Si ahora seleccionamos la opcin Buscar del men Edicin, e introducimos como valor de bsqueda el valor del CLSID, encontraremos algo similar a laFigura 40.

159

Desarrollo de aplicaciones COM+ para Internet / Intranet con ASP 3.0

Grupo EIDOS

Figura 40

Si quisiramos utilizar nosotros este componente en otro equipo, deberamos copiar el fichero COMPPORCENTAJE.DLL a la ubicacin del equipo destino que elijamos (normalmente se copian en la carpeta C:\WINNT\SYSTEM32, pero puede ser cualquier carpeta). A continuacin abriremos una ventana MSDOS y nos moveremos hasta esa carpeta, para escribir lo que indica el Cdigo fuente 122.

Regsvr32 CompPorcentaje.dll Cdigo fuente 122

Esto registrar el componente en el equipo. Vamos a comprobar ahora que podemos usar este componente desde una pgina ASP. Iniciamos el InterDev y creamos una pgina con el Cdigo fuente 123.

<%@ Language=VBScript %> <HTML> <HEAD> <META NAME="GENERATOR" Content="Microsoft Visual Studio 6.0"> </HEAD> <BODY> <% Set objPorcentaje = Server.CreateObject("CompPorcentaje.Porcentaje") Response.Write "El resultado es: " & objPorcentaje.calcular(1000) Set objPorcentaje = Nothing %> </BODY> </HTML> Cdigo fuente 123

Como el componente est registrado en la misma mquina en la que estamos usando el InterDev, ste es capaz de acceder al registro de Windows (concretamente a la type library) para proporcionarnos el IntelliSense: al escribir el nombre de la instancia del componente seguida del punto, nos aparece la lista de los mtodos disponibles (en este caso slo el mtodo calcular).
160

Grupo EIDOS

8. Componentes en Visual Basic

Al solicitar esta pgina desde el navegador, obtendremos el resultado correcto de 1070.

Rediseo del componente


Supongamos que decidimos redisear el componente, de tal forma que el parmetro del mtodo calcular no se pase por valor, sino por referencia, es decir, que el mtodo trabaje con el mismo valor original que se le pasa por parmetro, y no con una copia de uso interno del mtodo. Este cambio supone redisear el interfaz, porque vamos a modificar el mtodo calcular, que ahora no recibir el parmetro por valor, sino por referencia. No podemos redisear este mtodo desde la utilidad Generadora de clases. Ni siquiera eliminarlo y volverlo a crear. Tenemos que hacerlo manualmente desde la ventana de edicin de cdigo, borrando el cuerpo del mtodo y volvindolo a definir con la utilidad Generadora de clases. Ahora debemos dejar desactivada la casilla de verificacin de ByVal. Aprovecharemos tambin para hacer que el mtodo devuelva un booleano, en este caso True, para indicar que ha finalizado con xito. Esto tendr como resultado el Cdigo fuente 124.

Public Function calcular(cantidad As Variant) As Boolean End Function Cdigo fuente 124

Vemos que ahora, dentro de los parntesis, el nombre del parmetro no est precedido de la palabra ByVal. Con esto se sobreentiende ByRef, que es el valor por defecto para Visual Basic. Podramos haber conseguido lo mismo modificando nosotros manualmente todo el cdigo, en vez de usar la utilidad Generadora de clases. Aadamos ahora el cdigo necesario a la funcin. Esta vez hacemos el clculo del porcentaje y se lo asignamos al mismo parmetro, cantidad. Devolvemos como valor de retorno de la funcin el valor True. Todo esto tal cual aparece en el Cdigo fuente 125.

Public Function calcular(cantidad As Variant) As Boolean cantidad = cantidad * 1.07 calcular = True End Function Cdigo fuente 125

El problema se nos presenta ahora en el momento de recompilar, puesto que la dll est actualmente en uso por dos clientes: El Visual InterDev la est usando para proporcionarnos el IntelliSense. Esto tiene fcil arreglo: cerremos la ventana de edicin de la pgina ASP en que hemos utilizado el componente La aplicacin web est usando tambin el componente, puesto que al pedir la pgina desde el navegador se ha ejecutado la pgina y se ha cargado la dll en memoria. Si hemos tenido la
161

Desarrollo de aplicaciones COM+ para Internet / Intranet con ASP 3.0

Grupo EIDOS

precaucin de configurar, desde la consola de administracin de los servicios IIS, las propiedades de nuestra aplicacin web, en la pestaa Directorio, como se ve en la Figura 41, de tal forma que la Proteccin de la aplicacin est en el nivel Medio (agrupado) o Alto (aislado), podremos, desde esta misma ventana de configuracin del IIS, pulsar el botn Descargar, que descarga de memoria esta aplicacin web (y todas las que estuvieran agrupadas con ella).

Figura 41

Si con lo anterior no consiguiramos liberar la dll, deberemos ir a Inicio | Programas | Herramientas administrativas | Servicios. Dentro de la lista de servicios que aparece, buscaremos el denominado Servicio de admin. IIS, como se ve en la Figura 42. Pulsaremos sobre l con el botn derecho del ratn y seleccionaremos la opcin Detener. Esto detiene otros servicios aparte del de publicacin web, como la publicacin FTP y el correo SMTP. Despus de detener el servicio, debemos pulsar otra vez con el botn derecho del ratn y seleccionar la opcin Iniciar, para reiniciarlo. Luego tenemos que ir a la consola administrativa del IIS, en Inicio | Programas | Herramientas administrativas | Administrador de servicios Internet, y reiniciar manualmente el Sitio web predeterminado, que estar detenido como consecuencia de haber detenido el servicio de publicacin web. Esta operacin se ve en la Figura 43. Este proceso resulta pesado pero debe bastar para descargar definitivamente la dll.

162

Grupo EIDOS

8. Componentes en Visual Basic

Figura 42

Figura 43

La solucin definitiva, si todo lo anterior no es suficiente, es obvia: reiniciar el equipo. Esto no debe ser necesario en Windows 2000, mientras que en Windows NT es ms frecuente tener que recurrir a esta solucin extrema.

Para poder utilizar el nuevo componente, tendremos que modificar la pgina ASP, que quedar como en el Cdigo fuente 126.

<%@ Language=VBScript %>

163

Desarrollo de aplicaciones COM+ para Internet / Intranet con ASP 3.0

Grupo EIDOS

<HTML> <HEAD> <META NAME="GENERATOR" Content="Microsoft Visual Studio 6.0"> </HEAD> <BODY> <% Set objPorcentaje = CreateObject("CompPorcentaje.Porcentaje") cantidad = 1000 retorno = objPorcentaje.calcular(cantidad) Response.Write cantidad Set objPorcentaje = Nothing %> </BODY> </HTML> Cdigo fuente 126

Ahora creamos una variable de pgina llamada cantidad, a la que asignamos el valor 1000. Esta variable la pasamos como parmetro, y el mtodo del componente trabaja directamente con ella, con lo que al escribir despus su valor obtenemos el valor correcto de 1070. En cualquier caso, suele ser ms aconsejable pasar los parmetros a un mtodo por valor (ByVal) mejor que por referencia (ByRef). De esta forma conseguimos ms encapsulacin del cdigo del componente.

Reutilizacin del componente


El componente que acabamos de disear es un componente universal. Quiere esto decir que podemos usarlo desde cualquier aplicacin que permita el acceso a componentes COM. Esta es una de las principales ventajas de la componentizacin: la posibilidad de reutilizar el cdigo. Antes hemos visto cmo podamos utilizar el componente desde una pgina ASP. Vamos ahora a hacer un proyecto Visual Basic que tambin haga uso de l. Para eso seleccionaremos la opcin Agregar proyecto del men archivo, y seleccionaremos la opcin Exe estndar, como en laFigura 44.

Figura 44

164

Grupo EIDOS

8. Componentes en Visual Basic

Nombraremos al nuevo proyecto como PruebaPorcentaje. Aadimos al formulario un campo de texto y un botn, y les asignamos, mediante la ventana de Propiedades, los nombres que nos parezcan oportunos. El formulario quedar algo parecido a la Figura 45.

Figura 45

A este nuevo proyecto debemos aadirle la referencia al componente anterior CompPorcentaje, desde el men Proyecto | Referencias, y seleccionado la casilla de verificacin correspondiente al componente CompPorcentaje, como se ve en la Figura 46. De este modo Visual Basic nos facilitar el IntelliSense, y adems podremos utilizar el early binding.

Figura 46

Haciendo doble click sobre el botn, podemos escribir el cdigo necesario para el evento Click del mismo, que ser el del Cdigo fuente 127.
165

Desarrollo de aplicaciones COM+ para Internet / Intranet con ASP 3.0

Grupo EIDOS

Private Dim Dim Dim

Sub Command1_Click() objPorcentaje As CompPorcentaje.Porcentaje retorno As Boolean cantidad As Variant

cantidad = 1000 Set objPorcentaje = New CompPorcentaje.Porcentaje retorno = objPorcentaje.calcular(cantidad) Text1.Text = cantidad End Sub Cdigo fuente 127

Las lneas Dim objPorcentaje As CompPorcentaje.Porcentaje y Set objPorcentaje = New CompPorcentaje.Porcentaje slo son posibles gracias a que hemos incluido en el proyecto EXE la referencia al componente CompPorcentaje. Esto permite declarar la variable objPorcentaje como una variable de referencia a un objeto que se crear como una instancia a partir del mdulo de clase Porcentaje incluido en el proyecto ActiveX CompPorcentaje. Adems permite usar el operador New para hacer un enlace temprano, en tiempo de compilacin, con el cdigo de ese componente. Si no hubiramos incluido la referencia a CompPorcentaje, no podramos hacer nada de lo anterior, y tendramos que dejar el cdigo como se ve en el Cdigo fuente 128. El uso del mtodo CreateObject significa que no estamos haciendo enlace temprano, sino enlace tardo.

Private Dim Dim Dim

Sub Command1_Click() objPorcentaje As Object retorno As Boolean cantidad As Variant

cantidad = 1000 Set objPorcentaje = CreateObject("CompPorcentaje.Porcentaje") retorno = objPorcentaje.calcular(cantidad) Text1.Text = cantidad End Sub Cdigo fuente 128

En el Explorador de proyectos, pulsando con el botn derecho sobre el proyecto PruebaPorcentaje, debemos seleccionar la opcin Establecer como inicial, de tal forma que cuando pulsemos el icono de ejecucin de Visual Basic, sea ste el proyecto de arranque, se muestre el formulario, y podamos pulsar el botn. Esta pulsacin desencadenar la instanciacin del componente CompPorcentaje, y la invocacin al mtodo calcular, pasndole como parmetro, por referencia, la variable cantidad. A continuacin se le asigna su valor, ya actualizado por el mtodo, al campo de texto. Por supuesto que este proyecto EXE estndar podremos depurarlo desde el entorno de Visual Basic, estableciendo puntos de interrupcin con la tecla de funcin F9 y ejecutando paso a paso con F8.

166

Grupo EIDOS

8. Componentes en Visual Basic

Tipos de componentes
Hemos visto en los apartados anteriores que este primer componente que hemos desarrollado en Visual Basic era utilizable tanto desde una pgina ASP como desde un proyecto estndar de Visual Basic. Por supuesto que tambin podramos utilizarlo desde otra aplicacin escrita en cualquier lenguaje que soporte COM, como podra ser Visual C++. Es un componente que podramos llamar de uso universal. Podemos, sin embargo, disear componentes que sean ms restrictivos en cuanto a su aplicabilidad. Supongamos que desarrollamos un componente como el anterior, pero que permita la introduccin del nmero sobre el que vamos a calcular el porcentaje desde un campo de texto, es decir, que tenga un interfaz visual. Si creamos una pgina HTML desde cualquier editor de HTML, por ejemplo FrontPage, y seleccionamos la opcin Avanzadas del men Insertar, y a continuacin Control ActiveX, podemos marcar de la lista que aparece el control Control Calendar 9.0. El cdigo html que generar el FrontPage por nosotros quedara como el Cdigo fuente 129.

<html> <head> <meta http-equiv="Content-Type" content="text/html; charset=windows-1252"> <meta name="GENERATOR" content="Microsoft FrontPage 4.0"> <meta name="ProgId" content="FrontPage.Editor.Document"> <title>Pagina nueva 1</title> </head> <body> <p> <object classid="clsid:8E27C92B-1264-101C-8A2F-040224009C02" id="Calendar1" width="288" height="192"> <param name="_Version" value="524288"> <param name="_ExtentX" value="7620"> <param name="_ExtentY" value="5080"> <param name="_StockProps" value="1"> <param name="BackColor" value="-2147483633"> <param name="Year" value="2001"> <param name="Month" value="1"> <param name="Day" value="11"> <param name="DayLength" value="1"> <param name="MonthLength" value="2"> <param name="DayFontColor" value="0"> <param name="FirstDay" value="2"> <param name="GridCellEffect" value="1"> <param name="GridFontColor" value="10485760"> <param name="GridLinesColor" value="-2147483632"> <param name="ShowDateSelectors" value="-1"> <param name="ShowDays" value="-1"> <param name="ShowHorizontalGrid" value="-1"> <param name="ShowTitle" value="-1"> <param name="ShowVerticalGrid" value="-1"> <param name="TitleFontColor" value="10485760"> <param name="ValueIsNull" value="0"> </object> </p> </body> </html> Cdigo fuente 129

167

Desarrollo de aplicaciones COM+ para Internet / Intranet con ASP 3.0

Grupo EIDOS

Y en el navegador veremos algo como la Figura 47.

Figura 47

Podramos utilizar este componente desde una pgina ASP? La respuesta en no, lgicamente, puesto que las pginas ASP se ejecutan de forma desatendida en el servidor, y no podemos generar ningn interfaz visual (recordemos que dentro de una pgina ASP no podemos ni siquiera usar funciones estndar de Visual Basic como MsgBox). Con un cdigo en un pgina ASP como el del Cdigo fuente 130, no lograremos nada; no llegar a ver el control, porque en este contexto no tienen sentido los componentes con interfaz visual.

<% Set objCom = Server.CreateObject("MSCAL.Calendar") objCom.Day = 11 %> Cdigo fuente 130

Este sera un componente que sera utilizable en una aplicacin Visual Basic, o Visual C++, que tengan un interfaz visual, pero no dentro de una pgina ASP. Vayamos al caso opuesto. Si yo diseo un componente que acceda al modelo de objetos de ASP para escribir directamente cdigo HTML a travs del objeto Response, o para leer el valor de una variable de aplicacin (ms adelante veremos que todo esto es posible), estar haciendo uso de un modelo de objetos que no tendra ningn sentido si utilizase este componente desde una aplicacin Visual Basic o Visual C++. Este componente no sera utilizable en estas aplicaciones, pero s en pginas ASP.

168

Grupo EIDOS

8. Componentes en Visual Basic

Un componente ActiveX Server, como el adRotator, genera una cadena HTML, que tendra sentido slo si se estuviera ejecutando dentro de un servidor web, para enviar este resultado HTML a un navegador. Estos tres ejemplos de componentes mencionados son dependientes del entorno en el que se ejecutan, y no podran considerarse de aplicabilidad universal. Podramos disear componentes que fueran capaces de reconocer por s mismos el tipo de entorno en el que se ejecutan, es decir, si estn instanciados desde una pgina ASP o desde una aplicacin Visual Basic. Seran componentes que se adaptaran en cada caso al entorno, usando el modelo de objetos de ASP slo si reconocieran que lo tienen disponible. Esta capacidad de adaptacin los convertira en reutilizables dentro de una aplicacin Visual Basic. Hay componentes que hacen uso de otros componentes. Un caso muy frecuente es el de los componentes que acceden a una base de datos, haciendo uso de los componentes de ADO: Connection, Command y Recordset. Otro tipo de componente, que veremos con detalle ms adelante, es aqul que est involucrado en una transaccin sobre una base de datos. Estos componentes transaccionales tienen unas caractersticas especiales.

169

Modelos de aplicaciones cliente/servidor


Introduccin
Antes de continuar con el diseo de componentes para ASP, vamos a ver de forma resumida cmo ha ido evolucionando el concepto de aplicacin cliente/servidor, desde la idea tradicional hasta el modelo cliente/servidor que podemos conseguir en una aplicacin web y, en el caso que a nosotros nos interesa, en una aplicacin ASP.

Arquitectura cliente/servidor en dos capas


En las aplicaciones cliente/servidor tradicionales, como podra ser una aplicacin escrita en Visual Basic, slo hablamos de dos capas: Una sera la capa del servidor de base de datos, lo que se llama el backend. Es la capa encargada de servir los datos, garantizando su consistencia por medio de procedimientos almacenados y triggers. Esto es lo que se llama la lgica de datos. Otra sera la capa del cliente con el interfaz de usuario (el GUI), lo que se llama el frontend. Es la capa encargada de gestionar el interfaz de la aplicacin con el usuario, para mostrarle informacin, y tambin para recibirla a travs de formularios. Esto es lo que se llama la lgica de presentacin. Tambin es la capa encargada de asegurar que se cumplen las reglas conforme a la funcionalidad que queremos para nuestra aplicacin. Esto es lo que se llama la lgica de negocio.

Desarrollo de aplicaciones COM+ para Internet / Intranet con ASP 3.0

Grupo EIDOS

Conviene aclarar que habra que distinguir entre capas lgicas y capas fsicas. Cuando hablamos de capas normalmente nos referimos a capas lgicas. Por capas lgicas entendemos software, y por capas fsicas hardware. Lo usual es que la capa de datos est en una capa fsica separada, es decir, en un equipo separado donde slo se est ejecutando el software del gestor de base de datos, por ejemplo SQL Server u Oracle, y que la capa con la lgica de presentacin y la de datos est en otra capa fsica separada, es decir, el equipo del usuario, donde se ejecute la aplicacin cliente escrita en un lenguaje como Visual Basic. Pero es tambin muy normal que durante el tiempo de desarrollo estas dos capas lgicas estn en la misma capa fsica, es decir, que en nuestro equipo de desarrollo est ejecutndose el software del gestor de base de datos y el software de la aplicacin cliente. En estas aplicaciones cliente/servidor tradicionales hay una conexin permanente entre las dos capas, lo que las hace distintas de las aplicaciones web, como veremos a continuacin. Los equipos cliente en esta arquitectura tienden a ser lo que se llama fat clients. Necesitan bastante capacidad de proceso en su CPU para poder ejecutar la lgica de presentacin y la de negocio.

Arquitectura cliente/servidor en tres capas


El paso siguiente sera la de separar la capa cliente en dos capas, una para la lgica de presentacin y otra para la lgica de negocio. Podramos hablar entonces de tres capas: capa de presentacin, capa de negocio o intermedia, y capa de datos. De esta forma descargamos al cliente, para el que ya no es necesaria tanta capacidad de proceso en su CPU, y llevamos esta lgica de negocio a un servidor, que normalmente estar separado del servidor de base de datos. Podemos considerar que las aplicaciones web entran dentro de esta arquitectura, aunque con algunos matices. Una aplicacin web (y a nosotros nos interesan las aplicaciones ASP, que seran un caso particular) son aplicaciones especiales. Estn formadas por un conjunto de pginas HTML, ASP, y otros recursos, que se ejecutan dentro de un servidor. La capa de presentacin estara en el PC del cliente, donde se ejecuta el software del navegador (como puede ser el Internet Explorer o el Netscape Navigator), con la capacidad que ste tiene de interpretar el cdigo HTML para generar el interfaz de usuario, junto con la capacidad de ejecutar scripts escritos en lenguajes como JavaScript o VBScript, para dotar de un cierto dinamismo e interactividad a este interfaz. Otras posibilidades seran el uso de controles ActiveX, applets de Java, etc. La capa de negocio o intermedia estara en el servidor web, donde se ejecuta el software de servidor web (como puede ser el IIS o un servidor Netscape), con la capacidad de atender peticiones va HTTP de mltiples clientes. Esta lgica de negocio se codifica por medio de pginas web y componentes de servidor. La capa de datos est en el servidor de datos, donde se ejecuta el software del gestor de base de datos (como puede ser el SQL Server o el Oracle), con la capacidad de gestionar el acceso de clientes a los datos almacenados, asegurando su consistencia, administrando bloqueos, transacciones, haciendo uso de procedimientos almacenados, triggers, etc. Si la aplicacin va a tener que soportar accesos a la base de datos de muchos usuarios simultneamente, conviene que las capas de negocio y de datos estn en equipos fsicos indepen172

Grupo EIDOS

9. Modelos de apliciones cliente / servidor

dientes, para que el gestor de base de datos pueda ejecutarse de una forma mucho ms eficiente, ya que consume bastante memoria, CPU y accesos al disco. En tiempo de desarrollo es muy frecuente que las tres capas estn en el mismo equipo fsico, y que se estn ejecutando en la misma mquina el gestor de base de datos, el servidor web y el navegador. En las aplicaciones web no hay una conexin permanente entre cliente y servidor. Recordemos que el protocolo HTTP es un protocolo sin estado. Cuando un navegador cliente hace una peticin de un recurso a un servidor, se crea una conexin temporal entre los dos, el servidor atiende la peticin y manda la respuesta e inmediatamente se cierra la conexin. El servidor pierde completamente el rastro de este cliente, y destruye toda la informacin de estado que hubiera utilizado durante el tiempo en que estaba procesando la peticin, de forma que si este mismo cliente vuelve a hacer otra peticin al servidor, sera como empezar otra vez de cero. Varias soluciones se han desarrollado para conseguir mantener el estado, y convertir as el HTTP en un protocolo capaz de recordar al cliente entre distintas peticiones. Unas soluciones pasan por almacenar esta informacin de estado en el propio cliente, por medio de cookies, y otras pasan por almacenar esta informacin en el servidor, en bases de datos, en ficheros, o en el caso de pginas ASP conservando variables dentro del objeto Session. Tambin se usa con frecuencia el paso de informacin de una pgina a otra, por medio de parmetros ocultos (del tipo hidden) dentro de formularios. En cada caso ser ms adecuada una u otra solucin. El hecho de que la conexin entre cliente y servidor no sea permanente supone una desventaja de las aplicaciones web respecto a las aplicaciones cliente/servidor tradicionales. Resulta ms difcil conseguir que la lgica de la aplicacin funcione correctamente cuando se trata de un conjunto de pginas distintas que son enviadas al cliente una detrs de otra, sin mantenimiento de estado entre ellas. Sin embargo las aplicaciones web tambin tienen una ventaja, y es el hecho de que la parte cliente se actualiza automticamente, sin necesidad de ir a reinstalar cada vez que hay una modificacin. Esto es as porque el cdigo con la lgica de presentacin se ejecuta en el cliente, es cierto, pero es en el servidor donde se genera de forma dinmica en el momento en que se hace cada peticin (es decir, el script de la pgina ASP se encarga de generar dinmicamente el cdigo HTML que ser enviado al navegador del cliente para que ste lo interprete y construya el interfaz visual: marcos, tablas, etc). De esa manera si yo modifico las pginas HTML o ASP, cuando el cliente haga una nueva peticin recibir la versin actualizada de forma inmediata. Precisamente este hecho hace que las aplicaciones web no encajen perfectamente bien en el concepto de aplicaciones en tres capas, porque la lgica de presentacin realmente se genera en el servidor web, es decir, en la capa de negocio, aunque luego se ejecute en la capa de presentacin. Los procedimientos almacenados tambin se salen un poco del modelo de tres capas, porque suponen una lgica de negocio pero que est almacenada no en la capa intermedia sino en la capa de datos, es decir, en el gestor de la base de datos. En cualquier caso, esta divisin de una aplicacin en capas lgicas no debe entenderse como una clasificacin estricta. Normalmente el cliente en las aplicaciones web es lo que se llama un thin client, porque necesita muy poca capacidad de CPU. Realmente slo la necesaria para ejecutar un navegador, capaz de generar el interfaz de usuario con HTML y JavaScript. Si quiero conseguir un interfaz ms rico, tengo que cargar ms el cliente, con controles ActiveX y applets, pudiendo entonces descargar de trabajo al servidor.

173

Desarrollo de aplicaciones COM+ para Internet / Intranet con ASP 3.0

Grupo EIDOS

Ejemplo de una aplicacin ASP en tres capas


Para aclarar los conceptos expuestos, apliquemos en un ejemplo todo lo dicho sobre las capas de una aplicacin. La aplicacin estar formada por tres capas: La capa de datos estar formada por el gestor SQL Server. Usaremos la base de datos pubs que viene incorporada como ejemplo al instalar el gestor. Servir los datos a la aplicacin cliente, en este caso una pgina ASP. La capa intermedia estar formada por una pgina ASP, que genere dinmicamente una tabla HTML con los registros de la tabla stores de la base de datos pubs, y que ser servida por un servidor web, en este caso el IIS. La capa de presentacin ser un navegador, en este caso el Internet Explorer, que se encargar de pedir la pgina ASP al servidor y de recibir la respuesta en forma de cdigo HTML que mostrar por pantalla.

El cdigo de la pgina ASP podra ser como el Cdigo fuente 131.

<HTML> <HEAD> <META NAME="GENERATOR" Content="Microsoft Visual Studio 6.0"> </HEAD> <BODY> <% Set objCnx = Server.CreateObject("ADODB.Connection") objCnx.Open "Provider=SQLOLEDB.1;User ID=sa;Initial Catalog=pubs;Data Source=varrondo" Set objRst = objCnx.Execute("stores",,adCmdTable) %> <div align="center"> <table border="1"> <tr> <%for each elem in objRst.Fields%> <th><%=elem.Name%></th> <%next%> </tr> <%while not objRst.EOF%> <tr> <%for each elem in objRst.Fields%> <td><%=elem.Value%></td> <%next%> </tr> <%objRst.MoveNext%> <%wend%> </table> </div> <% objRst.Close objCnx.Close Set objRst = Nothing Set objCnx = Nothing %>

174

Grupo EIDOS

9. Modelos de apliciones cliente / servidor

</BODY> </HTML> Cdigo fuente 131

y conseguiramos el resultado que se muestra en la Tabla 6. stor_id 6380 7066 7067 7131 7896 8042 stor_name Eric the Read Books Barnum's News & Brews stor_address city state zip

788 Catamaugus Ave. Seattle 567 Pasadena Ave. 577 First St. Tustin

WA 98056 CA 92789 96745

Los Gatos CA

Doc-U-Mat: Quality Laundry and Books 24-A Avogadro Way Remulade WA 98014 Fricative Bookshop Bookbeat 89 Madison St. 679 Carson St.
Tabla 6

Fremont Portland

CA OR

90019 89076

Componentizacin de la capa intermedia


Diseo de la capa intermedia con un componente
Vamos a rescribir la capa intermedia de nuestra aplicacin, para poder usar las ventajas que ofrece la componentizacin. En realidad, escribiremos un componente orientado a los datos, a medio camino entre la capa intermedia y la capa de datos, puesto que su funcin ser la de recuperar los datos del gestor de base de datos y entregrselos a la capa intermedia. El cdigo de acceso a la base de datos vamos a incluirlo en un componente que devuelva un recordset con los registros de la tabla stores. La pgina ASP simplemente se encarga de crear el objeto e invocar al mtodo correspondiente, recuperando el recordset y formateando sus datos en una tabla HTML. De esta forma conseguiremos al menos tres ventajas: Este mismo componente que creemos podramos reutilizarlo en otras pginas ASP de esta misma aplicacin que necesiten obtener un recordset con los registros de la tabla stores. Tambin podramos utilizarlo en pginas ASP de otras aplicaciones web. Incluso en aplicaciones tradicionales escritas en Visual Basic o Visual C++. Si por cualquier motivo cambia la forma de acceder a los datos, porque cambiamos el gestor de base de datos de SQL Server a Access, o porque ahora decidimos acceder a travs de un procedimiento almacenado, slo tendremos que cambiar este componente y no har falta que modifiquemos el cdigo de la pgina ASP.

175

Desarrollo de aplicaciones COM+ para Internet / Intranet con ASP 3.0

Grupo EIDOS

El acceso a los datos ser ms rpido, porque el cdigo estar compilado dentro del componente, y adems podremos utilizar el operador New de Visual Basic, lo que supone un enlace temprano al componente. Desde el script de una pgina ASP slo podemos utilizar el enlace tardo que proporciona el mtodo CreateObject.

Para crear el componente, abrimos un nuevo proyecto ActiveX DLL de Visual Basic y cambiamos el nombre del proyecto a CompStores y el del mdulo de clase a Stores. Como el componente va a acceder a la base de datos a travs de ADO, necesitamos aadir al proyecto la referencia a ADO. Esto lo hacemos seleccionando la opcin Referencias del men Proyecto, como puede verse en la Figura 48, y en la lista que aparece seleccionando Microsoft ActiveX Data Objects 2.5 Library.

Figura 48

Al incluir esta referencia conseguimos dos cosas: Por una parte se carga la type library de ADO, y Visual Basic nos ayudar con el IntelliSense a medida que vamos escribiendo el cdigo. Podr utilizar el early binding, lo que supone un mayor rendimiento a la hora de ejecutar el componente

El cdigo del componente quedara como en el Cdigo fuente 132.

Option Explicit Public Function listaStores() As ADODB.Recordset Dim objCnx As ADODB.Connection Dim objRst As ADODB.Recordset Dim strCnx As String

176

Grupo EIDOS

9. Modelos de apliciones cliente / servidor

strCnx = "Provider=SQLOLEDB.1;User ID=sa;Initial Catalog=pubs;Data Source=varrondo" Set objCnx = New ADODB.Connection objCnx.Open strCnx Set objRst = New ADODB.Recordset objRst.Open "Stores", objCnx, , , adCmdTable Set listaStores = objRst End Function Cdigo fuente 132

Como se ve, el interfaz est formado por un nico mtodo que no recibe parmetros, y que devuelve un objeto recordset. Todo el acceso a la base de datos queda dentro del componente, y descargo de esa tarea al script de la pgina ASP, que ahora tendra el Cdigo fuente 133. Los objetos objCnx y objRst son locales al mtodo del componente, y se liberan automticamente al salir del mismo, sin necesidad de que yo lo haga explcitamente.

<%@ Language=VBScript %> <!--#include file="ADOVBS.inc"--> <HTML> <HEAD> <META NAME="GENERATOR" Content="Microsoft Visual Studio 6.0"> </HEAD> <BODY> <% Set objCom = Server.CreateObject("CompStores.Stores") Set objRst = objCom.listaStores %> <div align="center"> <table border="1"> <tr> <%for each elem in objRst.Fields%> <th><%=elem.Name%></th> <%next%> </tr> <%while not objRst.EOF%> <tr> <%for each elem in objRst.Fields%> <td><%=elem.Value%></td> <%next%> </tr> <%objRst.MoveNext%> <%wend%> </table> </div> <% Set objCom = Nothing %> </BODY> </HTML> Cdigo fuente 133

177

Desarrollo de aplicaciones COM+ para Internet / Intranet con ASP 3.0

Grupo EIDOS

Slo tengo que crear una instancia del componente e invocar al mtodo listaStores, recuperando el recordset que me devuelve en el objeto objRst. Luego slo hay que formatear los datos que contiene en una tabla HTML, igual que en el caso anterior.

Rediseo del componente de la capa intermedia


Si ahora decidimos cambiar el componente, para que acceda a travs de un procedimiento almacenado, no tengo que tocar el cdigo de la pgina ASP. El procedimiento almacenado es el del Cdigo fuente 134.

CREATE PROCEDURE RecuperaStores AS SELECT * FROM Stores Cdigo fuente 134

Y el Cdigo fuente 135 es el que tendra ahora el componente (recordar los pasos que hay que seguir para descargar la dll de la memoria y poder as recompilar).

Option Explicit Public Function listaStores() As ADODB.Recordset Dim objCnx As ADODB.Connection Dim objCmd As ADODB.Command Dim objRst As ADODB.Recordset Dim strCnx As String strCnx = "Provider=SQLOLEDB.1;User ID=sa;Initial Catalog=pubs;Data Source=varrondo" Set objCnx = New ADODB.Connection objCnx.Open strCnx Set objCmd = New ADODB.Command objCmd.ActiveConnection = objCnx objCmd.CommandText = "RecuperaStores" Set objRst = New ADODB.Recordset objRst.Open objCmd, , , , adCmdStoredProc Set listaStores = objRst End Function Cdigo fuente 135

Un segundo rediseo del componente de la capa intermedia


Incluso puedo redisear esta capa intermedia, llegando a una solucin que seguramente resulta ms ptima: en vez de que el mtodo del componente devuelva un objeto Recordset, que siempre consume ms recursos, haremos que devuelva una cadena, ya con el cdigo HTML necesario para construir la tabla. Nos serviremos para ello del mtodo GetString del Recordset de ADO, que devuelve los datos del recordset en forma de cadena.
178

Grupo EIDOS

9. Modelos de apliciones cliente / servidor

Este mtodo recibe cinco parmetros: El primero puede tomar nicamente el valor por defecto adClipString. El segundo es el nmero de registros que van a ser convertidos a la cadena. Si no especifico este parmetro, se convierten todos los registros. El tercero es el delimitador que se usar en la cadena para separar los distintos campos de un registro. El valor por defecto es un tabulador. Para conseguir formatear esta cadena en forma de tabla de HTML, nos interesa que este separador sea </td><td>, con lo cual cerramos la etiqueta de la celda anterior y abrimos la de la celda siguiente. El cuarto es el delimitador que usar en la cadena para separar los distintos registros. El valor por defecto es un retorno de carro. Nos interesa que este separador sea </td></tr><tr><td>, para cerrar la celda y fila anteriores, y abrir la fila y celda siguientes. El quinto y ltimo parmetro es el carcter que se usar para los campos que tengan valor NULL. Por defecto es la cadena vaca.

El Cdigo fuente 136 es el de la nueva versin del componente.

Option Explicit Public Function listaStores() As String Dim objCnx As ADODB.Connection Dim objCmd As ADODB.Command Dim objRst As ADODB.Recordset Dim strCnx As String Dim strRst As String strCnx = "Provider=SQLOLEDB.1;User ID=sa;Initial Catalog=pubs;Data Source=varrondo" Set objCnx = New ADODB.Connection objCnx.Open strCnx Set objCmd = New ADODB.Command objCmd.ActiveConnection = objCnx objCmd.CommandText = "RecuperaStores" Set objRst = New ADODB.Recordset objRst.Open objCmd, , , , adCmdStoredProc strRst = objRst.GetString(, , "</td><td>", "</td></tr><tr><td>") strRst = Mid(strRst, 1, Len(strRst) - 8) strRst = "<table border=1><tr><td>" & strRst & "</table>" listaStores = strRst End Function Cdigo fuente 136

La lnea strRst = Mid(strRst, 1, Len(strRst) - 8) es necesaria para quitar el <tr><td>del final de la cadena, que sobra puesto que ya no hay ms filas. El Cdigo fuente 137,de la pgina ASP, queda ahora mucho ms reducido.

<%@ Language=VBScript %> <!--#include file="ADOVBS.inc"--> <HTML>

179

Desarrollo de aplicaciones COM+ para Internet / Intranet con ASP 3.0

Grupo EIDOS

<HEAD> <META NAME="GENERATOR" Content="Microsoft Visual Studio 6.0"> </HEAD> <BODY> <% Set objCom = Server.CreateObject("CompStores.Stores") Response.Write objCom.listaStores Set objCom = Nothing %> </BODY> </HTML> Cdigo fuente 137

Arquitectura cliente/servidor en n capas


Cuando se divide la capa de negocio o intermedia de la aplicacin ASP en varias capas, empieza a hablarse de arquitectura en n capas. Generalmente se trata de cuatro capas, al dividir la capa intermedia en dos: Una capa est formada por componentes orientados al cliente, es decir, ms cercanos a la capa de presentacin, que hacen uso del modelo de objetos de ASP para escribir directamente cdigo HTML a travs del objeto Response. Otra capa est formada por componentes orientados a los datos, es decir, ms cercanos a la capa de datos, a los que accede a travs de ADO.

Ms adelante retomaremos este ejemplo, y veremos cmo se pueden crear estos componentes orientados al cliente, accediendo al modelo de objetos de ASP. Incluso la capa intermedia puede dividirse no slo en estas dos capas lgicas, sino en dos capas fsicas en dos servidores distintos: uno tiene el servidor web junto con los componentes orientados al cliente, y otro tiene el servidor de aplicacin junto con los componentes de lgica de negocio y los orientados a datos.

180

Diseo de componentes para ASP


Introduccin
En este tema nos vamos a centrar en las particularidades que tienen los componentes que diseemos para ASP. Ya hemos visto en temas anteriores que, si bien todos los componentes cumplen la especificacin COM, unos sern utilizables en un contexto y otros no. A nosotros nos interesan los componentes que sean utilizables desde pginas ASP, as como los condicionantes que esto nos impone a la hora de desarrollar el cdigo de los mismos.

Tipos Variant
Los que programamos en ASP sabemos que los lenguajes de script, como el VBScript, son lenguajes dbilmente tipados, donde slo existe el tipo Variant. Este hecho tiene su importancia a la hora de disear un componente pensado para ser utilizado desde una pgina ASP. Dentro del componente estoy programando en Visual Basic, que es un lenguaje que s me permite declarar las variables con distintos tipos. Volvamos al componente que ya hemos empleado en temas anteriores, que presentaba un mtodo que calculaba el incremento en un porcentaje del 7 por ciento sobre una cantidad pasada como argumento. En una de las versiones de este componente, diseamos el mtodo de tal forma que reciba este parmetro por referencia, es decir, va a trabajar con la variable original y no con una copia de la misma.

Desarrollo de aplicaciones COM+ para Internet / Intranet con ASP 3.0

Grupo EIDOS

Ya hemos probado este componente y hemos visto que funcionaba correctamente al instanciarlo desde una pgina ASP. Pero esto era as mientras en el mtodo tenamos el parmetro definido como Variant. De esta forma, desde la pgina ASP pasamos al componente una variable Variant, el componente trabaja con ella, tomndola como Variant, y puede modificar su valor. Si ahora abrimos el proyecto ActiveX DLL correspondiente a este componente, y modificamos el cdigo del mdulo de clase hasta dejarlo como queda en el Cdigo fuente 138, podemos volver a pedir la pgina ASP que lo utilizaba para ver lo que ocurre.

Public Function calcular(cantidad As Integer) As Boolean cantidad = cantidad * 1.07 calcular = True End Function Cdigo fuente 138

Lo nico que hemos cambiado es el tipo de datos del parmetro: ya no es Variant, sino Integer. Recordemos que el cdigo de la pgina ASP era como el Cdigo fuente 139.

<% Set objPorcentaje = CreateObject("CompPorcentaje.Porcentaje") cantidad = 1000 retorno = objPorcentaje.calcular(cantidad) Response.Write cantidad Set objPorcentaje = Nothing %> Cdigo fuente 139

El resultado que obtenemos es un error No coinciden los tipos: 'calcular'. Por qu ahora no funciona y antes s? Muy sencillo. Al pasar la variable por referencia, lo que le estamos pasando al mtodo es precisamente eso: una referencia a una variable, con lo cual el cdigo del mtodo va a acceder a la variable original. Como esta variable original estaba definida como Variant en el script de ASP, no es posible que el mtodo intente considerarla como Integer, y se produce el error. Escrito de esta forma, el componente no sera utilizable desde una pgina ASP. Veamos qu ocurre si el parmetro se pasa por valor, y no por referencia. Para ello volvemos a modificar el componente, hasta conseguir el Cdigo fuente 140.

Public Function calcular(ByVal cantidad As Integer) As Currency calcular = cantidad * 1.07 End Function Cdigo fuente 140

182

Grupo EIDOS

10. Diseo de componentes para ASP

Para probar esta nueva versin del componente, preparemos una pgina ASP con un formulario, que nos permita probar con distintos valores del parmetro. El Cdigo fuente 141 es el que escribimos para la pgina.

<%@ Language=VBScript %> <HTML> <HEAD> <META NAME="GENERATOR" Content="Microsoft Visual Studio 6.0"> </HEAD> <BODY> <%if Request.Form("boton")="" then%> <form method="post"> <input name="cantidad")> <input type="submit" name="boton"> </form> <%else%> <% Set objPorcentaje = Server.CreateObject("CompPorcentaje.Porcentaje") cantidad = Request.Form("cantidad") Response.Write "El resultado es: " & objPorcentaje.calcular(cantidad) Set objPorcentaje = Nothing %> <%end if%> </BODY> </HTML> Cdigo fuente 141

En la rama if generamos el formulario, con un campo de texto para introducir la cantidad y un botn de submitir, que enviar el formulario a la misma pgina. En la rama else recibimos ese formulario y recuperamos el valor del campo de texto, cuyo valor asignamos a la variable cantidad, que es la que pasamos como parmetro al mtodo del componente. Si pedimos la pgina y metemos el valor 1000 en el campo de texto, el funcionamiento es correcto. Le estamos suministrando al mtodo un parmetro de tipo Variant, cuando el mtodo espera recibir un parmetro del tipo Integer. Pero entre medias est el motor del script, que es el que se encarga de hacer automticamente la transformacin, tomando la variable cantidad, del tipo Variant, y suministrndole al mtodo del componente una copia, del tipo Integer. Por supuesto que si el motor de script no puede hacer conversin automtica, porque los tipos son incompatibles, tambin falla. Probmoslo metiendo en el campo de texto una cadena, en vez de un entero. Obtendremos el error No coinciden los tipos: 'objPorcentaje.calcular' . Como ltimo ejemplo, y para que esto quede claro, volvamos a redisear el componente para que reciba el parmetro por referencia, es decir otra vez como en el Cdigo fuente 142.

Public Function calcular(cantidad As Integer) As Boolean cantidad = cantidad * 1.07 calcular = True End Function Cdigo fuente 142

183

Desarrollo de aplicaciones COM+ para Internet / Intranet con ASP 3.0

Grupo EIDOS

Y rescribamos la rama else de la pgina ASP para que quede como en el Cdigo fuente 143.

<% Set objPorcentaje = CreateObject("CompPorcentaje.Porcentaje") cantidad = Request.Form("cantidad") retorno = objPorcentaje.calcular(cantidad) Response.Write cantidad Set objPorcentaje = Nothing %> Cdigo fuente 143

De esta forma, pongamos lo que pongamos en el campo de texto, obtendremos siempre el error de No coinciden los tipos: 'objPorcentaje.calcular'. Sin embargo, si cambiamos la lnea en la que se invoca el mtodo calcular del componente por la que aparece en el Cdigo fuente 144, veremos que, al menos, no obtendremos error.

retorno = objPorcentaje.calcular(Request.Form("cantidad")) Cdigo fuente 144

Este es un comportamiento un tanto curioso, pero que en todo caso no nos sirve en absoluto. Parece como si al pasarle al mtodo directamente el valor de Request.Form(cantidad), fuera considerada como una variable de tipo Integer, que es la que necesita el mtodo. Pero esto no es as en absoluto. En realidad, Request.Form(cantidad) no es ni siquiera una variable, sino un valor constante: ninguna propiedad, ni ningn elemento de cualquier coleccin del objeto Request es modificable directamente. Estamos consiguiendo lo mismo que si pusiramos la lnea del Cdigo fuente 145.

retorno = objPorcentaje.calcular(1000) Cdigo fuente 145

Como pasamos un valor constante, no una variable, no podemos acceder al valor modificado que debera devolvernos el mtodo. Luego no nos da error, pero tampoco nos es de ninguna utilidad. En definitiva, para componentes diseados para ser utilizados desde pginas ASP, me interesa pasar por valor los argumentos de los mtodos. Y esto por dos motivos: Consigo una mayor encapsulacin del cdigo del componente. Es posible que el componente trabaje internamente con tipos Integer, String, etc. El motor de script se encargar de hacer la transformacin automtica, siempre que los tipos sean compatibles, del Variant al tipo necesario en el mtodo del componente.

184

Grupo EIDOS

10. Diseo de componentes para ASP

Dentro del componente podemos usar los tipos de datos que permite el Visual Basic, como Integer, Currency, etc, siempre tengamos la precaucin de pasar los argumentos por valor. El motor de script har la transformacin automtica del tipo variant de la pgina ASP al tipo determinado en el argumento del mtodo del componente. Si activamos el control de errores en la pgina ASP con On Error Resume Next antes de invocar al mtodo, podremos capturar un posible error en la conversin en el caso de haber pasado un valor incorrecto (por ejemplo una cadena como argumento de un mtodo que espera un Integer).

Acceso al modelo de objetos de ASP desde un componente


Vamos a tratar ahora de los componentes que son especficos de ASP, puesto que hacen uso de su modelo de objetos, es decir, harn uso directo de los objetos Application, Response, etc. A partir de la versin 4 del IIS, todos los objetos instanciados bajo MTS tienen acceso al ObjectContext. En la versin 5 ya no se llama MTS, sino Servicio de Componentes, integrado en COM+, pero el ObjectContext sigue existiendo. Ms adelante veremos con ms detalle este objeto, pero ahora podemos adelantar que representa el contexto en el que se est ejecutando el componente, y le permite acceder a l. En este caso el contexto de ejecucin del componente ser la pgina ASP, ejecutndose dentro del entorno del servidor IIS, luego podr acceder al modelo de objetos de ASP.

Acceso al objeto Application


Para explicar esto, veremos el ejemplo de un componente que acceda al valor de una variable con mbito de aplicacin. Tendr un nico mtodo, que recibir como parmetro el nombre de la variable a la que queremos acceder, y devolver el contenido de la misma. El parmetro se pasar por valor, no por referencia. Llamaremos al componente CompApplication, y al mdulo de clase le llamaremos Application. Llamaremos objContext a la variable que va a contener la referencia al objeto de contexto. La instruccin mediante la que conseguimos que esta variable obtenga la referencia al contexto es GetObjectContext. Es imprescindible aadir al proyecto la referencia a COM+ Services Type Library, como se muestra en la Figura 49, si estamos trabajando en Windows 2000. De no hacerlo as, no nos fallar el componente en el momento de la compilacin, pero si en ejecucin, en el momento de capturar la referencia al objeto de contexto, es decir, justo en la lnea Set objContext = GetObjectContext. Adems de esta forma podemos declarar con Dim la variable objContext. A partir del objeto de contexto, puedo acceder al entorno en que se ejecuta el componente. En este caso, dentro de este entorno estn los objetos integrados de ASP, y entre ellos el objeto Application. Para obtener una referencia a este objeto, lo hacemos con Set objApplication = objContext("Application").

185

Desarrollo de aplicaciones COM+ para Internet / Intranet con ASP 3.0

Grupo EIDOS

Figura 49

El Cdigo fuente 146 muestra el contenido completo del mtodo leeVariable.

Public Function leeVariable(ByVal nombre As Variant) As Variant Dim objContext As ObjectContext Set objContext = GetObjectContext Set objApplication = objContext("Application") leeVariable = objApplication.Contents(nombre) End Function Cdigo fuente 146

Para poder probar este componente, lo haremos desde una pgina en la que demos valor a una variable de aplicacin, cuyo nombre pasaremos luego como parmetro al mtodo. El Cdigo fuente 147 podra ser el de la pgina.

Set objCom = Server.CreateObject("CompApplication.Application") Application("variable1")="aqu ira el valor de la variable" Response.Write objCom.leeVariable("variable1") Cdigo fuente 147

Si ejecutamos esta pgina, veremos que se muestra correctamente el valor de esa variable de mbito de aplicacin. Sin embargo, probemos a aadir un proyecto EXE estndar que haga uso de este componente, con un formulario que presente un botn y un campo de texto Text1, y escribamos como cdigo asociado al evento Click del botn el contenido en el Cdigo fuente 148. Agregemos a este nuevo proyecto las
186

Grupo EIDOS

10. Diseo de componentes para ASP

referencias al componente CompApplication y a COM+ Services Type Library, y luego con el botn derecho sobre el nombre del proyecto en el explorador de proyectos seleccionemos la opcin Establecer como inicial.

Private Sub Command1_Click() Dim objCom As CompApplication.Application Dim valor As Variant Set objCom = New CompApplication.Application valor = objCom.leeVariable("variable1") Text1.Text = valor End Sub Cdigo fuente 148

Si ejecutamos este proyecto veremos que da error en la lnea Set objApplication = objContext("Application") del componente. Esto se debe a que ahora el componente no se est ejecutando en el contexto de una aplicacin ASP, sino en el contexto de una aplicacin tradicional de Visual Basic, luego no puede acceder a travs de su contexto al objeto Application, que slo tiene sentido en una aplicacin ASP.

Acceso a los objetos Request y Response


Veamos ahora que tenemos acceso a otros objetos integrados de ASP, como son el Request y el Response. Haremos un componente que, en un nico mtodo, procese el formulario enviado mediante POST en la peticin del navegador del cliente y genere una tabla HTML con el contenido de sus elementos. Para mayor comodidad de programacin (la que nos proporciona el IntelliSense), aadiremos al proyecto la referencia al modelo de objetos de ASP, como aparece en la Figura 50. Por cierto, que la dll correspondiente se encuentra en dos ubicaciones distintas: en Winnt\system32\inetsrv\asp.dll y en Archivos de Programa\Microsoft Visual Studio\Common\IDE.

Figura 50

187

Desarrollo de aplicaciones COM+ para Internet / Intranet con ASP 3.0

Grupo EIDOS

Si llamamos CompFormulario al proyecto ActiveX DLL, y Formulario al mdulo de clase, el Cdigo fuente 149 muestra las lneas que debera contener el mtodo.

Public Sub procesaForm() Dim objContext As ObjectContext Dim objRequest As Request Dim objResponse As Response Dim strHTML As String Set objContext = GetObjectContext Set objRequest = objContext("Request") Set objResponse = objContext("Response") strHTML = "<table border=1><tr><th>Campo</th><th>Valor</th></tr>" For Each campo In objRequest.Form strHTML = strHTML & "<tr><td>" & campo & "</td><td>" & _ objRequest.Form(campo) & "</td></tr>" Next strHTML = strHTML & "</table>" objResponse.Write strHTML End Sub Cdigo fuente 149

El cdigo accede al objeto Request de ASP para ir leyendo, mediante un bucle foreach, a todos los elementos de la coleccin Form, y va construyendo una cadena strHTML con sus valores. En la ltima lnea, utiliza el mtodo Write del objeto Response para escribir esta cadena en la respuesta que ser enviada de vuelta al navegador del cliente. Una pgina ASP para probar este componente podra ser la del Cdigo fuente 150.

<%@ Language=VBScript %> <HTML> <HEAD> <META NAME="GENERATOR" Content="Microsoft Visual Studio 6.0"> </HEAD> <BODY> <%if Request.Form("boton")="" then%> <form method="post"> <input name="campoTexto")><br> <input type="checkbox" name="campoCheck")><br> <input type="submit" name="boton"> </form> <%else%> <% Set objCom = Server.CreateObject("CompFormulario.Formulario") objCom.procesaForm Set objCom = Nothing %> <%end if%> </BODY> </HTML> Cdigo fuente 150

188

Grupo EIDOS

10. Diseo de componentes para ASP

Vemos que en la rama else, cuando el formulario es submitido, slo es necesario instanciar el componente e invocar a su nico mtodo. El resultado que obtendremos ser algo parecido al de la Tabla 7. Campo Valor

campoTexto cualquier cosa campoCheck on boton Enviar consulta


Tabla 7

Retomemos ahora el componente que ya hemos utilizado en temas anteriores, que acceda a la tabla Stores de la base de datos Pubs, creada durante la instalacin del SQL Server. Este componente tena un nico mtodo listaStores, que devolva un objeto recordset, para ser formateado en la pgina ASP. Lo modificaremos ligeramente, de forma que ahora tenga un mtodo llamado recuperaTabla, que reciba como parmetro el nombre de la tabla que queremos mostrar, y devuelva un array bidimensional formado por todos los campos de todos los registros de la tabla. Este array lo conseguiremos utilizando del mtodo GetRows del objeto Recordset de ADO. Pues bien, ahora que ya sabemos acceder desde un componente al modelo de objetos de ASP, hagamos un segundo componente, que reciba el array que devuelve el primero, que formatee en una tabla HTML este array, y que la escriba directamente sobre el objeto Response. Llamemos CompStores1 al proyecto ActiveX del primer componente y CompStores2 al del segundo. CompStores1 podra tener algo parecido al Cdigo fuente 151.

Option Explicit Public Function recuperaTabla(ByVal nombreTabla As Variant) As Variant() Dim objCnx As ADODB.Connection Dim objCmd As ADODB.Command Dim objRst As ADODB.Recordset Dim strCnx As String strCnx = "Provider=SQLOLEDB.1;User ID=sa;Initial Catalog=pubs;Data Source=varrondo" Set objCnx = New ADODB.Connection objCnx.Open strCnx Set objCmd = New ADODB.Command objCmd.ActiveConnection = objCnx objCmd.CommandText = "SELECT * FROM " & nombreTabla Set objRst = New ADODB.Recordset objRst.Open objCmd, , , , adCmdText recuperaTabla = objRst.GetRows End Function Cdigo fuente 151

189

Desarrollo de aplicaciones COM+ para Internet / Intranet con ASP 3.0

Grupo EIDOS

Como este componente accede a la base de datos a travs de ADO, y queremos hacer uso del early binding, tenemos que aadir al proyecto la referencia a Microsoft ActiveX Data Objects 2.5 Library. Formamos la cadena SQL dinmicamente, con el parmetro del nombre de la tabla, y devolvemos como resultado del mtodo la ejecucin de GetRows sobre el recordset. Compilemos este componente y pasemos al siguiente. El componente CompStores2 quedara con el Cdigo fuente 152.

Option Explicit Public Sub generaTabla(ByVal nombreTabla As Variant) Dim objContext As ObjectContext Dim objResponse As Response Dim objCom As CompStores1.Stores1 Dim rec() Dim strHTML As String Dim i, j As Integer Set objContext = GetObjectContext Set objResponse = objContext("Response") Set objCom = New CompStores1.Stores1 rec = objCom.recuperaTabla(nombreTabla) strHTML = "<table border=1>" For i = 0 To UBound(rec, 2) strHTML = strHTML & "<tr>" For j = 0 To UBound(rec, 1) strHTML = strHTML & "<td>" & rec(j, i) & "</td>" Next strHTML = strHTML & "</tr>" Next strHTML = strHTML & "</table>" objResponse.Write strHTML End Sub Cdigo fuente 152

Dentro del mtodo obtenemos la referencia al objeto de contexto, y a partir de l la referencia al objeto Response. Creamos una instancia del componente CompStores1 e invocamos a su mtodo recuperaTabla, pasando el parmetro del nombre. Con el array bidimensional devuelto vamos construyendo una cadena strHTML con el cdigo necesario para formatear una tabla HTML. En la ltima lnea, escribimos esta cadena a travs del mtodo Write del objeto Response. Este componente no est orientado a los datos, es decir, no accede a la base de datos, luego no necesito aadir al proyecto la referencia a ADO. Si embargo, est orientado al cliente, porque tiene parte de la lgica de presentacin, puesto que accede al objeto Response del modelo de ASP. Para eso necesito aadir las referencias a las libreras de COM+ y ASP. Adems, este componente va a hacer uso del otro componente que acabamos de crear, CompStores1. Tendremos que aadir al proyecto esta referencia, como se muestra en la Figura 51.

190

Grupo EIDOS

10. Diseo de componentes para ASP

Figura 51

El Cdigo fuente 153 es todo lo que necesita la pgina ASP para usar los componentes. Se reduce a instanciar el componente CompStores2, e invocar su mtodo generaTabla, pasando como parmetro el nombre de la tabla que queramos visualizar. Probar con varias de ellas, como stores, authors, publishers,

Set objCom = Server.CreateObject("CompStores2.Stores2") objCom.generaTabla "Stores" Set objCom = Nothing Cdigo fuente 153

De esta manera hemos creado lo que podramos considerar una aplicacin en cuatro capas: La capa de presentacin est en la mquina del cliente, donde se ejecuta el software del navegador web, capaz de hacer la peticin de la pgina ASP y recibir la respuesta, todo a travs del protocolo HTTP. El cdigo HTML que recibe puede interpretarlo, y mostrar en este caso una tabla. Parte de la capa de presentacin se encuentra en la pgina ASP, que es la que realmente genera dinmicamente ese cdigo HTML, que luego se encargar de visualizar en el formato adecuado el navegador. La capa intermedia orientada al cliente estara formada por el componente CompStores2, que se encarga de hacer la peticin al componente CompStores1 de la tabla, pero que adems accede directamente al objeto Response para escribir el cdigo HTML de la tabla. Este componente se ejecuta en la misma mquina que el servidor web, y es gestionado por la pgina ASP, cuyo cdigo se encarga de crearlo y destruirlo cuando es oportuno. La capa intermedia orientada a los datos la implementa el componente CompStores1, que recibe la peticin de tabla que le hace el componente CompStores2, y que accede al gestor de
191

Desarrollo de aplicaciones COM+ para Internet / Intranet con ASP 3.0

Grupo EIDOS

base de datos a travs de los objetos de ADO. Si este componente se ejecutara en una mquina distinta de la del servidor web, podramos denominarla servidor de aplicacin. La capa de datos est formada por el gestor de base de datos, y podra ejecutarse en una mquina diferente de la del servidor web y de la del servidor de aplicacin.

El hecho de separar la capa intermedia en una capa orientada al cliente y otra orientada a datos, nos permite una mayor posibilidad de reutilizar los componentes. Si por ejemplo decidimos cambiar el componente que accede a la base de datos, porque vamos a usar otro servidor, o un procedimiento almacenado en vez de una cadena SQL, slo tendra que tocar ese componente y recompilarlo. Mientras el interfaz que le presenta al componente orientado al cliente no cambie (es decir, que siga recibiendo como parmetro un nombre de tabla y devolviendo un array bidimensional), todo funcionar igual que antes. Adems, al no depender el componente orientado a datos del modelo de objetos de ASP, puedo utilizarlo en otras aplicaciones, por ejemplo desde un EXE estndar de Visual Basic.

Recompilacin de componentes con enlace temprano


Cambiemos por ejemplo el cdigo del componente orientado a los datos por el Cdigo fuente 154.

Option Explicit Public Function recuperaTabla(ByVal nombreTabla As Variant) As Variant() Dim objCnx As ADODB.Connection Dim objRst As ADODB.Recordset Dim strCnx As String strCnx = "Provider=SQLOLEDB.1;User ID=sa;Initial Catalog=pubs;Data Source=varrondo" Set objCnx = New ADODB.Connection objCnx.Open strCnx Set objRst = New ADODB.Recordset objRst.Open nombreTabla, objCnx, , , adCmdTable recuperaTabla = objRst.GetRows End Function Cdigo fuente 154

Ahora no usamos el objeto Command, sino que pasamos como parmetro al mtodo Open del Recordset el nombre de la tabla. La ejecucin de la pgina ASP ser igual que antes. No tenemos que modificar el cdigo del componente orientado al cliente. Lo que s tenemos que hacer es recompilarlo. Como dentro de CompStores2 estamos usando enlace temprano (early binding) al CompStores1 mediante la instruccin Set objCom = New CompStores1.Stores1, al haber recompilado el CompStores1 tenemos que recompilar el CompStores2. De no hacerlo, al ejecutar la pgina ASP obtendramos el error Esta clase no admite Automatizacin o la interfaz esperada. Esta recompilacin no sera necesaria si utilizramos enlace tardo (late binding), es decir, si hubiramos usado Set objCom = CreateObject(CompStores1.Stores1).
192

Grupo EIDOS

10. Diseo de componentes para ASP

Implementacin de interfaces en Visual Basic


Los interfaces se definen en Visual Basic a travs de clases abstractas. Una clase abstracta no contiene cdigo de implementacin, slo las declaraciones de las funciones. La implementacin real del interfaz ocurre en otras clases, en aqullas que implementan el interfaz. Vamos a crear un nuevo proyecto ActiveX DLL de Visual Basic al que llamaremos CompInterfaz, con un mdulo de clase llamado IInterfaz1. Por convenio, a los nombres de interfaz se les suele anteponer la I. Estableceremos la propiedad de instanciacin de esta clase como PublicNotCreatable, como se ve en la Figura 52. Esto significa que no se pueden instanciar objetos a partir de esta clase. Slo ser una plantilla para otras clases que implementen el interfaz.

Figura 52

Con ayuda de la utilidad Generador de clases, aadimos un mtodo al mdulo de clase, como se muestra en el Cdigo fuente 155.

Public Function metodo1(ByVal par As Integer) As Integer End Function Cdigo fuente 155

Vamos a utilizar esta clase abstracta en otro mdulo de clase. Para ello aadimos un nuevo mdulo de clase al proyecto, llamado Implementa, y en su seccin de Declaraciones aadimos la lnea Implements IInterfaz1. Esto significa que esta clase acepta el contrato, con lo cual est obligada a implementar todos y cada uno de los mtodos que formaran parte del interfaz. En este caso el metodo1. Si no lo implementara, obtendramos un error de compilacin. Nada ms aadir esta lnea, aparecer en el combo de Objetos, en la esquina superior izquierda del panel de edicin, el nombre del interfaz. Si lo seleccionamos de la lista, automticamente aparecer la estructura del mtodo metodo1, al que se le antepone el nombre del interfaz y un guin bajo _, listo
193

Desarrollo de aplicaciones COM+ para Internet / Intranet con ASP 3.0

Grupo EIDOS

para que lo implementemos con las lneas de cdigo que creamos oportunas. Dejmoslo con el Cdigo fuente 156.

Implements IInterfaz1 Public Function metodo3(ByVal par As Integer) As Integer metodo3 = par + 3 End Function Private Function IInterfaz1_metodo1(ByVal par As Integer) As Integer IInterfaz1_metodo1 = par + 1 End Function Cdigo fuente 156

Como puede verse, hemos aadido adems un mtodo llamado metodo3, pero que no es fruto de implementar el interfaz anterior, sino un mtodo como los que hemos escrito hasta ahora. Vamos a repetir el proceso llevado a cabo con el mdulo de clase IInterfaz1, para crear otro mdulo de clase IInterfaz2, con un mtodo llamado metodo2. Haremos que la clase Implementa firme el contrato tambin con este interfaz, lo que le obliga a implementar tambin el metodo2. El resultado final se muestra en el Cdigo fuente 157.

Implements IInterfaz1 Implements IInterfaz2 Public Function metodo3(ByVal par As Integer) As Integer metodo3 = par + 3 End Function Private Function IInterfaz1_metodo1(ByVal par As Integer) As Integer IInterfaz1_metodo1 = par + 1 End Function Private Function IInterfaz2_metodo2(ByVal par As Integer) As Integer IInterfaz2_metodo2 = par + 2 End Function Cdigo fuente 157

Si ahora compilamos el proyecto, y desde una pgina ASP instanciamos este objeto, veremos que slo tenemos disponible el metodo3, pero no el metodo1 ni el metodo2. Qu es lo que est ocurriendo? Cuando se compila un proyecto ya sea con ActiveX DLL o con EXE, Visual Basic crea un interfaz por defecto para cada clase. Dicho interfaz toma el nombre de la clase, precedido por un carcter de subrayado bajo. Por ejemplo, el interfaz por defecto para la clase Implementa es _Implementa. Los mtodos que no forman parte de otro interfaz (precedido por la lnea de subrayado y el nombre del interfaz), como es el caso del metodo3, pasan a ser miembros del interfaz por defecto. Todo esto lo realiza Visual Basic sin que tengamos que especificrselo. Pues bien, al ser el VBScript de una pgina ASP un lenguaje en que no es posible asignar tipo a las variables, slo nos est permitido acceder a este interfaz por defecto, es decir, slo podemos acceder al metodo3. A continuacin veremos que para acceder a los otros interfaces, distintos del interfaz por defecto, es necesario declarar variables con el tipo especfico de esos interfaces.
194

Grupo EIDOS

10. Diseo de componentes para ASP

Vamos a probar este componente desde Visual Basic. Para ello, desde el men Archivo, seleccionemos la opcin Agregar proyecto, que elegiremos del tipo EXE estndar. El grupo de proyectos quedar al final como se muestra en la Figura 53.

Figura 53

Al formulario que se crea automticamente, aadimos un botn y hacemos doble clic sobre l para implementar el cdigo asociado a su evento Click, como se ve en el Cdigo fuente 158.

Private Dim Dim Dim Dim

Sub Command1_Click() objCom As Implementa i1 As IInterfaz1 i2 As IInterfaz2 var As Integer

Set objCom = New Implementa var = objCom.metodo3(1) Set i1 = objCom var = i1.metodo1(1) Set i2 = objCom var = i2.metodo2(1) End Sub Cdigo fuente 158

En l definimos las variables i1 e i2 del tipo de los dos interfaces IInterfaz1 e IInterfaz2. Luego instanciamos el componente e invocamos al metodo3. Luego asignamos sucesivamente a las variables de referencia i1 e i2 la referencia al objeto e invocamos el mtodo correspondiente a cada interfaz. Cuando usa Set para asignar valores a una variable de tipo interfaz, Visual Basic pregunta al objeto si ste tiene implementada dicha interfaz. El mtodo que utiliza para ello se llama QueryInterface y pertenece a la interfaz IUnknown. Vamos a establecer el proyecto EXE estndar recin creado como proyecto de inicio. Para ello pulsamos con el botn derecho sobre l en el Explorador de proyectos y seleccionamos la opcin Establecer como inicial.

195

Desarrollo de aplicaciones COM+ para Internet / Intranet con ASP 3.0

Grupo EIDOS

Si depuramos el componente, veremos que podemos invocar todos los mtodos correctamente, y la variable var toma los valores adecuados despus de la ejecucin de cada mtodo. En definitiva, desde el proyecto EXE estndar de Visual Basic conseguimos lo que no podamos hacer desde el script de ASP: acceder tanto a los mtodos del interfaz por defecto como a los mtodos de los interfaces IInterfaz1 e IInterfaz2. Como desarrollador de aplicaciones ASP, tal vez nunca utilicemos otras interfaces aparte de las que Visual Basic proporciona por defecto. La eleccin a la hora de realizar la implementacin depende de la complejidad de la aplicacin y de los requisitos del diseo. Desde luego, desde un componente instanciado desde una pgina ASP s podra acceder a interfaces, distintos del interfaz por defecto, que implemente un segundo componente. Las bibliotecas de tipos se utilizan para especificar los interfaces de un objeto, es decir, para definir los mtodos y parmetros de un interfaz, y no tiene nada que ver con la implementacin de sta. COM utiliza IDL para describir interfaces, ya que permite ver lo que realmente ocurre cuando se crea un componente. Las bibliotecas de tipos pueden formarse a partir de archivos IDL, los cuales, a su vez, pueden utilizarse en tiempo de compilacin o de ejecucin. La definicin de interfaces en visual Basic se hace con clases abstractas (o simplemente utilizando la interfaz por defecto) en vez de con el IDL. Visual Basic crea bibliotecas de tipos y las incluye en los componentes. Existen herramientas, como el OLE/COM Object Viewer incluido en Microsoft Visual Studio, que le permiten convertir cualquier biblioteca de tipos en IDL, incluso aquellas que se crearon con Visual Basic. Es importante observar que actualmente no pueden aprovecharse todas las posibilidades del IDL en Visual Basic.

196

Servicios de Componentes
Introduccin
En este tema se va a tratar de los Servicios de Componentes que proporciona el Windows 2000. Sin embargo, se empezar hablando del MTS (Microsoft Transaction Server), para situar al lector en el proceso de evolucin de Windows NT a Windows 2000, y poder establecer comparaciones tiles para aquellos que ya conocieran este producto. Adems, los conceptos del MTS son aplicables en su prctica totalidad a los Servicios de Componentes, exceptuando algunas diferencias que se comentarn adecuadamente.

Caractersticas del MTS (Microsoft Transaction Server)


Aunque su nombre pueda producir confusin, el MTS no es slo un monitor transaccional, sino que es un servidor de componentes, con soporte de Transacciones, que simplifica el desarrollo y distribucin de las aplicaciones servidoras que utilizan la tecnologa COM. Este servidor define un modelo de programacin y proporciona un entorno de ejecucin, adems de unas herramientas de administracin para las aplicaciones ms complejas. Pueden utilizarse herramientas como Visual Basic, Visual C++, Delphi, Visual J++, Visual FoxPro o incluso COBOL para construir aplicaciones servidoras para MTS sin necesidad de tener que codificar los complejos mecanismos de comunicacin entre componentes. Por esta razn, MTS reduce significativamente el tiempo necesario para la construccin de aplicaciones de n-capas, y aumenta la extensibilidad, escalabilidad y reusabilidad de las aplicaciones.

Desarrollo de aplicaciones COM+ para Internet / Intranet con ASP 3.0

Grupo EIDOS

Forma parte del Windows DNA (Windows Distributed interNet Application Architecture) para aplicaciones internet/intranet de n-capas. El MTS es un servicio creado para Windows NT. No es una parte integral del sistema operativo, sino que se instala como un servicio adicional, con el Windows NT Option Pack. Supone una funcionalidad aadida a la del COM, proporcionando un nuevo runtime para los objetos que se estn ejecutando en la capa intermedia de una aplicacin distribuida segn el modelo de n-capas. Esta funcionalidad aadida consiste sobre todo en soporte para transacciones distribuidas, seguridad integrada, pooling de hilos de ejecucin, y facilidades de configuracin y administracin de los componentes mediante el uso de propiedades declarativas. Para Windows 95/98 existe una versin reducida del MTS, del mismo modo que existe una versin reducida del servidor IIS denominada PWS (Personal Web Server). Como ya se ha comentado, el MTS no slo proporciona la funcionalidad necesaria para gestionar las transacciones distribuidas, sino que incluso componentes no-transaccionales pueden obtener ventajas en su ejecucin si hacen uso de los servicios que aporta. El MTS ana dos funcionalidades principales: Object request broker (ORB). Gestiona la instanciacin de objetos para los clientes. Sabe dnde estn los objetos y cmo crearlos. Gestiona la comunicacin entre los componentes, ahorrando al programador el trabajo de escribir el cdigo en C++ que hiciera lo mismo). En una pgina ASP, intercepta los Server.CreateObject y crea l mismo los objetos, usando sus propios objetos COM para supervisar a estos objetos. Monitor transaccional: MS DTC (Distributed Transaction Coordinator). Tiene dos funciones: Comparte recursos (procesos, hilos, ) del sistema entre los clientes. Cada proceso necesita una cantidad de memoria. Si se tienen muchos clientes simultneos, es necesaria mucha memoria, que no es un recurso especialmente caro en la actualidad, pero se requiere mucho tiempo de CPU para gestionar todos los procesos. Es mejor compartir procesos: un mismo proceso sirve a varios clientes. De esta forma hace falta menos CPU para gestionarlos, as que el rendimiento es mayor, con menos memoria RAM. Usa los protocolos de transacciones para coordinar las acciones de los distintos componentes. El programador no tiene que poner el cdigo para gestionar el rollback; todo est centralizado en el MTS.

Servicios que aporta el MTS


El MTS proporciona una serie de ventajas para el programador: Administrando los recursos del Sistema Operativo como procesos e hilos. Por esto varios usuarios pueden acceder y ejecutar la aplicacin a la vez. Sincronizando el acceso a los datos, para que no se reduzca el rendimiento cuando muchos usuarios accedan a la misma informacin de la base de datos. Obteniendo informacin acerca de los usuarios: quines son, qu tipo de operaciones realizan, as se evita que el trabajo de un usuario interfiera en el de otro.

198

Grupo EIDOS

11. Servicios de componentes

Implementando la seguridad, de tal manera que los usuarios slo tengan acceso a los recursos para los que el administrador les ha dado permisos. Implementando la administracin y configuracin, esto reduce el coste de distribucin, administracin y/o modificacin.

Estas ventajas las proporciona a travs de un conjunto de servicios:

Transacciones para componentes


Son similares a las de las bases de datos, a diferencia de que stas ltimas engloban un conjunto de sentencias SQL, mientras que las de componentes engloban el trabajo de uno o ms componentes. MTS monitoriza la interaccin entre los componentes y los recursos transaccionales, como pueden ser bases de datos, y coordina los cambios. Si algn componente corta la transaccin, MTS facilita el rollback de todos los cambios realizados por el componente y de todos los dems componentes que se ejecutaban en el mismo contexto de transaccin.

Comercio de objetos
MTS acta como un comerciante de objetos, sirviendo las peticiones de instanciacin que varios clientes hacen. MTS reconoce la peticin, coordina su creacin y mantenimiento, y destruye las instancias de componentes COM y de los hilos que stas hayan creado. La independencia de la ubicacin de los componentes respecto de los clientes es otra de las ventajas que aporta este servicio que, adems, soporta la reconfiguracin dinmica y el cambio de la ubicacin de un objeto sin tener que cambiar el cdigo de la aplicacin cliente, despus de la fase de desarrollo.

Independencia entre procesos


MTS permite agrupar varios componentes en paquetes, cada uno de los cuales trabaja en su propia rea de direcciones protegida. Esto es crtico cuando, por ejemplo, se est integrando un componente comprado a terceros en una solucin existente. Los errores de un componente no deberan propagarse a los componentes que estn en otro paquete.

Fondo comn de recursos


MTS administra de forma automtica y rene en un fondo comn, llamado pooling, dos de los recursos ms crticos para el servidor: hilos y conexiones a bases de datos. El fondo comn de conexiones a bases de datos administrado por el controlador ODBC o OLE DB evita al desarrollador el manejo complejas caractersticas de sincronizacin. MTS emplea un fondo comn de hilos para acelerar los tiempos de respuesta a los clientes, aportando tambin los mecanismos necesarios para que varios componentes compartan informacin sin que el desarrollador tenga que preocuparse de problemas de concurrencia ni de sincronizacin.

Activacin en el momento (Just-In-Time)


Permite que el sistema desactive y reactive un objeto mientras sus clientes le siguen haciendo referencia; esta posibilidad se traducen en un uso ms eficiente de los recursos del servidor. Desde el
199

Desarrollo de aplicaciones COM+ para Internet / Intranet con ASP 3.0

Grupo EIDOS

punto de vista del cliente, slo existe una copia del objeto desde que lo mand crear hasta que lo destruy. Realmente, el objeto puede desactivarse y reactivarse varias veces. La administracin de instancias de objetos y la activacin en el momento benefician la escalabilidad de las aplicaciones.

Seguridad
MTS proporciona un servicio de seguridad plenamente integrado con la seguridad de Windows NT, facilitando el control de uso por parte de personal no autorizado, incluso a los componentes comprados a terceros. Existen dos modelos de seguridad soportados por MTS: el modelo declarativo y el modelo programado". En el modelo declarativo la seguridad se configura con el Administrador de Usuario de Windows NT y con el Explorador de MTS. El modelo "programado" proporciona la funcionalidad necesaria para preguntar, en tiempo de ejecucin, quin quiere utilizar el componente. Un componente puede alterar su comportamiento dependiendo de la respuesta.

Conceptos principales del MTS


La intercepcin
El modelo COM no fue modificado para albergar esta nueva funcionalidad que ofrece el MTS. La capa de runtime del COM permanece igual que antes, pero convive ahora con una capa que se le superpone, que es la capa del runtime del MTS. Debido a esto, la compenetracin entre COM y MTS no es siempre todo lo eficiente que podra ser, y supone un esfuerzo adicional para el programador, que debe conocer los dos modelos. Veremos ms adelante que algunas tcnicas de programacin que son perfectamente vlidas para COM no lo son para MTS. Al ser dos capas de runtime distintas, para que el MTS pueda aportar funcionalidad aadida a los objetos COM que instancie un cliente, debe interponerse entre el cliente y el objeto en el momento de la creacin del mismo, para poder controlar as su ciclo de vida y sus caractersticas de ejecucin.

Propiedades declarativas. El catlogo del MTS


Para hacer uso de la funcionalidad del MTS, debemos darle la autorizacin para que se encargue de gestionar y supervisar las instancias de nuestros componentes. Esto se hace aadiendo los componentes a un paquete del MTS. Estos paquetes deben ser entendidos como unidades de administracin de componentes. Una vez registrado el componente, es posible configurar muchas de sus caractersticas de ejecucin mediante lo que se llaman propiedades declarativas. Ya se entiende la flexibilidad que todo esto supone. El programador construye sus componentes igual que antes, sin tener que hacer apenas nada especial. Despus de compilados, se registran en el MTS, y se modifican sus atributos declarativos, que describen las propiedades de ejecucin de ese componente. No hay necesidad de programar nada nuevo, ni recompilar. Las propiedades declarativas suponen un nuevo enfoque de programacin. Tradicionalmente, una aplicacin haca uso de los servicios proporcionados por el sistema operativo mediante un API de bajo nivel. Si ms adelante se quera variar el uso que la aplicacin haca de estos servicios, era necesario

200

Grupo EIDOS

11. Servicios de componentes

modificar el cdigo y recompilar. Ahora este esfuerzo no es necesario, y basta con modificar una serie de propiedades declarativas, sin necesidad de tocar una sola lnea de cdigo. La informacin de estas propiedades declarativas de cada componente registrado en algn paquete del MTS se guarda en el catlogo. Este catlogo almacena informacin adicional a la que se guarda en el registro de Windows.

Funcionamiento del MTS


Explicaremos aqu, de forma muy breve y simplificada, el funcionamiento interno del MTS. Esto ayudar a comprender algunas cosas que se vern ms adelante. El MTS Executive, encargado de gestionar el funcionamiento del MTS, trabaja con dos objetos COM principales (el objeto Context Wrapper y el objeto de contexto), y dos interfaces (interfaz ObjectContext e interfaz ObjectControl):

El objeto Context Wrapper


Es el objeto que ve realmente el cliente que pide una instancia de un objeto MTS, resultado de la intercepcin que ste realiza en el momento de la creacin. El MTS inspecciona el interfaz del objeto, crea un objeto Context Wrapper con ese interfaz y le devuelve esa referencia al cliente. No activa el objeto real hasta que el cliente pide el primer mtodo de ese objeto (JIT: Just-In-Time Activation). As ahorra recursos. Tambin lo destruye lo antes posible (ASAP: As-Soon-As-Possible Deactivation), sin que el cliente lo sepa: l sigue engaado con su referencia al Context Wrapper. El objeto es desactivado despus de cada llamada a un mtodo. Esto es eficiente, aunque no lo parezca, porque MTS guarda la DLL en su memoria cach, y no le lleva tiempo desactivar y reactivar. Pero el estado se pierde entre llamadas a los mtodos. Esto me asegura la propiedad de aislamiento de las transacciones. Si quiero guardar el estado del componente, tengo recurrir a otros mecanismos, como guardarlo en una base de datos o pasarlo como parmetro entre mtodos. En definitiva, el Context Wrapper sirve para engaar al cliente, que se crea que tiene la referencia al objeto mientras que realmente es el MTS el que gestiona cundo se activa y desactiva.

El objeto de contexto
Almacena informacin asociada con el objeto (creador del objeto, informacin de seguridad, transaccin en curso, etc). Es usada por el entorno para saber cmo el componente interacta. Todos los componentes registrados en MTS lo tienen. Suele decirse que el objeto de contexto es como la sombra del objeto. Almacena informacin de seguridad, que le permite al Context Wrapper saber si el cliente tiene permiso para usar los mtodos que ha pedido. Almacena informacin del contexto de ejecucin del componente. Esta informacin es la que le permite al MTS meter un componente, programado de forma aislada y como si fuera monousuario, dentro de una transaccin distribuida con gestin de concurrencia, sin que yo tenga que programar

201

Desarrollo de aplicaciones COM+ para Internet / Intranet con ASP 3.0

Grupo EIDOS

nada especial. Gracias a este objeto es posible monitorizar las transacciones y ver estadsticas desde la consola administrativa del MTS. IIS almacena informacin en el objeto de contexto, ya que IIS es parte del entorno y est construido con tecnologa MTS. Entre esta informacin almacenada estn las referencias a los objetos integrados de ASP. Luego no ser necesario pasar estas referencias a un objeto COM para que pueda utilizarlas. En resumen, el objeto de contexto puede utilizarse para: Informar que se ha terminado el trabajo del objeto. Evitar que se confirme una transaccin, ya sea temporal o permanentemente. Instanciar otros objetos de MTS e incluir su trabajo en el mbito de la transaccin del objeto creador. Averiguar la funcin del usuario que utiliza el objeto. Averiguar si dispone de los permisos necesarios. Averiguar si el objeto se est ejecutando en una transaccin. Recuperar objetos incorporados en Microsoft Internet Information Server.

El interfaz ObjectContext
El objeto de contexto que acabamos de ver implementa este interfaz ObjectContext. Puedo acceder a este interfaz desde cualquier objeto MTS con las lneas mostradas en el Cdigo fuente 159.

Dim objContext As ObjectContext Set objContext = GetObjectContext() Cdigo fuente 159

Los principales mtodos de este interfaz son: SetComplete: indica al MTS que el trabajo realizado por el objeto ha finalizado con xito, y puede ser confirmado cuando todos los objetos implicados en la transaccin terminen su trabajo. El mtodo SetComplete tambin indica al MTS que cualquier recurso retenido por el objeto, incluido el propio objeto, puede ser reciclado. SetAbort: indica al MTS que el trabajo realizado por el objeto no ha finalizado con xito, con lo cual todos los cambios hechos por este objeto y los realizados por otros objetos en la misma transaccin quedarn anulados. El mtodo SetComplete tambin indica al MTS que cualquier recurso retenido por el objeto, incluido el propio objeto, puede ser reciclado. CreateInstance: crea un nuevo objeto, pero adems MTS copia la informacin del objeto de contexto del objeto creador al objeto de contexto del objeto creado. As formar parte de la misma transaccin y tendr las mismas caractersticas de seguridad. Para que forme parte de la misma transaccin, el nuevo objeto debe tener su atributo transaccional configurado como Requiere una transaccin o Compatible con transacciones.

202

Grupo EIDOS

11. Servicios de componentes

EnableCommit: Declara que el trabajo de un objeto no est necesariamente terminado, pero que sus actualizaciones de la transaccin son consistentes y que podran confirmarse en su forma actual. El objeto mantiene su estado interno durante las llamadas realizadas a otros mtodos hasta que le llame a SetComplete o SetAbort, o hasta que la transaccin termina. EnableCommit es la establecida por defecto para un objeto, si ste no llama a otros mtodos del objeto de contexto. Por ejemplo, una compaa tiene un objeto Pedido que crea pedidos que hay que suministrar a los clientes. Un cliente puede crear un pedido a travs de internet y solicitar que le sea enviado a una direccin determinada. O el cliente puede ir a buscar el pedido directamente a uno de los almacenes de la compaa. Un fichero ASP crea el pedido llamando al mtodo AadirPedido del objeto Pedido. ste llama a EnableCommit ya que no sabe dnde ir el cliente a buscarlo. Una vez el cliente elija, la pgina ASP podr llamar a los mtodos DejarEnAlmacn o EnviarADireccin, para indicar qu debe hacerse con el pedido. Cada uno de estos dos ltimo mtodos llamarn a SetComplete. DisableCommit: Declara que el trabajo de un objeto no est terminado, que sus actualizaciones de la transaccin son inconsistentes y que, por lo tanto, no pueden ser autorizadas en su forma actual.

El interfaz ObjectControl
Un buen componente MTS implementa este interfaz. Tiene tres mtodos: Activate: es invocado automticamente por el MTS Excecutive cuando el cliente invoca un mtodo del componente. Aqu pondra el cdigo de inicializacin que sea global para todos los mtodos del componente. Por ejemplo, si todos los mtodos acceden a una BD, aqu creara la conexin. Deactivate: es invocado automticamente por el MTS Executive cuando finaliza la ejecucin del mtodo, dando como resultado un SetComplete o un SetAbort. Aqu pondra el cdigo de finalizacin que sea global para todos los mtodos del componente. En el ejemplo utilizado, ste sera el lugar en el que liberar la conexin. CanBePooled: devuelve un booleano que indica si el MTS puede meter este componente en un fondo compartido, o pooling, de objetos. En MTS 2.0 devuelve siempre False.

En estos mtodos Activate y Deactivate es donde se debe poner el cdigo de inicializacin y de finalizacin del objeto, no en los eventos Class_Initialize y Class_Terminate de Visual Basic. Por varios motivos: El MTS tiene que crear un objeto de prueba la primera vez que se usa un objeto MTS, para ver si es un objeto Java. Lo crea y lo destruye. En esta prueba llama a los mtodos Class_Initialize y Class_Terminate, con lo que hara la inicializacin y destruccin cuando no es necesaria. Si embargo en esta prueba no llama a Activate y Deactivate. El MTS no permite mantener el estado del componente entre llamadas, lo que significa que la inicializacin y finalizacin debe hacerse en Activate y Deactivate, que son los mtodos invocados precisamente entre estas llamadas. Desde los mtodos Class_Initialize y Class_Terminate no est disponible el objeto de contexto, con lo que no podremos acceder desde ellos, por ejemplo, a las caractersticas de seguridad del componente.

203

Desarrollo de aplicaciones COM+ para Internet / Intranet con ASP 3.0

Grupo EIDOS

Instanciar un objeto a partir de un componente MTS


Instanciar un objeto desde otro objeto de Visual Basic
Usando el operador New: Si se instancia el objeto a partir de un componente incluido en el mismo servidor COM (es decir, un mismo proyecto ActiveX DLL que contiene varios mdulos de clase), el Visual Basic sabe cmo tiene que crearlo, y no necesita llamar a las rutinas de COM para hacerlo. Entonces se crea una instancia privada, de la cual el MTS no sabe que existe. Como consecuencia, no se crea un objeto de contexto, aunque el componente est registrado en MTS, y el objeto creado no podr intervenir en transacciones. Es un objeto COM tradicional. Si se instancia desde otro servidor COM, s se llama a las rutinas de COM y el objeto creado dispondr de un objeto de contexto, en el caso de que estuviera registrado en COM.

Usando el mtodo CreateObject: Equivale a New cuando se instancia desde servidores COM distintos; sin embargo, New es ms eficiente por utilizar el enlace temprano. Siempre usa las rutinas de COM para crear el objeto, con lo que se crea un objeto de contexto para l. Pero no se transmite la informacin sobre el contexto del componente que lo cre, sino que se crea un objeto de contexto completamente nuevo, y no podr formar parte de su transaccin.

Usando el mtodo CreateInstance: Al crear el nuevo objeto, el MTS copia toda la informacin del objeto de contexto del objeto creador al objeto de contexto del objeto creado, con lo cual podr compartir la transaccin y las caractersticas de seguridad.

Instanciar un objeto desde una pgina ASP con VBScript


Usando el mtodo CreateObject: Esta funcin de VBScript hace una llamada directa a las rutinas COM, luego no pasa por IIS, y por lo tanto tampoco por MTS, luego el objeto correr en una transaccin separada en el caso de ser transaccional. No debe usarse en ASP.

Usando el mtodo Server.CreateObject: Este mtodo del objeto integrado Server transmite la peticin de instanciacin del objeto al IIS, que se encargar de utilizar el MTS en caso necesario. Si la pgina es transaccional, este componente correr en la misma transaccin. En definitiva, este mtodo emplea internamente el mtodo CreateInstance del interfaz ObjectContext.

204

Grupo EIDOS

11. Servicios de componentes

Introduccin a las transacciones


Para que una transaccin sea fiable ha de hacer lo que los usuarios y administradores esperan que haga; esto incluye la capacidad de devolver el estado a una situacin conocida, vlida y consistente en caso de que se produzca un fallo. Son las transacciones las que dan esta garanta al sistema. Una transaccin es una unidad indivisible de trabajo que puede ser deshecha en cualquier momento antes de que finalice. Son muy importantes pues proporcionan a los desarrolladores el marco adecuado para trabajar con componentes no muy fiables. Toda transaccin tiene un comienzo, uno o dos finales y algunos procesos que se ejecutan en medio. Una transaccin puede terminar sin ms o terminar y realizar una "vuelta atrs" al estado anterior como si no se hubiese realizado operacin alguna. Las transacciones pueden ser abortadas, tanto por los clientes como por el propio sistema de transacciones. Por ejemplo, un servidor de datos puede abortar una transaccin si sta mantiene bloqueos durante demasiado tiempo o si se produce un nter bloqueo. Para el comercio electrnico, el comportamiento transaccional es fundamental. Es inaceptable que un sistema funcione parte del tiempo s y parte no, aunque el tiempo que s est funcionando sea del 99%. Por ello, se ha hecho especial hincapi en los aspectos de recuperacin de las transacciones, para garantizar el 100% de fiabilidad. En una situacin en la que los elementos de la transaccin incluyen transferencias de una cuenta bancaria a otra, si el proceso de aumento de la cuenta se ejecuta correctamente, pero el de disminucin no, la transaccin debera fallar y no dar dinero que no se tiene. Cualquier actividad que pueda ser deshecha forma parte activa de la transaccin. Los accesos a bases de datos son los ejemplos clsicos que se incluyen en componentes transaccionales. Estos sistemas gestores de datos soportan las transacciones, permitiendo confirmar (Commit) o realizar una vuelta atrs (Roll Back) a sus actividades internas. El nombre genrico que se da a los sistemas que soportan este comportamiento es el de "administrador de recursos transaccionales". Microsoft Message Queue Server es un buen ejemplo de lo que es un administrador de recursos transaccionales. Una transaccin debe cumplir cuatro propiedades, que suelen denominarse propiedades ACID (tomando la primera letra de cada propiedad): Atomicidad: Las transacciones deben ser indivisibles, es decir, o se ejecutan todas las acciones o no se ejecuta ninguna. Consistencia: Toda transaccin debe llevar el sistema de un estado consistente a otro. Independencia: Para ser consistentes debemos imaginar que somos los nicos que estamos realizando operaciones en un momento dado; las dems transacciones deben ser invisibles para nosotros. Sirva de ejemplo el siguiente caso: un viajero pide cambiar un billete de un vuelo por otro distinto. Una transaccin se ocupara de cancelar el billete del primer vuelo, al tiempo que otra transaccin intentara aadir un pasajero nuevo en el otro vuelo. Supongamos ahora que la primera transaccin falla, el viajero no podra volver a su "asiento" anterior porque ahora estara ocupado con el nuevo viajero. Este tipo de anomalas se evitan gracias a la independencia de las transacciones. Durabilidad: Cuando una transaccin se confirma, permanece as aunque se produzcan errores del sistema, de las comunicaciones o del propio ordenador servidor.

205

Desarrollo de aplicaciones COM+ para Internet / Intranet con ASP 3.0

Grupo EIDOS

Duracin y resultado de una transaccin


Una transaccin empieza cuando un cliente llama a un objeto de MTS con su atributo de transaccin establecido en Requiere una transaccin o Requiere una nueva transaccin. Este objeto es, entonces, considerado la raz de la transaccin porque fue el primer objeto que la cre. Cuando sta termina, MTS determina el resultado de la transaccin, ya sea autorizando o abortando la transaccin. En el caso de las pginas ASP, esta raz de la transaccin suele ser la propia pgina ASP, que es ejecutada bajo la supervisin de los componentes COM del IIS, que en realidad son componentes MTS. Existen tres formas en las que una transaccin puede terminar: El objeto raz llama a SetComplete o SetAbort: Es, adems, el nico objeto que puede terminar una transaccin de esta forma, ya que los objetos que se han creado como parte de esa misma transaccin no influyen en su duracin. Eso s, pueden emitir su voto, que influir en el resultado final de la transaccin: en cuanto que alguno de los elementos que forman la transaccin emitan un voto negativa, la transaccin se da por no-vlida. La transaccin expira porque se agota su tiempo: El tiempo de expiracin por defecto para una transaccin es de 60 segundos. Si desea cambiar este valor, haga clic con el botn derecho del ratn en el icono del ordenador que aparece en el Explorador de MTS y, luego, clic en Propiedades. Establezca entonces la propiedad Transaccin TimeOut en la pestaa Opciones. El cliente libera al objeto raz.

Cuando una transaccin termina, MTS debe determinar su resultado y decidir si debe autorizar o abortar la transaccin. Determinar el resultado de la transaccin es un proceso anlogo a la toma de decisin de un grupo en el que se ha de llegar a una decisin unnime. Si un miembro del grupo disiente, habr que negociar una decisin unnime. Del mismo modo, cada objeto en una transaccin emite su voto llamando a un mtodo, ya sea SetComplete, SetAbort, EnableCommit o DisableCommit. MTS hace el recuento de los votos emitidos por cada objeto y determina el resultado. Si todos los objetos llamaron a SetComplete o a EnableCommit, se autorizar la transaccin, pero si alguno de ellos llam a SetAbort o a DisableCommit, se abortar la transaccin.

Activacin en el momento
Una de las consideraciones del diseo ms importantes a la hora de desarrollar componentes de MTS es el establecer de que forma se va a controlar el estado. El control del estado influye directamente en la escalabilidad de los componentes de MTS. Por otro lado, estos componentes administran el estado de forma diferente a como lo hacen los componentes COM tradicionales. El Estado es un conjunto de datos del objeto que se guarda despus de haber realizado ms de una llamada al objeto. El estado puede almacenarse en una de las tres capas: en la capa del cliente, en la de los objetos de MTS o en la de la base de datos. El estado almacenado en objetos de MTS tambin recibe el nombre de estado local. Las propiedades son un buen ejemplo de lo que es un estado. Un objeto puede tener propiedades que almacenen el nombre de un cliente, su direccin y nmero de telfono. Tambin puede tener mtodos que utilizan los valores de dichas propiedades. Un mtodo aade la informacin del cliente a la base de datos y,
206

Grupo EIDOS

11. Servicios de componentes

ms tarde, otro mtodo hace un ingreso en su cuenta. El objeto existe y guarda la informacin del cliente hasta que es liberado. Un objeto como ste, que mantiene el estado internamente despus de mltiples llamadas, recibe el nombre de stateful. Sin embargo, si el objeto no expone propiedades y, el nombre del cliente, su direccin y su nmero de telfono se pasan en cada llamada al mtodo, estaremos ante un objeto stateless. Este tipo de objetos no recuerdan las llamadas realizadas con anterioridad, no mantienen el estado. Es muy frecuente programar en un entorno de mono-usuario pensando que un objeto estar en activo todo el tiempo que lo necesite. Las llamadas a mtodos son sencillas porque el objeto recuerda la informacin de una llamada a otra. Sin embargo, los objetos que mantienen el estado ("stateful") influyen en la escalabilidad de una aplicacin. El estado puede consumir los recursos del servidor, como memoria, espacio en el disco y conexiones de la base de datos. Y, dado que el estado est vinculado a un cliente especfico, se mantendrn los recursos hasta que el cliente libere al objeto. Esta decisin ha de tenerse en cuenta junto con otros requisitos de la aplicacin. Como norma general, se debe evitar mantener el estado que consume recursos escasos o caros; almacenar las conexiones de la base de datos reduce la escalabilidad dado que existe un nmero limitado de conexiones a la base de datos que pueden asignarse y las conexiones que se han utilizado no pueden reunirse en el fondo comn. La Activacin en el momento ayuda a reducir el consumo de los recursos del sistema, ya que recicla los objetos cuando stos terminan su trabajo. Este tipo de activacin tambin asegura el aislamiento de las transacciones, de forma que la informacin de una transaccin no se llevar a la siguiente. Cuando un cliente llama a un mtodo de un objeto, MTS activa el objeto, crendolo y permitiendo a la llamada del mtodo llegar hasta ste. Una vez que el objeto termina y llama a SetComplete o a SetAbort y regresa de la llamada, MTS desactiva el objeto y libera sus recursos para que stos puedan ser utilizados por otros objetos. El objeto volver a activarse cuando el cliente llame a otro mtodo. Al desactivar el objeto, MTS libera todas sus referencias, destruyendo tambin todo su estado local, es decir, las variables locales y las propiedades. Sin embargo, MTS controla el puntero del cliente para que siga siendo vlido. Cuando el cliente llama a un mtodo del objeto desactivado, MTS lo activa crendolo de nuevo y permitiendo a la llamada del mtodo continuar. MTS controla el puntero del cliente para que de esta forma no sea consciente de que el objeto ha sido destruido y vuelto a crear. Sin embargo, el estado local del objeto se ha perdido y no recuerda nada de la activacin anterior. Un objeto no est desactivado cuando llama a EnableCommit o al DisableCommit o cuando rechaza hacer una llamada a cualquier otro mtodo del objeto contextual. Tampoco estar desactivado cuando termine la transaccin por haberse agotado su tiempo. El objeto slo se desactiva cuando llama a SetComplete o a SetAbort y regresa de la llamada del cliente. La activacin en el momento tiene un efecto sustancial sobre el estado del objeto. Dado que, cuando un objeto llama a SetComplete o a SetAbort pierde su estado en cuanto el mtodo regresa, los objetos que participan en las transacciones han de ser stateless. Es decir, no pueden mantener ningn tipo de dato de la instancia desde que quedan desactivados. No obstante, esto no quiere decir que todas las aplicaciones deben disearse hacia un modelo de programa que no mantenga el estado, ya que ste puede almacenarse y mantenerse fuera del objeto.

207

Desarrollo de aplicaciones COM+ para Internet / Intranet con ASP 3.0

Grupo EIDOS

Almacenar el estado del objeto


La activacin en el momento obliga a los objetos a ser stateless, es decir, que si el objeto llama a SetComplete o SetAbort, no guardar el estado local en variables dentro del objeto. Sin embargo, existe un lado prctico para el desarrollo del componente que debe examinarse. Habr ocasiones en las que se necesite almacenar el estado para los objetos de MTS, por ejemplo, una aplicacin en la que se necesite determinar el nombre de una ciudad a partir de un cdigo postal dado. Encontrar esta informacin en una base de datos, pero utilizar repetidamente una base de datos para hacer bsquedas de este tipo de dato esttico puede ser ineficaz. Sera mejor almacenar esta informacin en un objeto para bsqueda rpida. Existen varias posibilidades para almacenar el estado. En una transaccin es posible almacenar las propiedades de una instancia. Un objeto no tiene que llamar a SetComplete o a SetAbort cuando regresa de una llamada. Las transacciones ms complicadas podran necesitar varias llamadas desde el cliente, cada una realizando una parte del trabajo, hasta que la ltima llamada al mtodo llama a SetComplete o a SetAbort. En estas circunstancias, puede mantenerse el estado como dato de una instancia en variables locales. Cuando el ltimo mtodo llame a SetComplete o a SetAbort, el objeto quedar, finalmente, desactivado, liberando el dato de la instancia. Otra solucin obvia es la de almacenar el estado en variables dentro de los objetos Application o Session, segn el mbito que queramos que tengan. Tambin se puede almacenar el estado en un archivo. Los archivos crean una proteccin frente a accesos concurrentes y mantienen el estado a lo largo de mltiples transacciones. Sin embargo, no proporcionan bloqueo a nivel de registro; slo puede bloquearse el archivo completo. Por lo tanto, no son tiles para almacenar el estado que es compartido por muchos objetos, ya que un objeto puede dejar fuera al resto. Otra forma es utilizar el Administrador de Propiedades Compartidas, SPM (Shared Property Manager).

Administrador de Propiedades Compartidas (SPM)


El SPM permite almacenar propiedades y compartir los datos con todos los objetos del mismo paquete MTS. El SPM es rpido porque accede a sus propiedades en el mismo proceso (y el mismo paquete) y proporciona mecanismos de bloqueo para protegerse ante accesos concurrentes. La informacin almacenada en el SPM no puede ser compartida entre paquetes distintos. Un ejemplo de aplicacin del SPM podra ser el de una aplicacin bancaria en la que una serie de componentes realizan las operaciones de ingreso y retirada de efectivo, transferencias, ingreso de cheques, etc, y queremos asignar a cada una de estas operaciones un identificador nico por medio de un contador. Es decir, queremos una propiedad que sea compartida por todos los objetos instanciados a partir de estos componentes La solucin sera meter todos estos componentes en un mismo paquete, y crear otro componente que utilice el SPM para definir ese contador. Interesara no perder el estado si el paquete se descarga de memoria por estar en un perodo de inactividad. Esto puede ser configurado en los Servicios de Componentes del Windows 2000, de forma que en las propiedades avanzadas de configuracin del

208

Grupo EIDOS

11. Servicios de componentes

paquete dejaramos activado el botn de radio Dejar ejecutando cuando est inactivo, como se muestra en la Figura 54.

Figura 54

El estado se guarda en propiedades con nombre (objeto SharedProperty), agrupadas en grupos de propiedades tambin con nombre (objeto SharedPropertyGroup). Todo es gestionado por el administrador de SPM (objeto SharedPropertyGroupManager). En resumen, el SPM trabaja con tres objetos ordenados jerrquicamente: SharedPropertyGroupManager: Creargrupos de propiedades comunes y permite el acceso a los ya existentes. SharedPropertyGroup: Crea y permite el acceso a las propiedades comunes dentro de un grupo. SharedProperty: Establece o devuelve el valor de una propiedad concreta.

Obtener una referencia al SPM


Vamos a hacer un componente que implemente el contador comentado anteriormente. En un nuevo proyecto ActiveX DLL, al que podemos llamar CompContador, con un mdulo de clase llamado Contador, tendremos que aadir la referencia al Shared Property Manager Type Library si

209

Desarrollo de aplicaciones COM+ para Internet / Intranet con ASP 3.0

Grupo EIDOS

trabajamos con el MTS de Windows NT, o la referencia a los servicios COM+ si trabajamos en Windows 2000, como se muestra en la Figura 55.

Figura 55

El Cdigo fuente 160 basta para obtener una referencia al SPM.

Set objSPM = New SharedPropertyGroupManager Cdigo fuente 160

El MTS, o los Servicios de Componentes en Windows 2000, se encargan de asegurar que slo exista una instancia por servidor de este objeto. Si ya exista esta instancia, se nos asignar una referencia a la ya existente.

Crear un grupo de propiedades compartidas


El Cdigo fuente 161 es el necesario para crear un grupo de propiedades.

Set objPG = objSPM.CreatePropertyGroup("contadores", LockSetGet, Process, bExiste) Cdigo fuente 161

Este mtodo recibe cuatro argumentos:

210

Grupo EIDOS

11. Servicios de componentes

Nombre: Es el nombre que tendr el grupo de propiedades Nivel de aislamiento: Controla de qu forma funciona el bloqueo para el grupo. Dado que la propiedades en el grupo son comunes, habr muchos objetos que accedan y actualicen propiedades al mismo tiempo. El SPM dispone de mecanismos de bloqueo para evitar el acceso simultneo a las propiedades comunes. En la Tabla 8 se muestra los dos tipos de valores que existen para hacer el bloqueo. Constante LockSetGet Valor Descripcin 0 Establecido por defecto. Bloquea una propiedad durante una llamada; de esta forma se asegura que, cada operacin de lectura/escritura comn sea atmica. Con esto se consigue que dos clientes no puedan leer o escribir la misma propiedad simultneamente, pero no impide que otros clientes de accesos concurrentes lo hagan con otras propiedades en el mismo grupo. Bloquea todas las propiedades del grupo para uso exclusivo del llamador; este bloqueo se mantendr mientras est ejecutndose el mtodo en curso. Es apropiado utilizar este modo cuando existen interdependencias entre las propiedades o, en aquellos casos en los que un cliente tenga que actualizar una propiedad inmediatamente despus de haberla ledo y antes de que se acceda a ella otra vez.
Tabla 8

1 LockMethod

Tiempo de vida: controla la forma en que se borra el grupo de propiedad comn. En la Tabla 9 se muestran los dos valores posibles para este caso. Constante Standard 1 Process Valor Descripcin 0 Cuando todos los objetos MTS han liberado sus referencias del grupo de propiedad, ste se destruye automticamente. El grupo de la propiedad no se destruir hasta que el proceso en el que sta fue creada haya terminado. Entonces tendr que liberar todos los objetos SharedPropertyGroup envindolos a Nothing.
Tabla 9

El cuarto parmetro devuelve un booleano que indica si el grupo de propiedades exista o no previamente. Si ya exista, se devolver una referencia al grupo existente, y entonces el segundo y tercer parmetro no tienen validez, pues el grupo tendr los valores que le fueron dados en el momento de su creacin. Puede usarse el valor devuelto por este parmetro para verificar si se est creando el grupo o recibiendo la referencia a uno existente, ejecutando el cdigo de inicializacin de las variables del grupo slo en el primer caso.

211

Desarrollo de aplicaciones COM+ para Internet / Intranet con ASP 3.0

Grupo EIDOS

Crear una propiedad compartida


El objeto SharedPropertyGroup presenta dos mtodos y dos propiedades: CreateProperty: Crea una nueva propiedad comn, identificada por una cadena de caracteres que es nica en su grupo de propiedad. CreatePropertyByPosition: Crea una nueva propiedad comn, identificada por un ndice numrico en su grupo de propiedad. Property: Devuelve una referencia a la propiedad comn, una vez dado el nombre de la cadena por el que se identifica a tal propiedad. PropertyByPosition: Devuelve una referencia a la propiedad comn, una vez dado su ndice numrico en el grupo de propiedad comn.

El Cdigo fuente 162 permite crear una propiedad comn llamada id. El segundo argumento del mtodo devuelve un valor booleano que indica si la propiedad es creada en ese mismo momento o ya exista. En el primer caso, haramos la inicializacin del bloque if.

Set objP = objPG.CreateProperty("id", bExiste) If bExiste = False Then objP.Value = 100 Cdigo fuente 162

Si todo este cdigo lo incluimos en un mtodo que devuelva la propiedad compartida id y la incremente en 1, el resultado final sera el del Cdigo fuente 163.

Option Explicit Public Function generaId() As Integer Dim objSPM As SharedPropertyGroupManager Dim objPG As SharedPropertyGroup Dim objP As SharedProperty Dim bExiste As Boolean Set objSPM = New SharedPropertyGroupManager Set objPG = objSPM.CreatePropertyGroup("contadores", LockSetGet, Process, bExiste) Set objP = objPG.CreateProperty("id", bExiste) If bExiste = False Then objP.Value = 100 objP.Value = objP.Value + 1 generaId = objP.Value End Function Cdigo fuente 163

Podemos probar este componente con una pgina ASP tan simple como la que se muestra en el Cdigo fuente 164. Si pedimos esta pgina, incluso desde varias instancias distintas de navegador, podremos ver cmo el contador se va incrementando.
212

Grupo EIDOS

11. Servicios de componentes

Set objContador = Server.CreateObject("CompContador.Contador") Response.Write objContador.generaId Cdigo fuente 164

Si queremos probar ms a fondo el comportamiento del SPM, hagamos un nuevo proyecto ActiveX DLL llamado CompContador2, con un mdulo de clase Contador2. Este mdulo de clase contendr un mtodo exactamente igual al del componente anterior. Hagamos otra pgina ASP similar a la del Cdigo fuente 164, pero que trabaje con este nuevo componente. Podemos probar ahora varios casos: Si no registramos los componentes en el MTS, los componentes se ejecutan en el mismo proceso que el de la aplicacin web. Luego como comparten proceso, tambin comparten el mismo grupo de propiedades, y la propiedad id a la que acceden es la misma. Si registramos uno de los dos componentes en un paquete del MTS, configurado como Aplicacin de servidor, este componente se ejecutar en un espacio de proceso distinto al de la aplicacin web, y no comparte el grupo de propiedades con el otro componente. En este caso los contadores id son distintos Si registramos los dos componentes en el mismo paquete, se ejecutan en el mismo proceso y comparten la propiedad id. Si los registramos en paquetes distintos, se ejecutan en distintos procesos y no comparten la propiedad id.

En definitiva, lo normal sera que estos dos componentes tuvieran funcionalidad diferente, por ejemplo uno podra ejecutar operaciones de transferencias bancarias y otro de ingreso de cheques, pero que quisiramos numerar esas operaciones distintas con un contador nico. En ese caso, registraramos estos componentes en un mismo paquete, y dispondra cada uno de ellos de un mtodo generaId que accediera a la propiedad comn id, como hemos visto. Esta propiedad comn se conserva, incluso aunque el MTS est haciendo activacin justo a tiempo de los objetos.

Servicios de Componentes y COM+


El paso siguiente a COM y MTS era lgicamente integrar estos dos modelos en uno slo, de tal forma que se produzca una mayor compenetracin entre dos capas de runtime que antes eran distintas, con todos los problemas que esto supona. El resultado de la conjuncin de estas dos tecnologas ha resultado en el COM+. Ahora el MTS no se sirve como un aadido opcional a la funcionalidad del COM, sino como una parte constituyente del modelo conjunto: al instalar Windows 2000, estamos instalando lo que antes se llamaba MTS 2.0, y que ahora sera el MTS 3.0, pero ya integrado en el modelo COM+. COM+ est basado en COM: sigue siendo una especificacin binaria que permite que los componentes se comuniquen entre s, y permite una programacin basada en interfaces.
213

Desarrollo de aplicaciones COM+ para Internet / Intranet con ASP 3.0

Grupo EIDOS

Pero COM+ tambin est basado en MTS. Esto significa que extiende la funcionalidad bsica del COM, igual que haca el MTS, pero aade an ms funcionalidad que ste. Ahora esta funcionalidad aadida no se llama MTS, sino Servicios de Componentes. Igual que el MTS, los Servicios de Componentes aportan las siguientes funcionalidades: Monitor transaccional: Los componentes pueden ser ejecutados en el seno de una transaccin, sin tocar una sola lnea de cdigo, y los Servicios de Componentes se encargan de gestionarla, haciendo el commit o rollback correspondiente. El comportamiento que un objeto tendr ante las transacciones puede ser configurado administrativamente mediante propiedades declarativas. Gestor de componentes (ORB, Object Request Broker): Gestiona la vida del componente y guarda informacin de su contexto. Cada objeto est asociado con un nico contexto durante su vida, como si se tratara de su sombra. Mltiples objetos pueden estar asociados a un mismo contexto. Gestor de seguridad: Algunas caractersticas de seguridad no necesitan que sea aadida ni una sola lnea de cdigo y son configuradas administrativamente.

Pero adems, los Servicios de Componentes aportan algunas novedades: Componentes encolados: Combina COM con MSMQ. Permite invocar y ejecutar componentes de forma asncrona, estando el cliente o el servidor desconectados El cliente pide un mtodo de un componente encolado al Queued Components Recorder, que mete la peticin en una cola. El Queued Components Listener coge el mensaje y se lo pasa al Queued Components Player, para que sea ejecutado finalmente el mtodo sobre el componente. Fondo comn de objetos (Object Pooling): Mantiene instancias de componentes en un fondo comn o pool, que pueden ser usadas por cualquier cliente. Igual que el pool de conexiones a una BD. Actualmente slo puede usarse con componentes C++. Component Load Balancing (CLB): Puedo tener un mismo componente COM+ servido por varios servidores de aplicacin. Se utilizar uno u otro servidor en funcin de su carga de trabajo. No disponible todava en Windows 2000.

Muchos de los conceptos de MTS siguen teniendo aplicacin al hablar de los Servicios de Componentes. A veces slo cambia el nombre. Por ejemplo, el MTS ahora se llama Servicios de Componentes. Es accesible desde la opcin Herramientas administrativas del men Programas. Lo que antes se llamaba paquete ahora recibe el nombre de aplicacin COM+. Al igual que los paquetes del MTS, las aplicaciones COM+ pueden ser configuradas como: Aplicacin de biblioteca: Los objetos instanciados a partir de componentes registrados en esa aplicacin se ejecutarn en el mismo espacio de proceso que el cliente que instaci dicho objeto. Aplicacin de servidor: Los objetos instanciados a partir de componentes registrados en esa aplicacin se ejecutarn en un proceso de servidor dedicado. Este proceso que contiene la ejecucin de esta aplicacin era MTX.EXE en el MTS, y ahora pasa a ser DLLHOST.EXE, como puede verse en la Figura 56.

214

Grupo EIDOS

11. Servicios de componentes

Figura 56

La intercepcin en COM+
Ya hemos visto que para que el MTS fuera capaz de aadir su funcionalidad a los componentes COM, es necesario que se interponga entre el cliente y el objeto, de forma que pueda controlar el ciclo de vida y la ejecucin de ste. Para conseguir esto, la capa runtime del MTS, el MTXEX.DLL, se vala de dos objetos. El objeto Context Wrapper es el que se interpone en el momento del intento de instanciacin de un componente MTS por parte de un cliente: ste recibe una referencia a este objeto Context Wrapper, siendo as engaado, mientras que el MTS se encarga de gestionar la creacin del objeto real. Un segundo objeto, el objeto de contexto, se encarga de guardar informacin relativa al contexto de ejecucin del objeto, actuando como su sombra. El hecho de que el MTS no estuviera plenamente integrado en el modelo COM supona un problema importante, una de cuyas consecuencias principales era la necesidad del uso del mtodo CreateInstance del objeto de contexto. Si un componente MTS instanciaba otro componente MTS, y se empleaba el mtodo de Visual Basic CreateObject en vez de CreateInstance, ocurra lo siguiente: el runtime de Visual Basic pasaba la peticin de creacin del objeto al runtime del COM, que a su vez se la pasaba al MTS. Pero el runtime del COM no era capaz de pasar la informacin del contexto del objeto creador al del objeto creado. Como consecuencia, el MTS creaba un nuevo contexto para el nuevo objeto, pero que no era reflejo del contexto del objeto creador, luego no poda correr en la misma transaccin.
215

Desarrollo de aplicaciones COM+ para Internet / Intranet con ASP 3.0

Grupo EIDOS

La capa runtime del COM+ se basa en la idea del contexto. Todos los objetos se ejecutan dentro de un contexto. Varios objetos pueden estar en un mismo contexto. La intercepcin de la capa runtime del COM+ slo se produce cuando la llamada se hace desde un contexto hasta otro distinto. Para esta intercepcin no utiliza objetos Context Wrapper, sino objetos proxy especializados en hacer este cambio de contexto. En el momento de crear un objeto, la capa runtime del COM+ debe decidir si el nuevo objeto necesita un nuevo contexto o puede utilizar el contexto de su creador. Para tomar esta decisin, COM+ se basa en la informacin almacenada en el objeto de contexto. En la mayora de las ocasiones, los objetos instanciados a partir de componentes no-configurados se crean en el contexto de su creador, y los instanciados a partir de componentes configurados se crean en un nuevo contexto. Se entiende por componente configurado aqul que est registrado dentro de una aplicacin COM+, lo que significa que se le han configurado una serie de propiedades declarativas. Los objetos de ADO sin embargo son instancias de componente no-configurado. Ya no es necesario el uso del mtodo CreateInstance, aunque sigue pudiendo utilizarse para garantizar la compatibilidad con cdigo ya escrito. Las rutinas de COM+ saben perfectamente cmo deben pasar informacin del contexto en el momento de la creacin de objetos. Esto significa que el mtodo CreateObject, que utiliza dichas rutinas COM+, tendr el mismo efecto, y el objeto recin creado podr, por ejemplo, ejecutarse en la misma transaccin que el creador. El operador New de Visual Basic todava puede ser problemtico si los componentes correspondientes al objeto creado y al creador estn incluidos en la misma DLL. En este caso las rutinas de Visual Basic saben cmo crear el nuevo objeto y no utilizan las rutinas de COM+. Si estn en DLLs distintas, el operador New equivale al mtodo CreateObject y funcionar sin problemas. La referencia a un objeto es siempre relativa al contexto. Si un objeto 1 dentro un contexto 1 obtiene mediante CreateObject una referencia a un objeto 2 dentro de otro contexto 2, en realidad lo que tiene es la referencia a un proxy capaz de hacer el cambio del contexto 1 al contexto 2. Si el objeto 1 invoca un mtodo de un tercer objeto 3 dentro de un contexto 3, y le pasa como parmetro del mtodo esta referencia al objeto 2, se crear automticamente un nuevo proxy capaz de hacer el cambio del contexto 3 al contexto 2, y ser la referencia a este proxy la que utilice el objeto 3. Por lo tanto, pasar una referencia a un objeto como parmetro de un mtodo no supone ningn problema, porque los proxys necesarios se crean automticamente. Sin embargo, no sera correcto guardar la referencia que tena el objeto 1 al objeto 2, que es un proxy especializado en cambiar del contexto 1 al 2, como una variable dentro de un mdulo BAS de Visual Basic, ni como una propiedad compartida del SPM, porque esa referencia slo sera utilizable por el objeto 1, pero no por el objeto 3, que necesitara un proxy capaz de cambiar del contexto 3 al 2. Otro problema que se ha eliminado con COM+ es el del registro de Windows. La clave InProcServer32 de un componente COM contiene la ruta de la DLL donde se encuentra el componente. Sin embargo, en el momento de registrar el componente dentro de un paquete MTS, el valor de esta clave cambiaba por C:\WINNT\SYSTEM32\MTXEX.DLL, es decir, la ruta del MTS Executive. Esto era necesario para que el MTS pudiera hacer la intercepcin en el momento de la creacin del componente, ya que las rutinas COM no eran capaces de hacerlo por s mismas. El problema vena en el momento de recompilar el componente desde el Visual Basic: despus de la compilacin, ste llama automticamente a REGSVR32.EXE, y el componente volva a ser registrado segn la manera de COM, y el valor de la clave InProcServer32 volva a ser el de la ruta de la DLL, con lo que el componente ya no funcionaba correctamente porque el MTS no poda hacer la intercepcin.

216

Grupo EIDOS

11. Servicios de componentes

Para mitigar este problema, el MTS contaba con la posibilidad de Actualizar los componentes de un paquete, que consista en que el MTS inspeccionaba en el registro de Windows las claves de los componentes de dicho paquete, y correga automticamente sus valores. Todas estas dificultades se han eliminado con COM+. La clave InProcServer32 siempre contiene la ruta de la DLL, sea el componente congifurado o no-configurado. La diferencia estriba en que los componentes configurados tienen informacin adicional en el registro. No es necesario refrescar los componentes despus de cada recompilacin en Visual Basic.

217

Diseo de componentes COM+


En este tema vamos a ver de qu forma los Servicios de Componentes de COM+ (antes MTS) pueden afectar al diseo de los componentes. Comprobaremos cmo se produce la interceptacin de la que hemos hablado anteriormente, siendo estos Servicios de Componentes los encargados de gestionar la creacin y destruccin de los objetos que estn registrados en el catlogo de COM+. Veremos cmo por el simple hecho de registrar un componente en una aplicacin COM+ y configurar una serie de propiedades declarativas, podemos extender su funcionalidad sin necesidad de tocar una sola lnea de cdigo.

El interfaz ObjectControl
Hemos dicho que cuando un componente es registrado en el catlogo de COM+, los Servicios de Componentes se encargan de gestionar su creacin y destruccin. Si queremos conocer cundo es creado y destruido realmente el componente, podemos hacerlo implementado dentro del mismo el interfaz ObjectControl. Este interfaz tiene tres mtodos: Activate: es invocado cuando el componente es activado o re-activado (en el caso de los componentes C++, que pueden ser desactivados, almacenados en el pool, y re-activados). Si hago que mi componente implemente el interfaz ObjectControl, este mtodo ser invocado automticamente por las rutinas de COM+ antes que cualquier otro mtodo. Sera lgico usar este mtodo para incluir cdigo de inicializacin que sea global para todos los mtodos del

Desarrollo de aplicaciones COM+ para Internet / Intranet con ASP 3.0

Grupo EIDOS

objeto. Si se trata por ejemplo de un objeto que accede a una base de datos a travs de ADO, en este mtodo podramos crear la conexin. Tambin es normal obtener aqu la referencia al objeto del contexto, para poder usarla luego en los mtodos del componente. Deactivate: es invocado cuando el componente es desactivado. Igual que con el mtodo anterior, aqu pondra cdigo de finalizacin del objeto, como cierre de una conexin a travs de ADO. CanBePooled: este mtodo devuelve un valor booleano que indica si las rutinas COM+ pueden meter este objeto en un pool, una vez desactivado. Actualmente esta opcin slo estara disponible para componentes escritos en C++. Para componentes escritos en Visual Basic este mtodo devolver siempre False.

Vamos a construir ahora un componente en Visual Basic para comprobar lo que acabamos de ver. Abrimos un nuevo proyecto ActiveX DLL, al que llamaremos CompActivar, con un mdulo de clase al que llamaremos Activar. El componente har uso del objeto Response de ASP, para escribir directamente con Write. Implementar el interfaz ObjectControl, y adems tendr un mtodo adicional. Aadimos al proyecto las referencias a las libreras de COM+ y del modelo de objetos de ASP. El Cdigo fuente 165 muestra cmo quedaran estos mtodos.

Option Explicit Implements ObjectControl Private Sub ObjectControl_Activate() Dim objContext As ObjectContext Dim objResponse As Response Set objContext = GetObjectContext Set objResponse = objContext("Response") objResponse.Write "activado a las " & Time & "<br>" End Sub Private Sub ObjectControl_Deactivate() Dim objContext As ObjectContext Dim objResponse As Response Set objContext = GetObjectContext Set objResponse = objContext("Response") objResponse.Write "desactivado a las " & Time & "<br>" End Sub Private Function ObjectControl_CanBePooled() As Boolean ObjectControl_CanBePooled = False End Function Public Sub escribe() Dim objContext As ObjectContext Dim objResponse As Response Set objContext = GetObjectContext Set objResponse = objContext("Response") objResponse.Write "dentro del mtodo a las " & Time & "<br>" End Sub Cdigo fuente 165

220

Grupo EIDOS

12. Diseo de componentes COM+

El hecho de aadir la lnea Implements ObjectControl nos obliga a implementar los tres mtodos del interfaz; si no lo hacemos as, no podremos compilar. Esta lnea es necesaria para que los Servicios de Componentes puedan invocar automticamente a los mtodos del interfaz. En los mtodos ObjectControl_Activate, ObjectControl_Deactivate, y en el mtodo escribe, obtenemos una referencia al objeto de contexto, y a travs de l una referencia al objeto Response, para poder escribir directamente un corto mensaje y la hora del sistema. Ahora escribimos una pgina ASP con el Cdigo fuente 166.

<%@ Language=VBScript %> <%Response.Buffer = false%> <HTML> <HEAD> <META NAME="GENERATOR" Content="Microsoft Visual Studio 6.0"> </HEAD> <BODY> <% Set objCom = Server.CreateObject("CompActivar.Activar") inicio = Time Response.Write inicio & "<br>" while Time<>DateAdd("s",5,inicio) wend Response.Write Time & "<br>" objCom.escribe & "<br>" %> </BODY> </HTML> Cdigo fuente 166

Deshabilitamos el buffer en la segunda lnea, para poder ir recibiendo gradualmente en el navegador el resultado de la ejecucin de la pgina. Instanciamos el componente, obtenemos la hora del sistema y la escribimos con Write. El bucle WhileWend consiste en un temporizador muy rudimentario, que ralentizar la ejecucin de la pgina durante cinco segundos. Obtenemos nuevamente la hora del sistema, la escribimos, e invocamos al mtodo escribe del componente. Si ejecutamos la pgina, obtendremos: 9:38:04 9:38:09 dentro del mtodo a las 9:38:09 Es decir, no han sido invocados los mtodos Activate ni Deactivate. Esto es as porque todava el componente no est registrado en el catlogo de COM+, y los Servicios de Componentes no se han encargado de interceptar la creacin y destruccin del objeto. Vamos pues a registrarlo. Dentro de Programas | Herramientas administrativas, seleccionamos la opcin Servicios de Componentes. Esto abrir la consola de administracin de estos servicios, como se muestra en la Figura 57. Vayamos extendiendo el rbol de la consola del panel izquierdo hasta llegar a la carpeta de Aplicaciones COM+.

221

Desarrollo de aplicaciones COM+ para Internet / Intranet con ASP 3.0

Grupo EIDOS

Figura 57

En el panel derecho veremos las aplicaciones COM+ actualmente instaladas en el equipo. Para crear una nueva, pulsamos con el botn derecho sobre la carpeta Aplicaciones COM+ del panel izquierdo, y seleccionamos Nuevo | Aplicacin. En ese momento se inicia el asistente (ver Figura 58) para instalacin de aplicaciones COM+.

Figura 58

En la siguiente ventana (ver Figura 59) pulsaremos sobre el botn de Crear una aplicacin vaca. A esta aplicacin aadiremos luego nuestro componente recin creado.

222

Grupo EIDOS

12. Diseo de componentes COM+

Figura 59

En el siguiente paso (ver Figura 60) se nos pide el nombre de la nueva aplicacin, y adems se nos permite configurar en qu espacio de memoria queremos que se ejecuten los componentes de la aplicacin. Tenemos dos opciones, segn seleccionemos un tipo u otro de aplicacin: Aplicacin de biblioteca: las instancias de los componentes de la aplicacin se ejecutan en el mismo espacio de memoria que el cliente que las crea. Esta opcin puede ser recomendable en tiempo de desarrollo de los componentes. Aplicacin de servidor: las instancias de los componentes se ejecutan en un proceso separado del de la aplicacin cliente que los utiliza. Esta opcin es la que debe utilizarse en tiempo de produccin.

Figura 60

En la siguiente ventana (Figura 61) podemos elegir bajo que cuenta se ejecutarn los componentes. Si seleccionamos la opcin marcada por defecto, entonces cuando instanciemos el componente desde una pgina ASP, y si est activado el acceso annimo para la aplicacin web a la que pertenece dicha pgina, la cuenta utilizada ser la de invitado a internet (IUSR_nombreMquina).

223

Desarrollo de aplicaciones COM+ para Internet / Intranet con ASP 3.0

Grupo EIDOS

Figura 61

En la siguiente ventana basta con pulsar el botn de Finalizar, y ya est nuestra aplicacin creada. Ahora tenemos que aadir el componente. Para ello la expandimos en el rbol del panel izquierdo correspondiente a la aplicacin COM+ recin creada hasta llegar a la carpeta Componentes, como muestra la Figura 62.

Figura 62

224

Grupo EIDOS

12. Diseo de componentes COM+

La carpeta de Componentes no tiene ningn elemento, puesto que hemos creado una aplicacin vaca. Vamos a aadirlo pulsando con el botn derecho sobre la carpeta Componentes del panel izquierdo, y seleccionando Nuevo | Componente. Con esto arranca el asistente para la instalacin de componentes COM. En la pantalla que se muestra en la Figura 63, debemos pulsar la opcin Importar componentes ya registrados, puesto que al compilar el proyecto de Visual Basic, ya se ha encargado de registrarlo por nosotros en la mquina.

Figura 63

Despus de un momento, el que tarda en buscar en el registro de Windows los componentes registrados en la mquina, nos aparece la lista de la Figura 64, de la que debemos seleccionar nuestro componente.

Figura 64

Con esto el componente queda registrado, como se ve en la Figura 65. Ms adelante veremos las propiedades declarativas que podemos configurar, pero de momento nos basta con las que tiene por defecto.
225

Desarrollo de aplicaciones COM+ para Internet / Intranet con ASP 3.0

Grupo EIDOS

Figura 65

Antes de volver a ejecutar la pgina ASP, vamos a descargarla, para descargar con ello la dll del componente. Recordemos que esto podamos hacerlo desde la consola de administracin del IIS, pulsando con el botn derecho sobre el nombre de la aplicacin web y seleccionando la opcin Propiedades, y luego la pestaa Directorio. Si ahora pulsamos el botn Descargar, conseguiremos nuestro objetivo. Al ejecutar otra vez la pgina, el resultado que obtendremos ser: 10:50:50 10:50:55 activado a las 10:50:55 dentro del mtodo a las 10:50:55 desactivado a las 10:50:55 Como podemos ver, ahora los Servicios de Componentes han interceptado la creacin del componente. Con la instruccin Server.CreateObject("CompActivar.Activar"), no se produce la instanciacin inmediata del componente, sino que esta se produce al invocar el primer mtodo, es decir, en la instruccin Response.Write objCom.escribe. Por cierto, que si abrimos de nuevo la consola de administracin de los Servicios de Componente y expandimos el rbol de la izquierda hasta la carpeta Aplicaciones COM+, veremos en el panel de la derecha que el icono correspondiente a la aplicacin ASPComp muestra la bolita girando dentro de la caja. Esto significa que la DLL est cargada en memoria. Una de las ventajas de registrar el componente en una aplicacin COM+ es que podemos controlar la descarga de las DLLs. Basta con

226

Grupo EIDOS

12. Diseo de componentes COM+

pulsar con el botn derecho sobre el icono de la aplicacin y seleccionar la opcin Cerrar sistema. La DLL se descarga, y la bolita ahora deja de girar. Si no cerramos nosotros la aplicacin explcitamente, se cierra ella sola segn la opcin elegida en la pestaa Activacin de las propiedades de la aplicacin COM+, como se muestra en la Figura 66. Por defecto aparece marcada la opcin Minutos de inactividad antes de cerrar, con un valor de tres. Esto significa que si transcurren ms de tres minutos sin que se reciba una peticin de algn mtodo del componente incluido en dicha dll, la aplicacin se descargar.

Figura 66

Tambin podemos forzar nosotros mismos el comienzo de la aplicacin si pulsamos con el botn derecho sobre el icono de la aplicacin y seleccionamos la opcin Iniciar. De esta forma la primera peticin de la pgina ASP, que hace uso del componente de esta aplicacin, no se ralentizar por el proceso de carga de la dll en memoria, sino que se encontrar con que sta ya estaba cargada.

Activacin Just-In-Time (JIT)


Esta intercepcin que realiza los Servicios de Componentes, podemos deshabilitarla. Para ello, descarguemos previamente la aplicacin COM+, como hemos visto, y pasemos a ver las propiedades declarativas del componente, pulsando con el botn derecho sobre su icono dentro del administrador de los Servicios de Componentes, y seleccionando la opcin Propiedades. En la pestaa Transacciones (ver Figura 67), comprobemos que la opcin seleccionada por defecto es la de No se admite. De esta forma el componente nunca tendr voto en una transaccin, pero dispone de un objeto de contexto (luego puede acceder al objeto Response de ASP).

227

Desarrollo de aplicaciones COM+ para Internet / Intranet con ASP 3.0

Grupo EIDOS

Figura 67

Vayamos ahora a la pestaa Activacin para deseleccionar la casilla Habilitar activacin puntual, es decir, deshabilitamos la activacin Just-In-Time del componente. Esto se muestra en la Figura 68.

Figura 68

228

Grupo EIDOS

12. Diseo de componentes COM+

Y si ahora ejecutamos de nuevo la pgina ASP, el resultado obtenido ser: 12:02:13 12:02:18 dentro del mtodo a las 12:02:18 que es el mismo que se obtena cuando el objeto no estaba registrado en una aplicacin COM+. Hemos impedido que los Servicios de Componentes intercepten la creacin del objeto, luego no se invocan los mtodos Activate y Deactivate. Permitir que los Servicios de Componentes gestionen la activacin del componente supone una mejora en la escalabilidad de la aplicacin, pues los recursos del servidor son administrados de forma ms eficiente. El cliente no tiene que preocuparse de en qu momento se activa el componente, sino que lo hacen por l los Servicios de Componentes, activndolo en el momento preciso (activacin Just-InTime).

Inicializacin del componente


Utilicemos lo visto en los apartados anteriores para hacer un componente que obtenga la referencia al objeto de contexto en la inicializacin, dentro del mtodo Activate, para que est disponible en el resto de mtodos a travs de una variable miembro. Escribiremos un mtodo listaApplication que genere una tabla HTML con las variables de mbito de aplicacin, y otro listaSession que haga lo mismo con las variables de mbito de sesin. Creamos un nuevo proyecto ActiveX DLL con el nombre de CompApliSes, con un mdulo de clase llamado ApliSes. Aadimos al proyecto las referencias a las libreras de COM+ y del modelo de objetos de ASP. El cdigo de este mdulo ser el del Cdigo fuente 167.

Option Explicit Implements ObjectControl Private mvarobjContext As ObjectContext Private mvarobjResponse As Response Private Sub ObjectControl_Activate() Set mvarobjContext = GetObjectContext Set mvarobjResponse = mvarobjContext("Response") mvarobjResponse.Write "activado a las " & Time & "<br>" End Sub Private Sub ObjectControl_Deactivate() mvarobjResponse.Write "desactivado a las " & Time & "<br>" End Sub Private Function ObjectControl_CanBePooled() As Boolean ObjectControl_CanBePooled = False End Function Public Sub listaApplication() Dim strHTML As String Dim objApplication As Application

229

Desarrollo de aplicaciones COM+ para Internet / Intranet con ASP 3.0

Grupo EIDOS

Dim variable As Variant Set objApplication = mvarobjContext("Application") strHTML = "<table border=1><tr><th>Variable</th><th>Valor</th></tr>" For Each variable In objApplication.Contents strHTML = strHTML & "<tr><td>" & variable & "</td><td>" & _ objApplication.Contents(variable) & "</td></tr>" Next strHTML = strHTML & "</table>" mvarobjResponse.Write strHTML End Sub Public Sub listaSession() Dim strHTML As String Dim objSession As Session Dim variable As Variant Set objSession = mvarobjContext("Session") strHTML = "<table border=1><tr><th>Variable</th><th>Valor</th></tr>" For Each variable In objSession.Contents strHTML = strHTML & "<tr><td>" & variable & "</td><td>" & _ objSession.Contents(variable) & "</td></tr>" Next strHTML = strHTML & "</table>" mvarobjResponse.Write strHTML End Sub Cdigo fuente 167

Como puede verse, en el mtodo Activate del interfaz ObjectControl obtenemos la referencia al objeto de contexto, y a partir de l la referencia al objeto Response. Como los dos objetos van a ser utilizados por los mtodos listaApplication y listaSession, nos interesa guardarlos como variables miembro. En estos dos mtodos tomamos la referencia al objeto de ASP correspondiente, Application o Session, generamos el cdigo HTML necesario para la tabla, recorriendo la coleccin con un bucle Foreach, y escribimos directamente sobre el objeto Response. Registremos el componente dentro de la aplicacin COM+, ASPComp, y probmoslo desde una pgina ASP con un cdigo similar al del Cdigo fuente 168.

<%@ Language=VBScript %> <HTML> <HEAD> <META NAME="GENERATOR" Content="Microsoft Visual Studio 6.0"> </HEAD> <BODY> <% Application("var1")="valor1" Application("var2")="valor2" Application("var3")="valor3" Session("var1")="valor1" Session("var2")="valor2" Set objCom = Server.CreateObject("CompApliSes.ApliSes") Response.Write "<h3>Variables de Application</h3>" objCom.listaApplication

230

Grupo EIDOS

12. Diseo de componentes COM+

Response.Write "<h3>Variables de Session</h3>" objCom.listaSession %> </BODY> </HTML> Cdigo fuente 168

Tendremos el resultado que se muestra a continuacin:

VARIABLES DE APPLICATION
activado a las 13:14:47 Variable Valor var1 var2 var3 valor1 valor2 valor3

VARIABLES DE SESSION
Variable Valor var1 var2 valor1 valor2

desactivado a las 13:14:47 Podemos ver que el mtodo Activate ha sido invocado automticamente, y slo en el momento de llamar al primer mtodo, no en el CreateObject. Por eso el mensaje que genera este mtodo aparece entre el ttulo, escrito desde la pgina ASP, y la primera tabla, generada por el componente en el mtodo listaApplication. El mtodo Deactivate es invocado al finalizar la ejecucin de la pgina, y salir de mbito la variable de referencia objCom. Ms adelante veremos que un objeto puede ser desactivado y reactivado entre las llamadas a sus mtodos, en vez de activado en la primera llamada y desactivado despus de la ltima.

231

Desarrollo de aplicaciones COM+ para Internet / Intranet con ASP 3.0

Grupo EIDOS

Estado de un componente
El paradigma de Programacin Orientada a Objetos nos dice que los objetos se caracterizan por su identidad, estado y comportamiento. Pues bien, veremos que si queremos disear componentes que aprovechen al mximo los Servicios de Componentes, debemos programar componentes sin estado. Vamos a disear un componente que permita hacer un alta en una tabla. Esta tabla la crearemos en SQL Server, aunque podra valer otro gestor de base de datos, incluso Access. Aadiremos adems un procedimiento almacenado para realizar el alta. La secuencia SQL necesaria para crear la tabla y el procedimiento se muestra en el Cdigo fuente 169.

CREATE TABLE Clientes( id smallint PRIMARY KEY, nombre varchar(25), saldo money )

CREATE PROCEDURE alta @id smallint, @nombre varchar(25), @saldo money AS INSERT INTO Clientes VALUES(@id,@nombre,@saldo) Cdigo fuente 169

Disearemos el interfaz del componente de forma que disponga de una propiedad cadenaConex, que contendr la cadena de conexin, y un mtodo alta, que ser el que acceda mediante ADO a la base de datos, empleando para ello el procedimiento almacenado recin creado. En el Cdigo fuente 170 est el cdigo necesario para este componente.

Private Private Private Private Private

mvarcadenaConex As String objCnx As ADODB.Connection objCmd As ADODB.Command objRst As ADODB.Recordset objContext As ObjectContext

Public Sub alta(ByVal id As Integer, ByVal nombre As String, ByVal saldo As Currency) Dim objPar1, objPar2, objPar3 As ADODB.Parameter Set objContext = GetObjectContext Set objCnx = New ADODB.Connection objCnx.Open mvarcadenaConex Set objCmd = New ADODB.Command objCmd.ActiveConnection = objCnx objCmd.CommandText = "alta" Set objPar1=objCmd.CreateParameter("par1", adSmallInt, adParamInput, 2, id) Set objPar2=objCmd.CreateParameter("par2", adVarChar, adParamInput, 25, nombre) Set objPar3=objCmd.CreateParameter("par3", adCurrency, adParamInput, 8, saldo) objCmd.Parameters.Append objPar1 objCmd.Parameters.Append objPar2 objCmd.Parameters.Append objPar3 objCmd.Execute , , adCmdStoredProc

232

Grupo EIDOS

12. Diseo de componentes COM+

objContext.SetComplete objCnx.Close Set objCmd = Nothing Set objCnx = Nothing End Sub Public Property Let cadenaConex(ByVal vData As String) mvarcadenaConex = vData End Property Public Property Get cadenaConex() As String cadenaConex = mvarcadenaConex End Property Cdigo fuente 170

Comentemos algunas cosas de este cdigo. Como puede verse, una propiedad est implementada en Visual Basic mediante una variable miembro, en este caso mvarcadenaConex, a la que puede accederse para modificar su valor mediante un mtodo Property Let, o para obtener su valor mediante Property Get. En realidad una propiedad equivale pues a dos mtodos, y modificar el valor de la propiedad o leerla supone invocar un mtodo. En el cdigo obtenemos tambin la referencia al objeto de contexto, y cuando el mtodo alta ha finalizado su ejecucin, invocamos el mtodo SetComplete. Esto puede parecer extrao, puesto que este mtodo suele asociarse siempre con transacciones sobre bases de datos, al igual que el mtodo SetAbort. Pero realmente este mtodo nos permite aumentar la escalabilidad, porque equivale a informar a los Servicios de Componentes de que el objeto ha terminado su labor y puede ser desactivado. No es necesario que el componente sea transaccional para poder emplear cualquiera de estos dos mtodos. Vamos a crear ahora una pgina ASP con la que probar este componente. El Cdigo fuente 171 podra ser un ejemplo.

<%@ Language=VBScript %> <HTML> <HEAD> <META NAME="GENERATOR" Content="Microsoft Visual Studio 6.0"> </HEAD> <BODY> <% Set objCom = Server.CreateObject("CompAlta.Alta") objCom.cadenaConex = "Provider=SQLOLEDB.1;User ID=sa;Initial Catalog=ASPComp;Data Source=varrondo" Response.Write "La cadena de conexin es: " & objCom.cadenaConex & "<br>" objCom.alta 1,"pepe",1000 Response.Write "La cadena de conexin es: " & objCom.cadenaConex & "<br>" On Error Resume Next objCom.alta 2,"pepa",2000 if Err<>0 then Response.Write Err.description On Error Goto 0 Set objCom = Nothing %> </BODY> </HTML> Cdigo fuente 171

233

Desarrollo de aplicaciones COM+ para Internet / Intranet con ASP 3.0

Grupo EIDOS

Si la ejecutamos, veremos que funciona correctamente como podramos esperar. Instanciamos el componente y le asignamos valor a la propiedad cadenaConex. Esto equivale a invocar un mtodo, el Property Let. Luego obtenemos su valor y lo escribimos. Esto es una llamada al mtodo Property Get. Luego invocamos al mtodo alta, y seguidamente volvemos a escribir la propiedad cadenaConex. Activamos el gestor de errores de VBScript e invocamos una segunda vez al mtodo alta, con un nuevo valor de clave primaria. Este componente parece correcto, desde el punto de vista de la Programacin Orientada a Objetos. Tiene una propiedad de estado, la cadena de conexin, que es utilizada en uno de sus mtodos, alta. Sin embargo, vamos a ver lo que ocurre cuando registramos el componente en la aplicacin COM+ que venimos utilizando. Previamente hemos de quitar la DLL de memoria, mediante la descarga de la aplicacin web a travs de la consola de administracin del IIS. Eliminemos tambin los registros de la tabla, para evitar infringir la restriccin de clave primaria. Si ahora volvemos a ejecutar la pgina ASP, la primera alta se ejecuta correctamente, pero luego vemos que la propiedad cadenaConex aparece vaca, y la segunda alta falla al no serle suministrado al mtodo Open del objeto Connection una cadena de conexin correcta. Qu es lo que ha ocurrido? Los Servicios de Componentes han interceptado la creacin del objeto, y estn ahorrando recursos. Despus de la llamada al primer mtodo, el SetComplete comunica que el objeto ha terminado su labor y puede ser desactivado, y eso es exactamente lo que ocurre, con lo cual se pierde el estado. Si llamramos diez veces al mtodo alta, estaramos activando y desactivando el objeto diez veces, perdiendo entre las llamadas la informacin de estado del mismo. Esto puede parecer que tendr poco rendimiento, pero no es as, y se ahorran recursos que estaran sin utilizar entre las llamadas. Aunque la pgina ASP crea el objeto y no lo destruye hasta el final, realmente lo que obtiene no es la referencia al objeto real, sino al context wrapper, mientras el objeto real es creado y destruido bajo la gestin de los Servicios de Componentes. Una forma de conseguir que el componente funcionara correctamente sera volver a asignar valor a la propiedad cadenaConex antes de llamar por segunda vez al mtodo alta. Otra manera sera modificando una de las propiedades declarativas del componente. Si de entre sus propiedades elegimos la pestaa Activacin y desactivamos la casilla Habilitar activacin puntual, conseguimos que los Servicios de Componentes no gestionen la activacin Just-In-Time de este componente, que ahora se comportar como un objeto COM tradicional, cuyo tiempo de vida coincidir con el tiempo durante el que la pgina ASP guarda una referencia a l. Para que estos cambios en la propiedad declarativa del componente tengan efecto, debemos descargar previamente de memoria la aplicacin COM+. Pero de este modo perdemos las ventajas de escalabilidad mediante el ahorro de recursos que nos proporcionan los Servicios de Componentes. Ms eficaz sera hacer que la cadena de conexin fuera suministrada como parmetro al mtodo, junto con los otros tres. O permitir que el componente acceda al modelo de objetos de ASP mediante el objeto de contexto, para leer la cadena de conexin directamente de una variable de aplicacin. Tambin podramos usar el mtodo Activate del interfaz ObjectControl, para asignar en ese momento el valor a la cadena de conexin, leda desde el objeto Application. Hagmoslo as, como en el Cdigo fuente 172.
234

Grupo EIDOS

12. Diseo de componentes COM+

Option Explicit Implements ObjectControl Private mvarcadenaConex As String Private objContext As ObjectContext Public Sub alta(ByVal id As Integer, ByVal nombre As String, ByVal saldo As Currency) Dim objCnx As ADODB.Connection Dim objCmd As ADODB.Command Dim objRst As ADODB.Recordset Dim objPar1, objPar2, objPar3 As ADODB.Parameter Set objContext = GetObjectContext Set objCnx = New ADODB.Connection objCnx.Open mvarcadenaConex Set objCmd = New ADODB.Command objCmd.ActiveConnection = objCnx objCmd.CommandText = "alta" Set objPar1=objCmd.CreateParameter("par1", adSmallInt, adParamInput, 2, id) Set objPar2=objCmd.CreateParameter("par2", adVarChar, adParamInput, 25, nombre) Set objPar3=objCmd.CreateParameter("par3", adCurrency, adParamInput, 8, saldo) objCmd.Parameters.Append objPar1 objCmd.Parameters.Append objPar2 objCmd.Parameters.Append objPar3 objCmd.Execute , , adCmdStoredProc objContext.SetComplete objCnx.Close Set objCmd = Nothing Set objCnx = Nothing End Sub Private Sub ObjectControl_Activate() Dim objResponse As Response Dim objApplication As Application Set objContext = GetObjectContext Set objApplication = objContext("Application") mvarcadenaConex = objApplication("CadenaConex") Set objResponse = objContext("Response") objResponse.Write "activado a las " & Time & "<br>" End Sub Private Sub ObjectControl_Deactivate() Dim objResponse As Response Set objContext = GetObjectContext Set objResponse = objContext("Response") objResponse.Write "desactivado a las " & Time & "<br>" End Sub Private Function ObjectControl_CanBePooled() As Boolean ObjectControl_CanBePooled = False End Function Cdigo fuente 172

Si ahora ejecutamos la pgina con el Cdigo fuente 173, funcionar correctamente, y podremos comprobar en la ventana del navegador que el componente ha sido activado y desactivado dos veces.

Application("CadenaConex") = "Provider=SQLOLEDB.1;User ID=sa;Initial Catalog=ASPComp;Data Source=varrondo" Set objCom = Server.CreateObject("CompAlta.Alta") objCom.alta 1,"pepe",1000 objCom.alta 2,"pepa",2000

235

Desarrollo de aplicaciones COM+ para Internet / Intranet con ASP 3.0

Grupo EIDOS

Set objCom = Nothing Cdigo fuente 173

Hagamos ahora otro componente, que extienda la funcionalidad del anterior, permitiendo un mantenimiento sencillo de la tabla recin creada, por medio de tres mtodos: uno para hacer altas, otro bajas y otro consulta. Para hacer que el componente sea lo ms reutilizable posible, haremos que la cadena de conexin se suministre por medio de una variable de aplicacin, como acabamos de ver, y que el acceso a la base de datos sea a travs de procedimientos almacenados. Tendremos que aadir los dos nuevos que aparecen en el Cdigo fuente 174.

CREATE PROCEDURE baja @id smallint AS DELETE FROM Clientes WHERE id=@id

CREATE PROCEDURE consulta AS SELECT * FROM Clientes Cdigo fuente 174

El componente quedar como en el Cdigo fuente 175.

Private Private Private Private Private Private

objContext As ObjectContext objApplication As Application mvarcadenaConex As String objCnx As ADODB.Connection objCmd As ADODB.Command objRst As ADODB.Recordset

Public Function consulta() As Variant() Set objContext = GetObjectContext Set objApplication = objContext("Application") mvarcadenaConex = objApplication.Contents("CadenaConex") Set objCnx = New ADODB.Connection objCnx.Open mvarcadenaConex Set objCmd = New ADODB.Command objCmd.ActiveConnection = objCnx objCmd.CommandText = "consulta" Set objRst = objCmd.Execute(, , adCmdStoredProc) consulta = objRst.GetRows objCnx.Close Set objCmd = Nothing Set objCnx = Nothing End Function Public Sub baja(ByVal id As Integer) Dim objPar1 As ADODB.Parameter Set objContext = GetObjectContext Set objApplication = objContext("Application") mvarcadenaConex = objApplication.Contents("CadenaConex") Set objCnx = New ADODB.Connection objCnx.Open mvarcadenaConex Set objCmd = New ADODB.Command objCmd.ActiveConnection = objCnx

236

Grupo EIDOS

12. Diseo de componentes COM+

objCmd.CommandText = "baja" Set objPar1 = objCmd.CreateParameter("par1", adSmallInt, adParamInput, 2, id) objCmd.Parameters.Append objPar1 objCmd.Execute , , adCmdStoredProc objCnx.Close Set objCmd = Nothing Set objCnx = Nothing End Sub Public Sub alta(ByVal id As Integer, ByVal nombre As String, ByVal saldo As Currency) Dim objPar1, objPar2, objPar3 As ADODB.Parameter Set objContext = GetObjectContext Set objApplication = objContext("Application") mvarcadenaConex = objApplication.Contents("CadenaConex") Set objCnx = New ADODB.Connection objCnx.Open mvarcadenaConex Set objCmd = New ADODB.Command objCmd.ActiveConnection = objCnx objCmd.CommandText = "alta" Set objPar1 = objCmd.CreateParameter("par1", adSmallInt, adParamInput, 2, id) Set objPar2 = objCmd.CreateParameter("par2", adVarChar, adParamInput, 25, nombre) Set objPar3 = objCmd.CreateParameter("par3", adCurrency, adParamInput, 8, saldo) objCmd.Parameters.Append objPar1 objCmd.Parameters.Append objPar2 objCmd.Parameters.Append objPar3 objCmd.Execute , , adCmdStoredProc objCnx.Close Set objCmd = Nothing Set objCnx = Nothing End Sub Cdigo fuente 175

Y la pgina ASP necesaria para probar su funcionamiento est en el Cdigo fuente 176.

<%@ Language=VBScript %> <HTML> <HEAD> <META NAME="GENERATOR" Content="Microsoft Visual Studio 6.0"> </HEAD> <BODY> <% Set objCom = Server.CreateObject("CompMantenimiento.Mantenimiento") Application("CadenaConex") = "Provider=SQLOLEDB.1;User ID=sa;Initial Catalog=ASPComp;Data Source=varrondo" %> <%Select Case Request.Form("boton")%> <%Case "alta"%> <form method="POST"> <input name="id"><br> <input name="nombre"><br> <input name="saldo"><br> <input type="submit" name="boton" value="confirmar alta"> </form> <%Case "confirmar alta"%> <% objCom.alta Request.Form("id"),Request.Form("nombre"),Request.Form("saldo")

237

Desarrollo de aplicaciones COM+ para Internet / Intranet con ASP 3.0

Grupo EIDOS

menu %> <%Case "baja"%> <form method="POST"> <input name="id"><br> <input type="submit" name="boton" value="confirmar baja"> </form> <%Case "confirmar baja"%> <% objCom.baja Request.Form("id") menu %> <%Case "consulta"%> <% contenido = objCom.consulta Response.Write "<table border=1>" for i=0 to UBound(contenido,2) Response.Write "<tr>" for j=0 to UBound(contenido,1) Response.Write "<td>" & contenido(j,i) & "</td>" next Response.Write "</tr>" next Response.Write "</table>" menu %> <%Case Else%> <%menu%> <%End Select%> <%Set objCom = Nothing%>

<%Sub menu%> <form method="POST"> <input type="submit" name="boton" value="alta"> <input type="submit" name="boton" value="baja"> <input type="submit" name="boton" value="consulta"> </form> <%End Sub%> </BODY> </HTML> Cdigo fuente 176

Cadena del constructor


Otra forma de aumentar la posibilidad de reutilizar nuestros componentes es pasarle una cadena en el momento de la construccin de un objeto a partir del componente. El contenido de esta cadena es asignado por medio de propiedades declarativas. Esto tiene una aplicacin evidente en el caso de que el componente acceda a una base de datos. Si la cadena de conexin, necesaria para conectarse a la fuente de datos, se le suministra por medio de un parmetro en el instante de la construccin, podemos administrativamente modificar el contenido de esta cadena para que el mismo componente nos sirva para el acceso a distintas fuentes de datos.

238

Grupo EIDOS

12. Diseo de componentes COM+

Adems si le pasamos la cadena de conexin de esta forma, en vez de recuperarla del objeto Application, podemos reutilizar el componente desde clientes que no sean pginas ASP, puesto que ya no hacemos uso de un modelo de objetos especfico. Retomemos el ejemplo del componente de altas, que habamos llamado CompAlta. Eliminemos del proyecto la referencia a la librera con el modelo de objetos de ASP, que ya no vamos a utilizar. Eliminemos tambin, por claridad, los mtodos del interfaz ObjectControl. Si sustituimos: Implements ObjectControl por Implements IobjectConstruct, tendremos disponible el combo izquierdo el interfaz, y al seleccionarlo se generar automticamente el cdigo inicial de su nico mtodo, Construct. En este mtodo slo tenemos que tomar el parmetro pCtorObj, que es un objeto cuya propiedad ConstructString contiene precisamente la cadena del constructor, cuyo valor definimos mediante una propiedad declarativa. A continuacin asignamos a la variable miembro mvarcadenaConex este valor. Todo esto puede verse en el Cdigo fuente 177.

Option Explicit Implements IObjectConstruct Private mvarcadenaConex As String Public Sub alta(ByVal id As Integer, ByVal nombre As String, ByVal saldo As Currency) Dim objCnx As ADODB.Connection Dim objCmd As ADODB.Command Dim objRst As ADODB.Recordset Dim objPar1, objPar2, objPar3 As ADODB.Parameter Set objCnx = New ADODB.Connection objCnx.Open mvarcadenaConex Set objCmd = New ADODB.Command objCmd.ActiveConnection = objCnx objCmd.CommandText = "alta" Set objPar1=objCmd.CreateParameter("par1", adSmallInt, adParamInput, 2, id) Set objPar2=objCmd.CreateParameter("par2", adVarChar, adParamInput, 25, nombre) Set objPar3=objCmd.CreateParameter("par3", adCurrency, adParamInput, 8, saldo) objCmd.Parameters.Append objPar1 objCmd.Parameters.Append objPar2 objCmd.Parameters.Append objPar3 objCmd.Execute , , adCmdStoredProc objCnx.Close Set objCmd = Nothing Set objCnx = Nothing End Sub Private Sub IObjectConstruct_Construct(ByVal pCtorObj As Object) mvarcadenaConex = pCtorObj.ConstructString End Sub Cdigo fuente 177

Si ahora vamos a la consola de administracin de los Servicios de Componentes, y dentro de las Propiedades del componente CompAlta seleccionamos la pestaa Activacin, podemos marcar la casilla Habilitar construccin de objetos y dar valor a esta propiedad declarativa, como se ve en la Figura 69. Si ejecutamos ahora una pgina ASP con un cdigo tan sencillo como el del Cdigo fuente 178, todo funcionar correctamente. Ya se adivina lo fcil que es hacer que este componente trabaje contra otra
239

Desarrollo de aplicaciones COM+ para Internet / Intranet con ASP 3.0

Grupo EIDOS

base de datos, incluso de otro fabricante, con tal de que disponga de un procedimiento almacenado llamado alta que necesite los mismos tres parmetros, y configuremos administrativamente su nueva cadena de conexin, sin necesidad de modificar en absoluto el cdigo del componente, ni por supuesto de recompilarlo.

Figura 69

Set objCom = Server.CreateObject("CompAlta.Alta") objCom.alta 1,"pepe",1000 objCom.alta 2,"pepa",2000 Set objCom = Nothing Cdigo fuente 178

240

Componentes transaccionales
Introduccin
En este tema vamos a ver componentes transaccionales, es decir, aquellos cuyas operaciones sobre una base de datos deben ser englobadas dentro de una transaccin. El caso ms tpico lo constituye la transferencia de dinero de una cuenta a otra. Utilizaremos la tabla de Clientes, ya conocida de temas anteriores, a la que aadiremos una segunda tabla LogTransferencias y dos procedimientos almacenados. Para lograr una mayor claridad, reduciremos el cdigo lo ms posible. El Cdigo fuente 179 muestra las secuencias SQL para generar la tabla y los procedimientos almacenados nuevos.

CREATE TABLE LogTransferencias( fecha datetime NOT NULL, idEmi smallint NOT NULL, cantidad money NOT NULL, idRec smallint NOT NULL, PRIMARY KEY NONCLUSTERED(fecha,idEmi,cantidad,idRec) )

CREATE PROCEDURE movimiento @id smallint, @cantidad money AS UPDATE Clientes SET saldo = saldo + @cantidad WHERE id=@id

Desarrollo de aplicaciones COM+ para Internet / Intranet con ASP 3.0

Grupo EIDOS

CREATE PROCEDURE registro @fecha datetime, @idEmi smallint, @cantidad money, @idRec smallint AS INSERT INTO LogTransferencias VALUES(@fecha,@idEmi,@cantidad,@idRec) Cdigo fuente 179

En vez de usar un nico procedimiento almacenado para hacer la transferencia, invocaremos al procedimiento almacenado movimiento una vez para cada cuenta, la de origen y la de destino. Esto nos permitir entender mejor los problemas transaccionales en ASP con componentes. Antes de nada veremos unos conceptos previos, relativos a componentes transaccionales.

El contexto y las transacciones Pautas para el desarrollo de componentes transaccionales


Conseguir una referencia del objeto de contexto. La informacin de contexto para un objeto est almacenada en este tipo de objeto, que es capaz de vigilar el trabajo realizado por aqul, as como su informacin de seguridad. Los objetos obtienen una referencia de su objeto de contexto, llamando a la funcin GetObjectContext, funcin que proporcionan los Servicios de Componentes. Los objetos COM+ utilizan el objeto de contexto para informar de si han terminado o no su trabajo con xito, as como para obtener informacin de la transaccin o de seguridad. Llamar a SetComplete si la transaccin tiene xito. Cuando un objeto termina su trabajo en una transaccin con xito, debe llamar al mtodo SetComplete del objeto de contexto. Esto indicar a los Servicios de Componentes que el trabajo realizado por el objeto puede ser confirmado cuando todos los objetos implicados en la transaccin terminen su trabajo. El mtodo SetComplete tambin indica a los Servicios de Componentes que cualquier recurso retenido por el objeto, incluido el propio objeto, puede ser reciclado. Llamar a SetAbort si la transaccin falla. Cuando un objeto no termina con xito su trabajo en una transaccin, ha de llamar al mtodo SetAbort del objeto de contexto. Esto indicar a los Servicios de Componentes que todos los cambios hechos por este objeto y los realizados por otros objetos en la misma transaccin quedarn anulados. Este mtodo tambin indicar a los Servicios de Componentes que cualquier recurso, incluido el propio objeto, puede ser reciclado. Administrar el estado cuidadosamente. El estado representa los datos del objeto que se mantienen despus de haber realizado ms de una llamada al mtodo del objeto. Las variables locales o globales permiten mantener el estado del objeto, pero no debe almacenar los estados de esta forma si se participa en una transaccin. Los Servicios de Componentes reciclan el objeto, cuando la transaccin termina, para liberar, de esta manera, recursos o har que se pierda cualquier tipo de informacin en las variables locales y globales.

La Propiedad MTSTransactionMode de Visual Basic, como se ve en la Figura 70, permite establecer el atributo de transaccin para una clase. Cuando se compile el proyecto, Visual Basic guardar esta
242

Grupo EIDOS

13. Componentes transaccionales

propiedad en la biblioteca de tipos del componente. Luego, si el componente se aade a una aplicacin COM+, los Servicios de Componentes leern el valor de la propiedad MTSTransactionMode y automticamente establecer el atributo de la transaccin en ese valor, tarea que simplifica enormemente la administracin de componentes escritos en Visual Basic.

Figura 70

Casos prcticos
La pgina contiene todo el cdigo transaccional
En el presente captulo veremos una serie de casos, con distintas opciones de diseo de la aplicacin para conseguir la misma funcionalidad final: efectuar una transferencia entre dos cuentas y guardar un registro de la misma en una tabla de log. Veremos cmo afecta cada diseo al comportamiento transaccional de la aplicacin. Veremos una pgina ASP con todo el cdigo, parte del cdigo en componentes, todo el cdigo en componentes, distintas configuraciones de dichos componentes, etc. De este modo, viendo una serie de casos prcticos, se pretende que quede claro cmo se encargan los Servicios de Componentes de gestionar las transacciones cuando estn involucradas pginas ASP y componentes registrados en aplicaciones COM+. Veamos un primer ejemplo en el que todo el cdigo de acceso a la base de datos se encuentra en el script de la pgina ASP, como se muestra en el Cdigo fuente 180. En la rama if de esta pgina crearemos un formulario que permita efectuar una transferencia de dinero de una cuenta a otra. El formulario se submitir a la propia pgina, que ser tratado en la rama else.

<%@ transaction=required %> <!--#INCLUDE file="ADOVBS.INC"--> <html> <head> <title>Transferencia</title>

243

Desarrollo de aplicaciones COM+ para Internet / Intranet con ASP 3.0

Grupo EIDOS

</head> <body> <%Application("CadenaConex") = "Provider=SQLOLEDB.1;User ID=sa;Initial Catalog=ASPComp;Data Source=varrondo"%> <%if Request.Form("boton")="" then%> <form method="POST"> <input name="idEmi"><br> <input name="cantidad"><br> <input name="idRec"><br> <input type="submit" name="boton" value="transferir"> </form> <%else idEmi=Request.Form("idEmi") cantidad=Request.Form("cantidad") idRec=Request.Form("idRec") Set objCnx=Server.CreateObject("ADODB.Connection") objCnx.Open Application("CadenaConex") Set objCmd=Server.CreateObject("ADODB.Command") objCmd.ActiveConnection=objCnx objCmd.CommandText="movimiento" Set objPar1=objCmd.CreateParameter("par1",adSmallInt,adParamInput,2,idEmi) Set objPar2=objCmd.CreateParameter("par2",adCurrency,adParamInput,8,cantidad) objCmd.Parameters.Append objPar1 objCmd.Parameters.Append objPar2 objCmd.Execute numReg,,adCmdStoredProc if numReg=0 then Response.Write "<b>No existe el idEmi</b>" ObjectContext.SetAbort objCnx.Close Response.End end if objCmd.Parameters("par1")=idRec objCmd.Parameters("par2")=cantidad objCmd.Execute numReg,,adCmdStoredProc if numReg=0 then Response.Write "<b>No existe el idRec</b>" ObjectContext.SetAbort objCnx.Close Response.End end if objCmd.CommandText="registro" objCmd.Parameters.Delete "par1" objCmd.Parameters.Delete "par2" Set objPar1=objCmd.CreateParameter("par1",adDate,adParamInput,8,date) Set objPar2=objCmd.CreateParameter("par2",adSmallInt,adParamInput,2,idEmi) Set objPar3=objCmd.CreateParameter("par3",adCurrency,adParamInput,8,cantidad) Set objPar4=objCmd.CreateParameter("par4",adSmallInt,adParamInput,2,idRec) objCmd.Parameters.Append objPar1 objCmd.Parameters.Append objPar2 objCmd.Parameters.Append objPar3 objCmd.Parameters.Append objPar4 objCmd.Execute numReg,,adCmdStoredProc objCnx.Close Set objCmd=Nothing Set objCnx=Nothing end if%>

244

Grupo EIDOS

13. Componentes transaccionales

<% Sub OnTransactionCommit if Request.Form("boton")<>"" then Response.Write "<h2>Transaccin completada</h2>" end if End Sub Sub OnTransactionAbort Response.Write "<h2>Transaccin abortada</h2>" End Sub %> </body> </html> Cdigo fuente 180

En la rama else creamos una nica conexin sobre la que instanciamos un objeto Command, que reutilizaremos modificando o eliminando los parmetros de su coleccin Parameters, invocando sucesivamente a los procedimientos almacenados movimiento, una vez para la cuenta emisora y otra vez para la receptora, y registro, para escribir en la tabla de log de transferencias. La variable numReg que nos devuelve el mtodo Execute ser la que nos permita comprobar si el cliente exista o no exista. Si su valor es igual cero, no hay ningn registro afectado, luego el cliente no exista. Si su valor es igual a uno, s exista el registro. Por simplificar el cdigo, sta ser la nica comprobacin que hagamos. No verificaremos por ejemplo que el saldo del cliente despus de la operacin permanezca mayor que cero. La directiva <%@ transaction=required %> indica a COM+ que la pgina debe ejecutarse en el contexto de una transaccin. Si no existe una, como es el caso, es creada automticamente. Podemos comprobar que si se produce un error porque alguno de los clientes no existe, o generamos nosotros alguno intencionadamente con la lnea Err.Raise vbObjectError + numError, o hacemos explcitamente ObjectContext.SetAbort en la pgina, la transaccin hace rollback automticamente. Recordemos que los eventos OnTransactionCommit y OnTransactionAbort se automticamente cuando la transaccin ha tenido xito o ha fracasado, respectivamente. disparan

Acabemos diciendo que si la ejecucin de la pgina llega a su fin y no se ha producido ninguna instruccin SetAbort, se considera implcitamente que el voto de la pgina en la transaccin es de SetComplete.

Parte del cdigo transaccional en un componente


Hemos visto cmo con la sencilla directiva <%@ transaction=required %> podemos hacer que todo el cdigo contenido en una pgina ASP sea englobado dentro de una misma transaccin. Pero este curso trata de componentes, as que vamos a disear un componente con el cdigo que accede a la tabla Clientes. Creamos un nuevo proyecto ActiveX DLL, al que llamaremos CompTransferencia, con un mdulo de clase llamado Transferencia. Dispondr de un nico mtodo, llamado mover, que acceder a la base de datos a travs del procedimiento almacenado movimiento. Este mtodo ser invocado tanto para
245

Desarrollo de aplicaciones COM+ para Internet / Intranet con ASP 3.0

Grupo EIDOS

retirar el dinero del cliente origen como para ingresarlo en el de destino. Caso de no existir el cliente solicitado, generar un error, que se encargar de recoger la pgina ASP. Acceder a la cadena de conexin a travs de la variable CadenaConex de mbito de aplicacin. El cdigo definitivo puede verse en el Cdigo fuente 181. Debemos aadir al proyecto las referencias a las libreras de los servicios de COM+, del modelo de objetos de ASP, y de ADO.

Option Explicit Public Sub mover(ByVal id As Integer, ByVal cantidad As Currency) Dim objContext As ObjectContext Dim objApplication As Application Dim cadenaConex As String Dim objCnx As ADODB.Connection Dim objCmd As ADODB.Command Dim objPar1, objPar2 As ADODB.Parameter Dim numReg As Integer Set objContext = GetObjectContext Set objApplication = objContext("Application") cadenaConex = objApplication.Contents("CadenaConex") Set objCnx = New ADODB.Connection objCnx.Open cadenaConex Set objCmd = New ADODB.Command objCmd.ActiveConnection = objCnx objCmd.CommandText = "movimiento" Set objPar1 = objCmd.CreateParameter("par1", adSmallInt, adParamInput, 2, id) Set objPar2 = objCmd.CreateParameter("par2", adCurrency, adParamInput, 8, cantidad) objCmd.Parameters.Append objPar1 objCmd.Parameters.Append objPar2 objCmd.Execute numReg, , adCmdStoredProc objCnx.Close Set objCmd = Nothing Set objCnx = Nothing If numReg = 0 Then Err.Raise vbObjectError + 1000, "mover", "No existe el cliente" End Sub Cdigo fuente 181

Compilemos el componente. La pgina ASP necesaria para utilizar este componente slo necesita instanciarlo e invocar sus mtodos, como se ve en el Cdigo fuente 182. El cdigo necesario para escribir en la tabla de log lo mantenemos todava en la pgina ASP.

<%@ transaction=required %> <!--#INCLUDE file="ADOVBS.INC"--> <html> <head> <title>Transferencia</title> </head> <body> <%Application("CadenaConex") = "Provider=SQLOLEDB.1;User ID=sa;Initial Catalog=ASPComp;Data Source=varrondo"%> <%if Request.Form("boton")="" then%>

246

Grupo EIDOS

13. Componentes transaccionales

<form method="POST" id=form1 name=form1> <input name="idEmi"><br> <input name="cantidad"><br> <input name="idRec"><br> <input type="submit" name="boton" value="transferir"> </form> <%else idEmi=Request.Form("idEmi") cantidad=Request.Form("cantidad") idRec=Request.Form("idRec") Set objCom=Server.CreateObject("CompTransferencia.Transferencia") On Error Resume Next objCom.mover idEmi,-cantidad if Err<>0 then Response.Write "<b>Error en el idEmi: </b>" & Err.description ObjectContext.SetAbort Response.End end if objCom.mover idRec,cantidad if Err<>0 then Response.Write "<b>Error en el idRec: </b>" & Err.description ObjectContext.SetAbort Response.End end if On Error Goto 0 Set objCnx=Server.CreateObject("ADODB.Connection") objCnx.Open Application("CadenaConex") Set objCmd=Server.CreateObject("ADODB.Command") objCmd.ActiveConnection=objCnx objCmd.CommandText="registro" Set objPar1=objCmd.CreateParameter("par1",adDate,adParamInput,8,date) Set objPar2=objCmd.CreateParameter("par2",adSmallInt,adParamInput,2,idEmi) Set objPar3=objCmd.CreateParameter("par3",adCurrency,adParamInput,8,cantidad) Set objPar4=objCmd.CreateParameter("par4",adSmallInt,adParamInput,2,idRec) objCmd.Parameters.Append objPar1 objCmd.Parameters.Append objPar2 objCmd.Parameters.Append objPar3 objCmd.Parameters.Append objPar4 objCmd.Execute numReg,,adCmdStoredProc objCnx.Close Set objCmd=Nothing Set objCnx=Nothing end if%> <% Sub OnTransactionCommit if Request.Form("boton")<>"" then Response.Write "<h2>Transaccin completada</h2>" end if End Sub Sub OnTransactionAbort Response.Write "<h2>Transaccin abortada</h2>" End Sub %> </body> </html> Cdigo fuente 182

247

Desarrollo de aplicaciones COM+ para Internet / Intranet con ASP 3.0

Grupo EIDOS

Si probamos ahora la pgina, veremos que funciona correctamente. Si ponemos por ejemplo un cliente de destino que no exista, aparece el mensaje de error correspondiente, y la transaccin hace rollback automtico, no habindose restado la cantidad del saldo del cliente de origen. Esto es as porque el cdigo de la propia pgina es el encargado de decidir el rollback; el componente se limita a efectuar la operacin con la base de datos y generar el error en caso necesario. Pero si ahora registramos el componente en la aplicacin COM+, veamos qu sucede. Dejemos el componente con la propiedad declarativa por defecto para las transacciones, es decir, No se admite. Esto es configurable en la pestaa Transacciones de las Propiedades del componente, como aparece en la Figura 71.

Figura 71

Si ejecutamos de nuevo la pgina y ponemos un cliente de destino que no exista, o se produce cualquier otro error en la pgina, no se hace rollback de las operaciones efectuadas por el componente. Esto es as porque la configuracin No se admite para las transacciones significa que el componente no participa en la transaccin de la pgina, y no tiene voto en la misma. Sin embargo, las operaciones efectuadas por la pgina s hacen rollback en caso de error, y no llega a escribirse la lnea en la tabla LogTransferencias. Lo podemos comprobar haciendo ObjectContext.SetAbort explcitamente, a continuacin de la lnea del Execute que escribe en esa tabla. En este caso se hace rollback de la escritura en la tabla LogTransferencia, pero las actualizaciones en la tabla Clientes se mantienen.

La opcin Deshabilitada para las transacciones del componente tiene el mismo efecto.
Sin embargo, si configuramos el componente para que su comportamiento transaccional sea de Compatible, esto significa que el componente participa de la transaccin del cliente, en este caso la pgina ASP, con lo cual todo el cdigo ASP y el del componente forman una nica transaccin, que

248

Grupo EIDOS

13. Componentes transaccionales

fallar o tendr xito en su conjunto. El componente tambin tiene voto en esa transaccin, aunque no estamos utilizando ahora mismo esta posibilidad (lo haremos ms adelante). Si la pgina no hubiera arrancado la transaccin, es decir, no incluye la directiva <%@ transaction=required %>, entonces no habra ninguna transaccin en curso y no se creara una nueva para el componente. Podemos comprobar que en ese caso no se hace rollback ni de las operaciones efectuadas por el componente, ni de las efectuadas por el cdigo de la pgina, en caso de hacerse SetAbort. Al no estar la pgina definida como transaccional, no tiene acceso al ObjectContext y la instruccin ObjectContext.SetAbort genera un error. Dentro del bloque if de recepcin del error del componente est activado el gestor de errores de VBScript con On Error Resume Next, y lo pasa por alto, pero no podra hacer este SetAbort por ejemplo al final de la pgina. Si configuramos ahora la propiedad transaccional del componente como Necesario, y al no haber arrancado una transaccin la pgina, se crear una transaccin particular para el componente. Sin embargo, al no hacer el SetAbort desde dentro del componente, tampoco se hace rollback de las actualizaciones del componente ni de la pgina. La opcin Necesita nuevo produce en este caso el mismo efecto. Pero si volvemos a declarar la pgina como transaccional, y el componente como Necesita nuevo, entonces se iniciar una transaccin nueva para el componente, independiente de la transaccin en la cual se est ejecutando la pgina. En este caso, el SetAbort efectuado por la pgina slo tiene efecto en la transaccin propia, y no hace rollback de los cambios en la base de datos que hubiera provocado el componente.

Voto transaccional de un componente


En el caso de declarar la pgina como transaccional, y el componente como Compatible o Necesario, hemos visto que todo funciona correctamente. Pero lo normal es aprovechar ms las ventajas que nos proporcionan los Servicios de Componentes, y hacer que nuestro componente emita su voto respecto al SetCommit o SetAbort de la transaccin. Esto puede hacerlo gracias al objeto de contexto, que guarda informacin sobre la transaccin dentro de la cual se est ejecutando el componente. sta puede ser la suya propia, o la que ya haba iniciado la pgina. Veremos esto con detalle. Rediseemos el componente de forma que ahora pueda emitir su voto transaccional. Dejaremos que siga generando un error en el caso de no existir el cliente, pero ya no ser la pgina la que haga SetAbort al captar ese error, sino que lo har el propio componente. Por supuesto, primero har el SetAbort y luego generar el error, en ese orden. El Cdigo fuente 183 ser ahora el del componente.

Option Explicit Public Sub mover(ByVal id As Integer, ByVal cantidad As Currency) Dim objContext As ObjectContext Dim objApplication As Application Dim cadenaConex As String Dim objCnx As ADODB.Connection Dim objCmd As ADODB.Command Dim objPar1, objPar2 As ADODB.Parameter Dim numReg As Integer

249

Desarrollo de aplicaciones COM+ para Internet / Intranet con ASP 3.0

Grupo EIDOS

Set objContext = GetObjectContext Set objApplication = objContext("Application") cadenaConex = objApplication.Contents("CadenaConex") Set objCnx = New ADODB.Connection objCnx.Open cadenaConex Set objCmd = New ADODB.Command objCmd.ActiveConnection = objCnx objCmd.CommandText = "movimiento" Set objPar1 = objCmd.CreateParameter("par1", adSmallInt, adParamInput, 2, id) Set objPar2 = objCmd.CreateParameter("par2", adCurrency, adParamInput, 8, cantidad) objCmd.Parameters.Append objPar1 objCmd.Parameters.Append objPar2 objCmd.Execute numReg, , adCmdStoredProc objCnx.Close Set objCmd = Nothing Set objCnx = Nothing If numReg = 0 Then objContext.SetAbort Err.Raise vbObjectError + 1000, "mover", "No existe el cliente" Else objContext.SetComplete End If End Sub Cdigo fuente 183

En el Cdigo fuente 184 puede verse el fragmento del cdigo de la pgina ASP en que se invocan los mtodos del componente.

Set objCom=Server.CreateObject("CompTransferencia.Transferencia") On Error Resume Next objCom.mover idEmi,-cantidad if Err<>0 then Response.Write "<b>Error en el idEmi: </b>" & Err.description Response.End end if objCom.mover idRec,cantidad if Err<>0 then Response.Write "<b>Error en el idRec: </b>" & Err.description Response.End end if On Error Goto 0 Cdigo fuente 184

Marquemos la pgina como transaccional, y el componente con la opcin Deshabilitada o No se admite. En este caso si introducimos en el formulario un cliente de destino inexistente, el componente emite un voto de SetAbort, pero no tiene ninguna validez puesto que no participa de la transaccin de la pgina. La transaccin se da por buena y los cambios en la base de datos son definitivos. Adems se disparar el evento OnTransactionCommit. Si hago SetAbort desde la pgina, el registro insertado en la tabla de LogTransferencias hace rollback, pero no las modificaciones en la tabla Clientes, que permanecen. Si ahora declaro el comportamiento transaccional del componente como Compatible o Necesario, entrar a formar parte de la transaccin iniciada por la pgina, con lo que el cdigo de la pgina y del
250

Grupo EIDOS

13. Componentes transaccionales

componente forman una nica transaccin. El voto del componente afecta a toda la transaccin conjunta, igual que el de la pgina, y si alguno de ellos hace SetAbort, se hace rollback de todas las modificaciones, tanto en la tabla LogTransferencias como en la tabla Clientes. Este es el comportamiento que normalmente nos va a interesar. Si hacemos el cambio en el cdigo de la pgina, de forma que desactivemos el gestor de errores de VBScript antes de la segunda llamada al mtodo mover, y eliminamos las lneas del Response.End, como se ve en el Cdigo fuente 185, veremos que si introducimos un id de cliente de origen inexistente, en la primera llamada a mover se hace SetAbort de la transaccin, y en la segunda obtenemos el error Realiz una llamada a un mtodo en un componente COM+ que tiene una transaccin que se ha anulado o que est en curso de anulacin. Esto se debe a que el SetAbort de la primera llamada hace que en el objeto de contexto asociado al componente se marca la transaccin como anulada, y los Servicios de Componentes pueden as liberar los recursos asociados a este objeto, que es inservible mientras dura la transaccin, que ya est anulada.

Set objCom=Server.CreateObject("CompTransferencia.Transferencia") On Error Resume Next objCom.mover idEmi,-cantidad if Err<>0 then Response.Write "<b>Error en el idEmi: </b>" & Err.description end if On Error Goto 0 objCom.mover idRec,cantidad if Err<>0 then Response.Write "<b>Error en el idRec: </b>" & Err.description end if Cdigo fuente 185

Slo nos queda por probar declarar el componente como Necesita nuevo. Con esta configuracin, se inicia una transaccin para el componente, pero es independiente de la transaccin iniciada para la pgina. Si introducimos en el formulario un id de cliente inexistente, se hace rollback de la transaccin del componente, no de la de la pgina. Hay un detalle ms: la transaccin iniciada para la pgina abarca todo el tiempo de ejecucin de la pgina, pero para el componente se inicia una cada vez que se invoca al mtodo mover. Por lo tanto, la operacin de retirar el dinero de un cliente y la operacin de ingresarlo en otro cliente no se consideran una nica transaccin, sino transacciones distintas, y no se har rollback de las dos sino de aqulla que haya fallado.

Dos componentes transaccionales invocados desde ASP


Hagamos ahora que el cdigo que inserta el registro en la tabla LogTransferencias est tambin dentro de un componente. Llamaremos al proyecto ActiveX DLL CompLog, y al mdulo de clase Log, con un cdigo como el del Cdigo fuente 186.

Option Explicit Public Sub registrar(ByVal fecha As Date, ByVal idEmi As Integer, ByVal cantidad As Currency, ByVal idRec As Integer) On Error GoTo Errores

251

Desarrollo de aplicaciones COM+ para Internet / Intranet con ASP 3.0

Grupo EIDOS

Dim Dim Dim Dim Dim Dim

objContext As ObjectContext objApplication As Application cadenaConex As String objCnx As ADODB.Connection objCmd As ADODB.Command objPar1, objPar2, objPar3, objPar4 As ADODB.Parameter

Set objContext = GetObjectContext Set objApplication = objContext("Application") cadenaConex = objApplication.Contents("CadenaConex") Set objCnx = New ADODB.Connection objCnx.Open cadenaConex Set objCmd = New ADODB.Command objCmd.ActiveConnection = objCnx objCmd.CommandText = "registro" Set objPar1=objCmd.CreateParameter("par1", adDate, adParamInput, 8, fecha) Set objPar2=objCmd.CreateParameter("par2", adSmallInt, adParamInput, 2, idEmi) Set objPar3=objCmd.CreateParameter("par3",adCurrency,adParamInput,8,cantidad) Set objPar4=objCmd.CreateParameter("par4", adSmallInt, adParamInput, 2, idRec) objCmd.Parameters.Append objPar1 objCmd.Parameters.Append objPar2 objCmd.Parameters.Append objPar3 objCmd.Parameters.Append objPar4 objCmd.Execute , , adCmdStoredProc objCnx.Close Set objCmd = Nothing Set objCnx = Nothing Exit Sub Errores: objContext.SetAbort Err.Raise vbObjectError + 1000, "registrar", "Fall el registro en el log" End Sub Cdigo fuente 186

El cdigo necesario en la pgina ASP, como se ve en el Cdigo fuente 187, queda mucho ms reducido. Es el entramado que aglutina la funcionalidad de los componentes, invocando ordenadamente sus mtodos.

<%@ transaction=required %> <!--#INCLUDE file="ADOVBS.INC"--> <html> <head> <title>Transferencia</title> </head> <body> <%Application("CadenaConex") = "Provider=SQLOLEDB.1;User ID=sa;Initial Catalog=ASPComp;Data Source=varrondo"%> <%if Request.Form("boton")="" then%> <form method="POST" id=form1 name=form1> <input name="idEmi"><br> <input name="cantidad"><br> <input name="idRec"><br> <input type="submit" name="boton" value="transferir"> </form> <%else

252

Grupo EIDOS

13. Componentes transaccionales

idEmi=Request.Form("idEmi") cantidad=Request.Form("cantidad") idRec=Request.Form("idRec") Set objCom1=Server.CreateObject("CompTransferencia.Transferencia") On Error Resume Next objCom1.mover idEmi,-cantidad if Err<>0 then Response.Write "<b>Error en el idEmi: </b>" & Err.description Response.End end if objCom1.mover idRec,cantidad if Err<>0 then Response.Write "<b>Error en el idRec: </b>" & Err.description Response.End end if On Error Goto 0 Set objCom2=Server.CreateObject("CompLog.Log") On Error Resume Next objCom2.registrar date,idEmi,cantidad,idRec if Err<>0 then Response.Write "<b>Error en el log: </b>" & Err.description Response.End end if On Error Goto 0 end if%> <% Sub OnTransactionCommit if Request.Form("boton")<>"" then Response.Write "<h2>Transaccin completada</h2>" end if End Sub Sub OnTransactionAbort Response.Write "<h2>Transaccin abortada</h2>" End Sub %> </body> </html> Cdigo fuente 187

Lo normal en este caso sera declarar la pgina como transaccional y declarar los componentes como Compatible o Necesario respecto a su comportamiento transaccional. Hagamos las pruebas pertinentes, y veremos que todo funciona correctamente.

Un componente transaccional invoca a otro


Cambiemos ahora el interfaz del componente CompTransferencia, de forma que el mtodo mover reciba los id del cliente de origen y de destino de la transferencia. De esta forma slo hay que invocar al mtodo una vez. Adems, este mismo componente ser el encargado de instanciar al componente CompLog e invocar su mtodo registrar. En definitiva, el mtodo del componente CompTransferencia queda como en el Cdigo fuente 188.

253

Desarrollo de aplicaciones COM+ para Internet / Intranet con ASP 3.0

Grupo EIDOS

Option Explicit Public Sub mover(ByVal idEmi As Integer, ByVal cantidad As Currency, ByVal idRec As Integer) Dim objContext As ObjectContext Dim objApplication As Application Dim cadenaConex As String Dim objCnx As ADODB.Connection Dim objCmd As ADODB.Command Dim objPar1, objPar2 As ADODB.Parameter Dim numReg As Integer Dim objCom As CompLog.Log Set objContext = GetObjectContext Set objApplication = objContext("Application") cadenaConex = objApplication.Contents("CadenaConex") Set objCnx = New ADODB.Connection objCnx.Open cadenaConex Set objCmd = New ADODB.Command objCmd.ActiveConnection = objCnx objCmd.CommandText = "movimiento" Set objPar1=objCmd.CreateParameter("par1", adSmallInt, adParamInput, 2, idEmi) Set objPar2=objCmd.CreateParameter("par2",adCurrency,adParamInput,8,-cantidad) objCmd.Parameters.Append objPar1 objCmd.Parameters.Append objPar2 objCmd.Execute numReg, , adCmdStoredProc If numReg = 0 Then objContext.SetAbort Err.Raise vbObjectError + 1000, "mover", "No existe el cliente de origen" End If objCmd.Parameters("par1") = idRec objCmd.Parameters("par2") = cantidad objCmd.Execute numReg, , adCmdStoredProc If numReg = 0 Then objContext.SetAbort Err.Raise vbObjectError + 1000, "mover", "No existe el cliente de destino" End If objCnx.Close Set objCmd = Nothing Set objCnx = Nothing Set objCom = New CompLog.Log objCom.registrar Date, idEmi, cantidad, idRec objContext.SetComplete End Sub Cdigo fuente 188

Y el cdigo de la pgina ASP queda ahora todava ms reducido, como se muestra en el Cdigo fuente 189.

<%@ transaction=required %> <!--#INCLUDE file="ADOVBS.INC"--> <html> <head> <title>Transferencia</title> </head>

254

Grupo EIDOS

13. Componentes transaccionales

<body> <%Application("CadenaConex") = "Provider=SQLOLEDB.1;User ID=sa;Initial Catalog=ASPComp;Data Source=varrondo"%> <%if Request.Form("boton")="" then%> <form method="POST" id=form1 name=form1> <input name="idEmi"><br> <input name="cantidad"><br> <input name="idRec"><br> <input type="submit" name="boton" value="transferir"> </form> <%else idEmi=Request.Form("idEmi") cantidad=Request.Form("cantidad") idRec=Request.Form("idRec") Set objCom1=Server.CreateObject("CompTransferencia.Transferencia") On Error Resume Next objCom1.mover idEmi,cantidad,idRec if Err<>0 then Response.Write "<b>Se produjo un error: </b>" & Err.description 'Response.End end if On Error Goto 0 end if%> <% Sub OnTransactionCommit if Request.Form("boton")<>"" then Response.Write "<h2>Transaccin completada</h2>" end if End Sub Sub OnTransactionAbort Response.Write "<h2>Transaccin abortada</h2>" End Sub %> </body> </html> Cdigo fuente 189

255

Acceso a MSMQ desde ASP


Servicios de mensajera entre aplicaciones
Los sistemas distribuidos han ido evolucionando. Al principio slo haba una mquina potente, el host, que era compartido por muchos ordenadores clientes. Al aumentar la potencia de clculo y abaratarse el coste, los clientes empezaron a compartir el peso de la aplicacin, y empez a poderse hablar de aplicacin distribuida, desapareciendo la figura del host. Pero empez la preocupacin por la comunicacin entre esos ordenadores que comparten la lgica de la aplicacin. Los modelos de componentes como DCOM o CORBA permiten la comunicacin entre distintos componentes de una aplicacin, o entre distintas aplicaciones, ejecutndose en mquinas diferentes, pero esto lo hacen a travs de mensajes sncronos, es decir, que una aplicacin enva un mensaje a otra, y queda en espera hasta que no recibe una respuesta. Esta suposicin de que la aplicacin de destino va a estar disponible para devolver una respuesta inmediata no siempre es cierta, sobre todo en un entorno como el de una aplicacin web. En situaciones as tienen su aplicacin los sistemas de mensajera, como el MSMQ de Microsoft. Estos sistemas de mensajera entre aplicaciones usan mensajes asncronos. Un cliente enva un mensaje a un servidor, pero en vez de esperar una respuesta inmediata, prosigue con su trabajo. El mensaje queda almacenado en una cola, de tal forma que cuando el servidor est disponible para procesarlo, lo har, y le enviar una respuesta al cliente. Las aplicaciones que se comunican pueden estar en plataformas distintas, sistemas operativos distintos, incluso pueden no estar conectados permanentemente. Internet es un ejemplo de conexin no permanente entre plataformas y sistemas operativos distintos.

Desarrollo de aplicaciones COM+ para Internet / Intranet con ASP 3.0

Grupo EIDOS

Suele compararse un servicio de mensajera con un servicio de email. La diferencia principal es que un servicio de email intercambia informacin entre personas y un servicio de mensajera lo hace entre aplicaciones. Los servicios de mensajera entre aplicaciones trabajan con mensajes y colas. Un mensaje es un trozo de informacin intercambiado entre dos aplicaciones. El formato y contenido de este mensaje es especfico de la aplicacin (puede ser texto o binario), pero para el sistema de mensajera esto es indiferente. No exige un formato especfico para estos mensajes. De hecho, ni siquiera inspecciona su contenido, limitndose a transmitirlo. Sin embargo otras tecnologas, como HTTP, FTP, ODBC, etc, tambin permiten la comunicacin entre plataformas distintas, pero son para tipos particulares de aplicaciones, y se exige un formato especfico para los mensajes. Las colas son los lugares donde se depositan estos mensajes.

MSMQ (Message Queuing Server)


MSMQ no es algo nuevo. Existen otras tecnologas de mensajera para PCs. Este servicio est integrado en Windows NT Server en su versin Enterprise, y algo ms reducido en la versin normal, bajo el nombre de MSMQ 1.0. Tambin est incluido en Windows 2000, donde es un servicio ms que recibe el nombre de Message Queuing Server. La parte cliente se encuentra en todas las versiones de Windows. El MSMQ proporciona la tecnologa necesaria para el envo de mensajes entre aplicaciones, y la gestin de colas. Para acceder a estos servicios, podemos hacerlo a travs de un API. Adems ofrece un modelo COM para poder ser usado desde cualquier lenguaje que soporte esta tecnologa. Podremos utilizarlo por tanto desde una pgina ASP. Ya hemos dicho que los servicios de mensajera entre aplicaciones, como el MSMQ, son muy parecidos a los servicios de correo, pero presentan diferencias: Los servidores de correo transmiten mensajes entre personas, y el MSMQ los transmite entre aplicaciones. Garantizan mayor seguridad de que el mensaje ha llegado a su destino. En un servicio de correo no podemos estar seguros de que el mensaje enviado haya llegado correctamente. Con el MSMQ es posible saber exactamente cundo ha llegado.

El MSMQ es ms lento que otros mtodos de comunicacin de ms bajo nivel, como sockets o canalizaciones con nombre, named pipes. De hecho, MSMQ usa internamente estos mtodos, aunque de forma completamente transparente para m. Sin embargo esta lentitud est compensada por las ventajas que ofrece. Si quiero obtener ms rendimiento, los mensajes se pueden almacenar en RAM. Esto supone mayor velocidad en la gestin de los mensajes, pero ante un fallo del servidor podra perderlos. Si quiero ms fiabilidad ante posibles fallos, los mensajes se pueden almacenar en el disco duro y ser recuperados cuando el servidor se recupere del fallo.

258

Grupo EIDOS

14. Acceso a MSMQ desde ASP

Habr una serie de situaciones en las que interese utilizar el MSMQ para transmitir mensajes entre mquinas que comparten la lgica de una aplicacin distribuida: Si prevemos que las comunicaciones entre los ordenadores pueden fallar o no ser permanentes, o incluso puede estar apagado temporalmente el ordenador de destino. Es decir, no esta garantizada la disponibilidad de la mquina. El MSMQ simplemente depositar el mensaje en la cola de destino correspondiente hasta que el ordenador vuelva estar disponible. Si queremos lograr ms escalabilidad del sistema. Parece que esto no tiene sentido, puesto que la transmisin de mensajes con MSMQ es ms lenta, pero en realidad conseguimos ms escalabilidad en el sentido de que se puede manejar ms trfico con picos variables de mensajes sin fallo, aunque cada uno de ellos los maneje ms lentamente. Con comunicaciones sncronas el servidor tiene que estar sobredimensionado para poder soportar los picos ms fuertes en el trfico de mensajes, y an as puede llegar a sobrecargarse. Con comunicaciones asncronas, slo tiene que estar dimensionado para el trfico medio esperado. En los momentos de picos, los mensajes simplemente se almacenarn hasta que puedan ser procesados. Cuando nos interese garantizar que el mensaje ha sido recibido por la aplicacin de destino, pero no es necesario obtener una respuesta inmediata al mensaje.

Funcionamiento del MSMQ


En un sistema MSMQ hay tres tipos de servidores: Controlador principal PEC (Primary Enterprise Controller): Gestiona la configuracin de todo el sistema. Contiene los certificados para validar las claves. Controlador del sitio (Site Controller): Contiene informacin de todos los ordenadores y colas de un sitio (ordenadores conectados por una red rpida). Varios sitios forman el sistema. En el sitio donde est el PEC, ste sirve tambin de controlador de sitio. Enrutador de mensajes (Message Router): Gestiona el envo de mensajes entre sitios. El controlador de sitio sirve tambin de router. Si un sitio tiene mucho trfico se le pueden aadir routers adicionales.

Y hay dos tipos de clientes: Cliente independiente: Tiene su propia cola de mensajes. Se usa normalmente en porttiles. Cliente dependiente: No tiene cola; depende de un servidor MSMQ.

El MSMQ permite tres modos de envo de mensajes: Basado en memoria: Es el ms rpido. El mensaje se almacena en la memoria hasta que el gestor puede contactar con el gestor de destino. Si hay un problema en la comunicacin, esperar hasta poder hacerlo. El inconveniente es que si hay un fallo en la mquina, se pierde el mensaje. Basado en disco: Es ms lento. El mensaje se almacena en el disco. Cuando llega a la mquina de destino, se elimina del disco. Si hay un fallo en la mquina, se puede recuperar luego del disco. Hace falta un sistema de archivos como el NTFS que permite esta recuperacin.

259

Desarrollo de aplicaciones COM+ para Internet / Intranet con ASP 3.0

Grupo EIDOS

Basado en transacciones: Utiliza los Servicios de Componentes, antes MTS.

Creacin de una cola


Para acceder a la consola de administracin del servicio MSMQ en Windows 2000, debemos seleccionar Administracin de equipos, dentro de las Herramientas administrativas del men de Inicio. Si expandimos el rbol correspondiente a Servicios y Aplicaciones, obtendremos un resultado como el que aparece en la Figura 72.

Figura 72

Si pulsamos con el botn derecho sobre la carpeta de Colas privadas, y del men emergente seleccionamos la opcin Nuevo | Cola privada, podemos crear una nueva cola. Slo hay que suministrar la informacin que se pide en una ventana como en la Figura 73, es decir, el nombre de la cola y su comportamiento transaccional.

Figura 73

260

Grupo EIDOS

14. Acceso a MSMQ desde ASP

Si extendemos ahora el rbol de la cola1 recin creada obtendremos lo que aparece en la Figura 74.

Figura 74

Vemos que en la subcarpeta de Mensajes de la cola no hay ahora ninguno.

Modelo de objetos de MSMQ


Trabajaremos con tres objetos principales de este modelo: MSMQQueueInfo: Permite almacenar las colas de un servidor MSMQ. Lo usaremos como punto de partida para cualquier operacin con colas: crear, modificar, borrar, etc. MSMQQueue: Representa una cola abierta por medio del mtodo Open del objeto MSMQQueueInfo. MSMQMessage: Representa un mensaje.

Vamos a ver que podemos utilizar este modelo COM para acceder al servicio MSMQ desde una pgina ASP. Y lo primero que haremos ser repetir lo mismo que conseguimos desde la consola de administracin del servicio. Para ello creemos una pgina ASP con el Cdigo fuente 190.

<%@ Language=VBScript %> <HTML> <HEAD> <META NAME="GENERATOR" Content="Microsoft Visual Studio 6.0"> </HEAD>

261

Desarrollo de aplicaciones COM+ para Internet / Intranet con ASP 3.0

Grupo EIDOS

<BODY> <% Set objQueueInfo = Server.CreateObject("MSMQ.MSMQQueueInfo") objQueueInfo.PathName = ".\PRIVATE$\cola2" objQueueInfo.Create %> </BODY> </HTML> Cdigo fuente 190

En esta pgina simplemente recogemos una referencia al objeto MSMQQueueInfo. A continuacin le asignamos a la propiedad PathName el nombre de la cola. En caso de tratarse de colas privadas, este nombre es de la forma nombreDelServidor\PRIVATE$ \nombreDeLaCola, aunque el nombre del servidor puede sustituirse por un punto, quedando de la forma .\PRIVATE$\nombreDeLaCola. Por ltimo, basta llamar al mtodo Create. Siempre debe asignarse la propiedad PathName antes de llamar al mtodo Create. Si ejecutamos la pgina podremos ver en la consola de administracin del MSMQ que se ha creado una nueva cola privada, de nombre cola2. Ejecutando el Cdigo fuente 191 conseguiramos eliminarla.

Set objQueueInfo = Server.CreateObject("MSMQ.MSMQQueueInfo") objQueueInfo.PathName = ".\PRIVATE$\cola2" objQueueInfo.Delete Cdigo fuente 191

Envo de mensajes
Ahora vamos a enviar un mensaje a la cola1 recin creada desde una pgina ASP. Lo primero es comprobar que se disponen de los permisos necesarios para enviar un mensaje a la cola. Si desde el administrador del servicio MSMQ, pulsamos con el botn derecho sobre el nombre de la cola y seleccionamos la opcin Propiedades, y luego la pestaa Seguridad, obtendremos lo que se muestra en la Figura 75. Vemos que por defecto, el grupo Todos, en el que desde luego estar incluida la cuenta de invitado a internet IUSR_nombreServidor que normalmente usaremos al ejecutar una pgina ASP con acceso annimo, tiene activado el permiso de Escribir mensaje, pero no as los de recibir ni inspeccionar mensaje. Pero como ahora slo queremos escribir, con esto es suficiente. En el Cdigo fuente 192 se pueden ver las instrucciones que son necesarias para escribir un mensaje en la cola.
262

Grupo EIDOS

14. Acceso a MSMQ desde ASP

Figura 75

<%@ Language=VBScript %> <HTML> <HEAD> <META NAME="GENERATOR" Content="Microsoft Visual Studio 6.0"> </HEAD> <BODY> <!--METADATA type="typelib" file="C:\winnt\system32\mqoa.dll"--> <% Set objQueueInfo = Server.CreateObject("MSMQ.MSMQQueueInfo") objQueueInfo.PathName = ".\PRIVATE$\cola1" Set objQueue = objQueueInfo.Open(MQ_SEND_ACCESS,MQ_DENY_NONE) Set objMsg = Server.CreateObject("MSMQ.MSMQMessage") objMsg.Label = "Mensaje 1" objMsg.Body = "Cuerpo del mensaje" objMsg.Send objQueue objQueue.Close Set objMsg = Nothing Set objQueue = Nothing Set objQueueInfo = Nothing %> </BODY> </HTML> Cdigo fuente 192

263

Desarrollo de aplicaciones COM+ para Internet / Intranet con ASP 3.0

Grupo EIDOS

Igual que antes, primero obtenemos la referencia al objeto MSMQQueueInfo, y le asignamos la propiedad PathName que identifica a la cola. A continuacin aplicamos el mtodo Open sobre este objeto para obtener una referencia a la cola. Este mtodo Open recibe dos parmetros, que son especificados por medio de constantes. Para poder utilizar los nombres de estas constantes en vez de tener que recordar su valor numrico, utilizamos la directiva METADATA con el nombre de la DLL en que se encuentran, que en este caso es MQOA.DLL. El parmetro Access especifica el modo de apertura de la cola por la aplicacin, es decir, que va a hacer con ella. Puede tomar los valores: MQ_RECEIVE_ACCESS (1): Permite inspeccionar o recibir mensajes de la cola. En el segundo caso, los mensajes se eliminan a medida que son ledos. MQ_SEND_ACCESS (2): Permite enviar mensajes a la cola. MQ_PEEK_ACCESS (32): Slo permite inspeccionar los mensajes, pero no recibirlos.

El parmetro ShareMode especifica qu acceso tienen los dems a la cola mientras est siendo utilizada por la aplicacin. Puede tomar los valores: MQ_DENY_NONE (0): Si he abierto la cola en uno de los modos MQ_SEND_ACCESS o MQ_PEEK_ACCESS, sta es la nica opcin. Permito a los dems el acceso total a la cola. MQ_DENY_RECEIVE_SHARE (1): Si he abierto en modo MQ_RECEIVE_ACCESS, tengo la opcin anterior o sta. Con ella impido que otros reciban mensajes de la cola, aunque pueden seguir enviando.

Luego creamos un objeto MSMQMessage y le asignamos valor a sus propiedades Label, que contiene la etiqueta del mensaje, y Body, que almacena su contenido. El mtodo Send invocado sobre este objeto necesita como parmetro el nombre de la cola a la que va a ser enviado. Para finalizar, cerramos la cola y destruimos los objetos. En la consola de administracin del servicio MSMQ podremos ver que el mensaje se ha enviado y almacenado en la cola, como se ve en la Figura 76.

Figura 76

264

Grupo EIDOS

14. Acceso a MSMQ desde ASP

Por cierto, que podemos configurar las propiedades del mensaje que queremos que aparezcan en el panel izquierdo. Basta con pulsar con el botn derecho sobre la subcarpeta Mensajes de la cola, y seleccionar la opcin Ver | Elegir columnas. Aparecer una ventana como la de la Figura 77 en la que podremos seleccionar la informacin que queremos ver de los mensajes.

Figura 77

Prioridad de los mensajes


El mensaje que acabamos de enviar tiene una prioridad por defecto de 3, que es el nivel de prioridad intermedio. Pero yo puedo modificar este valor por defecto, y asignar valores que van desde 0 para la prioridad mnima hasta 7 para la mxima. Si cambiamos ahora la pgina ASP por el contenido del Cdigo fuente 193, estamos asignando al nuevo mensaje una prioridad de 7, que es superior a la del mensaje anterior.

Set objQueueInfo = Server.CreateObject("MSMQ.MSMQQueueInfo") objQueueInfo.PathName = ".\PRIVATE$\cola1" Set objQueue = objQueueInfo.Open(MQ_SEND_ACCESS,MQ_DENY_NONE) Set objMsg = Server.CreateObject("MSMQ.MSMQMessage") objMsg.Label = "Mensaje 2" objMsg.Body = "Cuerpo del mensaje" objMsg.Priority = 7 objMsg.Send objQueue objQueue.Close Set objMsg = Nothing Set objQueue = Nothing Set objQueueInfo = Nothing Cdigo fuente 193

265

Desarrollo de aplicaciones COM+ para Internet / Intranet con ASP 3.0

Grupo EIDOS

Podemos comprobar en la consola de administracin del MSMQ, como se ve en la Figura 78, que este segundo mensaje se coloca delante del anterior en la cola, puesto que su prioridad es mayor.

Figura 78

Recepcin de mensajes
Una vez enviado el mensaje, vamos a intentar recuperarlo desde una pgina ASP. Normalmente las pginas ASP se limitarn a enviar mensajes a una cola, y ser otra aplicacin la encargada de recuperarlos y procesarlos, pero vamos a ver que tambin desde el VBScript de una pgina ASP podemos hacer esto mismo, aunque slo sea en este caso para listarlos en una tabla. De momento slo vamos a inspeccionar el mensaje, es decir, veremos su contenido pero no lo eliminaremos de la cola. Creamos para ello una nueva pgina ASP con el cdigo que puede verse en el Cdigo fuente 194.

Set objQueueInfo = Server.CreateObject("MSMQ.MSMQQueueInfo") objQueueInfo.PathName = ".\PRIVATE$\cola1" Set objQueue = objQueueInfo.Open(MQ_PEEK_ACCESS,MQ_DENY_NONE) Set objMsg = objQueue.PeekCurrent Response.Write objMsg.Label & " - " & objMsg.Body objQueue.Close Set objMsg = Nothing Set objQueue = Nothing Set objQueueInfo = Nothing Cdigo fuente 194

266

Grupo EIDOS

14. Acceso a MSMQ desde ASP

Esta vez abrimos la cola en modo MQ_PEEK_ACCESS, es decir, para inspeccionar. A continuacin obtenemos una referencia a un objeto MSMQMessage a partir del mtodo PeekCurrent invocado sobre la cola. Este mtodo recupera el mensaje sobre el que est posicionado el cursor, que ahora mismo es el primer mensaje de la cola, que ser el segundo enviado puesto que tena mayor prioridad. Escribimos la etiqueta y el cuerpo del mensaje, cerramos la cola, y eliminamos los objetos. Si ejecutamos esta pgina, obtendremos el error de Acceso denegado. Esto es debido a que la cuenta de invitado a internet no tiene los permisos necesarios para inspeccionar los mensajes almacenados en esta cola. Vamos a concedrselos a travs del grupo Todos, como se ve en la Figura 79, activando la casilla de verificacin correspondiente a Inspeccionar mensaje.

Figura 79

Ahora s podremos ejecutar la pgina y obtener el contenido del mensaje sin problemas. Si lo que queremos es inspeccionar el contenido de todos los mensajes de la cola, debemos hacerlo a travs de un bucle, como se puede ver en el Cdigo fuente 195.

Set objQueueInfo = Server.CreateObject("MSMQ.MSMQQueueInfo") objQueueInfo.PathName = ".\PRIVATE$\cola1" Set objQueue = objQueueInfo.Open(MQ_PEEK_ACCESS,MQ_DENY_NONE) Set objMsg = objQueue.PeekCurrent(,,100) Do While True

267

Desarrollo de aplicaciones COM+ para Internet / Intranet con ASP 3.0

Grupo EIDOS

If objMsg Is Nothing Then Exit Do Response.Write "<b>" & objMsg.Label & "</b>: " & objMsg.Body & "<br>" Set objMsg = objQueue.PeekNext(,,100) Loop objQueue.Close Set objMsg = Nothing Set objQueue = Nothing Set objQueueInfo = Nothing Cdigo fuente 195

Utilizamos el mtodo de lectura anticipada, y luego un bucle infinito Do While True, del que slo se sale con Exit Do en el caso de que el mensaje ledo en un paso del bucle sea igual a Nothing, es decir, que ya no queden mensajes en la cola. Tanto en el mtodo PeekCurrent, que lee el mensaje actual, como el PeekNext, que lee el siguiente, son slo mtodos de inspeccin de mensajes: leen el mensaje pero no lo eliminan de la cola. Cuando se invoca a cualquiera de estos dos mtodos, la ejecucin se detiene hasta que se lee el mensaje de la cola o hasta que se consume el tiempo de espera. Este tiempo de espera es el tercero de los tres parmetros opcionales que pueden recibir estos mtodos, el ReceiveTimeout, que se especifica en milisegundos. Antes no hemos utilizado este parmetro porque sabamos que haba un mensaje en la cola. Pero si en este caso no lo utilizamos, la ejecucin de la pgina entrara en un bucle infinito, porque despus de leer el ltimo mensaje de la cola, volvera a ejecutar el bucle y se quedara intentando leer uno nuevo de forma indefinida. En el cdigo de ejemplo se han asignado 100 milisegundos de timeout de recepcin. Si en vez de slo inspeccionar un mensaje queremos recibirlo, es decir, leerlo y eliminarlo de la cola, debemos escribir algo parecido al Cdigo fuente 196.

Set objQueueInfo = Server.CreateObject("MSMQ.MSMQQueueInfo") objQueueInfo.PathName = ".\PRIVATE$\cola2" Set objQueue = objQueueInfo.Open(MQ_RECEIVE_ACCESS,MQ_DENY_NONE) Set objMsg = objQueue.ReceiveCurrent(,,,100) Response.Write objMsg.Label & " - " & objMsg.Body objQueue.Close Set objMsg = Nothing Set objQueue = Nothing Set objQueueInfo = Nothing Cdigo fuente 196

Ahora abrimos la cola en modo MQ_RECEIVE_ACCESS en vez de MQ_PEEK_ACCESS, e invocamos al mtodo ReceiveCurrent en vez de PeekCurrent. Para que funcione la pgina, debemos conceder permisos de recepcin de mensajes en la cola activando la casilla de verificacin correspondiente a Recibir mensaje, como se aprecia en la Figura 80.

268

Grupo EIDOS

14. Acceso a MSMQ desde ASP

Figura 80

Se puede observar en la consola de administracin del servicio MSMQ que el mensaje ha desaparecido de la cola despus de haber sido ledo.

Colas de diario
Se pueden almacenar copias de los mensajes para llevar un control de los mensajes enviados y recibidos. Estas copias se llaman mensajes de diario, y se almacenan en las copias de diario. Para que la cola permita almacenamiento de diario, desde el administrador del servicio MSMQ pulsamos con el botn derecho sobre el nombre de la cola y seleccionamos la casilla de verificacin Habilitado dentro del apartado Diario, como se ve en la Figura 81. De esta forma, al eliminarse el mensaje de la cola, se almacena una copia del mismo en la subcarpeta denominada Mensajes del diario. Lo podemos comprobar si enviamos un nuevo mensaje y luego lo recibimos. La copia del mensaje queda almacenada como se ve en la Figura 82.

269

Desarrollo de aplicaciones COM+ para Internet / Intranet con ASP 3.0

Grupo EIDOS

Figura 81

Figura 82

270

Grupo EIDOS

14. Acceso a MSMQ desde ASP

Envo de un componente COM+


Veamos ahora que a una cola podemos enviar datos binarios como cuerpo de un mensaje, y en concreto vamos a enviar la instancia de un componente. Continuamos trabajando con nuestra tabla de Clientes de captulos anteriores. Hacemos para ello un nuevo proyecto ActiveX DLL de Visual Basic al que llamaremos CompCliente, con un mdulo de clase llamado Cliente. Con el complemento Generador de clases, aadimos tres propiedades al mdulo, una por cada campo de la tabla Clientes. Los objetos COM+ que enve en un mensaje tienen que soportar la persistencia, o dicho de otra forma, ser serializables. Con C++ se pueden construir componentes que implementen el interfaz IPersist, de tal forma que cuando el MSMQ tiene que meter un objeto en el cuerpo de un mensaje, lo serializa a travs de este interfaz. Esos datos binarios serializados son los que se almacenan en el cuerpo del mensaje. Con Visual Basic no puedo hacer esto, pero las rutinas de su runtime se encargan de simular este interfaz: lee las variables y valores del objeto y las mete en un PropertyBag, y luego las serializa a travs del interfaz IPersist. Realmente las clases de Visual Basic no implementan ese interfaz, sino que cuando el MSMQ busca ese interfaz, las rutinas del runtime se encargan de invocar los eventos Class_ReadProperties y Class_WriteProperties. Por lo tanto, tenemos que declarar primero de todo el mdulo de clase como serializable, configurando su propiedad Persistable al valor 1-Persistable, como se ve en la Figura 83.

Figura 83

Adems debemos implementar los procedimientos Class_ReadProperties y Class_WriteProperties, que sern invocados automticamente en la serializacin y en el proceso inverso, leyendo o escribiendo en el PropertyBag. El Cdigo fuente 197 muestra el resultado definitivo.

Private mvarid As Integer

271

Desarrollo de aplicaciones COM+ para Internet / Intranet con ASP 3.0

Grupo EIDOS

Private mvarnombre As String Private mvarsaldo As Currency Public Property Let id(ByVal vData As Integer) mvarid = vData End Property Public Property Get id() As Integer id = mvarid End Property Public Property Let nombre(ByVal vData As String) mvarnombre = vData End Property Public Property Get nombre() As String nombre = mvarnombre End Property Public Property Let saldo(ByVal vData As Currency) mvarsaldo = vData End Property Public Property Get saldo() As Currency saldo = mvarsaldo End Property Private Sub Class_ReadProperties(PropBag As PropertyBag) mvarid = PropBag.ReadProperty("id") mvarnombre = PropBag.ReadProperty("nombre") mvarsaldo = PropBag.ReadProperty("saldo") End Sub Private Sub Class_WriteProperties(PropBag As PropertyBag) PropBag.WriteProperty "id", mvarid PropBag.WriteProperty "nombre", mvarnombre PropBag.WriteProperty "saldo", mvarsaldo End Sub Cdigo fuente 197

Hay un inconveniente ms, y es que las limitaciones inherentes a un lenguaje de script como es el VBScript nos impiden ejecutar desde una pgina ASP el cdigo necesario para enviar, y posteriormente recibir, este componente serializado a una cola de MSMQ. Tenemos que hacerlo tambin a travs de otro componente. Vamos a hacerlo creando un nuevo mdulo de clase en el mismo proyecto, al que llamaremos GestionMSMQ, y que tendr dos mtodos: uno para enviar el objeto a la cola y otro para recibir el objeto desde la cola. Debemos aadir al proyecto la referencia a la librera de Microsoft Message Queue, como se ve en la Figura 84. El Cdigo fuente 198 muestra el estado final de este nuevo mdulo de clase. En el mtodo EnviaComponente asignamos a la propiedad Body del mensaje el objeto instanciado. En el otro mtodo, RecibeComponente, recorremos en un bucle, slo de inspeccin, la cola de mensajes hasta encontrar el primero cuya etiqueta coincide con la que recibe el mtodo como parmetro. En ese momento, se recibe el mensaje, con lo que se borra de la cola, se sale del bucle y posteriormente de la funcin.

272

Grupo EIDOS

14. Acceso a MSMQ desde ASP

Figura 84

Option Explicit Private objCliente As CompCliente.Cliente Private objQueueInfo As MSMQ.MSMQQueueInfo Private objQueue As MSMQ.MSMQQueue Private objMsg As MSMQ.MSMQMessage Public Function EnviaComponente(ByVal id As Integer, ByVal nombre As String, ByVal saldo As Currency) As Variant On Error GoTo Errores Set objCliente = New CompCliente.Cliente objCliente.id = id objCliente.nombre = nombre objCliente.saldo = saldo Set objQueueInfo = New MSMQ.MSMQQueueInfo objQueueInfo.PathName = ".\PRIVATE$\cola1" Set objQueue = objQueueInfo.Open(MQ_SEND_ACCESS, MQ_DENY_NONE) Set objMsg = New MSMQ.MSMQMessage objMsg.Label = "Mensaje Cliente" objMsg.Body = objCliente objMsg.Send objQueue objQueue.Close Set objMsg = Nothing Set objQueue = Nothing Set objQueueInfo = Nothing EnviaComponente = "Mensaje enviado" Exit Function Errores: EnviaComponente = Err.Description End Function

273

Desarrollo de aplicaciones COM+ para Internet / Intranet con ASP 3.0

Grupo EIDOS

Public Function RecibeComponente(Etiqueta As String) As Variant On Error GoTo Errores Set objQueueInfo = New MSMQ.MSMQQueueInfo objQueueInfo.PathName = ".\PRIVATE$\cola1" Set objQueue = objQueueInfo.Open(MQ_RECEIVE_ACCESS, MQ_DENY_NONE) RecibeComponente = "Mensaje no encontrado" Set objMsg = objQueue.PeekCurrent(, , 100) Do While True If objMsg Is Nothing Then Exit Do If objMsg.Label = Etiqueta Then Set objMsg = objQueue.ReceiveCurrent(, , , 100) Set RecibeComponente = objMsg.Body Exit Do Else Set objMsg = objQueue.PeekNext(, , 100) End If Loop Salida: objQueue.Close Set objMsg = Nothing Set objQueue = Nothing Set objQueueInfo = Nothing Exit Function Errores: RecibeComponente = Err.Description Resume Salida End Function Cdigo fuente 198

Si enviamos ahora varios mensajes a la cola, algunos como ya hemos visto, y otros utilizando el mdulo de clase recin creado, con una pgina ASP tan simple como la del Cdigo fuente 199, tendremos en la cola un aspecto parecido al que muestra la Figura 85.

Set objCom = Server.CreateObject("CompCliente.GestionMSMQ") objCom.EnviaComponente 7,"pepe",7000 Set objCom = Nothing Cdigo fuente 199

Probemos ahora que funciona el otro mtodo. Cada vez que ejecutemos la pgina mostrada en el Cdigo fuente 200, deben ir apareciendo uno a uno todos los objetos que hayamos almacenado en la cola, y deben irse eliminando de la misma conforme son recuperados. En esta pgina ASP slo estamos recuperando el objeto, pero es fcil imaginar que podramos hacer un alta en la tabla con los datos recuperados. De esta forma podramos, por ejemplo, ir almacenando las peticiones de altas de clientes en la cola, para luego ser procesadas todas de golpe en otro momento.

274

Grupo EIDOS

14. Acceso a MSMQ desde ASP

Figura 85

Set objCom = Server.CreateObject("CompCliente.GestionMSMQ") 'objCom.EnviaComponente 7,"pepe",7000 'Set objCom = Nothing 'Response.End On Error Resume Next Set objCliente = objCom.RecibeComponente("Mensaje Cliente") if Err=0 then Response.Write objCliente.id & "<br>" Response.Write objCliente.nombre & "<br>" Response.Write objCliente.saldo & "<br>" else Response.Write "No hay ms mensajes de clientes en la cola" end if Cdigo fuente 200

275

Acceso a ADSI desde ASP


Directorios y Servicios de Directorio
Lo primero que podramos decir es que un directorio. Un directorio es una forma de almacenar informacin. Pero realmente una base de datos relacional es tambin una forma de almacenar informacin, aunque distinta. Dnde est entonces la diferencia? Las diferencias que hay entre un directorio y una base de datos relacional, aunque tampoco se puede establecer una separacin muy precisa entre una y otra cosa, seran: Un directorio guarda informacin jerrquica, en forma de rbol, del mismo modo que el sistema de archivos est organizado en carpetas, subcarpetas y ficheros. La informacin que contiene el directorio est almacenada en objetos. Un directorio contiene objetos. Suelen estar replicados, es decir, su informacin almacenada de forma redundante en varios lugares distintos, sin que sea vital el hecho de que estn o no sincronizados. Estn ms optimizados para lectura que para escritura. Disponen, por ejemplo, de sofisticadas funciones de bsqueda, utilizando indexaciones para optimizar la velocidad.

El ejemplo ms utilizado para explicar lo que podra ser un directorio sera el de un listn telefnico. Almacena informacin, que est replicada, sin importar demasiado que la informacin almacenada en distintos sitios coincida exactamente. Est ms optimizado para lectura (bsqueda de un nmero de telfono) que para escritura (en este caso la escritura significa hacer una nueva impresin de listines).

Desarrollo de aplicaciones COM+ para Internet / Intranet con ASP 3.0

Grupo EIDOS

No importa como est implementado internamente el directorio (podra utilizarse una base de datos relacional). Lo que importa es cmo veo y como accedo yo a esa informacin desde fuera. Si un Directorio es un almacenamiento de informacin, un Servicio de Directorio es el software que se encarga de obtener esa informacin. Tambin se encarga de proporcionar la gestin de seguridad, de forma que slo accedan a la informacin almacenada las personas que estn autorizadas. Lo normal es que el Servicio de Directorio contenga internamente al Directorio. Ejemplos de esto son el Active Directory de Microsoft y los Servicios de Directorio de Novell. Hay muchos ms directorios, como los de Microsoft Exchange, Lotus Notes, etc. El problema est en que cada uno de ellos tiene su propio servicio de directorio especfico, y la forma de acceder es distinta

Active Directory de Microsoft


Es un directorio que almacena la informacin correspondiente a todos los recursos de un dominio: ordenadores, impresoras, aplicaciones, archivos, cuentas de usuario, permisos de seguridad, etc. Adems, los administradores pueden aadir nuevos contenidos a este directorio, de forma que almacene otra informacin adicional que consideren til. El concepto que incorpora Active Directory no es algo nuevo. Lleva existiendo mucho tiempo en otros sistemas operativos. En Windows ha tardado en aparecer por la sencilla razn de que este sistema operativo empez siendo un simple entorno grfico. Es slo ltimamente, con Windows NT y Windows 2000 cuando ha comenzado a ser un sistema operativo realmente potente, y ha necesitado de la incorporacin de este directorio. En Windows NT 4 ya se almacenaba la informacin en un directorio, pero slo era accesible con una API especfica para ese directorio. Active Directory cumple el protocolo estndar LDAP. Adems el modelo de seguridad es mejor que el que haba en Windows NT. Por defecto, el Active Directory guarda informacin global del dominio, pero apenas guarda informacin local de cada miembro del dominio, como cuentas de usuario. Esta informacin se guarda en las mquinas individuales. Pero hemos dicho que el Active Directory puede ser configurado por los administradores para que almacene nueva informacin. Algunas posibilidades seran: Replicar en el directorio la informacin de las mquinas individuales, de forma que podra ser recuperada en el caso de que una de estas mquinas falle. Guardar mis preferencias de escritorio en el Active Directory. As puedo recuperarlas cuando me conecte desde cualquier PC del dominio. Si una aplicacin que corre en una mquina necesita un componente que no tiene instalado, podra buscar en el Active Directory para encontrar en qu mquina se encuentra y solicitarlo.

La informacin almacenada en el Active Directory es realmente de dos tipos. Por una parte est la informacin que se necesita para la gestin del dominio, como equipos, cuentas, impresoras, etc. Por otra parte est la informacin que se quiera guardar, como un directorio de propsito general Disponer de un servicio de directorio como el Active Directory de Microsoft supone varias ventajas:

278

Grupo EIDOS

15. Acceso a ADSI desde ASP

Simplifica la gestin del administrador, que a travs de este servicio de directorio puede configurar de igual forma cuentas, servidores, equipos, aplicaciones, etc. Permite la instalacin automtica de aplicaciones segn el usuario, independientemente de la maquina desde la cual ste haga login en el sistema, utilizando tecnologas IntelliMirror. Por ejemplo, se podra configurar de tal forma que todos los empleados del departamento de Nminas de la compaa tengan acceso a una cierta aplicacin de gestin de nminas. Permite una bsqueda ms eficientes de los recursos de los que dispone el dominio. Por ejemplo, se puede hacer una bsqueda de una impresora con unas determinadas caractersticas de impresin en color o calidad. Permite que el administrador delegue funciones y asigne privilegios a usuarios y grupos. Proporciona una seguridad ms robusta, al ser este servicio de directorio el nico punto de entrada a los recursos del dominio. Funciona como la autoridad central que gestiona el control de acceso a los recursos del dominio, mediante varios mecanismos de autenticacin. Adems este control de acceso es independiente de si el usuario hizo login a travs de la red local o desde internet. Permite controlar mejor los equipos, concediendo slo a ciertos usuarios o grupos la posibilidad de instalar aplicaciones en los equipos y modificar el registro de la mquina Permite el desarrollo de aplicaciones que se adapten al usuario, segn la informacin que hay almacenada sobre l en el directorio. En el caso del departamento de Nminas, por ejemplo, se podra desarrollar una aplicacin que tuviera una opcin de men disponible slo para el jefe del departamento, pero no para los empleados.

ADSI (Active Directory Services Interface)


Hemos dicho que hay muchos servicios de directorio, cada uno con su forma especfica de acceder a la informacin almacenada. Esto complica mucho la labor del administrador. Es aqu donde interviene el ADSI. Es un conjunto de interfaces COM que permiten acceder a los servicios de directorio para los que tenga un proveedor ADSI. Estos proveedores son objetos COM que implementan estos interfaces. La idea es similar a la de OLE DB, que es un conjunto de objetos COM de propsito general que permiten acceder a distintas BDs para las que tenga un proveedor OLE DB. No importa que estas bases de datos sean de fabricantes distintos y estn implementadas de formas completamente diferentes. De igual forma, con ADSI puedo acceder a los servicios de directorio para los que tenga proveedor. Los proveedores ADSI hacen de intermediarios. La aplicacin cliente se comunica con ellos a travs de los interfaces estndar de ADSI, y ellos se comunican con el servicio de directorio con su API especfica. Igual sucede con OLE DB: la aplicacin cliente (a travs de ADO) se comunica con los proveedores OLE DB a travs de interfaces comunes, y estos proveedores se comunican con el gestor de base de datos correspondiente. El Active Directory de Microsoft es slo uno de los muchos servicios de directorio a los que se puede acceder utilizando ADSI. No hace falta que los servicios de directorio sean compatibles con LDAP. Mediante ADSI tambin puedo acceder a servidores web, FTP, de email, etc.
279

Desarrollo de aplicaciones COM+ para Internet / Intranet con ASP 3.0

Grupo EIDOS

Gracias a que ADSI proporciona unos interfaces comunes para acceder a varios servicios de directorio distintos, los administradores pueden gestionar de forma nica varios de estos servicios de directorio, y los usuarios pueden tener un nico login para acceder a todos los servicios (no uno para la red, otro para email, etc). Hay varios proveedores ADSI: Proveedor ADSI para LDAP (Lightweight Directory Access Protocol). Para acceder a Active Directory de Windows 2000, al directorio de servidores Exchange, o al directorio de Site Server, se usa este proveedor, puesto que estos tres directorios mencionados cumplen con el protocolo LDAP. ADSI usa COM y es de alto nivel, luego puedo usarlo desde cualquier lenguaje que acepte COM. LDAP sin embargo est escrito en C, y es de bajo nivel. Es algo parecido a ODBC y OLE DB: ODBC es de bajo nivel, y es ms difcil trabajar con l que con OLE DB. De igual manera, se puede acceder a Active Directory directamente con LDAP, pero resulta ms cmodo como programador hacerlo con ADSI. Desde nuestras pginas ASP usaremos el proveedor ADSI para LDAP para acceder a Active Directory. Proveedor ADSI para Winnt. Sirve para dos cosas. Por una parte, en Windows NT 4.0 no haba Active Directory. Este proveedor recoge informacin de las mquinas de la red, y la presenta como si estuviera almacenada en un directorio similar al Active Directory de Windows 2000, aunque con una funcionalidad ms limitada. Por otra parte, en Windows 2000 sirve para recuperar informacin de la mquina local, que por defecto no se almacena en el Active Directory. Proveedor ADSI para IIS. Accede a la metabase que guarda la informacin de configuracin del servicio web, ftp, etc. Proveedor ADSI para los servicios de directorio de Novell.

Estructura de Active Directory


La informacin de un directorio se guarda en unas entidades llamadas objetos, como impresoras, equipos, etc. Estos objetos se organizan en una estructura jerrquica, tipo rbol, y disponen de una serie de propiedades o atributos. Pero no hay que confundir estos objetos con los objetos COM. Es decir, estas propiedades no son las propiedades de un objeto COM, sino una pequea informacin almacenada en el objeto bajo un nombre, por ejemplo la propiedad Description. Las propiedades de un objeto del directorio son parejas nombre valor, aunque algunas propiedades pueden tener mltiples valores. Hay dos tipos de objetos ADSI: containers y leafs. Parecido a las carpetas y archivos del sistema de ficheros de Windows, con la diferencia de que los contenedores tambin son objetos con su propia informacin. Es decir, que siguiendo con el smil, un contenedor es como una carpeta y un archivo juntos. ADO ofrece un conjunto de interfaces que permiten acceder de forma similar a los datos contenidos en distintas bases de datos, usando sentencias SQL para localizar estos datos. De la misma forma, ADSI ofrece un conjunto de interfaces que permiten acceder de forma similar a los objetos contenidos en distintos directorios, usando cadenas que podramos comparar con la ruta fsica (Path) de un archivo en el sistema de ficheros. Estas cadenas se llaman ADsPath, y sirven para localizar esos objetos dentro del directorio. Cada proveedor usa una sintaxis distinta para estas cadenas que identifican los objetos del directorio, pero la cadena siempre empieza con el nombre del proveedor. De esta forma, no hay que hacer igual
280

Grupo EIDOS

15. Acceso a ADSI desde ASP

que cuando abrimos una conexin de ADO, a la cual estoy obligado a suministrar el proveedor mediante una cadena de conexin. Con ADSI la propia cadena ADsPath incluye las dos cosas: el proveedor y la identificacin del objeto del directorio.

Proveedor ADSI para WinNT


Recordemos que en Windows 2000 este proveedor sirve para recuperar informacin de la mquina local, que por defecto no se almacena en el Active Directory. Para acceder a los objetos del directorio se usa el binding. Los objetos ya existen en el directorio, es decir, no tengo que hacer CreateObject. Lo que quiero es recoger una referencia a una instancia concreta, mediante el mtodo GetObject, pasando como parmetro el nombre del objeto, en vez del nombre de la clase del componente, como hara con el mtodo CreateObject. Por ejemplo, para coger una referencia a la raz del directorio WinNT hago Set objRaiz = GetObject(WinNT:) . De esta forma obtengo un objeto COM que referencia al objeto real almacenado en el directorio. Este objeto COM tendr unas propiedades por ser objeto COM, y otras propiedades por ser objeto de directorio, en las cuales almacena informacin. Si escribimos en una pgina ASP el Cdigo fuente 201, obtendremos un resultado parecido al que se muestra en la Tabla 10.

<%@ Language=VBScript %> <HTML> <HEAD> <META NAME="GENERATOR" Content="Microsoft Visual Studio 6.0"> </HEAD> <BODY> <%Set objRaiz = GetObject("ADs")%> <div align="center"> <table border="1"> <tr><th>Nombre</th><td><%=objRaiz.Name%></td></tr> <tr><th>Ruta</th><td><%=objRaiz.ADsPath%></td></tr> <tr><th>Clase</th><td><%=objRaiz.Class%></td></tr> <tr><th>Padre</th><td><%=objRaiz.Parent%></td></tr> </table> </div> </BODY> </HTML> Cdigo fuente 201

Nombre ADs: Ruta ADs:

Clase Namespaces Padre


Tabla 10

281

Desarrollo de aplicaciones COM+ para Internet / Intranet con ASP 3.0

Grupo EIDOS

En la pgina ASP nos limitamos a recoger una referencia al objeto raz del directorio, y luego mostramos en una tabla algunas de sus propiedades. Comentemos algunas cosas. La clase del objeto ha resultado ser Namespaces, y no tiene padre. Conviene recordar que la estructura de los objetos dentro del directorio sigue una estructura jerrquica en forma de rbol. Si este objeto no tiene padre, significa que es el raz. Este objeto tambin se conoce como ADSI Router, y de l derivan en jerarqua todos los proveedores ADSI intalados en el equipo. Estos proveedores son objetos de la clase Namespace, como podemos ver si ejecutamos la pgina anterior, sustituyendo el parmetro ADsPath por Set objProveedor = GetObject("WinNT:"). En la Tabla 11 est el resultado obtenido. Nombre WinNT: Ruta WinNT:

Clase Namespace Padre ADs:


Tabla 11

Como se puede ver, hemos bajado un nivel en el rbol del directorio. Este objeto, de la clase Namespace, tiene como padre al anterior. Este objeto representa al proveedor ADSI para WinNT. Hay que hacer notar que el nombre del proveedor es sensible a las maysculas (devolvera error si ponemos Winnt en vez de WinNT), pero no as el resto de la cadena ADsPath. Esto es as en la mayora de los proveedores ADSI. Si ponemos Set objDominio = GetObject("WinNT://nombreDominio"), donde nombreDominio es el nombre del dominio al que est conectado el equipo, avanzamos un nivel ms, y obtenemos el objeto que representa al dominio. Pero adems para este objeto podemos mostrar una propiedad ms, llamada Schema. La Tabla 12 muestra un posible resultado. Nombre GRUPO Ruta WinNT://GRUPO

Clase Domain Padre WinNT: Schema WinNT://GRUPO/Schema/Domain


Tabla 12

282

Grupo EIDOS

15. Acceso a ADSI desde ASP

La propiedad Schema devuelve el ADsPath del objeto Schema, que especifica qu informacin (propiedades obligatorias y opcionales) debe contener un objeto de la clase a la que pertenece el objeto con el que estamos trabajando. Estas propiedades que estamos mostrando pertenecen al interfaz IADs, que deben implementar todos los objetos de un directorio ADSI. Son propiedades de objeto COM, no de objeto de directorio. Las propiedades, todas de slo lectura, del interfaz IADs son las siguientes: ADsPath: contiene la ruta que identifica al objeto en el directorio. Class: clase a la que pertenece el objeto. Guid: GUID nico que identifica al objeto o a su clase, segn el proveedor. Name: nombre comn del objeto. Parent: contiene la ruta que identifica al objeto superior en la jerarqua del rbol. Schema: contiene la ruta del objeto Schema que describe a este objeto, es decir, qu tipo de informacin debe almacenar (propiedades obligatorias y opcionales).

Y los mtodos del interfaz IADs son: Get: obtiene el valor de una propiedad identificada por su nombre. GetEx: igual que Get, pero tambin para propiedades con valores mltiples. En vez de devolver un valor nico, devuelve un array de valores Variant. GetInfo: carga los valores de las propiedades de este objeto desde el servicio de directorio. En vez de acceder a las propiedades del objeto del directorio all donde estn almacenadas, normalmente en otra mquina de la red, lo que sera muy lento, accedo a una copia local inprocess llamada cach de propiedades. Esta copia local puede actualizarse con este mtodo. Put: asigna valor a una propiedad. PutEx: igual que Put, pero tambin para propiedades con valores mltiples. PutInfo: hace el proceso inverso a GetInfo, es decir, enva los valores de las propiedades desde la cach hasta el servicio de directorio. GetInfoEx: igual que GetInfo, pero no carga los valores de todas la propiedades, sino slo lo de aquellas en las que est interesado.

Contenedores
El ltimo objeto del cual hemos obtenido una referencia, el correspondiente al dominio, es en realidad un objeto container dentro de la jerarqua del directorio suministrado por el proveedor para WinNT. Un contenedor tiene objetos hijo, que pueden recorrerse con la misma sintaxis empleada para recorrer las colecciones de ASP, como puede verse en el Cdigo fuente 202.

283

Desarrollo de aplicaciones COM+ para Internet / Intranet con ASP 3.0

Grupo EIDOS

<%@ Language=VBScript %> <HTML> <HEAD> <META NAME="GENERATOR" Content="Microsoft Visual Studio 6.0"> </HEAD> <BODY> <%Set objDominio = GetObject("WinNT://nombreDeDominio")%> <div align="center"> <table border="1"> <tr> <th>Nombre</th> <th>Ruta</th> <th>Clase</th> <th>Padre</th> </tr> <%for each objHijo in objDominio%> <tr> <td><%=objHijo.Name%></td> <td><%=objHijo.ADsPath%></td> <td><%=objHijo.Class%></td> <td><%=objHijo.Parent%></td> </tr> <%next%> </table> </div> </BODY> </HTML> Cdigo fuente 202

Donde nombreDeDominio es el nombre de un dominio. El resultado devuelto sera similar al de la Figura 86.

Figura 86

284

Grupo EIDOS

15. Acceso a ADSI desde ASP

Los contenedores, aparte de ofrecer el interfaz IADs, presentan tambin el interfaz IADsContainer. Este interfaz tiene las propiedades: Count: Contiene el nmero de objetos hijo del contenedor. Es slo de lectura. No est implementada actualmente por el proveedor para WinNT. Filter: contiene un array de cadenas que representan las clases de objetos que queremos listar del contenedor. Es de lectura/escritura. Hints: Permite especificar qu propiedades queremos cargar de los objetos incluidos en el contenedor. Es de lectura/escritura.

Los mtodos del interfaz IADsContainer son: CopyHere: copia aqu, como hijo de este contenedor, un objeto del servicio de directorio desde su ubicacin original. Create: crea un objeto de directorio como hijo de este contenedor. Delete: elimina un objeto de directorio que es hijo de este contenedor. GetObject: obtiene una referencia a un objeto de directorio que es hijo de este contenedor. MoveHere: igual que CopyHere, con la diferencia de que elimina el objeto de su ubicacin original.

Propiedades de los objetos del directorio


Las propiedades que hemos visto hasta ahora, de los interfaces IADs e IADsContainer, son las propiedades que tienen los objetos de directorio igual que otros objetos COM. Pero adems de estas propiedades, los objetos de un directorio tienen otras propiedades, en unos objetos distintas que en otros, segn est especificado en el Schema correspondiente. A estas propiedades no puedo acceder con la sintaxis del punto, como hago con las propiedades de cualquier objeto COM, sino con unos mtodos especiales, ya nombrados antes, como Get y Put. Si por ejemplo queremos obtener una tabla con las propiedades obligatorias y opcionales del objeto que representa al servicio del IIS, escribiremos el Cdigo fuente 203.

<%@ Language=VBScript %> <HTML> <HEAD> <META NAME="GENERATOR" Content="Microsoft Visual Studio 6.0"> </HEAD> <BODY> <% Set objIIS = GetObject("WinNT://GRUPO/varrondo/IISADMIN") Set objSchema = GetObject(objIIS.Schema) %> <h3>Propiedades obligatorias</h3> <table border="1"> <%for each prop in objSchema.MandatoryProperties%> <tr>

285

Desarrollo de aplicaciones COM+ para Internet / Intranet con ASP 3.0

Grupo EIDOS

<th><%=prop%></th> <td><%= objIIS.Get(prop)%></td> </tr> <%next%> </table> <h3>Propiedades opcionales</h3> <table border="1"> <%On Error Resume Next%> <%for each prop in objSchema.OptionalProperties%> <tr> <th><%=prop%></th> <td><%= objIIS.Get(prop)%></td> </tr> <%next%> </table> </BODY> </HTML> Cdigo fuente 203

Es necesario activar el manejador de errores de VBScript con On Error Resume Next, por un motivo que veremos a continuacin, pero que podemos adelantar diciendo que algunas propiedades no almacenan un valor, sino un array de valores, que no es directamente representable con Response. Write. Despus de obtener la referencia al objeto que representa al servicio IIS, obtenemos la referencia al objeto que representa al Schema, es decir, al objeto que especifica qu propiedades obligatorias y opcionales tiene que guardar el primer objeto. Los dos son objetos del directorio: el segundo especifica las propiedades que almacena el primero, es decir, su esquema. Podemos ver que el Path del objeto Schema es WinNT://GRUPO/Schema/Service. Si queremos ver todos los objetos Schema almacenados en el directorio, no tenemos ms que ejecutar el Cdigo fuente 202, pero obteniendo ahora la referencia al objeto contenedor de esquemas, con Set objSchema = GetObject("WinNT://GRUPO/Schema"). Despus recorremos cada una de las colecciones de propiedades, obteniendo el valor almacenado para cada propiedad mediante el mtodo Get con objIIS.Get(prop). Utilizamos las propiedades MandatoryProperties y OptionalProperties, que pertenecen al interfaz IADsClass implementado por todos los objetos Schema, y que contienen la coleccin de propiedades obligatorias y opcionales que debe tener un objeto de directorio representado por ese objeto Schema. El resultado que se obtiene ser parecido al de la Tabla 13.

PROPIEDADES OBLIGATORIAS
StartType 2

ServiceType 32 DisplayName Servicio de admin. IIS

286

Grupo EIDOS

15. Acceso a ADSI desde ASP

Path

G:\WINNT\System32\inetsrv\inetinfo.exe

ErrorControl 1

PROPIEDADES OPCIONALES
HostComputer LoadOrderGroup ServiceAccountName LocalSystem Dependencies
Tabla 13

WinNT://GRUPO/varrondo

Las propiedades de un objeto del directorio pueden estar almacenadas en cualquier lugar del dominio. Acceder a esa propiedad all donde est sera muy lento. Por eso lo que se hace es acceder a una copia local llamada cach de propiedades. Realmente los mtodos Get, GetEx, Put y PutEx acceden a esta copia local. Para actualizar el contenido de este cach se usa el mtodo GetInfo del interfaz IADs. Si slo quiero actualizar algunas propiedades, se usa GetInfoEx. Para hacer la actualizacin en sentido contrario, es decir, para enviar las propiedades de nuestra cach, que quiz hemos modificado, de vuelta al directorio, se usa el mtodo SetInfo. La primera vez que pido una propiedad, se invoca automticamente al mtodo GetInfo para traer las propiedades a la cach. No hace falta que lo haga yo explcitamente, a no ser que piense que la copia local est obsoleta.

Propiedades con valores mltiples


Los valores de las propiedades obtenidos con el mtodo Get son del tipo Variant. Eso significa que puede ser cualquier cosa: vaco, una cadena, un objeto, un array de valores, etc. De hecho, en el ejemplo anterior haba algunas propiedades que guardaban un array de valores. Para recorrer estos valores puede usarse el mtodo GetEx. Si en el cdigo anterior cambiamos por el Cdigo fuente 204 las lneas encargadas de recorrer las propiedades opcionales, obtendremos un resultado como en la Tabla 14.

<h3>Propiedades opcionales</h3> <table border="1"> <%for each prop in objSchema.OptionalProperties%> <tr> <th><%=prop%></th> <td> <%for each valor in objIIS.GetEx(prop)%>

287

Desarrollo de aplicaciones COM+ para Internet / Intranet con ASP 3.0

Grupo EIDOS

<%=valor%> <%next%> </td> </tr> <%next%> </table> Cdigo fuente 204

PROPIEDADES OPCIONALES
HostComputer LoadOrderGroup ServiceAccountName LocalSystem Dependencies RPCSS ProtectedStorage
Tabla 14

WinNT://GRUPO/varrondo

La propiedad Dependencies, que antes no poda mostrarse, ahora s. Vemos que es un array formado por dos elementos.

Modificacin de propiedades
Para poder modificar una propiedad de un objeto del directorio, primero debemos contar con los permisos adecuados. La cuenta bajo la que se ejecutan normalmente las pginas ASP es la cuenta de invitado a internet IUSR_NombreMquina, y esta cuenta normalmente tiene permisos muy restringidos. Luego para poder ejecutar con xito una pgina ASP que modifique propiedades de objetos de directorio debemos, o bien conceder permisos a esta cuenta de invitado a internet, o bien ejecutar la pgina ASP bajo otra cuenta con los permisos adecuados. Una vez hecho esto, el Cdigo fuente 205 muestra cmo podramos cambiar el valor de la propiedad DisplayName del objeto que representa al servicio IIS. Esta propiedad es el texto descriptivo del servicio que aparece al seleccionar la opcin Servicios de las Herramientas administrativas de Windows 2000.

Set objIIS = GetObject("WinNT://GRUPO/varrondo/IISADMIN") objIIS.Put "DisplayName","Nuevo nombre para el Servicio" objIIS.SetInfo Cdigo fuente 205

288

Si quiere ver ms textos en este formato, vistenos en: http://www.lalibreriadigital.com. Este libro tiene soporte de formacin virtual a travs de Internet, con un profesor a su disposicin, tutoras, exmenes y un completo plan formativo con otros textos. Si desea inscribirse en alguno de nuestros cursos o ms informacin visite nuestro campus virtual en: http://www.almagesto.com.

Si quiere informacin ms precisa de las nuevas tcnicas de programacin puede suscribirse gratuitamente a nuestra revista Algoritmo en: http://www.algoritmodigital.com. No deje de visitar nuestra reviata Alquimia en http://www.eidos.es/alquimia donde podr encontrar artculos sobre tecnologas de la sociedad del conocimiento.

Si quiere hacer algn comentario, sugerencia, o tiene cualquier tipo de problema, envelo a la direccin de correo electrnico lalibreriadigital@eidos.es.

Grupo EIDOS http://www.eidos.es

Si quiere ver ms textos en este formato, vistenos en: http://www.lalibreriadigital.com. Este libro tiene soporte de formacin virtual a travs de Internet, con un profesor a su disposicin, tutoras, exmenes y un completo plan formativo con otros textos. Si desea inscribirse en alguno de nuestros cursos o ms informacin visite nuestro campus virtual en: http://www.almagesto.com. Si quiere informacin ms precisa de las nuevas tcnicas de programacin puede suscribirse gratuitamente a nuestra revista Algoritmo en: http://www.algoritmodigital.com. No deje de

visitar nuestra reviata Alquimia en http://www.eidos.es/alquimia donde podr encontrar artculos sobre tecnologas de la sociedad del conocimiento.
Si quiere hacer algn comentario, sugerencia, o tiene cualquier tipo de problema, envelo a la direccin de correo electrnico lalibreriadigital@eidos.es.

Grupo EIDOS http://www.eidos.es

También podría gustarte