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.

DESARROLLO DE
APLICACIONES COM+

PARA INTERNET/INTRANET CON ASP 3


VCTOR ARRONDO, NGEL ESTEBAN

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:

18

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.

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

Descripcin

ASPCode

Un entero generado por IIS.

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

Breve descripcin del error.

File

Nombre del archivo ASP que se estaba procesando cuando se produjo el error.

Line

Lnea del archivo ASP que gener el error.

Number

Cdigo de error estndar de COM.

Source

Devuelve el cdigo fuente real, si est disponible, de la lnea que caus el error.
Tabla 1

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

Descripcin

AtEndOfLog

Indica si se leyeron o no todos los registros del archivo.

CloseLogFiles

Cierra todos los archivos de registro abiertos.

OpenLogFile

Abre un archivo de registro para lectura o escritura.

ReadFilter

Filtra los registros del archivo segn la fecha y la hora.

ReadLogRecord

Lee el siguiente registro disponible del archivo de registro actual.

WriteLogRecord

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

Descripcin

BytesReceived

Nmero de bytes recibidos del navegador como una peticin.

BytesSent

Nmero de bytes enviados al navegador como una respuesta.

ClientIP

Direccin IP del cliente.

Cookie

Indica los contenidos de cualquier cookie enviada en la peticin.

CustomFields

Un vector de cabeceras personalizadas que se aadieron a la peticin.

DateTime

La fecha y hora de la peticin en formato GMT.

Method

El tipo de operacin, tal como puede ser GET o POST.

ProtocolStatus

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

La URL de la pgina que contiene el enlace que inici la peticin, si est disponible.

ServerIP

La direccin IP del servidor Web.

ServerName

El nombre del servidor Web.

ServerPort

El nmero de puerto por el que se recibi la peticin.

ServiceName

Nombre del servicio, como puede ser el servicio FTP (MSFTPSVC) o Web
(W3SVC).

TimeTaken

El tiempo de procesamiento total para devolver y crear la pgina devuelta.

URIQuery

Cualquier parmetro aadido a la cadena de consulta (QueryString) de la URL en la


peticin.

27

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

Grupo EIDOS

URIStem

La URL que demand el cliente.

UserAgent

La cadena de agente de usuario (tipo de navegador) enviada por el cliente.

UserName

Nombre de inicio de sesin del usuario si no ha accedido de forma annima.

Win32Status

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

Descripcin

Baja (proceso IIS)

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.

Alta (aislada)

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

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:

56

Contents: contiene todas las variables a nivel de sesin menos las creadas con al etiqueta
<OBJECT>.

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

4. Componentes de Servidor

Grupo EIDOS

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

4. Componentes de Servidor

Grupo EIDOS

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

4. Componentes de Servidor

Grupo EIDOS

<%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

4. Componentes de Servidor

Grupo EIDOS

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

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

Grupo EIDOS

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

4. Componentes de Servidor

Grupo EIDOS

<%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

4. Componentes de Servidor

Grupo EIDOS

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

4. Componentes de Servidor

Grupo EIDOS

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

4. Componentes de Servidor

Grupo EIDOS

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:

86

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.

4. Componentes de Servidor

Grupo EIDOS

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:

88

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:

4. Componentes de Servidor

Grupo EIDOS

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

4. Componentes de Servidor

Grupo EIDOS

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.

102

Constante

Descripcin

adCmdText

Evala el comando como una sentencia SQL.

Grupo EIDOS

5. Componentes de acceso a datos. ADO

adCmdTable

Evala el comando como el nombre de una tabla.

adCmdStoredProc

Evala el comando como un procedimiento almacenado.

adCmdUnkown

El tipo del comando SQL es desconocido.

adCmdTableDirect

Se evala como el nombre de una tabla

adCmdFile

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.

104

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.

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:

122

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

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:

130

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.

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:

144

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.

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

150

Componentes COM

Grupo EIDOS

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

7. El modelo COM

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

162

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.

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

Private
Dim
Dim
Dim

Grupo EIDOS

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

stor_name

stor_address

city

state

zip

6380

Eric the Read Books

788 Catamaugus Ave. Seattle

WA 98056

7066

Barnum's

567 Pasadena Ave.

Tustin

CA

92789

7067

News & Brews

577 First St.

Los Gatos CA

96745

7131

Doc-U-Mat: Quality Laundry and Books 24-A Avogadro Way Remulade WA 98014

7896

Fricative Bookshop

89 Madison St.

Fremont

CA

90019

8042

Bookbeat

679 Carson St.

Portland

OR

89076

Tabla 6

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:

184

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.

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:

198

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.

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:

202

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.

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:

204

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.

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

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.

LockSetGet

LockMethod

Tabla 8

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

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.

Standard
Process

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:

214

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.

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

valor1

var2

valor2

var3

valor3

VARIABLES DE SESSION
Variable Valor
var1

valor1

var2

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

Dim
Dim
Dim
Dim
Dim
Dim

Grupo EIDOS

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

Figura 81

Figura 82

270

Grupo EIDOS

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:
ADs:

Ruta

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

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

WinNT://GRUPO/varrondo

LoadOrderGroup
ServiceAccountName LocalSystem
Dependencies
Tabla 13

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

WinNT://GRUPO/varrondo

LoadOrderGroup
ServiceAccountName LocalSystem
Dependencies

RPCSS
ProtectedStorage
Tabla 14

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