Sei sulla pagina 1di 302

Developing Web Applications

Contenido
1 INTRODUCCIN A LA PROGRAMACIN WEB....5
1.1 TIPOS DE APLICACIONES ......................................................... 5
1.1.1 1.1.2 1.1.3 1.1.4 1.2.1 1.2.2 1.2.3 1.2.4 1.3.1 1.3.2 1.3.3 1.3.4 1.3.5 1.3.6 1.3.7 1.3.8 Qu puede crear? ................................................................... 5 Cmo funcionan las aplicaciones Web .................................... 5 Lo que proporciona ASP.NET.................................................. 6 Ventajas de ASP.NET ............................................................... 6 Partes de una aplicacin Web.................................................. 7 Componentes de formulario Web ............................................. 7 Marco de trabajo .NET............................................................. 8 Lenguajes de programacin ................................................... 10

CREAR UN INTERFACE DE USUARIO...................57


4.1 USAR CONTROLES ................................................................. 57
4.1.1 4.1.2 4.1.3 4.1.4 4.1.5 4.1.6 4.1.7 4.1.8 4.1.9 4.1.10 4.1.11 4.1.12 4.1.13 4.1.14 4.1.15 4.2.1 4.2.2 4.2.3 4.2.4 4.3.1 4.3.2 4.3.3 4.3.4 4.3.5 Seleccionar una disposicin ...................................................57 Elegir el control correcto........................................................58 Trabajar con texto...................................................................59 Trabajar con tablas y listas ....................................................60 Aadir elementos a una lista o tabla en diseo ......................60 Aadir elementos a una lista o tabla en ejecucin .................60 Obtener el elemento seleccionado de una lista ......................61 Usar vinculacin de datos sencilla con listas.........................62 Aadir elementos a DataGrid, DataList y Repeater ..............62 Ejecutar comandos..................................................................63 Leer y escribir opciones..........................................................65 Mostrar grficos y avisos........................................................65 Agrupar controles ...................................................................66 Obtener fechas ........................................................................67 Obtener archivos del cliente ...................................................68 Usar validacin.......................................................................69 Combinar validaciones ...........................................................70 Cancelar la validacin............................................................70 Personalizar la validacin......................................................70 Formas de navegar .................................................................72 Uso de hiperenlaces y redireccin..........................................72 Mtodo Transfer......................................................................72 Mtodo Execute.......................................................................73 Mostrar una pgina en una nueva ventana ............................74

1.2 USO DE ASP.NET................................................................... 7

1.3 VISUAL STUDIO.NET ........................................................... 11


Pgina de inicio...................................................................... 11 Ventanas de Visual Studio .NET............................................. 11 Cuadro de herramientas......................................................... 12 Editar documentos Web.......................................................... 12 Editar cdigo .......................................................................... 12 Explorador de soluciones ....................................................... 13 Ejecutar un proyecto .............................................................. 13 Establecer puntos de Interrupcin e Inspeccionar Variables ................................................................................ 13 1.3.9 Ejecutar sentencias................................................................. 13 1.3.10 Ayuda ...................................................................................... 14

4.2 VALIDAR DATOS ................................................................... 69

4.3 NAVEGACIN ENTRE FORMULARIOS .................................... 72

1.4 RESUMEN .............................................................................. 14 1.5 PRCTICA: COMIENZO CON VISUAL STUDIO .NET .............. 14
1.5.1 1.5.2 1.5.3 1.5.4 Personalizar el Marco de Trabajo .NET................................ 15 Configurar una cuenta de alojamiento Web .......................... 15 Elegir un proveedor de servicio ............................................. 15 Explorar los tutoriales rpidos de ASP.NET ......................... 16

1.6 REPASO ................................................................................. 16

4.4 RESUMEN .............................................................................. 76 4.5 PRCTICA: EDITOR DE TEXTO BASADO EN WEB .................. 76
4.5.1 4.5.2 4.5.3 4.5.4 4.5.5 Crear el formulario de registro ..............................................76 Crear el formulario NewAccount............................................78 Crear el formulario FileManager...........................................80 Crear el formulario FileEditor ...............................................82 Crear el formulario Web NonAuthorized ...............................84

APLICACIONES DE FORMULARIO WEB .............17


2.1 CREAR UN PROYECTO DE APLICACIN WEB ........................ 17
2.1.1 2.1.2 2.1.3 2.1.4 2.1.5 2.1.6 2.2.1 2.2.2 2.2.3 2.2.4 2.2.5 Crear una nueva aplicacin Web ........................................... 17 Organizar su proyecto con IIS ............................................... 17 Crear directorios virtuales para aplicaciones Web............... 17 Aadir controles y escribir cdigo......................................... 18 Archivos de un proyecto de formulario Web.......................... 19 Archivos en una aplicacin Web ............................................ 20 Sucesos en el ciclo de vida de una aplicacin Web ............... 20 Conservar datos en un formulario Web ................................. 20 Sucesos de aplicacin y sesin ............................................... 21 Sucesos de formulario Web .................................................... 22 Sucesos de controles de servidor............................................ 23

4.6 REPASO ................................................................................. 85

ADO.NET. ......................................................................87
5.1 ACCESO A DATOS CON ADO.NET........................................ 87
5.1.1 5.1.2 5.1.3 5.1.4 5.1.5 5.1.6 5.1.7 5.1.8 5.1.9 5.1.10 5.2.1 5.2.2 5.2.3 5.2.4 5.2.5 5.2.6 5.2.7 5.2.8 5.3.1 5.3.2 5.3.3 5.3.4 ADO.NET ................................................................................87 Conectar con una base de datos .............................................88 Crear un conjunto de datos.....................................................88 Mostrar un conjunto de datos .................................................88 Cambiar registros en la base de datos ...................................89 Cmo hace referencia a objetos ADO.NET............................89 Aadir, cambiar y borrar filas................................................90 Actualizar la base de datos desde el conjunto de datos .........91 Crear una conexin en tiempo de ejecucin...........................92 Actualizar una Conexin en tiempo de ejecucin...................92 Mostrar un conjunto de datos en un DataGrid.......................94 Mostrar un conjunto de datos en un DataList ........................95 Mostrar datos en otros controles de lista ...............................96 Seleccionar registros concretos..............................................97 Ejecutar comandos sobre una base de datos..........................98 Devolver un valor desde una base de datos ...........................98 Cambiar registros directamente en la base de datos .............99 Recuperar registros directamente de la base de datos.........100 Transacciones .......................................................................101 Transacciones de conjunto de datos .....................................102 Transacciones de base de datos............................................103 Transacciones de empresa....................................................106

2.2 RESPONDER A SUCESOS ........................................................ 20

2.3 DNDE SE HACE EL PROCESAMIENTO?............................... 24


2.3.1 Establecer los lmites de aplicacin....................................... 24 2.3.2 Gestin de procesos................................................................ 25 2.3.3 Determinar cuando termina una aplicacin .......................... 25

2.4 RESUMEN .............................................................................. 26 2.5 PRCTICA: CREAR UNA APLICACIN WEB SENCILLA .......... 26
2.5.1 2.5.2 2.5.3 2.5.4 Crear el interface de usuario ................................................. 26 Crear una clase llamada FlashCardClass............................. 27 Almacenar un objeto FlashCardClass en Session ................. 28 Utilizar FlashCardClass en los sucesos del formulario Web......................................................................................... 29

5.2 USAR CONJUNTOS DE DATOS EN FORMULARIOS WEB .......... 94

2.6 REPASO ................................................................................. 30

TRABAJAR CON OBJETOS WEB ............................31


3.1 FUNDAMENTOS DE LOS ESPACIOS DE NOMBRES .................. 31
3.1.1 3.1.2 3.1.3 3.1.4 3.2.1 3.2.2 3.2.3 3.2.4 3.2.5 3.3.1 3.3.2 3.3.3 3.3.4 Comprender los espacios de nombres.................................... 31 Referencias Frente a Importaciones ...................................... 33 Clases y mdulos .................................................................... 34 Interfaces ................................................................................ 42 Generalidades de los espacios de nombres Web ................... 43 Uso del objeto Application ..................................................... 44 Uso del objeto Page................................................................ 45 Uso del objeto Request ........................................................... 45 Uso del objeto Response......................................................... 46 Niveles de estado .................................................................... 47 Uso de cadenas de consulta ................................................... 47 Uso de cookies ........................................................................ 47 Uso del estado de vista ........................................................... 48

5.3 PROCESO DE TRANSACCIONES ............................................ 101

3.2 ESPACIOS DE NOMBRES EN UNA APLICACIN WEB ............. 43

5.4 RESUMEN ............................................................................ 106 5.5 PRCTICA: APLICACIN DE GESTIN DE CONTACTOS ....... 107
5.5.1 5.5.2 5.5.3 5.5.4 5.5.5 Inicie un proyecto y cree el formulario SwichtBoard...........107 Aadir componentes de base de datos ..................................107 Crear el formulario AddContact...........................................108 Crear el formulario Calls .....................................................112 Crear los formularios DeleteContact y ContactTypes .........117

3.3 MANTENIMIENTO DE INFORMACIN DE ESTADO ................. 47

5.6 REPASO ............................................................................... 117

CAPTURAR Y CORREGIR ERRORES ..................119


6.1 USO DEL MANEJO DE EXCEPCIONES.................................... 119
6.1.1 6.1.2 6.1.3 6.1.4 6.1.5 Tcnicas de control de excepciones......................................119 Usar bloques de control de excepciones...............................119 Causar excepciones...............................................................122 Definir nuevas excepciones...................................................123 Uso de sucesos de error ........................................................123

3.4 RESUMEN .............................................................................. 51 3.5 PRCTICA: USAR OBJETOS Y GRABAR DATOS ...................... 51
3.5.1 3.5.2 3.5.3 3.5.4 Crear el interface de usuario ................................................. 51 Crear una clase Translator .................................................... 51 Almacenar un objeto Translator en sesin............................. 53 Use el objeto TransClass en los sucesos del formulario Web......................................................................................... 53

6.2 USAR PGINAS DE ERROR ................................................... 125


6.2.1 Control de excepciones relacionadas con internet...............125 6.2.2 Pginas de error a nivel de aplicacin.................................125 6.2.3 Pginas de error a nivel de pgina.......................................126

3.6 RESUMEN .............................................................................. 55

MCAD/MCSD
6.3 REGISTRO DE EXCEPCIONES ................................................127
6.3.1 6.3.2 6.3.3 6.3.4 Usar seguimiento para registrar errores..............................127 Activar y desactivar el seguimiento ......................................127 Escribir mensajes en el registro de seguimiento ..................128 Leer el registro de seguimiento.............................................129 8.7.2 Crear el formulario Web LogIn............................................ 171 8.7.3 Mostrar informacin de usuario .......................................... 175 8.7.4 Temas avanzados.................................................................. 176

8.8 REPASO ................................................................................176

6.4 RESUMEN ............................................................................129 6.5 PRCTICA: AADIR CONTROL DE EXCEPCIONES A UNA APLICACIN .........................................................................129
6.5.1 6.5.2 6.5.3 6.5.4 Ampliar el control de errores ...............................................129 Aadir un suceso de error.....................................................131 Crear y ver el registro de seguimiento .................................132 Ampliar el control de excepciones a otros formularios Web .......................................................................................132

GENERAR Y DESPLEGAR APLICACIONES....... 177


9.1 GENERAR UNA APLICACIN WEB .......................................177
9.1.1 Configurar las opciones de generacin ............................... 177 9.1.2 Identificar la aplicacin ....................................................... 177 9.1.3 Configurar la aplicacin ...................................................... 179

9.2 DESPLEGAR UNA APLICACIN WEB ....................................179


9.2.1 9.2.2 9.2.3 9.2.4 9.2.5 9.2.6 9.3.1 9.3.2 9.3.3 9.3.4 9.3.5 9.3.6 9.3.7 9.3.8 Uso de las herramientas desSubida ..................................... 179 Alojamiento en su propio servidor ....................................... 179 Configurar un directorio virtual .......................................... 180 Copiar la aplicacin............................................................. 180 Instalar componentes compartidos. ..................................... 180 Asignar privilegios de seguridad. ........................................ 181 Controlar el servidor............................................................ 182 Reparar aplicaciones............................................................ 183 Afinar aplicaciones desplegadas.......................................... 184 Configurar las opciones de Cach ....................................... 184 Cambiar el nivel de proteccin ............................................ 185 Ajustar los atributos de processModel................................. 185 Ajustar los atributos de sessionState.................................... 185 Consejos de optimizacin..................................................... 185

6.6 REPASO ...............................................................................132

PROGRAMACIN AVANZADA DE FORMULARIOS WEB .............................................. 133


7.1 GUARDAR Y RECUPERAR INFORMACIN DEL USUARIO ......133
7.1.1 7.1.2 7.1.3 7.1.4 7.1.5 7.1.6 7.1.7 7.1.8 7.1.9 7.1.10 7.1.11 Identificar usuarios de la aplicacin Web............................133 Almacenar nformacin de suario en el cliente .....................133 Almacenar informacin de usuario en el servidor ...............136 Crear claves nicas para identificar usuarios .....................136 Crear un archivo para guardar informacin del usuario ....136 Crear un archivo XML..........................................................137 Crear un esquema XML ........................................................137 Especificar un campo clave ..................................................137 Leer XML en un conjunto de datos.......................................137 Guardar informacin del usuario en el servidor..................138 Recuperar informacin de usuario del DataSet ...................139

9.3 MANTENER UNA APLICACIN .............................................181

9.4 DESPLEGAR ENTRE VARIOS SERVIDORES ............................186


9.4.1 Crecer con varios procesadores........................................... 186 9.4.2 Crecer con varios servidores ............................................... 186 9.4.3 Compartir informacin de estado ........................................ 186

7.2 ENVIAR CORREO .................................................................139


7.2.1 Enviar correo desde un cliente .............................................139 7.2.2 Enviar correo desde el servidor............................................140

7.3 USO DE MARCOS .................................................................141


7.3.1 7.3.2 7.3.3 7.3.4 7.3.5 7.4.1 7.4.2 7.4.3 7.4.4 7.4.5 Crear marcos en Visual Studio .............................................141 Crear un conjunto de marcos ...............................................141 Crear pginas y aadirlas al conjunto de marcos ...............141 Comprobar el soporte del navegador para marcos .............141 Apuntar a un marco desde un enlace....................................142 Antes de usar secuencias de comandos ................................143 Seleccionar un lenguaje de secuencias de comandos...........144 DOM......................................................................................144 Aadir secuencias de comandos en lnea .............................144 Respuesta a sucesos con secuencia de comandos ................145

9.5 RESUMEN.............................................................................187 9.6 PRCTICA: GENERAR Y DISTRIBUIR UNA APLICACIN WEB 187
9.6.1 9.6.2 9.6.3 9.6.4 Preparar la aplicacin ......................................................... 188 Despliegue la aplicacin ...................................................... 188 Comprobar el rendimiento de la aplicacin ........................ 188 Afinar la aplicacin.............................................................. 188

9.7 REPASO ................................................................................189

7.4 SECUENCIAS DE COMANDOS DE CLIENTE ...........................142

10 PROBAR APLICACIONES WEB............................. 191


10.1 CREAR PRUEBAS ..................................................................191
10.1.1 10.1.2 10.1.3 10.1.4 10.1.5 10.1.6 10.1.7 Desarrollar un plan de pruebas ........................................... 191 Tipos de pruebas................................................................... 192 Pruebas de unidad................................................................ 192 Pruebas de integracin......................................................... 194 Pruebas de regresin............................................................ 195 Pruebas de carga.................................................................. 195 Pruebas de plataforma ......................................................... 196

7.5 CONSUMIR SERVICIOS WEB XML ......................................147


7.5.1 Encontrar servicios Web XML..............................................148 7.5.2 Usar un servicio Web XML...................................................148 7.5.3 Uso de servicios Web XML desde secuencias de comando de cliente...............................................................................148

10.2 EJECUTAR PRUEBAS ............................................................196


10.2.1 Ejecutar pruebas con ACT ................................................... 196 10.2.2 Ejecutar pruebas con ensamblados .NET ............................ 198 10.2.3 Compilaciones y pruebas desatendidas ............................... 200

7.6 RESUMEN ............................................................................150 7.7 PRCTICA: USO DE CARACTERSTICAS AVANZADAS ..........150


7.7.1 7.7.2 7.7.3 7.7.4 7.7.5 Comprobar el soporte de caractersticas avanzadas ...........151 Almacenar informacin de usuario ......................................152 Crear un formulario Web para correo .................................153 Crear un interface de usuario basado en marcos ................155 Prctica extra con secuencias de comandos y cookies ........155

10.3 DEPURADO ..........................................................................202


10.3.1 10.3.2 10.3.3 10.3.4 10.3.5 Poner a trabajar los resultados de las pruebas ................... 202 Clases Debug y Trace........................................................... 204 Mostrar alertas y mensajes .................................................. 204 Registrar mensajes de Debug y Trace.................................. 205 Depurado remoto.................................................................. 205

7.8 REPASO ...............................................................................155

MANTENER LA SEGURIDAD ................................ 157


8.1 AUTENTICAR Y AUTORIZAR USUARIOS ...............................157
8.1.1 Acceso por uuarios annimos...............................................157 8.1.2 Acceso por usuarios autenticados ........................................157 8.1.3 Autenticacin con archivos HTM y HTML...........................158

10.4 RESUMEN.............................................................................206 10.5 PRCTICA: PRUEBAS Y DEPURADO .....................................206


10.5.1 10.5.2 10.5.3 10.5.4 Repasar un plan de pruebas................................................. 206 Escribir pruebas de unidad .................................................. 207 Crear una prueba de carga .................................................. 207 Recorrer un proceso remoto................................................. 207

8.2 AUTENTICACIN DE WINDOWS ..........................................158


8.2.1 8.2.2 8.2.3 8.2.4 8.2.5 8.3.1 8.3.2 8.3.3 8.3.4 8.3.5 8.3.6 Activar la autenticacin Windows ........................................158 Permitir o denegar el acceso a usuarios concretos..............159 Autorizacin basada en rol...................................................160 Obtener la identidad del usuario ..........................................160 Configuracin de IIS y autenticacin Windows ...................160 Activar la autenticacin por formularios .............................161 Establecer el modo de autenticacin por formulario ...........161 Crear un formulario Web de conexin .................................162 Autenticar usuarios con una base de datos ..........................163 Aadir usuarios a una base de datos....................................164 Autenticar usuarios contra una base de datos .....................165

10.6 REPASO ................................................................................207

11 CREAR CONTROLES WEB..................................... 209


11.1 CREAR CONTROLES DE USUARIO WEB ................................209
11.1.1 11.1.2 11.1.3 11.1.4 11.1.5 11.1.6 11.1.7 Crear y usar controles de usuario........................................ 209 Crear un control de usuario y dibujar su interface ............. 209 Escribir las propiedades, mtodos y sucesos del control .... 210 Agregar el control a un formulario Web.............................. 211 Usar el control en el cdigo ................................................. 211 Aadir sucesos al control de usuario................................... 212 Activar el diseo en rejilla ................................................... 213

8.3 AUTENTICACIN POR FORMULARIOS..................................161

11.2 CREAR CONTROLES COMPUESTOS .......................................213


11.2.1 Crear y usar controles compuestos ...................................... 213 11.2.2 Crear el proyecto de control personalizado ........................ 214 11.2.3 Crear el proyecto de prueba ................................................ 215 11.2.4 Agregar el control personalizado al proyecto de prueba .... 215 11.2.5 Crear el aspecto del control compuesto............................... 217 11.2.6 Crear propiedades y mtodos............................................... 218 11.2.7 Control de sucesos................................................................ 219 11.2.8 Lanzar sucesos...................................................................... 220 11.2.9 Cambio de tamao del control ............................................. 221 11.2.10 Superclasificar controles de servidor.................................. 222

8.4 AUTENTICACIN PASSPORT ................................................166


8.4.1 Activar la autenticacin Passport.........................................167

8.5 PROPORCIONAR COMUNICACIONES SEGURAS ....................168


8.5.1 8.5.2 8.5.3 8.5.4 8.5.5 Activar la comunicacin segura ...........................................168 Generar una peticin de certificado.....................................169 Solicitar un certificado .........................................................169 Instalar el certificado............................................................169 Usar comunicaciones seguras ..............................................170

8.6 RESUMEN ............................................................................170 8.7 PRCTICA: CREAR UNA APLICACIN SEGURA ....................170
8.7.1 Activar la autenticacin por formularios .............................170

11.3 CREAR CONTROLES PERSONALIZADOS TRAZADOS .............222


11.3.1 Crear y usar controles trazados........................................... 222

Developing Web Applications


11.3.2 11.3.3 11.3.4 11.3.5 11.3.6 11.3.7 Crear la apariencia del control............................................ 223 Guardar configuracin de propiedad .................................. 224 Recuperar texto contenido.................................................... 225 Responder a acciones de usuario ......................................... 226 Obtener datos desde el usuario ............................................ 229 Aadir controles personalizados a la caja de herramientas ........................................................................ 231 11.3.8 Establecer el icono y TagPrefix para controles personalizados ..................................................................... 231 13.2.6 13.2.7 13.2.8 13.2.9 Repetir tareas........................................................................261 Insertar enlaces y otros elementos HTML............................262 Ordenar elementos................................................................263 Tareas condicionales ............................................................263

13.3 RESUMEN ............................................................................ 264 13.4 LAB: CREAR EL LIBRO DE RECETAS .................................... 264
13.4.1 13.4.2 13.4.3 13.4.4 Ejercicio 1: Crear y anexar una hoja de estilo ....................264 Ejercicio 2: Proporcionar hojas de estilo alternativas ........265 Ejercicio 3: Transformacin XSL .........................................265 Ejercicio 4: Por si mismo .....................................................266

11.4 RESUMEN ............................................................................ 232 11.5 PRCTICA: CREAR CONTROLES PERSONALIZADOS ............ 232
11.5.1 Ejercicio 1: Crear un control de usuario AddressBox......... 232 11.5.2 Ejercicio 2: Crear el control personalizado compuesto DigitPad............................................................................... 232 11.5.3 Ejercicio 3: Cree el control personalizado trazado BartChar .............................................................................. 233

13.5 REPASO ............................................................................... 266

14 PROPORCIONAR AYUDA .......................................267


14.1 AADIR AYUDA A APLICACIONES WEB .............................. 267
14.1.1 Etiquetas de ayuda (ToolTip)................................................267 14.1.2 Mostrar ayuda como formulario Web o HTML....................267 14.1.3 Mostrar ayuda HTML ...........................................................268

11.6 REPASO ............................................................................... 233

12 TRABAJAR CON MULTIMEDIA............................ 235


12.1 INTERPRETAR AUDIO .......................................................... 235
12.1.1 12.1.2 12.1.3 12.1.4 12.2.1 12.2.2 12.2.3 12.2.4 12.2.5 12.2.6 Formas de interpretar audio ................................................ 235 Interpretar sonidos de fondo ................................................ 235 Incrustar sonidos .................................................................. 236 Sonido como objetos ActiveX ............................................... 236 Formas de mostrar video...................................................... 240 Elemento img ........................................................................ 240 Incrustar videos .................................................................... 240 Videos como objetos ActiveX................................................ 241 Objetos ActiveX en Netscape Navigator .............................. 242 Versiones de Windows Media Player................................... 242

14.2 HTML HELP WORKSHOP ................................................... 269


14.2.1 14.2.2 14.2.3 14.2.4 14.2.5 14.2.6 14.2.7 Crear ayuda HTML...............................................................269 Opciones de proyecto............................................................270 Tablas de contenido ..............................................................270 ndice.....................................................................................272 Referencias cruzadas ............................................................273 Bsqueda ...............................................................................274 Compilar y previsualizar ......................................................274

12.2 MOSTRAR VIDEO ................................................................ 240

14.3 ENLAZAR AYUDA HTML CON FORMULARIOS WEB........... 275


14.3.1 Mostrar el visor de ayuda HTML .........................................275 14.3.2 Mostrar ayuda HTML en el navegador ................................275 14.3.3 Ayuda sensible a contexto.....................................................275

12.3 ANIMAR PGINAS WEB ...................................................... 243


12.3.1 Formas de mostrar animaciones .......................................... 243 12.3.2 Animar Texto ........................................................................ 243 12.3.3 Animar grficos sencillos ..................................................... 244 12.3.4 Mostrar animaciones como objetos o plugins...................... 245 12.3.5 Animar con secuencias de comandos de cliente .................. 245 12.3.6 Animar con HTML+TIME.................................................... 246 12.3.7 Uso de HTML+TIME ........................................................... 246 12.3.8 Crear lneas de tiempo ......................................................... 247 12.3.9 Contenedores de tiempo ....................................................... 248 12.3.10 Animar atributos .................................................................. 249 12.3.11 Controlar audio, video y otros medios ................................ 249

14.4 RESUMEN ............................................................................ 276 14.5 LAB: CREAR Y USAR UN ARCHIVO DE AYUDA HTML........ 277
14.5.1 14.5.2 14.5.3 14.5.4 Ejercicio 1: Crear un proyecto de ayuda .............................277 Ejercicio 2: Activar contenidos, ndice y bsqueda .............277 Ejercicio 3: Aadir palabras clave al ndice........................277 Ejercicio 4: Enlazar ayuda con un formulario Web.............278

14.6 REPASO ............................................................................... 278

15 GLOBALIZAR APLICACIONES WEB ...................279


15.1 SELECCIONAR UN MTODO ................................................. 279
15.1.1 15.1.2 15.1.3 15.1.4 15.1.5 15.2.1 15.2.2 15.2.3 15.2.4 15.2.5 15.2.6 Formas de globalizar aplicaciones Web ..............................279 Detectar la cultura del usuario.............................................279 Redirigir a una aplicacin especfica de cultura..................280 Ajustar a la cultura actual en tiempo de ejecucin ..............281 Ensamblados satlite.............................................................284 Cmo funcionan los ensamblados satlite............................284 Preparar los elementos HTML para recursos......................285 Crear archivos de recursos...................................................285 Cargar archivos de recursos ................................................286 Leer y configurar la cultura del interface de usuario ..........286 Mostrar cadenas de recurso .................................................287

12.4 RESUMEN ............................................................................ 250 12.5 PRCTICA: CREAR UNA APLICACIN MULTIMEDIA ........... 250
12.5.1 Ejercicio 1: Usar sonido y movimiento................................ 250 12.5.2 Ejercicio 2: Mostrar una presentacin de diapositivas ....... 250

15.2 CREAR Y USAR ENSAMBLADOS SATLITE .......................... 284

12.6 REPASO ............................................................................... 251

13 DAR FORMATO A SALIDA DE APLICACIN WEB.............................................................................. 253


13.1 HOJAS DE ESTILO EN CASCADA .......................................... 253
13.1.1 13.1.2 13.1.3 13.1.4 13.1.5 13.1.6 13.1.7 13.1.8 13.1.9 13.2.1 13.2.2 13.2.3 13.2.4 13.2.5 Cmo funcionan los estilos................................................... 253 Usar hojas de estilo con formularios Web ........................... 254 Modificar estilos ................................................................... 254 Aadir estilos........................................................................ 254 Usar clases de estilo............................................................. 255 Crear estilos para elementos concretos ............................... 255 Crear estilos anidados.......................................................... 255 Cambiar la hoja de estilo en ejecucin ................................ 256 Comportamientos.................................................................. 257 Cmo funcionan las transformaciones XSL ......................... 258 Crear un archivo XML ......................................................... 258 Crear un archivo XSL........................................................... 259 Cambiar el diseo................................................................. 260 Incluir otras plantillas.......................................................... 260

15.3 TEMAS DE GLOBALIZACIN ................................................ 288


15.3.1 Temas de programacin general ..........................................288 15.3.2 Codificacin de caracteres ...................................................288

15.4 RESUMEN ............................................................................ 290 15.5 PRCTICA: CONVERSOR DE MONEDA ................................. 290
15.5.1 Ejercicio 1: Crear el formulario Web del conversor de moneda .................................................................................290 15.5.2 Ejercicio 2: Crear los archivos de recurso del interface de usuario .............................................................................291 15.5.3 Ejercicio 3: Cargar recursos segn la cultura.....................291 15.5.4 Ejercicio 4: Conversin dependiente de cultura ..................292

13.2 TRANSFORMACIONES XSL................................................. 258

15.6 REPASO ............................................................................... 293

16 PREGUNTAS Y RESPUESTAS.................................295

MCAD/MCSD

Developing Web Applications

1 Introduccin a la programacin Web


En este captulo aprender sobre las aplicaciones Internet y las herramientas que usar para crearlas. Este captulo introduce los conceptos y trminos utilizados en el libro, incluyendo las cmo funcionan las aplicaciones Web, las partes de una aplicacin Web, cmo est organizado el marco de trabajo .NET y cmo usar el entorno de programacin Visual Studio .NET. Las secciones de este captulo proporcionarn un vistazo de alto nivel de conceptos que se explicarn con ms detalle en captulos posteriores. Para completar este captulo necesitar: Tener instalado Visual Studio .NET Acceso a Internet por medio de una red de rea local, banda ancha o mdem

1.1 Tipos de aplicaciones


Las aplicaciones Web son uno de los cuatro tipos de aplicaciones Internet que puede crear usando Visual Studio .NET y ASP.NET. En esta leccin aprender un poco sobre los diferentes tipos de aplicaciones Internet y ver como funciona una aplicacin Web.

1.1.1 Qu puede crear?


Hablando estrictamente, una aplicacin Internet es cualquier aplicacin que usa Internet de cualquier forma. Esto significa que aplicaciones que piden a los usuarios que se registren en Internet o que proporcionen ayuda en Internet son, en cierto grado, aplicaciones Internet. Esta definicin es demasiado amplia para ser el tema de un solo libro. Para centrar un poco el tema vamos a identificar cuatro tipos de aplicaciones Internet: Aplicaciones Web. Proporcionan contenido desde un servidor a mquinas cliente en Internet. Los usuarios ven la aplicacin Web a travs de un navegador. Servicios Web. Estos componentes proporcionan servicios de procesamiento desde un servidor a otras aplicaciones en Internet. Aplicaciones preparadas para Internet. Son aplicaciones independientes que incorporan aspectos de Internet para proporcionar registro en lnea, ayuda, actualizaciones u otros servicios. Aplicaciones de igual a igual. Son aplicaciones independientes que usan Internet para comunicarse con otros usuarios que ejecutan sus propias instancias de la aplicacin. Puede usar Visual Studio.NET para crear todos estos tipos de aplicaciones. El primer tipo, aplicaciones Web, es el tema de este libro.

1.1.2 Cmo funcionan las aplicaciones Web


Las aplicaciones Web usan una arquitectura cliente-servidor. La aplicacin Web reside en un servidor y responde a las peticiones de mltiples clientes a travs de Internet. En el lado cliente, la aplicacin Web es alojada por un navegador. El interface de usuario de la aplicacin toma la forma de pginas HTML interpretadas y mostradas por el navegador cliente. En el lado servidor la aplicacin corre bajo Microsoft IIS. IIS administra la aplicacin, pasa peticiones de los clientes a la aplicacin, y devuelve las respuestas de la aplicacin a los clientes. Estas peticiones y respuestas se pasan sobre Internet usando el protocolo HTTP. Un protocolo es un conjunto de reglas que describe cmo se comunican dos o ms elementos sobre un medio, como Internet. La aplicacin Web compone las respuestas a las peticiones a partir de recursos encontrados en el servidor. Estos recursos incluyen el cdigo ejecutable en ejecucin en el servidor (lo que tradicionalmente denominamos aplicacin en programacin Windows), formularios Web, pginas HTML, archivos de imagen y otros medios que componen el contenido de la aplicacin. Las aplicaciones son muy similares a los sitios Web tradicionales, salvo que ejecutan el contenido presentado al usuario en realidad lo compone dinmicamente un ejecutable, en lugar de servirlos a partir de una pgina esttica almacenada en el servidor. La parte ejecutable de la aplicacin Web permite hacer muchas cosas que no se pueden hacer con un sitio Web esttico, como: Reunir informacin del usuario y almacenarla en el servidor Realizar tareas para el usuario, como hacer un pedido de un producto, realizar clculos complejos o recuperar informacin de una base de datos. Identificar a un usuario concreto y mostrar un interface personalizado para l. Presentar contenido altamente voltil, como inventario, pedidos pendientes e informacin de envos. 5

MCAD/MCSD

Esta es solo una lista parcial. Bsicamente, puede hacer con una aplicacin Web todo lo que imagine hacer con una aplicacin cliente/servidor. Lo que hace especial a una aplicacin Web es que la interaccin cliente/servidor tiene lugar sobre Internet.

1.1.3 Lo que proporciona ASP.NET


ASP.NET es la plataforma que se usa para crear aplicaciones Web y servicios Web que se ejecutan bajo IIS. ASP.NET no es la nica forma de crear una aplicacin Web. Otras tecnologas, notablemente CGI, tambin permiten crear aplicaciones Web. Lo que hace especial a ASP.NET es su estrecha integracin con el servidor Microsoft, programacin, acceso a datos y herramientas de seguridad. ASP.NET proporciona un alto nivel de coherencia en el desarrollo de aplicaciones Web. En cierto sentido es similar al nivel de coherencia que proporciona Microsoft Office al desarrollo de aplicaciones de sobremesa. ASP.NET es parte del marco de trabajo .NET y se compone de varios componentes diferentes. Herramientas de desarrollo Web Visual Studio .NET: Incluye las herramientas visuales para diseo de pginas Web y plantillas de aplicacin, gestin de proyectos y herramientas de despliegue para aplicaciones Web. Espacios de nombres System.Web: Son parte del marco de trabajo .NET e incluye las clases que se ocupan de temas especficos de Web como peticiones y respuestas HTTP, navegadores y correo electrnico. Controles de servidor y HTML: Son los componentes de interface de usuario que se usan para obtener informacin de y proporcionar respuestas a los usuarios. Adems de los componentes anteriores, ASP.NET tambin usa los siguientes componentes de programacin y herramientas Windows ms generales. Estos elementos no son parte de ASP.NET, pero son claves para la programacin ASP.NET. Servicios de Informacin Internet (IIS) de Microsoft: Como se mencion en la seccin anterior, IIS aloja las aplicaciones Web en un servidor Windows. Lenguajes de programacin Visual Basic .NET, Visual C# y JScript: Estos tres lenguajes tienen soporte integrado en Visual Studio .NET para crear aplicaciones Web. El marco de trabajo .NET: Es el conjunto completo de clases de programacin Windows; incluyen las clases ASP.NET as como clases para otras tareas como acceso a archivos, conversin de tipos de datos, manipulacin de arrays y cadenas, etc. Clases y herramientas ADO.NET para bases de datos: Estos componentes proporcionan acceso a bases de datos SQL Server y ODBC. El acceso a datos a menudo es un componente clave de las aplicaciones Web. Centro de Pruebas de Aplicaciones (Application Center Text, ACT): Este componentes de Visual Studio .NET proporciona una forma automatizada para hacer pruebas de stress a aplicaciones Web. ASP.NET es la plataforma ms completa para desarrollar aplicaciones Web que corren bajo IIS. Sin embargo, es importante recordar que ASP.NET no es independiente de plataforma. Como est alojado en IIS, ASP.NET debe correr en servidores Windows. Para crear aplicaciones Web que corran en servidores que no sean Windows/IIS, debe usar otras herramientas por lo general CGI.

1.1.4 Ventajas de ASP.NET


ASP.NET tiene muchas ventajas sobre otras sobre otras plataformas cuando se trata de crear aplicaciones Web. Probablemente la ms significativa sea su integracin con el servidor y herramientas de programacin Windows. Las aplicaciones Web creadas con ASP.NET son ms fciles de crear, depurar y desplegar porque todas estas tareas se pueden realizar desde un solo entorno Visual Studio.NET. ASP.NET proporciona estas otras ventajas a los desarrolladores de aplicaciones Web: Las partes ejecutables de una aplicacin Web estn compiladas de modo que se ejecutan ms deprisa que las secuencias de comandos interpretadas. Actualizaciones sobre la marcha de aplicaciones Web desplegadas sin reiniciar el servidor. Acceso al marco de trabajo .NET, que ampla el API de Windows. Uso del ampliamente conocido lenguaje de programacin Visual Basic, que se ha mejorado para que soporte completamente la programacin orientada a objetos. Introduccin del lenguaje C#, que proporciona una versin con tipos seguros y orientada a objetos de C. Gestin de estado automtica para los controles de una pgina Web (llamados controles de servidor) de forma que se comportan de una manera ms similar a los controles Windows. Capacidad de crear nuevos controles de usuario a partir de los existentes. Seguridad integrada mediante el servidor Windows u otros mtodos de autorizacin/autenticacin. Integracin con ADO.NET para proporcionar acceso a bases de datos y herramientas de diseo de base de datos desde Visual Studio.NET Soporte completo de XML, CSS y otros estndares Web nuevos y establecidos. 6

Developing Web Applications

Caractersticas integradas para cach de pginas Web solicitadas con frecuencia, localizacin de contenido para lenguajes concretos y deteccin de capacidades del navegador.

1.2 Uso de ASP.NET


En esta leccin aprender cmo organiza ASP.NET una aplicacin Web en partes y aprender las funciones y nombres de estas partes. Se mostrarn los formularios Web, que son el elemento central del interface de usuario de las aplicaciones Web. ASP.NET es parte de un marco de trabajo .NET mayor, de modo que esta leccin tambin discutir cmo est organizado el marco de trabajo .NET y cmo corren las aplicaciones .NET a diferencia de de las aplicaciones Windows tradicionales que puede estar acostumbrado a usar. Finalmente esta leccin termina con una discusin de los lenguajes de programacin que puede usar para crear aplicaciones Web. ASP.NET no est ligado a ningn lenguaje de programacin, y al final e esta leccin se indican algunos otros lenguaje disponibles y se explican algunas de las diferencias principales entre los dos lenguajes tratados en este libro: Visual Basic .NET y C#.

1.2.1 Partes de una aplicacin Web


Una aplicacin Web consta de tres partes: contenido, lgica del programa e informacin de configuracin Web. La tabla 1.1 resume estas partes y da ejemplos de donde residen en una aplicacin Web ASP.NET:
Tabla 1. 1: Partes de una Aplicacin Web ASP.NET Parte Tipos de Archivos Descripcin
Contenido Formularios Web, HTML, imgenes, audio, video, otros datos Archivos ejecutables, secuencias de comandos Los archivos de contenido determinan la apariencia de una aplicacin Web. Pueden contener texto e imgenes estticos as como elementos compuestos sobre la marcha por la lgica del programa (como una consulta a una base de datos). La lgica del programa determina cmo responde la aplicacin a las acciones del usuario. Las aplicaciones Web ASP.NET tienen un archivo DLL que corre en el servidor, y tambin pueden incluir secuencias de comandos que corren en la mquina cliente. Los archivos y opciones de configuracin determinan cmo corre la aplicacin en el servidor, quin tiene acceso, cmo se manejan los errores y otros detalles.

Lgica de programa

Configuracin

Archivo de configuracin Web, hojas de estilo, opciones IIS

El formulario Web es el elemento clave de una aplicacin Web. Un formulario Web es un cruce entre una pgina Web ordinaria y un formulario Windows. Tiene el mismo aspecto y un comportamiento similar a una pgina HTML, pero tambin tiene controles que responden a sucesos y ejecutan cdigo, como un formulario Windows. En una aplicacin Web terminada la parte ejecutable del formulario Web est almacenada en un ejecutable que corre en el servidor bajo el control de IIS. La parte de contenido del formulario Web reside en un directorio de contenido en el servidor Web. Cuando un usuario navega a una pgina de formulario Web en su navegador se produce esta secuencia: 1. 2. 3. IIS arranca el ejecutable de la aplicacin Web si no est ya en ejecucin El ejecutable compone una respuesta al usuario en base al contenido de la pgina de formularios Web que ha solicitado y a la lgica de programa que proporciona contenido dinmico. IIS devuelve la respuesta al usuario en forma de HTML.

Una vez que el usuario obtiene el formulario Web solicitado puede introducir datos, seleccionar opciones, pulsar botones y usar cualquier control que aparezca en la pgina. Algunos controles, como los botones, hacen que la pgina se enve de vuelta al servidor para procesar el suceso, y la secuencia se repite. El ciclo de sucesos se describe en mayor detalle en el apartado 2.2, Crear Aplicaciones de Formulario Web.

1.2.2 Componentes de formulario Web


Los formularios Web pueden contener varios tipos de componentes, como resume la tabla 1.2.
Tabla 1. 2: Componentes en un Formulario Web Componente Ejemplos
Controles de Servidor

TextBox, Label, Button, ListBox, DropDownList, DataGrid

Descripcin
Responden a sucesos de usuario ejecutando procedimientos en el servidor. Tienen caractersticas incorporadas para grabar datos introducidos por el usuario entre presentaciones de la pgina. Se usan para definir el interface de usuario de un formulario Web. Representan los elementos visuales estndar que proporciona HTML. Son tiles cuando no se necesitan las caractersticas ms avanzadas de los controles de servidor.

Controles HTML

Text Area, Table, Image, Submit Button, Reset Button

MCAD/MCSD

Componente
Controles de Datos Componentes de Sistema

Ejemplos
SqlConnection, SqlCommand, OleDbConnection, OleDbCommand, DataSet

Descripcin
Proporcionan una forma para conectar con, ejecutar comandos sobre y recuperar datos desde bases de datos SQL y OLE y archivos de datos XML. Proporcionan acceso a los diferentes sucesos a nivel de sistema que se producen en el servidor.

FileSystemWatcher, EventLog, MessageQueue

Los controles de servidor y HTML se usan para crear el interface de usuario de un formulario Web. Los controles de datos y componentes de sistema aparecen en el formulario Web solo en tiempo de diseo para proporcionar una forma visual para configurar sus propiedades y manejar sus sucesos. En tiempo de ejecucin los controles de datos y componentes de sistema no tienen representacin visual. El Captulo 4, Crear un Interface de Usuario, proporciona mayor detalle sobre el uso de controles de servidor y HTML en un formulario Web.

1.2.3 Marco de trabajo .NET


ASP.NET es una parte importante del marco de trabajo .NET, pero es solo una parte. Comprender lo que proporciona el marco de trabajo .NET le ayudar a programar su aplicacin con eficacia y le evitar escribir nuevo cdigo para realizar tareas que ya estn implementadas dentro del marco de trabajo .NET. Primero, un pequeo trasfondo. El marco de trabajo .NET es la nueva plataforma de programacin de Microsoft para desarrollar software Windows y Web. Se compone de dos partes: Un motor de ejecucin llamado sistema de ejecucin de lenguaje comn (common language runtime, CLR). Una librera de clases que proporciona funciones centrales de programacin, como aquellas de las que anteriormente se dispona solo por medio del API Windows, y funciones a nivel de aplicacin usadas para desarrollo Web (ASP.NET), acceso a datos (ADO.NET), seguridad y gestin remota. Las aplicaciones .NET no se ejecutan de la misma forma que las aplicaciones tradicionales que puede estar acostumbrado a crear. En lugar de compilarse en un ejecutable que contiene cdigo nativo, el cdigo .NET se compila en lenguaje intermedio de Microsoft (MSIL) y se almacena en un archivo llamado un ensamblado. En tiempo de ejecucin el ensamblado se compila a su estado final mediante el CLR. Durante la ejecucin el CLR proporciona gestin de memoria, comprobaciones de seguridad de tipos y otras tareas de tiempo de ejecucin para la aplicacin. La figura 1-1 muestra como funciona. Las aplicaciones que se ejecutan bajo el CLR se denominan cdigo administrado porque el CLR se preocupa de muchas de las tareas que anteriormente tendra que realizar el ejecutable de la aplicacin. El cdigo administrado resuelve el problema de registro y versiones de componentes en la programacin Windows (el infierno de las DLL), porque el ensamblado contiene toda la informacin de versiones y tipos que necesita el CLR para ejecutar la aplicacin. El CLR maneja el registro dinmicamente en tiempo de ejecucin, en lugar de estticamente mediante el registro del sistema como se hace con las aplicaciones basadas en COM.

Fig. 1- 1: Cmo se Ejecuta una Aplicacin .NET

La librera de clases .NET proporciona acceso a todas las caractersticas del CLR. La librera de clases .NET est organizada en espacios de nombres. Cada espacio de nombres contiene un grupo de clases funcionalmente relacionadas. La tabla 1-3 resume los espacios de nombres .NET que son de ms inters para los programadores de aplicaciones Web.
Tabla 1. 3: Resumen de la Librera de Clases del Marco de Trabajo .NET Componente Ejemplos Descripcin
Tipos Comunes System Todos los tipos de datos comunes, incluyendo cadenas, arrays y tipos numricos. Estas clases incluyen mtodos para convertir tipos, manipular cadenas y arrays y tareas matemticas. Acceso a bases de datos. Estas clases incluyen mtodos para conectar con bases de datos, ejecutar comandos, recuperar datos y modificar datos. Depurado y seguimiento de ejecucin de aplicaciones

Acceso a Datos

System.Data, System.Data.Common, System.Data.OleDb, System.Data.SqlClient, System.Data.SqlTypes


System.Diagnostics

Depurado

Developing Web Applications

Componente
Acceso a Archivos Comunicaciones Red Seguridad

System.IO, System.IO.IsolatedStorage, System.DirectoryServices System.NET, System.Net.Sockets

Ejemplos

Descripcin
Acceso al sistema de ficheros. Incluyen mtodos para leer y escribir archivos y obtener rutas y nombres de archivo. Comunicacin sobre Internet usando protocolos de bajo nivel como TCP/IP. Estas clases se usan cuando se crean aplicaciones de igual a igual. Proporcionan autenticacin y autorizacin de usuarios y encriptacin de datos. Creacin de aplicaciones cliente servidor que corren sobre Internet. Son las clases principales usadas para crear aplicaciones ASP.NET.

System.Security, System.Security.Cryptography, System.Security.Permissions, System.Security.Policy, System.Web.Security System.Web, System.Web.Caching, System.Web.Configuration, System.Web.Hosting, System.Web.Mail, System.Web.SessionState, System.Web.UI, System.Web.UI.Design, System.Web.UI.WebControls, System.Web.UI.HtmlControls System.Web.Services, System.Web.Services.Configuration, System.Web.Services.Description, System.Web.Services.Discovery, System.Web.Services.Protocols System.Windows.Forms, System.Windows.Forms.Design Sytem.XML, System.Xml.Schema, System.Xml.Serialization, System.Xml.Xpath, System.Xml.Xsl

Aplicaciones Web

Servicios Web

Crear y publicar componentes que se pueden usar sobre Internet. Son las clases centrales que se usan para crear servicios Web ASP.NET.

Aplicaciones Windows Datos XML

Creacin de aplicaciones usando componentes de interface de usuario de Windows. Proporcionan formularios y controles Windows y la capacidad de crear controles propios. Crear y acceder archivos XML.

Puesto que los espacios de nombres .NET organizan las clases por funciones, puede usarlos para localizar las clases y miembros de clase que proporcionan las caractersticas del CLR que quiere utilizar. Por ejemplo, el espacio de nombres System es uno de los que se usan ms normalmente porque contiene las clases para todos los tipos de datos fundamentales. En cualquier momento en que declare una variable con un tipo numrico, de cadena o de array, est usando el espacio de nombres System. Esta aproximacin permite que el marco de trabajo .NET proporcione mtodos integrados para convertir tipos de datos y manipular cadenas y arrays. Por ejemplo, las siguientes lneas de cdigo usan los mtodos integrados de las clases String y Array para ordenar una lista. Visual Basic .NET
Declara e inicializa una cadena Dim strFruta As String = naranjas manzanas melocotones kiwis nectarinas mangos Declara un array Dim arrFruta As String() Pone cada fruta en un elemento del array arrFruta = strFruta.Split( ) Ordena el array System.Array.Sort(arrFruta) Pone el array ordenado en la cadena strFruta = String.Join( , arrFruta)

Visual C#
//Declara e inicializa una cadena string strFruta = naranjas manzanas melocotones kiwis nectarinas mangos; //Declara un array string[] arrFruta; //Pone cada fruta en un elemento del array arrFruta = strFruta.Split( .ToCharArray()); //Ordena el array System.Array.Sort(arrFruta) //Pone el array ordenado en la cadena strFruta = System.String.Join( , arrFruta)

Muchos de los mtodos de clase del espacio de nombres System se pueden usar directamente sin crear primero un objeto a partir de la clase. Estos mtodos se llaman miembros compartidos (shared) en Visual Basic .NET y miembros estticos (static) en Visual C#. Los miembros compartidos y estticos se pueden llamar desde el propio nombre de la clase, como en la lnea System.Array.Sort del cdigo anterior. Otro ejemplo de clase con miembros compartidos/estticos es la clase Math, como se muestra en los siguientes mtodos Pi y Pow.

MCAD/MCSD

Visual Basic .NET


Obtiene el rea de un crculo dblAreaCirculo = System.Math.Pi * System.Math.Pow(intRadio, 2)

Visual C#
//Obtiene el rea de un crculo dblAreaCirculo = System.Math.Pi * System.Math.Pow(intRadio, 2);

1.2.4 Lenguajes de programacin


ASP.NET e, indudablemente, todo el marco de trabajo .NET, son independientes del lenguaje de programacin. Esto significa que puede elegir cualquier lenguaje que tenga implementado un compilador conforme al CLR. Adems de desarrollar sus propios lenguajes de programacin, Microsoft ha formado alianzas con muchos proveedores de lenguajes para proporcionar soporte .NET para Perl, Pascal, Eiffel, Cobol, Python, Smalltalk y otros lenguajes de programacin. Este libro trata la creacin de aplicaciones Web con los lenguajes de programacin Visual Basic .NET y Visual C#. Estos dos lenguajes son funcionalmente equivalentes, lo que significa que ambos proporcionan las mismas capacidades para crear aplicaciones Web. Las diferencias entre ambos lenguajes son de sintaxis y de estilo. La mayora de los programadores elegirn el lenguaje con el que estn familiarizados. Los programadores de Visual Basic estarn ms cmodos desarrollando aplicaciones Web en Visual Basic .NET. Los programadores C o C++ estarn ms cmodos con C#. Si es nuevo en la programacin o si est pensando ampliar sus habilidades de programacin a nuevos lenguajes, aprender ambos lenguajes es un objetivo prctico. Esto es cierto en particular cuando se crean aplicaciones Web, puesto que la mayora de las tareas se ejecutan por medio de clases del marco de trabajo .NET, lo que significa que el cdigo Visual Basic .NET y C# son prcticamente idnticos. La tabla 1.4 resume algunas diferencias significativas entre los dos lenguajes. Esta informacin es til si est eligiendo un lenguaje de programacin por primera vez o si est pensando cambiar entre lenguajes.
Tabla 1. 4: Diferencias entre Visual Basic .NET y Visual C# Caracterstica Visual Basic .NET
Diferenciacin de maysculas No diferencia maysculas response.write(Yo) correcto Utiliza sentencias de comienzo y final para delimitar Sub Muestra(strX As String) Response.Write(strX) End Sub De forma predetermina se permite la conversin implcita: Dim intX as Integer intX = 3.14 Permitido Puede limitar las conversiones incluyendo una sentencia Option Strict On al inicio del mdulo

Visual C# .NET
Diferencia maysculas response.write(Yo) //error Response.Write(Yo) //correcto Utiliza llaves para delimitar void Muestra(string strX) { Response.Write(strX) } Las conversiones de tipos se realizan explcitamente mediante moldeo: int intX; intX = 3.14; intX = (int)3.14 // Error //Moldeo, correcto

Bloques funcionales

Conversin de tipos

O usando mtodos de conversin de tipos String strX; strX = intX.ToString();

Arrays

Los elementos se especifican mediante parntesis arrFruta(1) = Manzana

Los elementos se especifican usando corchetes arrFruta[1] = Manzana; Hay que incluir los parntesis tras todos los mtodos strX = objX.ToString(); Las sentencias terminan con punto y coma Response.Write(Hola); Las sentencias continan hasta el punto y coma y pueden abarcar todas las lneas necesarias intX = System.Math.Pi * intRadio;

Mtodos

Puede omitir los parntesis tras el nombre de mtodo si no hay argumentos. strX = objX.ToString

Terminacin de sentencias Continuacin de sentencias

Las sentencias terminan por retorno de carro Response.Write(Hola) Las sentencias se continan con un carcter de subrayado intX = System.Math.Pi * _ intRadio

10

Developing Web Applications

Caracterstica
Operador de cadena

Visual Basic .NET


Usa el ampersand (&) o el signo de suma (+) para unir cadenas strFruta = Manzanas & _ Naranjas

Visual C# .NET
Utiliza el signo de suma (+) para unir cadenas strFruta = Manzanas + Naranjas; Utiliza ==, >, <, >=, <=, != para comparar valores if(intX >= 5) Usa el operador ! para expresar negacin lgica if(!IsPostBack) Usa == para comparar variables objeto if(objX == objY) Usa la palabra clave null para comprobar si existe un objeto. if(objX == null)

Operadores de comparacin Negacin

Utiliza =, >, <, >=, <=, <> para comparar valores If intX > 5 Then Utiliza la palabra clave Not para expresar negacin lgica If Not IsPostBack Then

Comparacin de objetos

Usa la palabra clave Is para comparar variables objeto, If objX Is objY Then

Existencia de objetos

Usa la palabra clave Nothing o la funcin IsNothing para comprobar si existe un objeto. If IsNothing(objX) Then

Adems de las diferencias que se ven en la tabla hay diferencias significativas en las palabras clave entre los dos lenguajes. Los ejemplos de cdigo en este libro muestran estas diferencias.

1.3 Visual Studio.NET


El entorno de programacin Visual Studio .NET presenta nuevos tipos de ventanas, nuevas formas de gestionar estas ventanas y nueva integracin de contenido Internet. Esta leccin ofrece un recorrido de estas nuevas caractersticas, as como un vistazo a algunas de las caractersticas ms antiguas de depurado y ayuda de Visual Studio .NET desde el punto de vista de la programacin de aplicaciones Web. Si ha programado con versiones anteriores de Visual Studio .NET y se salta esta leccin tenga en cuenta que ya no puede hacer cambios a una aplicacin a la vez que depura sin reiniciar la aplicacin. Esta caracterstica de Visual Studio .NET, llamada edita-y-contina, ya no est disponible en Visual Basic .NET o Visual C#.

1.3.1 Pgina de inicio


Cuando se arranca Visual Studio .NET lo primero que se ve es la pgina de inicio. La pgina de inicio contiene varios paneles para hacer ms fcil encontrar la informacin y ayudar a simplificar algunas tareas como abrir un archivo reciente. El panel Proyectos muestra los cuatro proyectos ms recientes en forma de enlaces. Para abrir uno de estos proyectos pulse sobre su nombre. Para crear un proyecto nuevo o abrir un proyecto existente no mostrado en la lista de proyectos recientes pulse el botn correspondiente en este panel. A la izquierda de la pgina de inicio hay una lista de temas que contienen informacin sobre Visual Studio .NET, otros productos de Microsoft, programacin, alojamiento de sitios Web y otra informacin. Esta informacin es dinmica, mucha de ella procedente de Internet. Esto asegura que esta informacin es actual; es una buena idea comprobarla ocasionalmente para ver las ltimas noticias. De especial inters para los desarrolladores de aplicaciones Web es el panel Alojamiento Web. Este panel enlaza con sitios Web que pueden alojar sus aplicaciones ASP.NET en Internet. Algunos de estos sitios, como Brinkster, ofrecen alojamiento gratuito limitado. Estos servicios de alojamiento son extremadamente tiles cuando se est aprendiendo ASP.NET ya que permiten compartir su trabajo con el mundo sin el esfuerzo y el gasto de configurar su propio servidor Web. El panel Mi Perfil permite configurar sus preferencias para Visual Studio .NET. Estas opciones le permiten cambiar el diseo de ventanas, configurar el lenguaje de programacin que use con ms frecuencia, y determinar si la ayuda se muestra en los paneles de diseo de Visual Studio .NET o en una ventana como aplicacin separada. La ventana de ayuda puede estar un poco sobrecargada cuando se muestra dentro de Visual Studio .NET, de modo que salvo que tenga un monitor de 19 pulgadas es una buena idea seleccionar la opcin Ayuda Externa.

1.3.2 Ventanas de Visual Studio .NET


Visual Studio .NET tiene dos tipos de ventana: de documentos y de herramientas. Las ventanas de documentos muestran el contenido de su aplicacin: los formularios, pginas Web y cdigo aparecen todos en las ventanas de documentos. Puede tener varias ventanas de documentos abiertas a la vez, y puede cambiar entre ellas pulsando sus lengetas cerca de la parte superior de la pantalla. Las ventanas de herramientas muestran los componentes que se usan para crear la aplicacin. Estos componentes incluyen los controles, conexiones con bases de datos, clases y propiedades que se usan en el proyecto. Las 11

MCAD/MCSD

ventanas de herramientas se muestran a izquierda y derecha de las ventanas de documentos y se pueden mostrar y ocultar pulsando sus lengetas. Para que una ventana de herramientas con lengeta permanezca en pantalla pulse el icono Auto Ocultar en la parte superior derecha de la ventana, que tiene la imagen de una chincheta. Pulse de nuevo la chincheta para que la ventana vuelva de nuevo a la presentacin con lengetas. Puede usar la presentacin con lengetas para ocultar las ventanas a ambos lados de la ventana de documentos para tener ms espacio para editar el contenido de sus aplicaciones. La presentacin con lengetas para las ventanas es la opcin predeterminada para Visual Studio .NET. Puede desactivar esta caracterstica seleccionado Opciones en el men Herramientas y seleccionando sus preferencias en el cuadro de dilogo.

1.3.3 Cuadro de herramientas


El cuadro de herramientas muestra los controles y componentes que se pueden aadir a una ventana de documento. El contenido del cuadro de herramientas cambia dependiendo del tipo de documento que se est editando. Cuando se est editando un formulario Web, por ejemplo, el cuadro de herramientas muestra los controles de servidor, controles HTML, controles de datos y otros componentes que se pueden aadir a un formulario Web. Los componentes en el cuadro de herramientas estn categorizados. Cuando se pulsa sobre una categora se muestran los elementos de la categora. Puede recorrer los elementos del cuadro de herramientas pulsando las flechas de la parte superior e inferior de la lista de componentes. Cuando el documento actual es cdigo el cuadro de herramientas contiene solo el Anillo del Portapapeles. El anillo del portapapeles registra los ltimos 20 elementos que se han cortado o copiado, de modo que se pueden volver a pegar en un documento. Para pegar un elemento del anillo del portapapeles pulse y arrastre el elemento al lugar donde quiere insertarlo. Cuando se mueve el puntero del ratn sobre un elemento Visual Studio lo expande para mostrar ms del texto que contiene.

1.3.4 Editar documentos Web


Puede editar formularios Web y documentos HTML visualmente usando las mismas tcnicas de arrastrar y soltar que se usan en formularios Windows, o como archivos de texto. Para cambiar entre los modos de edicin pulse las lengetas Diseo y HTML en la parte inferior de la ventana de documento. Hay tareas que no es posible realizar visualmente, por lo que a menudo tendr que editar documentos Web como texto. Tambin puede ser ms conveniente usar el modo HTML en lugar de las herramientas visuales si ya est familiarizado con HTML. La tecnologa IntelliSense de Visual Studio .NET proporciona ayuda para completar elementos HTML. Puede volver al modo diseo para ver los cambios hechos en el modo HTML sencillamente pulsando la lengeta Diseo en la parte inferior de la ventana de documentos.

1.3.5 Editar cdigo


Las pginas de formularios Web tienen archivos de cdigo subyacente asociados. Estos archivos se crean automticamente cuando se crea un nuevo formulario Web. Tienen el mismo nombre base que el formulario Web con la extensin .vb o .cs aadida tras la extensin .aspx. Visual Studio .NET genera una definicin de clase, procedimiento de inicializacin y procedimiento de suceso Page_Load para cada archivo de cdigo subyacente de un formulario Web. No debera cambiar el cdigo de las regiones marcadas Cdigo Generado por el Diseador Web Forms, porque este cdigo puede ser modificado ms adelante por Visual Studio .NET y sus cambios se podran sobrescribir. Puede ocultar el cdigo generado pulsando el signo menos (-) a la izquierda de la directiva #Region. Al pulsar el signo menos la regin se colapsa en una sola lnea y el signo menos cambia a ms (+), que se puede pulsar para expandir la regin de nuevo. Puede usar esta misma caracterstica de esquematizacin para colapsar o expandir bloques de cdigo como definiciones de clase y procedimientos. El editor de cdigo de Visual Studio .NET tambin proporciona el completado mediante IntelliSense para palabras clave y miembros de clase que se usen en cdigo. Si est programando en Visual Basic la caracterstica de auto completar tambin corregir la capitalizacin de palabras clave y nombres de miembros cuando se complete una lnea. Si est usando C# , Visual Studio .NET no reconocer una palabra clave o nombre de miembro si no est correctamente capitalizado. Esto se debe a que Visual Basic .NET no diferencia maysculas y minsculas y C# si.

12

Developing Web Applications

El editor de cdigo destaca los errores sintcticos y las variables no declaradas cuando se completa cada lnea. Estos errores se subrayan con una lnea quebrada, y si se coloca el puntero sobre un error se muestra una descripcin del error. Puede activar y desactivar la mayora de las opciones del editor de cdigo mediante el cuadro de dilogo Opciones. Tambin puede usar este cuadro de dilogo para cambiar el indentado automtico, completado de bloques de cdigo y otras opciones propias del lenguaje.

1.3.6 Explorador de soluciones


Visual Studio .NET organiza las aplicaciones en proyectos y soluciones. Un proyecto es una coleccin de archivos que compondrn ltimamente un nico ejecutable. Una solucin es un grupo de proyectos que componen una nica unidad funcional. Los archivos que componen una solucin se ven usando el Explorador de Soluciones. El proyecto que se muestra en negrita es el proyecto de inicio. El proyecto de inicio es el proyecto que se ejecuta cuando se pulsa Iniciar. Cuando se estn desarrollando varios proyectos como parte de una solucin el proyecto de inicio normalmente llama a los otros proyectos de la solucin. La informacin sobre una solucin se almacena en un archivo de solucin (.sln), que de forma predetermina se coloca en la carpeta Mis Documentos. Puede abrir la solucin usando este archivo o puede abrir directamente los proyectos usando sus archivos de proyecto (.vbproj o .csproj), que se encuentran en las carpetas de proyecto. Si se abre un archivo de proyecto Visual Studio .NET crea un nuevo archivo de solucin cuando se guarda el proyecto.

1.3.7 Ejecutar un proyecto


Puede ejecutar un proyecto dentro de Visual Studio .NET pulsando Iniciar en la barra de herramientas, seleccionando Iniciar en el men Depurar o pulsando F5. Cuando se ejecuta un proyecto Visual Studio .NET genera los archivos del proyecto y muestra los errores que se produzcan en la ventana Lista de Tareas, en la parte inferior de la ventana de documento. Pulsando dos veces sobre la descripcin del error en la lista de tareas se selecciona la lnea donde est el error en la ventana de documento de modo que se puede corregir. Si no se producen errores durante la generacin Visual Studio .NET inicia la aplicacin en modo de depuracin y, en el caso de una aplicacin Web, inicia Internet Explorer y muestra la pgina de inicio de la aplicacin. Si se produce un error mientras se ejecuta la aplicacin en modo de depurado, Visual Studio .NET muestra el error en el navegador. En este punto tiene dos opciones: Si sabe qu ha causado el error, puede detener la aplicacin cerrando el navegador y volviendo a Visual Studio para corregirlo. Si no est seguro de qu ha causado el error, puede pulsar Atrs en el navegador, cambiar a Visual Studio para colocar un punto de interrupcin en una posicin en el cdigo antes de que ocurra el error, y volver al navegador para repetir la tarea. Visual Studio detendr la aplicacin en el punto de interrupcin de modo que se podr recorrer el cdigo paso a paso para localizar el origen del error. Una vez localizado el error deber detener la aplicacin antes de poder corregirlo.

1.3.8 Establecer puntos de Interrupcin e Inspeccionar Variables


Puede detener un proyecto en una lnea de cdigo concreta estableciendo un punto de interrupcin. Cuando Visual Studio .NET ejecuta el proyecto lo detiene y muestra la lnea que contiene el punto de interrupcin en el editor de cdigo antes de que se ejecute esta lnea. Para establecer un punto de interrupcin pulse en el margen gris a la izquierda donde quiere romper, o seleccione la lnea y pulse F9. El punto de interrupcin se representa mediante un crculo rojo en el margen gris a la izquierda de la lnea. Una vez que Visual Studio .NET se detiene en un punto de interrupcin puede ver el valor de las variables activas colocando el puntero sobre la variable. Si la variable es de tipo complejo, como un objeto o un array, puede ver sus datos aadindola a una ventana de Inspeccin. Para aadir un elemento a una ventana de inspeccin seleccione el elemento y arrstrelo a la ventana de inspeccin. Pulse en el signo ms junto al elemento en la ventana de inspeccin para ver sus subelementos, como elementos del array o propiedades del objeto.

1.3.9 Ejecutar sentencias


Tras detenerse en un punto de interrupcin puede continuar la ejecucin de la aplicacin pulsando Continuar en la barra de herramientas o pulsando F5. Puede ejecutar una lnea cada vez pulsando F10 o F11. 13

MCAD/MCSD

F10 ejecuta cada llamada a procedimiento como una sentencia nica. En otras palabras, paso a paso sobre el procedimiento, ejecutndolo y detenindose en la siguiente lnea del procedimiento actual. F11 ejecuta las llamadas paso a paso por instrucciones, entrando dentro del procedimiento y detenindose en su primera lnea. Para ejecutar una nica lnea de cdigo fuera del contexto del proyecto escriba el cdigo en la ventana de comando. Los resultados de las sentencias escritas en la ventana de comando se dirigen a la siguiente lnea de la ventana.

1.3.10 Ayuda
Visual Studio. NET contiene una coleccin combinada de ayuda para el entorno de programacin, lenguajes, marco de trabajo .NET, soporte tcnico y artculos de la red del desarrollador. La ayuda se muestra en una ventana de documento o fuera de Visual Studio en una ventana separada, dependiendo de las preferencias configuradas en la pgina de inicio o en la caja de dilogo Opciones. El sistema de ayuda incluye tres formas de localizar temas: la ventana Contenido, la ventana ndice y la ventana Buscar. Estas ventanas actan como caja de herramientas, se pueden acoplar y despus ocultar o mostrar usando lengetas. Cada una de las ventanas de navegacin proporciona una lista desplegable Filtrado por: que le permite seleccionar un lenguaje de programacin o tema concreto en el que buscar. Esta caracterstica es especialmente til en las ventanas Buscar e ndice porque la coleccin de ayuda combinada es muy amplia. Los filtros Visual Basic y Temas Relacionados y Visual C# y Temas Relacionados incluyen la mayora de los temas necesarios en este libro. Los temas que incluyen ejemplos sintcticos o de cdigo tienen en la parte superior de cada pgina un icono de filtro de lenguaje que parece un embudo. Pulse sobre el icono para cambiar el lenguaje de programacin mostrado en el tema o ver los ejemplos para todos los lenguajes. Adems de la ayuda incluida con Visual Studio .NET Microsoft aloja el sitio Web GotDotNet en www.gotdotnet.com. Este sitio Web incluye tutoriales sobre el uso de ASP.NET y enlaces con muchos otros sitios Web relacionados.

1.4 Resumen
Hay cuatro tipos de aplicaciones Internet: las aplicaciones Web, servicios Web, aplicaciones adaptadas para Internet y aplicaciones igual a igual. Las aplicaciones Web corren en un servidor, procesando peticiones de usuario para pginas y componen estas pginas usando cdigo ejecutable y recursos estticos en el servidor. Las aplicaciones Web pueden proporcionar contenido dinmico en base a recursos dinmicos del servidor, como una base de datos, y en base a entradas del usuario, como la creacin de una tabla de amortizacin de hipoteca a partir de informacin del usuario. ASP.NET es una plataforma para crear aplicaciones Web que se ejecutan sobre servidores Windows usando IIS y el marco de trabajo .NET. Las aplicaciones Web se componen de contenido, un ejecutable y archivos de configuracin. El contenido de una aplicacin Web se muestra mediante formularios Web. Los formularios Web usan componentes HTML como pginas HTML convencionales; sin embargo, como los formularios Windows, pueden responder a sucesos de usuario como pulsaciones de ratn. El ejecutable de una aplicacin Web se almacena en un archivo dll llamado ensamblado. Los ensamblados se compilan en un estado intermedio, y la compilacin final la hace el CLR justo antes de ejecutar la aplicacin. El marco de trabajo .NET lo componen el CLR y la librera de clases .NET. La librera de clases .NET hace que las tareas de tiempo de ejecucin del CLR estn disponibles para los programadores. Las clases .NET estn agrupadas en espacios de nombres por tareas de programacin. Estos agrupamientos le ayudan a localizar la clase, mtodo o propiedad que necesita para cumplir una tarea. Use la pgina de inicio de Visual Studio .NET para ver informacin actual del producto, para abrir proyectos nuevos o existentes, configurar preferencias de entorno y registrarse en servicios de alojamiento Web. Edite pginas de formulario Web y HTML visualmente usando el modo de Diseo de la ventana de documentos; edtelas como texto usando el modo HTML de la misma ventana. Configure el filtro de lenguaje de la ayuda para ver los ejemplos de cdigo en un nico lenguaje de programacin o en varios. Modifique las caractersticas del entorno Visual Studio .NET usando la caja de dilogo Opciones.

1.5 Prctica: comienzo con Visual Studio .NET


En esta prctica se familiarizar con el entorno de programacin Visual Studio .NET, se registrar en un alojamiento de aplicaciones Web y ver los tutoriales rpidos de ASP.NET. Estos ejercicios establecen una base para las habilidades especficas de programacin que aprender en los siguientes captulos.

14

Developing Web Applications

1.5.1 Personalizar el Marco de Trabajo .NET


En este ejercicio personalizar la presentacin de ventanas en Visual Studio .NET para maximizar el rea de diseo. Tambin cambiar las opciones para ver la ayuda en una ventana externa, separada, y especificar un filtro de lenguaje en la ayuda. Cuando se arranca Visual Studio .NET por primera vez el diseo de ventana predeterminado muestra las ventanas del Explorador de Servidores y del Cuadro de Herramientas como lengetas en el lado izquierdo de la pantalla y las ventanas del Explorador de Soluciones y de Propiedades en el lado derecho. Para maximizar el espacio de pantalla para edicin de documentos Web y cdigo Seleccione Ocultar Todo Automticamente, o Pulse Ocultar Automticamente en la esquina superior derecha de las ventanas del Explorador de Soluciones y de Propiedades. El botn Ocultar Automticamente tiene el aspecto de una chincheta. Cuando se activa la opcin de ocultar automticamente la ventana desaparece cuando el puntero del ratn sale de ella. La ventana reaparece cuando el puntero se mueve sobre la lengeta en el borde de la ventana. Otra opcin predeterminada de Visual Studio .NET es mostrar la ventana de ayuda dentro de una ventana de documento. La propia ayuda tiene unas cuantas ventanas, de modo que esta presentacin de ventana dentro de ventana puede quedar un poco saturada. Para mostrar la ayuda en su propia ventana 1. En el men Herramientas seleccione Opciones. Visual Studio .NET muestra el dilogo Opciones 2. En la caja de dilogo Opciones pulse Ayuda en la carpeta Entorno. Visual Studio .NET muestra las opciones de ayuda. 3. Marque la opcin Ayuda externa y pulse Aceptar. Si experimenta con el diseo de ventanas de Visual Studio .NET y no le gustan los resultados puede restablecer las opciones de ventana predeterminadas. Para restablecer las opciones de ventana predeterminadas 1. En el men Herramientas seleccione Opciones. Visual Studio .NET muestra el dilogo Opciones. 2. En el cuadro de dilogo Opciones, carpeta Entorno, seleccione General. 3. Pulse el botn Restablecer diseo de ventana. Visual Studio .NET muestra una advertencia pidiendo confirmacin de que quiere restablecer el diseo de ventanas a su valor predeterminado. 4. Pulse Aceptar para cerrar la advertencia y de nuevo para cerrar el cuadro de dilogo Opciones. Visual Studio .NET restablece el diseo previo de las ventanas.

1.5.2 Configurar una cuenta de alojamiento Web


En este ejercicio va a configurar una cuenta de alojamiento Web que le permitir desplegar aplicaciones Web para prueba y evaluacin pblicas en Internet. No necesita tener una cuenta de alojamiento Web para completar las lecciones de este libro, puesto que puede ejecutar y depurar aplicaciones localmente. Sin embargo, tener una cuenta de alojamiento Web le permite probar cmo gestiona su aplicacin mltiples usuarios simultneos y tambin le permite compartir sus logros en programacin con otros, una buena diversin. Para configurar el alojamiento Web 1. Seleccione un proveedor de servicio de alojamiento 2. Regstrese con el servicio 3. Conecte con el servicio y suba la informacin 4. Para mostrar el panel Alojamiento Web en Visual Studio .NET seleccione la ventana de documento de la pgina de inicio y pulse la lengeta Alojamiento Web. Las siguientes secciones describen con ms detalle los pasos para configurar una cuenta de alojamiento Web.

1.5.3 Elegir un proveedor de servicio


El panel de alojamiento Web recoge una serie de proveedores de servicio de alojamiento que soportan aplicaciones ASP.NET. Cada uno de estos proveedores ofrece una combinacin diferente de servicios gratuitos y de pago. Para evaluar cul de estos proveedores es el que le conviene visite su pgina Web pulsando sobre su enlace en la pgina de inicio de Visual Studio. Adems del coste debe considerar: Nivel de Asistencia: Proporciona un foro de usuarios u otro rea donde se pueda responder a sus preguntas?. Si lo hace, compruebe lo que dicen otros usuarios. Capacidad para Migrar: Podr pasar con facilidad las aplicaciones de la etapa de pruebas a despliegue completo? Proporciona el servicio de alojamiento el almacenamiento y prestaciones que necesita? Soporte de Base de Datos: La mayor parte de servicios proporcionan alojamiento de Base de Datos, pero cada uno cobra una tarifa diferente por este servicio. 15

MCAD/MCSD

Para registrarse con un proveedor de servicio Nota: Regstrese con el servicio para crear su propia cuenta. El procedimiento exacto vara para cada proveedor, pero todos siguen estos pasos bsicos. 1. En el panel de alojamiento Web pulse el enlace pulse el enlace Registrar Con del proveedor de servicio que ha elegido. Visual Studio .NET muestra el procedimiento de registro en una ventana de documento. 2. Siga las instrucciones del proveedor de servicio, que normalmente pedir informacin de nombre, direccin y correo electrnico. Cuando la informacin est completa el proveedor de servicio le enviar por correo electrnico una contrasea para proporcionar acceso a la nieva cuenta. Los proveedores de servicio mostrados en el panel de alojamiento Web proporcionan alojamiento en un paso, lo que significa que puede subir sus aplicaciones completas directamente desde el panel de alojamiento Web de Visual Studio. Para subir una aplicacin al servicio de alojamiento 1. Desde el panel de alojamiento Web de Visual Studio .NET pulse el enlace Subir Directamente a su Cuenta en el proveedor de servicio con el que se haya registrado. Visual Studio .NET muestra la pgina de conexin del servicio en una ventana de documento. 2. En la pgina de conexin, escriba el nombre de usuario y contrasea para su cuenta (normalmente se la enviarn por correo electrnico). Una vez conectado, el proveedor de servicio mostrar una pgina de subida en una ventana de documento. 3. En la lista de la izquierda, seleccione la carpeta que contiene la aplicacin a subir. En la lista de la derecha, seleccione una carpeta del servidor a la que subir la aplicacin. Pulse Subir para subir el proyecto al alojamiento Web. Tras subir la aplicacin, Vd. y otros pueden verla navegando a su situacin en Internet. Los proveedores de alojamiento de servicio Web no piden que los usuarios se registren para ver una aplicacin, solo para subirla.

1.5.4 Explorar los tutoriales rpidos de ASP.NET


En este ejercicio va a instalar los tutoriales rpidos del SDK de .NET y ver los tutoriales rpidos para ASP.NET. Los tutoriales rpidos contienen informacin sobre los diferentes aspectos del marco de trabajo .NET y son uno de los mejores recursos para aprended a programar usando ASP.NET. Para instalar y ver los tutoriales rpidos 1. En el men de Inicio de Windows seleccione Programas, Microsoft .NET Framework SDK, Ejemplos y Tutoriales. Windows muestra la pgina de instalacin de Tutoriales rpidos, tutoriales y ejemplos de Microsoft Framework SDK. 2. Pulse el paso 1 para instalar las bases de datos utilizadas en los ejemplos de los tutoriales. 3. Pulse el paso 2 para instalar y configurar los sitios Web usados en los ejemplos de los tutoriales. 4. La siguiente vez que acceda a los tutoriales rpidos Internet Explorer se saltar la pgina de instalacin y le llevar directamente a la pgina tutoriales rpidos, tutoriales y ejemplos 5. Pulse el enlace Tutorial Rpido ASP.NET para ver la pgina del tutorial. La pgina del tutorial rpido de ASP.NET muestra cmo realizar diferentes tareas de programacin en Visual Basic .NET, Visual C# y JScript. Presenta los formularios Web en modo HTML en lugar de modo Diseo, como hace este libro en gran medida.

1.6 Repaso
Las siguientes preguntas estn pensadas para reforzar informacin clave mostrada en este captulo. Si no es capaz de contestar a una pregunta repase la leccin correspondiente e intente de nuevo. Las respuestas se pueden encontrar en el captulo 16. 1. 2. 3. 4. De tres ejemplos de en que se diferencia una aplicacin Web de una aplicacin Windows tradicional. Cules son las dos partes del marco de trabajo .NET? Cmo se restablecen las opciones de ventana predeterminadas en Visual Studio .NET? Por qu no completa automticamente el editor de cdigo la siguiente lnea de cdigo parcial (slo usuarios de Visual C#)?
int intX = system.math

5.

Cundo no puede usar ASP.NET para crear una aplicacin?

16

Developing Web Applications

2 Aplicaciones de Formulario Web


En este captulo aprender cmo crear una aplicacin Web usando Microsoft Visual Studio .NET y ASP.NET. Aprender cmo iniciar un nuevo proyecto, crear un interface de usuario bsico, escribir cdigo para responder a sucesos y preservar datos dentro de la aplicacin. Como ASP.NET est integrado con los servicios de informacin Internet (IIS) de Microsoft, tambin aprender cmo usarlo para organizar su aplicacin Web. Antes de completar las lecciones deber: Haber instalado Visual Studio .NET, IIS y las extensiones de servidor de FrontPage en su ordenador. Estar familiarizado con los aspectos bsicos de uso de Visual Studio .NET, incluyendo cmo aadir controles a un formulario Windows, cmo aadir cdigo a controles, y como ejecutar una aplicacin dentro de Visual Studio .NET. Puede ver instrucciones para estas tareas en los tutoriales rpidos.

2.1 Crear un proyecto de aplicacin Web


Los formularios Web son objetos de aplicacin que definen el interface de usuario de su aplicacin Web. El texto y controles que se colocan en un formulario Web determinan lo que ve un usuario cuando ejecuta la aplicacin. En este aspecto los formularios Web son similares a una aplicacin Windows. A diferencia de las aplicaciones Windows, sin embargo, las aplicaciones Web corren en un servidor y se distribuyen a los clientes sobre Internet. Sin embargo, la forma en que se crea y organiza un proyecto de aplicacin Web tiene diferencias significativas frente al trabajo con aplicaciones Windows en Visual Studio .NET. Estas diferencias se explican en la siguiente seccin.

2.1.1 Crear una nueva aplicacin Web


El primer paso en la creacin de una aplicacin de formularios Web es comenzar un nuevo proyecto. Visual Studio .NET proporciona plantillas para cada tipo de aplicacin que puede crear. La plantilla para una nueva aplicacin Web se denomina Aplicacin Web ASP.NET. Cuando crea un nuevo proyecto creando esta plantilla Visual Studio .NET crea un archivo de proyecto, un formulario Web en blanco y otros archivos de apoyo usados por la aplicacin. Para crear una aplicacin Web desde Visual Studio .NET siga estos pasos: 1. 2. En la pgina de inicio de Visual Studio .NET pulse Nuevo Proyecto. Visual Studio .NET muestra la caja de dilogo Nuevo Proyecto. Visual Studio .NET pone las aplicaciones Web en el directorio virtual localhost. En la caja de dilogo Nuevo Proyecto seleccione la plantilla Aplicacin Web ASP.NET, escriba el nombre del nuevo proyecto en la caja de texto Ubicacin y pulse Aceptar

Cuando se crea un proyecto de aplicacin Web en Visual Studio .NET el entorno de programacin crea una nueva carpeta y genera un conjunto de archivos para el proyecto. Visual Studio .NET da a la carpeta el mismo nombre del proyecto y la pone en el directorio raz del sitio Web predeterminado que aloja IIS en su ordenador. Esta ubicacin se muestra se muestra en la caja de texto Ubicacin de la caja de dilogo Nuevo Proyecto como http://localhost/nombreproyecto.

2.1.2 Organizar su proyecto con IIS


Es importante tener en cuenta que las aplicaciones Web solo pueden existir en una ubicacin que IIS ha publicado como directorio virtual. Un directorio virtual es un recurso compartido identificado por un alias que representa una situacin fsica en un servidor. Si intenta seleccionar una carpeta fsica como C:\MisArchivos en el cuadro de dilogo Nuevo Proyecto Visual Studio .NET desactiva el botn Aceptar. No se puede crear una aplicacin Web aqu. La carpeta virtual //localhost es la carpeta raz Web en su ordenador. IIS determina la ubicacin fsica de su carpeta raz Web local. De forma predeterminada IIS la instala en su disco de arranque en \Inetpub\wwwroot. En lugar de usar esta opcin predeterminada y dejar que se sature con proyectos de ejemplo, cdigo de produccin y otros estorbos organice sus proyectos creando carpetas separadas para ejemplos, pruebas y cdigo de produccin. Comparta estas carpetas en la Web antes de crear nuevos proyectos. Recuerde que Visual Studio .NET crea una nueva carpeta para cada nuevo proyecto, de modo que cree solo las carpetas para organizar los tipos de proyectos que va a crear.

2.1.3 Crear directorios virtuales para aplicaciones Web


Use IIS para crear nuevos directorios virtuales y para administrar los sitos Web alojados en su ordenador. Crear un directorio virtual para usar con Visual Studio .NET precisa dos tareas principales: Crear el directorio virtual: Los directorios virtuales especifican donde se almacenan fsicamente los proyectos, de modo que selos para ayudar a organizar sus proyectos durante el desarrollo.

17

MCAD/MCSD

Aadir las Extensiones FrontPage al directorio virtual para crear una subweb. Una subweb es simplemente un directorio virtual que contiene un sitio Web. Al aadir las Extensiones FrontPage a un directorio virtual se permite que Visual Studio .NET cree y mantenga las aplicaciones Web en este directorio. Para aadir un directorio virtual en IIS siga estos pasos. 1. 2. 3. Pulse con el botn derecho sobre el icono Sitio Web Predeterminado en IIS y en el men Nuevo pulse Directorio Virtual. IIS inicia el asistente de creacin de nuevo directorio virtual para guiarle. Puse Siguiente en la pgina de ttulo del asistente para ver la pgina Alias del directorio virtual. Escriba un alias para la capeta. El alias es el nombre que usar para identificar el recurso en esta carpeta. En Visual Studio .NET este es el nombre que usar para especificar la ubicacin de su proyecto. Pulse Siguiente. El asistente mostrar la pgina Directorio de contenido del sitio Web. Escriba la ruta del directorio fsico asociado con el directorio virtual. Este el directorio base donde se almacenarn los archivos del proyecto. Pulse Siguiente; el asistente muestra la pgina Permisos de acceso. Mantenga los permisos predeterminados (Lectura y Ejecutar secuencias de comandos). Pulse Siguiente y Finalizar para crear el directorio virtual y terminar el asistente.

4. 5.

Crear una Subweb Para aadir las extensiones FrontPage a un directorio virtual: 1. 2. Pulse con el botn derecho en el icono localhost en IIS y seleccione Nuevo Web de Extensiones de Servidor IIS inicia el asistente para nuevo subweb para guiarle a la hora de aadir las extensiones FrontPage a su directorio virtual. Pulse siguiente en la pantalla de ttulo del asistente para mostrar la pgina Nombre de subweb. Escriba el nombre del directorio virtual en la caja de texto Nombre de directorio. Este nombre corresponde al alias que se introdujo en el paso 3 del procedimiento anterior. Escriba una descripcin para el directorio en la caja de texto Ttulo, o djela en blanco. Pulse Siguiente. El asistente muestra la pgina Control de acceso. Acepte las opciones predeterminadas de control de acceso pulsando siguiente, y pulse finalizar para crear la nueva subweb.

3.

4.

Crear un nuevo proyecto en el directorio virtual Despus de crear un nuevo directorio virtual y aadirle las extensiones de servidor puede usarlo desde Visual Studio .NET para crear nuevos proyectos. Para crear un proyecto de aplicacin Web en su nuevo directorio virtual seleccione Nuevo Proyecto en el men Archivo y especifique el nombre del directorio virtual en la caja de dilogo Nuevo Proyecto. La ubicacin especificada en la caja de dilogo tiene la forma http://nombreservidor/directoriovirtual. El nombre de servidor localhost indica que el servidor corre en la mquina de desarrollo. El nombre directoriovirtual es el alias que se cre para el directorio virtual en las tareas anteriores.

2.1.4 Aadir controles y escribir cdigo


Cuando Visual Studio .NET crea una aplicacin muestra un nuevo formulario Web en la ventana central. Arrastre controles desde la caja de herramientas al formulario Web como hara con un formulario Windows. Para aadir cdigo que responda a sucesos en el formulario Web pulse dos veces sobre el control. Visual Studio .NET. muestra la ventana Cdigo. Aada su cdigo al procedimiento de suceso que se proporciona para el control. Por ejemplo, el siguiente cdigo muestra Hola Web! en Internet Explorer cuando se pulsa un botn: Visual Basic .NET
Private Sub Button1_Click(ByVal sender as System.Object, _ ByVal e as System.EventArgs) Handles Button1.Click Response.Write(Hola Web!<br>!) End Sub

Visual C#
private void Button1_Click(object sender, System.EventArgs e){ Response.Write(Hola Web!<br>); }

Para ejecutar la aplicacin pulse F5. Visual Studio .NET genera la aplicacin y muestra la pgina en el navegador. Cuando se pulsa Button1 el navegador muestra Hola Web!. Al cerrar el navegador termina la aplicacin. Como puede ver en este ejemplo las aplicaciones de formularios Web son similares a las aplicaciones de Windows. Sin embargo, las aplicaciones de formularios Web tienen las siguientes diferencias significativas: Herramientas. Los formularios Web no pueden usar controles Windows estndar. En su lugar usan controles de servidor, controles HTML, controles de usuario o controles creados especialmente para formularios Web. 18

Developing Web Applications

Interface de usuario. La apariencia de un formulario Web la determina el navegador en el que se muestra. Diferentes navegadores (y versiones diferentes del mismo navegador) soportan diferentes caractersticas de HTML, lo que puede cambiar el aspecto y el comportamiento de sus formularios Web. Pero no se alarme demasiado, los controles web manejan la mayor parte de estas diferencias de forma elegante, como ver en el captulo 4, Crear un Interface de Usuario. Tiempo de vida. Los formularios Windows se instancian, existen durante el tiempo necesario y se destruyen. Los formularios Web parecen comportarse de esta misma forma, pero de hecho se instancian, se envan al navegador y se destruyen inmediatamente. Esto significa que todas las variables y objetos declarados en un formulario Web se destruyen tan pronto como se muestra el formulario. Para poder hacer algo interesante necesita guardar informacin en objetos especiales de estado que proporciona ASP.NET. Ver ms sobre objetos de estado en el captulo 3, Trabajar con Objetos Web. Ejecucin. Las partes ejecutables de una aplicacin Web residen en un servidor Web. De esta forma, las aplicaciones Web son de algn modo la aplicacin cliente/Servidor definitiva: el nico software instalado en el lado cliente es el navegador, y todo el interface de usuario y lgica de negocios corren en el servidor. Toda la comunicacin entre el cliente y el servidor se producen mediante HTML. Esto significa que incluso las aplicaciones Web sofisticadas representan un riesgo de seguridad escaso para el cliente y por tanto pasan a travs de los firewall sin problemas. La estructura fsica de una aplicacin Web y donde se produce el procesamiento se explican en el apartado 3 de este captulo.

2.1.5 Archivos de un proyecto de formulario Web


El formulario Web es solo uno de los once archivos que genera Visual Studio .NET cuando crea un nuevo proyecto de formulario Web. La tabla 2-1 describe el cometido de cada uno de estos archivos. Visual Studio .NET crea estos archivos para cada nuevo proyecto. Solo los archivos en negrita se ven en el explorador de soluciones.
Tabla 2. 1: Archivos de proyecto Web Forms
Nombre de Archivo AssemblyInfo, AssembyInfo.csvb Global.asax Global.asax.vb, Global.asax.cs Styles.css Web.config Contiene Todas las opciones de generacin del proyecto, incluyendo versin, nombre de la compaa, GUID, opciones del compilador, etc. Sucesos globales que se producen en la aplicacin Web, como al iniciar o detener la aplicacin. Solo puede haber uno por proyecto y debe estar en el directorio raz del mismo. Cdigo utilizado en Global.asax. Este archivo no se muestra en el explorador de soluciones. Definiciones de estilos para utilizar en el HTML generado por el proyecto Opciones que utiliza el servidor Web cuando procesa este proyecto. Estas opciones determinan cmo se informa de los errores, qu tipo de identificacin de usuario utilizar, etc. Solo puede haber uno por proyecto y se encuentra en la raz del mismo. Descripcin de servicios Web que proporciona este proyecto Descripcin visual de un formulario Web. Cdigo que responde a los sucesos en el formulario Web. De forma predeterminada, este archivo no se muestra en el explorador de soluciones. Recursos XML que utiliza el formulario Web. No se muestra en el explorador de soluciones. Archivo de proyecto que recoge los archivos y opciones usados en tiempo de diseo. No se muestra en el explorador de soluciones Preferencias Web para el proyecto en tiempo de diseo. No se muestra en el explorador de soluciones.

Nombreproyecto.disco
WebForm1.aspx WebForm1.aspx.vb, WebForm1.aspx.cs WebForm1.aspx.resx

Nombreproyecto.vbproj, Nombreproyecto.csproj Nombreproyecto.vbproj.webinfo, Nombreproyecto.csproj.webinfo

Adems de los archivos de la tabla 2.1 los proyectos de aplicacin Web pueden contener cualquier otro tipo de archivo. Los tipos principales de archivos que se aadirn a un proyecto de aplicacin Web se muestran en la tabla 2.2. Los proyectos de aplicacin Web a menudo incluirn estos diferentes tipos de archivos fuente:
Tabla 2. 2: Tipos de archivo para proyectos de Formulario Web
Extensin .asxp Elemento de Proyecto Formulario Web Descripcin Cada formulario Web constituye una pgina Web ASP.NET. Las aplicaciones pueden tener uno o ms formularios Web. Los formularios Web tienen archivos de cdigo asociados con la extensin .aspx.vb (Visual Basic) o .aspx.cs (Visual C#) Las pginas Web que no tienen cdigo de servidor aparecen como pginas HTML. El cdigo que define los objetos de la aplicacin se almacena en clases Los controles de usuario construidos a partir de otros formularios Web y controles de servidor en Visual Studio .NET Crea un esquema XML con las clases DataSet.

.htm .vb o .cs .ascx .xsd

Pgina HTML Clase o mdulo Control de usuario

DataSet

19

MCAD/MCSD

2.1.6 Archivos en una aplicacin Web


Cuando se genera un proyecto de formularios Web Visual Studio .NET compila todo el cdigo fuente en un ejecutable (DLL) y lo coloca en un directorio /bin. La parte visual de la aplicacin permanece como archivos aspx y html, como se ve en la figura 2.1. En la figura, cuando un navegador solicita la pgina de inicio (http://www.mysite.com/Hello.aspx) de la aplicacin, IIS arranca el ejecutable de la aplicacin (Hello.dll) y genera una respuesta. En este caso la respuesta consiste en mostrar la pgina definida en Hello.dll. Si se produce un suceso, como la pulsacin del ratn, en la pgina, se enva de vuelta al servidor, donde es manejada por la DLL de la aplicacin. Los dos apartados siguientes tratan los detalles de manejo de los sucesos y donde se produce el procesamiento.

Fig. 2. 1: Archivos en una Aplicacin Web

2.2 Responder a sucesos


En esta leccin aprender sobre los sucesos en el ciclo de vida de una aplicacin Web y en qu se diferencia este ciclo de vida del de una aplicacin Windows. Los sucesos de aplicacin Web se producen a nivel aplicacin, pgina y control de servidor. La secuencia de estos sucesos y cmo se ejecutan afecta a cmo se responde a ellos en el cdigo.

2.2.1 Sucesos en el ciclo de vida de una aplicacin Web


Una aplicacin Web vive mientras tiene sesiones activas, mientras que los formularios Web viven escasamente un momento. La vida de una aplicacin Web comienza cuando un navegador solicita su pgina de inicio. En este momento entra en accin el servidor Web, arrancando el ejecutable (DLL) que responde a la peticin. El ejecutable crea una instancia del formulario Web solicitado, genera el HTML para responder a la peticin y enva la respuesta al navegador. Entonces destruye la instancia del formulario Web. Cuando el navegador tiene el HTML generado el usuario puede escribir en cajas de texto, seleccionar botones de opcin y realizar otras tareas hasta que lance un suceso de reenvo, como pulsar un botn. Los sucesos de reenvo hacen que el navegador enve los datos de la pgina (estado de vista) al servidor para procesar el suceso. Cuando el servidor recibe el estado de vista crea una nueva instancia del formulario Web, rellena los datos del estado de vista y procesa el suceso que ha ocurrido. Tan pronto como el servidor termina enva el HTML resultante al navegador y destruye la instancia del formulario Web. Cuando el usuario termina y cierra el navegador o va a otro sitio Web, la sesin de usuario termina; si no hay sesiones de otros usuarios, la aplicacin termina. Esto no siempre funciona bien. ASP.NET gestiona la memoria mediante recoleccin de basura en lugar de cuenta de referencias, como hace OLE. La recoleccin de basura significa que peridicamente el servidor recorre las referencias entre objetos. Cuando localiza un objeto que no est en uso se deshace del objeto y recupera la memoria. Esto significa que no se sabe exactamente cundo se va a producir el suceso Application_End.

2.2.2 Conservar datos en un formulario Web


Como los formularios Web tienen tiempos de vida muy cortos ASP.NET realiza unos pasos especiales para preservar los datos introducidos en controles de un formulario Web. Los datos introducidos en cada control se envan con cada peticin y se restauran a los controles en Page_Init. Los datos en estos controles estn entonces disponibles en el suceso Page_Load. Los datos que ASP-NET preserva entre llamadas forman el estado de vista del formulario Web. El estado de vista de un formulario Web est disponible solo dentro del mismo formulario. Para que los datos introducidos en un formulario estn disponibles para otros formularios de la aplicacin es necesario grabar los datos en una variable de estado en los objetos Application o Session. Estos objetos proporcionan dos niveles de alcance: Variables de estado Application. Estn disponibles para todos los usuarios de una aplicacin. Puede pensar en el estado Application como datos globales multiusuario. Todas las sesiones pueden leerlas y escribirlas. Variables de estado Session. Estn disponibles solo para una sesin (usuario). El estado Session es como los datos globales en una aplicacin Windows estndar. Solo la sesin actual tiene acceso a su estado Session. Las variables de estado Application y Session no se declaran de la misma forma que las variables ordinarias, sino que se crean en cdigo sobre la marcha. Por ejemplo, el siguiente cdigo graba el nmero de pulsaciones de botn en el estado Session:

20

Developing Web Applications

Visual Basic .NET


Private Sub Button1_Click(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles Button1.Click Graba el nmero de pulsaciones en el estado de sesin Session(Clicks) = Session(Clicks) + 1 Muestra el nmero de pulsaciones Response.Write(Nmero de pulsaciones: & session(Clicks)) End Sub

Visual C#
//En Global.asax.cs protected void Session_Start(Object sender, EventArgs e){ //Inicializa la variable de estado de sesin Clicks Session[Clicks] = 0; } private void Button1_Click(Object sender, System.EventArgs e){ //Graba el nmero de pulsaciones en el estado de sesin Session[Clicks] = (int)Session[Clicks] + 1; //Muestra el nmero de pulsaciones Response.Write(Nmero de pulsaciones: + Session[Clicks] + <br>); }

Puede guardar cualquier tipo de datos en un variable de estado, desde un entero a objetos completos. Como las variables de estado son datos globales necesita desarrollar estrategias para trabajar con ellas en su aplicacin. El manejo de variables de estado en su aplicacin se trata en profundidad en el captulo 3, Trabajar con Objetos Web. Importante: En Visual C# hay que inicializar las variables de estado Application antes de poder realizar la mayora de operaciones sobre ellas. Por ejemplo, hay que asignar un valor a la variable de estado Clicks antes de poder realizar el moldeo a entero. En caso contrario se recibir un error en tiempo de ejecucin, ya que su estado es nulo.

2.2.3 Sucesos de aplicacin y sesin


Puede escribir cdigo para responder a los sucesos de Application y Session en el archivo Global.asax. Utilice los sucesos de Application para inicializar objetos y datos que quiere tener disponibles para todas las sesiones actuales de la aplicacin Web. Use los sucesos de Session para inicializar datos que quiere mantener a lo largo de sesiones individuales, pero que no quiere compartir entre sesiones. La tabla 2.3 indica los manipuladores de suceso de Application y describe cuando se producen.
Tabla 2. 3: Manipuladores de Suceso de Aplicacin
Nombre del manipulador Se produce cuando: El primer usuario visita la pgina inicial de la aplicacin No hay ms usuarios en la aplicacin Al comienzo de cada peticin al servidor. Un peticin se produce cada vez que un navegador entra en alguna de las pginas de la aplicacin. Al final de cada peticin al servidor. Un nuevo usuario visita la pgina de inicio de la aplicacin. Un usuario abandona la aplicacin, ya sea cerrando su navegador o por exceso de tiempo.

Application_Start Application_End Application_BeguinRequest Application_EndRequest Session_Start Session_End

En formularios Web una sesin es una instancia nica del navegador. Un nico usuario puede tener varias instancias del navegador corriendo en su propia mquina. Si varias instancias visitan la aplicacin, cada una tiene su propia sesin. Para ver cmo se producen los sucesos de Application y Session aada el siguiente cdigo al archivo Global.asax de un proyecto de formulario Web. Visual Basic .NET
Sub Application_Start(ByVal Sender As Object, ByVal e as EventArgs) Registra el inicio de la aplicacin Application(CuentaAplicacion) = Application(CuentaAplicacion) + 1 End Sub Sub Session_Start(ByVal Sender As Object, ByVal e as EventArgs) Cuenta sesiones Application(CuentaSesion) = Application(CuentaSesiones) + 1

21

MCAD/MCSD

Muestra la cuenta de aplicaciones Response.Write(Nmero de Aplicaciones: & _ Application(CuentaAplicacion) & <br>) Muestra la cuenta de sesiones Response.Write(Nmero de Sesiones: & _ Application(CuentaSesion) & <br>) End Sub Sub Session_End(ByVal Sender As Object, ByVal e as EventArgs) Decrementa las sesiones Application(CuentaSesiones) = Application(CuentaSesiones) - 1 End Sub

Visual C#
protected void Application_Start(Object sender, EventArgs e){ //Crea las variables de estado de la aplicacin Application[CuentaAplicacion] = 0; Application[CuentaSesion] = 0; //Registra el inicio de la aplicacin Application[CuentaAplicacion] = (int)Application[CuentaAplicacion] + 1; } protected void Session_Start(Object sender, EventArgs e){ //Cuenta sesiones Application[CuentaSesion] = (int)Application[CuentaSesion] + 1; //Muestra la cuenta de aplicaciones Response.Write(Nmero de aplicaciones: + Application[CuentaAplicacion] + <br>; //Muestra la cuenta de aplicaciones Response.Write(Nmero de sesiones: + Application[CuentaSesion] + <br>; } protected void Session_End(Object sender, EventArgs e){ //Decrementa las sesiones Application[CuentaSesion] + (int)Application[CuentaSesion]; }

Para comprobar estos sucesos ejecute el cdigo anterior, inicie una nueva instancia del navegador y vaya a la direccin. Cada nueva instancia del navegador incremente la cuenta de sesiones, pero la cuenta de aplicaciones siempre es 1. Es importante darse cuenta de que los objetos intrnsecos como Session y Response no estn disponibles en Application_Start. Para usar estos objetos debe esperar a que se produzca el suceso de creacin.

2.2.4 Sucesos de formulario Web


Los sucesos de formulario Web se usan para procesar y mantener datos utilizados en una pgina Web, para responder a la vinculacin de datos y para manejar excepciones en una pgina Web. Los sucesos de la tabla 2-4 se producen en el orden mostrado. Los procedimientos de suceso con los que ms trabajar en su cdigo son Page_Load y Page_Error.
Tabla 2. 4: Sucesos de Formulario Web
Nombre del manipulador Se produce cuando: Los controles de servidor se cargan e inicializan a partir del estado de vista. Es el primer paso en el ciclo de vida del formulario Web. Los controles de servidor se cargan en el objeto Page. En este punto est disponible la informacin de estado de vista, de modo que es donde se pone el cdigo para cambiar la configuracin de controles o mostrar texto en la pgina. La aplicacin est a punto de mostrar el objeto Page. Se descarga la pgina de memoria. Se produce una excepcin no controlada. Se aborta una transaccin. Se acepta una transaccin. Un control de servidor en la pgina se vincula con un origen de datos. Se libera el objeto Page en memoria. Es el ltimo suceso en el ciclo de vida del objeto Page.

Page__Init Page_Load

Page_PreRender Page_Unload Page_Error Page_AbortTransaction Page_CommitTransaction Page_DataBinding Page_Disposed

Puede combinar el suceso Page_Load con la propiedad IsPostBack para inicializar datos la primera vez que un usuario visita un formulario Web. Es similar a un suceso Session_Start, pero se produce a nivel de pgina en 22

Developing Web Applications

lugar de a nivel aplicacin. El siguiente cdigo inicializa un objeto y lo almacena en el estado de sesin la primera vez que se visita una pgina: Visual Basic .NET
Declara un nuevo objeto Dim FlashCard as New FlashCardClass() Private Sub Page_Load(ByVal Sender As System.Object, _ ByVal e As System.EventArgs) Handles MyBase.Load Si es la primera vez que se visita la pgina If Not Page.IsPostback Then Baraja las tarjetas FlashCard.Baraja() Almacena el objeto en una variable de sesin Session(FlashCard) = FlashCard End If Recupera la variable de sesin FlashCard = Session(FlashCard) RefreshDisplay; End Sub

Visual C#
//Declara un nuevo objeto FlashCard FlashCardClass FlashCard = new FlashCardClass(); private void Page_Load(object sender, System.EventArgs e){ if(!isPostBack){ //Baraja las tarjetas FlashCard.Baraja(); //Almacena el objeto en una variable de sesin Session[FlashCard] = FlashCard; } //Recupera la variable de sesin FlashCard = (FlashCardClass)Session[FlashCard]; RefreshDisplay(); }

Los otros sucesos de pgina permiten modificar la apariencia de la pgina y responder a sucesos de datos. Vinculacin de datos, procesamiento de transacciones y trazado se tratan en mayor detalle en captulos posteriores.

2.2.5 Sucesos de controles de servidor


Los controles de servidor, como Button, TextBox, y DropDownList tienen sus propios conjuntos de sucesos que se producen en respuesta a acciones del usuario. Sin embargo, no todos los sucesos de control de servidor se crean igual. Hay tres tipos de sucesos de control de servidor: Sucesos de reenvo: Estos sucesos hacen que se enve la pgina Web al servidor para procesamiento inmediato. Los sucesos de reenvo afectan a las prestaciones aparentes porque lanzan una ida y vuelta al servidor. Sucesos en cach: Estos sucesos se almacenan en el estado de vista de la pgina para ser procesados cuando se produzca un suceso de reenvo. Sucesos de validacin: Estos sucesos se manejan en la pgina sin envo o almacenamiento en cach. Los controles de validacin de servidor usan este tipo de sucesos

Fig. 2. 2: Secuencia de Sucesos en un Formulario Web

La figura 2.2 muestra la secuencia de sucesos de control de servidor en un formulario Web. Los controles de validacin se evalan antes de enviar la pgina al servidor. Cuando se enva la pgina se gestionan Page_Init y Page_Load, despus los sucesos en cach y finalmente el suceso que caus el envo de la pgina. Los controles Button, LinkButton e ImageButton causan sucesos de reenvo. Los controles TextBox, DropDownList, ListBox, RadioButton y CheckBox proporcionan sucesos en cach; sin embargo puede cambiar este comportamiento cambiando su propiedad AutoPostBack a True. Para ver cmo interactan los sucesos de validacin, en cach y de reenvo cree un formulario con controles de servidor TextBox, RequiredFieldValidator y Button. De a la propiedad ControlToValidate del RequiredFieldValidator el valor TextBox1 y aada el siguiente cdigo a los manipuladores de suceso del TextBox y el Button.

23

MCAD/MCSD

Visual Basic .NET


Private Sub Button1_Click(ByVal sender As System.Object, _ ByVal e as System.EventArgs) Handles Button1.Click Response.Write(Pulsado el botn <br>) End Sub Private Sub TextBox1_TextChanged(ByVal sender As System.Object, _ ByVal e as System.EventArgs) Handles TextBox1.TextChanged Response.Write(Texto cambiado <br>) End Sub

Visual C#
private void Button1_Click(object sender, System.EventArgs e){ Response.Write(Pulsado el botn <br>); } private void TextBox1_TextChanged(object sender, System.EventArgs e){ Response.Write(Texto cambiado <br>); }

Si deja la caja de texto en blanco y pulsa el botn se muestra el RequiredFieldValidator no se procesa ningn otro suceso en la pgina y la pgina no se enva al servidor. Si escribe en la caja de texto y pulsa el botn la pgina se enva al servidor, y se procesa el suceso TextChanged antes que el suceso Click.

2.3 Dnde se hace el procesamiento?


Como sabe por la leccin anterior, las aplicaciones Web corren en un servidor. Pero las aplicaciones Web no son como las aplicaciones Windows, que se inician cuando un usuario arranca un ejecutable y terminan cuando el usuario cierra la aplicacin. En cambio, las aplicaciones Web se inician cuando un navegador pide una pgina Web y terminan cuando no se hacen ms peticiones. Para manejar esta diferencia las aplicaciones Web usan IIS para gestionar sus procesos en el servidor. En esta leccin aprender cmo determina IIS qu pginas Web son parte de una aplicacin concreta, cmo se ejecutan las DLL de las aplicaciones en el servidor, y cmo determina IIS cuando cerrar una aplicacin.

2.3.1 Establecer los lmites de aplicacin


IIS define una aplicacin Web como cualquier archivo que se ejecuta dentro de un conjunto de directorios de un sitio Web. Los lmites de la aplicacin los determina su estructura de directorios. El lmite de la aplicacin comienza en un directorio que contiene la pgina de inicio de la aplicacin y termina en su ltimo directorio subordinado. Cuando Visual Studio .NET crea un nuevo proyecto de aplicacin Web crea un nuevo directorio para el proyecto e identifica el primer formulario Web creado en el proyecto (Webform1.aspx) como pgina de inicio. Una pgina de inicio es la pgina designada por Visual Studio como primera pgina a mostrar en la aplicacin. Todos los directorios subordinados, como /bin, son parte de la aplicacin. Si el diseo de la aplicacin cambia durante el desarrollo o si quiere ejecutar rpidamente la pgina actual durante el depurado, puede que quiera cambiar la pgina de inicio de la aplicacin. Para designar un formulario Web o pgina HTML diferente como pgina de inicio siga estos pasos. 1. En la ventana Proyecto seleccione el formulario Web o pgina HTML que quiere indicar como pgina de inicio de la aplicacin. 2. En el men Proyecto seleccione Proyecto Web y Establecer como Pgina de Inicio. Visual Studio .NET usar la pgina seleccionada como primera a mostrar de la aplicacin. Cada proyecto que se crea tiene su propia pgina de inicio, y por tanto es una nica aplicacin. Si quiere combinar varios proyectos en una aplicacin Web puede organizarlos usando IIS. Para incluir una aplicacin Web subordinada como parte de una aplicacin nica mayor siga estos pasos: 1. En IIS, seleccione la aplicacin subordinada que se va a incluir como parte de la aplicacin contenedor. 2. En el men Accin seleccione Propiedades. IIS muestra el dilogo de propiedades de la aplicacin. 3. Pulse Quitar. Esto elimina el punto inicial de la aplicacin y por tanto la incluye como parte de la aplicacin que se encuentra en el nivel inmediato superior de la jerarqua. Pulse Aceptar para confirmar el cambio y volver a IIS. Igualmente, en ocasiones querr romper una aplicacin grande, con varios directorios, en aplicaciones menores debido a cambios de diseo. Para romper una aplicacin con varios directorios en aplicaciones menores siga estos pasos: 1. En IIS, seleccione el directorio subordinada que se convertir en nueva aplicacin Web. 24

Developing Web Applications

2. En el men Accin seleccione Propiedades. IIS muestra el dilogo de propiedades de la aplicacin. 3. Pulse Crear para que el directorio se convierta en punto de inicio de aplicacin. Pulse Aceptar para confirmar el cambio y volver a IIS. El cambio en los lmites de la aplicacin puede afectar a las variables de estado Application. Es importante darse cuenta de que todas las DLL dentro de los lmites de una aplicacin tienen acceso al mismo estado Application. Esto puede causar interacciones inadvertidas entre DLL,s si no se desarrollan tenindolo en cuenta.

2.3.2 Gestin de procesos


Es importante establecer los lmites de aplicacin porque IIS los usa para determinar cmo se ejecuta la aplicacin en el servidor. IIS le da tres opciones para la forma de ejecutar la aplicacin Web. En proceso con IIS (Inetinfo.exe): Esta opcin mejora las prestaciones porque todas las llamadas se hacen dentro del proceso; sin embargo, no ofrece proteccin. Si una aplicacin falla, puede corromper la memoria y afectar a Inetinfo.exe, as como a otras aplicaciones que corren en el proceso. Agrupada con otros procesos de aplicacin Web en DLLHost.exe: Es la opcin predeterminada y proporciona un equilibrio entre proteccin y prestaciones. Si una aplicacin falla puede afectar a otra aplicacin del grupo, pero no a Inetinfo.exe. Aislada en su propia instancia de DLLHost.exe: Las aplicaciones aisladas no afectan a otras aplicaciones ni son afectadas por ellas. Sin embargo, las llamadas a otras aplicaciones deben cruzar lmites de proceso, y esto afecta a las prestaciones. Para establecer la forma en que IIS ejecuta su aplicacin siga estos pasos: 1. En IIS seleccione el directorio que contiene el punto de inicio de la aplicacin 2. En el men Accin seleccione Propiedades. IIS muestra el dilogo de propiedades de la aplicacin 3. Seleccione la opcin adecuada en la lista desplegable Permisos de ejecucin. Pulse Aceptar para confirmar el cambio volver a IIS. Para asegurar la fiabilidad del servidor ejecute las aplicaciones con proteccin agrupada o aislada. La opcin en proceso es principalmente un artefacto de versiones anteriores de IIS, que solo proporcionaba este modelo de proceso. La opcin agrupada es la predeterminada para nuevas aplicaciones, y es la que se usar para la mayor parte de las aplicaciones Web porque permite que las aplicaciones accedan a otros componentes en el proceso de agrupamiento en lugar de necesitar que se clasifiquen las llamadas para acceso fuera de proceso. La opcin aislada proporciona la mayor proteccin contra aplicaciones errticas; sin embargo, precisa que las llamadas a otras aplicaciones sean clasificadas, lo que daa las prestaciones. Hay un lmite prctico de 10 procesos aislados por servidor, de modo que solo se debe usar esta opcin para aplicaciones crticas.

2.3.3 Determinar cuando termina una aplicacin


Cuando un usuario solicita una pgina por primera vez IIS inicia la aplicacin Web, si no est corriendo ya, y crea una sesin para este usuario. Todas las peticiones posteriores hechas por el usuario son parte de la misma sesin. Las sesiones son importantes por dos razones: Permiten que ASP.NET mantenga datos especficos del usuario llamados estado Session. Los estados Session y Application se trataron en el apartado 2 de este captulo. Determinan cuando termina la aplicacin. Cuanto termina la ltima sesin, IIS finaliza la aplicacin. La duracin de una sesin viene determinada por un valor de tiempo lmite establecido en el archivo web.config del proyecto, con un valor predeterminado de 20 minutos. Esto significa que 20 minutos despus de que el usuario haga su ltima peticin a una aplicacin, la sesin de usuario termina. Cuando no hay ms sesiones, la aplicacin termina. Recuerde que IIS define una aplicacin Web como cualquier archivo que se ejecuta dentro de un conjunto de directorios en un sitio Web. De modo que si un usuario solicita cualquier de los archivos .aspx o .htm del conjunto de directorios de la aplicacin dentro del plazo de 20 minutos, se mantiene la sesin de usuario. Nota: Solo se tiene un control indirecto sobre el momento de finalizacin de la aplicacin mediante el tiempo lmite de sesin. Es importante comprender esto porque controla el ciclo de vida de la aplicacin en el servidor. La reduccin del valor del tiempo lmite de sesin puede liberar recursos en el servidor porque los datos de sesin expiran ms rpidamente. Sin embargo, establecer un valor demasiado bajo puede hacer que las sesiones terminen mientras estn en uso, lo que probablemente causar errores en la aplicacin. Para cambiar el valor de tiempo lmite de sesin siga estos pasos: 25

MCAD/MCSD

1. Abra el proyecto en Visual Studio .NET 2. Abra el archivo Web.config pulsando sobre el en la ventana del Explorador de Soluciones 3. Edite el valor de la variable timeout en la siguiente lnea del archivo;
<sessionState mode=InProc stateConnectionString=tcpip=127.0.0.1:42424 sqlConnectionString=data source=127.0.0.1:user id=sa;password= cookieless=false timeout=20 />

4. Grabe el archivo

2.4 Resumen
Las aplicaciones Web usan formularios Web para crear un interface de usuario que se presenta por medio de un navegador Internet en el ordenador del usuario El cdigo y recursos que responden a sucesos y realizan tareas tiles reside y corre en el servidor Web que aloja la aplicacin. Como las aplicaciones Web estn distribuidas entre un cliente y un servidor, hay cuatro diferencias significativas entre programacin para la Web y programacin para Windows. o Las aplicaciones Web usan controles de servidor y controles HTML en lugar de controles Windows o Las aplicaciones Web se muestran en un navegador Web en lugar de su propia ventana o Los formularios Web no son persistentes mientras se muestran. Debe preservar los datos persistentes en una variable de estado durante los sucesos de pgina y control. o El procesamiento se produce en el servidor y los datos se intercambian mediante un ciclo de peticiones y respuestas Las aplicaciones Web estn controladas por sucesos y los sucesos se producen a nivel aplicacin, pgina y control de servidor. Los sucesos de controles de servidor son de tres tipos, y se producen en el siguiente orden o Los sucesos de validacin se producen antes de enviar la pgina al servidor o Los sucesos en cach se recogen mientras se muestra la pgina y se procesan una vez que la pgina enva una peticin al servidor. o Los sucesos de reenvo hacen que la pgina enve una peticin al servidor, pero su procedimiento de suceso se procesa en ltimo lugar entre todos los sucesos. Los lmites de una aplicacin Web los determina su estructura de directorios. Los lmites de la aplicacin afectan al alcance de los datos almacenados en el estado Application y permiten especificar el proceso en el que el servidor ejecuta la aplicacin. Para crear el directorio raz de la aplicacin, configurar los lmites de aplicacin y determinar el proceso en que se ejecuta se utiliza IIS.

2.5 Prctica: Crear una aplicacin Web sencilla


En esta prctica crear la aplicacin FlashCards. FlashCards es una aplicacin sencilla, con un solo formulario, que muestra problemas matemticos y evala el resultado introducido como las tarjetas de clculo rpido usadas en una clase de matemticas en una escuela elemental1. Para completar la aplicacin FlashCards crear un formulario Web, aadir controles de servidor al formulario y controlar estos controles desde el procedimiento de suceso Page_Load.

2.5.1 Crear el interface de usuario


En este ejercicio iniciar el proyecto FlashCards y crear el interface de usuario aadiendo controles de servidor al formulario Web. Para Crear un Nuevo Proyecto de Aplicacin Web 1. Abra un nuevo proyecto de aplicacin ASP.NET. En la caja de dilogo Nuevo Proyecto escriba el nombre FlashCards y pulse aceptar 2. En la ventana Propiedades cambie el nombre de WebForm1.aspx a FlashCards.aspx Para Aadir los Controles al Interface de Usuario Aada controles de servidor al formulario Web y defina las siguientes propiedades: Control Label1 Tipo de Control Label Propiedad ID Font Text ID Font Valor lblFeedBack Arial, Bold, XXL Flash Cards lblFirst Arial, Bold, XXL

Label2

Label

Estn locos estos yanquis. (N del T).

26

Developing Web Applications

Label3 <HR> TextBox1

Label Horizontal Rule TextBox

ID Font Size Color ID AutoPostBack Font

LblSecond Arial, Bold, XXL 4 #000000 txtAnswer True Arial, Bold, XXL

Consejo: Si quiere crear varios controles con propiedades similares cree el primer control, configure sus propiedades y copie y pegue para crear nuevos controles. En formularios Web, esto no crea un array de controles como en formularios Windows.

2.5.2 Crear una clase llamada FlashCardClass


En este ejercicio crear una clase que contendr la lgica y los datos que usa la aplicacin FlashCards. Un clase es una definicin de un objeto usado para realizar una tarea en un programa. En el captulo 3, Trabajar con Objetos Web hay ms informacin sobre programacin orientada a objetos. La clase FlashCardClass creada aqu genera problemas matemticos aleatorios que se mostrarn en el formulario Web. Esta es la lgica que usa la aplicacin. En esta aplicacin, y en la mayora, la lgica (FlashCardClass) est separada del interface de usuario (formulario Web). Para Crear una Clase 1. En el men Proyecto seleccione Agregar Clase. Visual Studio .NET muestra la caja de dilogo Agregar Nuevo Elemento. Llame a la clase FlashCardClass y pulse Abrir. 2. En la ventana de cdigo, aada el siguiente: Visual Basic .NET
Public Dim Dim Dim Class FlashCardClass mintFirstNumber, mintSecondNumber As Integer mstrOp As String = "+" mrndNumber As Random

Public Sub New() ' Inicializa el objeto generador de nmeros aleatorios. mrndNumber = New Random() End Sub Public Sub Shuffle(Optional ByVal Min As Integer = 1, _ Optional ByVal Max As Integer = 12) ' Obtiene los nmeros aleatorios mintFirstNumber = mrndNumber.Next(Min, Max) mintSecondNumber = mrndNumber.Next(Min, Max) End Sub Public ReadOnly Property FirstNumber() Get FirstNumber = mintFirstNumber End Get End Property Public ReadOnly Property SecondNumber() Get SecondNumber = mintSecondNumber End Get End Property Public Property Operation() As String Get Operation = mstrOp End Get Set(ByVal Value As String) mstrOp = Value End Set End Property

27

MCAD/MCSD

' Calcula la respuesta segn la operacin actual. Public Function Answer() As Integer Select Case mstrOp Case "+" Answer = mintFirstNumber + mintSecondNumber Case "x", "*" Answer = mintFirstNumber * mintSecondNumber Case "-" Answer = mintFirstNumber - mintSecondNumber End Select End Function End Class

Visual C#
public class FlashCardClass{ int mintFirstNumber, mintSecondNumber; string mstrOp = "+"; Random mrndNumber; public FlashCardClass(){ // Inicializa el objeto generador de nmeros aleatorios. mrndNumber = new Random(); } public void Shuffle(int Min, int Max){ // Obtiene los nmeros aleatorios. mintFirstNumber = mrndNumber.Next(Min, Max); mintSecondNumber = mrndNumber.Next(Min, Max); } // Baraja sin parmetros, predeterminados Min = 0, Max = 12. public void Shuffle(){ // Obtiene los nmeros aleatorios. mintFirstNumber = mrndNumber.Next(0, 12); mintSecondNumber = mrndNumber.Next(0, 12); } public int FirstNumber{ get{return mintFirstNumber;} } public int SecondNumber{ get{return mintSecondNumber;} } public string Operation{ get{return mstrOp;} set{mstrOp = value;} } // Calcula la respuesta en base a la operacin actual. public int Answer(){ switch(mstrOp){ case "+": return mintFirstNumber + mintSecondNumber; case "x": return mintFirstNumber * mintSecondNumber; case "*": return mintFirstNumber * mintSecondNumber; case "-": return mintFirstNumber - mintSecondNumber; default : return 0; } } }

2.5.3 Almacenar un objeto FlashCardClass en Session


En este ejercicio aadir al archivo Global.asax cdigo para inicializar una variable de estado de sesin que contenga un objeto FlashCardClass que utilizar el formulario Web. El archivo Global.asax contiene los sucesos que se producen cuando se inicia la aplicacin y cuando se inician nuevas sesiones. El objeto FlashCardClass se almacena en una variable de sesin de modo que se mantiene durante toda la sesin de usuario. Para crear una variable de estado de sesin 1. En la ventana Proyecto, pulse dos veces sobre el archivo Global.asax y pulse el enlace haga click aqu para cambiar a vista de cdigos. 2. En la ventana de cdigo, aada el siguiente procedimiento de suceso Session_Start.

28

Developing Web Applications

Visual Basic .NET


Sub Session_Start(ByVal Sender As Object, ByVal e As EventArgs) Crea un nuevo objeto FlashCard Dim FlashCard As New FlashCardClass() Almacena el objeto en una variable de sesin Session(FlashCard) = FlashCard End Sub

Visual C#
protected void Session_Start(Object sender, EventArgs e){ //Crea un nuevo objeto FlashCard FlashCardClass FlashCard = new FlashCardClass(); //Almacena el objeto en una variable de sesin Session[FlashCard] = FlashCard; }

2.5.4 Utilizar FlashCardClass en los sucesos del formulario Web


En este ejercicio aadir cdigo al formulario Web para utilizar el objeto FlashCardClass almacenado en la variable de estado de sesin. De esta forma se enlaza la lgica (FlashCardClass) con la interface de usuario (FlashCard.aspx). Para Usar el Objeto FlashCardClass En los Procedimientos de Suceso del Formulario Web 1. Abra el mdulo de cdigo del formulario Web en la ventana de cdigo pulsando dos veces sobre cualquier parte del formulario Web. 2. Declare a nivel mdulo una variable que recibir el objeto del estado de sesin. Visual Basic .NET
Dim FlashCard As FlashCardClass

Visual C#
FlashCardClass FlashCard;

3. En el procedimiento del suceso Page_Load aada el siguiente cdigo para asignar la variable de estado de sesin a la variable FlashCard que acaba de crear. Visual Basic .NET
Private Sub Page_Load(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles MyBase.Load Recupera la variable de sesin FlashCard = Session(FlashCard) RefreshDisplay End Sub

Visual C#
private void Page_Load(object sender, System.EventArgs e){ //Recupera la variable de sesin FlashCard = (FlashCardClass)Session[FlashCard]; RefreshDisplay(); }

4. Aada el siguiente cdigo al procedimiento de suceso TextChanged del cuadro de texto Visual Basic .NET
Private Sub txtAnswer_TextChanged(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles txtAnswer.TextChanged If txtAnswer.Text = FlashCard.Answer Then lblFeedback.Text = Correcto Obtiene otro par de nmeros FlashCard.Shuffle() Renueva la salida para mostrar los nuevos nmeros RefreshDisplay() Borra la respuesta txtAnswer.Text = Else lblFeedback.Text = Error, pruebe otra vez End If End Sub

Visual C#
private void txtAnswer_TextChanged(object sender, System.EventArgs e){ if(txtAnswer.Text == FlashCard.Answer().ToString()){ lblFeedback.Text = Correcto; //Obtiene otro par de nmeros FlashCard.Shuffle();

29

MCAD/MCSD

//Renueva la salida para mostrar los nuevos nmeros RefreshDisplay(); //Borra la respuesta txtAnswer.Text =; } else lblFeedback.Text = Error, pruebe otra vez; }

5. Escriba el siguiente procedimiento auxiliar para refrescar la pantalla Visual Basic .NET
Private Sub RefreshDisplay() lblFirst.Text = FlashCard.FirstNumber lblSecond.Text = FlashCard.Operation & FlashCard.SecondNumber End Sub

Visual C#
private void RefreshDisplay(){ lblFirst.Text = FlashCard.FirstNumber.ToString(); lblSecond.Text = FlashCard.Operation + FlashCard.SecondNumber.ToString(); }

6. Ejecute y pruebe la aplicacin (N del T: es necesario pulsar Enter tras escribir la respuesta para provocar el suceso TextChanged) Consejo: El uso de una variable a nivel de formulario para contener los datos almacenados en variables de estado de sesin o aplicacin ayuda a capturar los errores. Visual Studio .NET no impone que se declaren las variables de estado. Escribir mal una variable de estado crea otra nueva, vaca.

2.6 Repaso
Las siguientes preguntas estn pensadas para reforzar informacin clave presentada en este captulo. Si no es capaz de contestar a una pregunta repase la leccin correspondiente e intente de nuevo. Las respuestas a estas preguntas se encuentran en el captulo 16. 1. Explique donde guarda Visual Studio .NET los proyectos de aplicacin Web. 2. Indique las cuatro diferencias principales entre aplicaciones Web y Windows. 3. Describa el ciclo de vida de una aplicacin Web: Cundo se instancian los formularios Web y durante cuanto tiempo existen? 4. Cmo se conservan los datos persistentes, como variables sencillas, en una aplicacin Web? 5. Qu determina los lmites de una aplicacin Web?

30

Developing Web Applications

3 Trabajar con objetos web


En este captulo aprender cmo crear y organizar objetos en Microsoft Visual Studio .NET, usar los objetos que proporciona ASP.NET y guardar objetos y datos entre peticiones a formularios Web. Visual Basic .NET, C# y ASP.NET comparten un marco de trabajo comn, de modo que todas las tcnicas de programacin orientada a objetos que aprenda aqu se aplican a todos los aspectos de la programacin de aplicaciones de formularios Web. Para completar las lecciones de este captulo deber: Estar familiarizado con los aspectos bsicos de los lenguajes de programacin Visual Basic, C# o C++. Esto incluye familiaridad con los conceptos de variables, procedimientos, estructuras de decisin y alcance. Para una introduccin a Visual Basic .NET y C# vea la ayuda de Visual Studio Comprender los sucesos en el ciclo de vida de una aplicacin Web tal como se trat en la leccin 2 del captulo 2, Crear Aplicaciones de Formulario Web

3.1 Fundamentos de los espacios de nombres


Visual Basic .NET y C# proporcionan un conjunto completo de conceptos de programacin orientada a objetos, incluyendo clases abstractas, interfaces y sobrecarga o sustitucin de miembros de clase. Estas caractersticas son fundamentales en el lenguaje y se usan a todo lo ancho del marco de trabajo .NET. Aprendiendo a usar estas caractersticas por si mismo comprender cmo est implementado el marco de trabajo .NET y ser ms capaz de usarlas en sus aplicaciones.

3.1.1 Comprender los espacios de nombres


En el captulo anterior vio en el archivo Global.asax cdigo generado que tena este aspecto: Visual Basic .NET
Imports System Imports System.Web

Visual C#
using System; using System.Web;

Estas sentencias permiten usar cdigo de los espacios de nombres System y System.Web sin especificar los nombres completos. Sin estas sentencias una llamada a un simple mtodo del espacio de nombres System sera as: Visual Basic .NET
System.Array.Sort(strArray)

Visual C#
System.Array.Sort(strArray);

Al incluir el espacio de nombres System al comienzo del cdigo este mtodo de Array se reduce a: Visual Basic .NET
Array.Sort(strArray)

Visual C#
Array.Sort(strArray);

Los espacios de nombres son una forma de organizar el cdigo. Proporcionan proteccin frente a nombres conflictivos, llamados a veces colisiones de espacio de nombres. Esta proteccin es especialmente necesaria en grandes proyectos donde es muy fcil que dos elementos tengan accidentalmente el mismo nombre. Organizando el cdigo en espacios de nombres se reduce la posibilidad de estos problemas. Para crear un espacio de nombres encierre un Class o Module en un bloque Namespace ... End Namespace o namespace{...} Para aadir ms de una clase o mdulo a un espacio de nombres, especifique el mismo nombre de espacio de nombres para todos. La parte en negrita de este cdigo crea un espacio de nombres para el mdulo Strings: Visual Basic .NET
' Nombre de Proyecto: Wombat. Namespace Utils Public Module Strings Public Function Sort(ByVal strText As String, _ Optional ByVal bAlphaOrder As Boolean = True) As String ' Declara e inicializa un array de cadenas. Dim strArray As String() = {""} ' Convierte la cadena en un array usando System.String. strArray = strText.Split(" ") ' Usa System.Array para ordenar. System.Array.Sort(strArray) ' Si no est en orden alfabtico, invierte el array. If Not bAlphaOrder Then ' Usa System.Array para invertir. System.Array.Reverse(strArray) End If

31

MCAD/MCSD

' Devuelve la cadena ordenada. Sort = System.String.Join(" ", strArray) End Function End Module End Namespace

Visual C#
// Project name: Wombat. namespace Utils{ class Strings{ // Coge una cadena, la ordena y devuelve una cadena. public static string Sort(string strText , bool bAlphaOrder){ // Declara e inicializa un array de cadena. string[] strArray = {""}; char[] strSep = {' '}; // Convierte la cadena en un array usando System.String. strArray = strText.Split(strSep); // Usa System.Array para ordenar. System.Array.Sort(strArray); // Si no es orden alfabtico, invierte el array. if (!bAlphaOrder){ // Usa System.Array para invertir. System.Array.Reverse(strArray); } // Devuelve la cadena. return System.String.Join(" ", strArray); } // El mismo mtodo con un parmetro. public static string Sort(string strText){ return Sort(strText, true); } } }

Importante: El ejemplo anterior tambin usa dos espacios de nombres .NET: System.Array y System.String. Los espacios de nombres System son la nueva forma de acceder a funciones a las que anteriormente se acceda mediante el API de Windows por medio de sentencias Declare. Ahora es incluso ms fcil porque Visual Basic .NET, C# y el marco de trabajo .NET usan los mismos tipos de datos escalares y convenciones de paso de parmetros. A diferencia del API de Windows los espacios de nombres System proporcionan un interface orientado a objetos para loas funciones Windows. Si est familiarizado con el API de Windows puede que le lleve tiempo acostumbrarse, pero las ventajas del motor de ejecucin comn para lenguajes y del cdigo administrado son enormes. Como los espacios de nombres son una herramienta de organizacin para el cdigo que querr usar en cualquier parte, son pblicos por definicin. Cuando se usan en el cdigo la referencia tiene la forma: NombreProyecto.NombreEspacio.NombreModulo.NombreMiembro Puede usar cdigo de espacios de nombres en su aplicacin de dos formas. Usando el nombre completamente cualificado del miembro. La parte en negrita del siguiente cdigo llama a la funcin Sort del espacio de nombres Wombat.Util. Visual Basic .NET
Private Sub Button1_Click(ByVal sender as System.Object, _ ByVal e As System.EventArgs) Handles Button1.Click Ordena el texto TextBox1.Text = Wombat.Utils.Strings.Sort(TextBox1.Text) End Sub

Visual C#
private void Button1_Click(object sender, System.EventArgs e){ TextBox1.Text = Wombat.Utils.Strings.Sort(TextBox1.Text); }

Aadir una sentencia Imports en Visual Basic .NET o using en C# al comienzo de la clase o mdulo. Esta sentencia proporciona un atajo para el nombre de miembro ya no es necesario usar el nombre completo. La parte en negrita del siguiente cdigo usa el espacio de nombres Util en el proyecto Wombat

32

Developing Web Applications

Visual Basic .NET


Importa el espacio de nombres del proyecto Wombat Imports Wombat.Utils Public Class WebForm1 Se omiten las declaraciones y cdigo de inicializacin Private Sub Button1_Click(ByVal sender as System.Object, _ ByVal e As System.EventArgs) Handles Button1.Click Ordena el texto TextBox1.Text = Strings.Sort(TextBox1.Text) End Sub End Class

Visual C#
//Importa el espacio de nombres Utils del proyecto Wombat using Wombat.Utils; namespace csNamespaces{ public class WebForm1 : System.Web.UI.Page{ //Se omiten las declaraciones y el cdigo de inicializacin private void Button1_Click(object sender, System.EventArgs e){ TextBox1.Text = Strings.Sort(TextBox1.Text); } } }

Los espacios de nombres utilizan notacin de punto (.) para especificar jerarqua. Considere la siguiente declaracin: Visual Basic .NET
Nombre de proyecto: Wombat Namespace Utils Namespace Types Namespace Digits Public Enum Numeric Zero : Nine End Enum End Namespace End Namespace End Namespace

Visual C#
//Nombre de Proyecto: Wombat namespace Utils{ namespace Types{ namespace Digits{ public Enum Numeric{ Zero, ..., Nine } } } }

Esta declaracin es equivalente a: Visual Basic .NET


Nombre de proyecto: Wombat Namespace Utils.Types.Digits Public Enum Numeric Zero : Nine End Enum End Namespace

Visual C#
//Nombre de Proyecto: Wombat namespace Utils.Types.Digits{ public Enum Numeric{ Zero, ... ,Nine } }

Para usar cualquiera de las dos declaraciones de espacio de nombres anteriores pede usar el nombre completamente cualificado: Visual Basic .NET
Dim numVar As Wombat.Utils.Types.Digits.Numeric

Visual Basic C#
Wombat.Utils.Types.Digits.Numeric numVar;

O puede usar sentencias Imports y Using: Visual Basic .NET


Imports Wombat.Utils.Types.Digits Dim numVar as Numeric

Visual C#
using Wombat.Utils.Types.Digits Numeric numVar

3.1.2 Referencias Frente a Importaciones


Se aaden referencias de proyecto para usar espacios de nombres que estn fuera del proyecto actual. Use sentencias Imports o using para proporcionar una abreviatura para el espacio de nombres. La sentencia Imports o using sencillamente proporciona una forma abreviada para hacer referencia al espacio de nombres en cdigo. 33

MCAD/MCSD

Para aadir una referencia a un proyecto: 1. En el men Proyecto seleccione Agregar Referencia. Visual Studio .NET muestra el cuadro de dilogo Agregar Referencia. 2. Seleccione la referencia que quiere aadir de la lista de componentes .NET, COM o Proyecto. Pulse Aceptar. 3. Visual Studio aade las referencias a la ventana de proyecto.

3.1.3 Clases y mdulos


Los proyectos de Visual Studio almacenan el cdigo en clases y mdulos. Versiones anteriores de Visual Basic introdujeron el concepto de clases y cmo se diferencian de los mdulos de cdigo. Este concepto es el mismo en Visual Basic .NET: se usan las clases para elementos que definen su propio almacenamiento y los mdulos para cdigo que no tiene datos persistentes. Adems, se instancias clases para crear objetos antes de usarlos, mientras que se llama al cdigo de los mdulos directamente. En C#, sin embargo, todo el cdigo est contenido en una clase. Si quiere crear mtodos o propiedades que se puedan llamar sin tener que crear un objeto declare estos elementos como estticos. El mtodo Sort de la clase Utils creado en la seccin anterior muestra el equivalente C# de un mdulo Visual Basic .NET. Visual Basic .NET y C# usan cuatro conceptos clave para trabajar con mdulos y clases. Estos conceptos son nuevos en Visual Basic .NET y, lgicamente, en C#, puesto que es un lenguaje completamente nuevo. Sin embargo los programadores de C++ estarn familiarizados con estos conceptos. La tabla 3.1 describe estos conceptos en ambos lenguajes.
Tabla 3. 1: Conceptos clave de orientacin a objetos
Concepto Definicin En Visual Basic .NET Se define una clase o mdulo usando bloques Class...End Class o Module...End Module. En versiones anteriores esto estaba implcito en el tipo de archivo y solo se poda tener una clase o mdulo por archivo. Hay cinco niveles de acceso a las clases, mdulos y sus miembros: Public, Protected, Friend, Protected Friend y Private. El acceso est explcito en la declaracin del elemento en lugar de oculto en las propiedades del archivo. Las clases pueden heredar miembros de otra y sustituir, ensombrecer o sobrecargar miembros de la clase heredada. Las clases tienen mtodos New y Finalize a los que se llama cuando se crea o destruye un objeto basado en la clase. En Visual C# Las clases se definen con la palabra clave class. Todo el cdigo ejecutable es parte de una clase.

Acceso

Hay cinco niveles de acceso a las clases y sus miembros: public, protected, internal, protected internal y private.

Herencia

Las clases pueden heredar miembros de clases base y sustituir o sobrecargar miembros de la clase heredada. Las clases tienen constructores o destructores a los que se llama cuando se crea o destruye un objeto basado en la clase. Los mtodos constructores tienen el mismo nombre que la clase y los destructores usan el nombre de clase precedido por una tilde (~)

Constructores y Destructores

Clases Abstractas e Interfaces

Puede crear interfaces y clases, mtodos y propiedades abstractos. Los interfaces definen los nombres de miembro y listas de parmetros para las clases que usan el interface. Los miembros abstractos proporcionan los elementos que sern heredados por las clases derivadas de ellos.

Crear clases/mdulos y proporcionar acceso En Visual Basic, use bloques ClassEnd Class y ModuleEnd Module para definir clases y mdulos. En Visual C# use la palabra clave class para definir clases. Puede tener uno o ms clases/mdulos en un solo archivo. Use las palabras clave de acceso usadas en la tabla 3.2 para definir qu otras clases o mdulos pueden usar los miembros de la clase o mdulo actual.
Tabla 3. 2: Niveles de acceso para clases y mdulos
Visual Basic Public Friend Protected Protected Friend Private Visual C# public internal protected protected internal private Disponible para Todos los miembros de todas las clases y proyectos Todos los miembros del proyecto actual Todos los miembros de la clase actual y derivadas en cualquier proyecto. Se puede usar solo en definiciones de miembros, no de clases o mdulos Todos los miembros de la clase actual y derivadas en el proyecto actual. Se puede usar solo en definiciones de miembros, no de clases o mdulos. Disponible solo en la clase actual.

Por ejemplo, la siguiente clase solo est disponible en el proyecto actual. Visual Basic .NET
Friend Class Translator Private mstrText As String

34

Developing Web Applications

' Controla el acceso a las variables a nivel de mdulo. Public Property Text() As String Get Text = mstrText End Get Set(ByVal Value As String) mstrText = Value End Set End Property ' Traduce el valor de la propiedad Text. Public Sub Translate() Dim strWord As String, intCount As Integer Dim arrWords() As String Dim bCaps As Boolean ' Convierte la cadena en un array usando System.String. arrWords = mstrText.Split(" ") For intCount = 0 To UBound(arrWords) ' Comprueba si la palabra usa maysculas. If LCase(arrWords(intCount)) <> arrWords(intCount) Then bCaps = True arrWords(intCount) = LCase(arrWords(intCount)) End If strWord = arrWords(intCount) ' Hace la traduccin. If strWord <> "" Then strWord = Right(strWord, Len(strWord) - 1) & _ Left(strWord, 1) & "ay" ' Vuelve a poner mayscula si es necesario If bCaps Then strWord = UCase(Left(strWord, 1)) & _ Right(strWord, Len(strWord) - 1) End If End If ' Vuelve a poner en el array. arrWords(intCount) = strWord ' Restablece el indicador de maysculas. bCaps = False Next ' Reconstruye la cadena a partir del array. mstrText = String.Join(" ", arrWords) End Sub End Class

Visual C#
internal class Translator{ string mstrText; // Controla el acceso a las variables a nivel de mdulo. public string Text { get{return mstrText;} set{mstrText = value;} } /// Traduce el valor en la propiedad Text public void Translate(){ string strWord; string[] arrWords; bool bCaps = false; // Convierte la cadena en un array usando System.String. arrWords = mstrText.Split(' '); for(int intCount = 0; intCount <= arrWords.GetUpperBound(0); intCount++){ // Cambia a minsculas. strWord = arrWords[intCount].ToLower(); // Comprueba si la palabra usa mayscula. if(!arrWords[intCount].Equals(strWord)) bCaps = true;

35

MCAD/MCSD

// Hace la traduccin. if(strWord != ""){ strWord = strWord.Substring(1,strWord.Length - 1) + strWord.Substring(0,1) + "ay"; // Vuelve a poner mayscula si es necesario. if(bCaps) strWord = strWord.Substring(0,1).ToUpper() + strWord.Substring(1, strWord.Length - 1); } // Coloca la palabra en el array. arrWords[intCount] = strWord; // Restablece el indicador de mayscula. bCaps = false; } // Reconstruye la cadena a partir del array. mstrText = String.Join(" ", arrWords); } }

Puede acceder a la propiedad Text y al mtodo Translate de la anterior clase Translator desde dentro del proyecto donde est incluida, pero no desde otros proyectos. La parte en negrita del siguiente cdigo muestra el uso de estos miembros desde un formulario Web. Visual Basic .NET
Private Sub butTranslate_Click(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles butTranslate.Click Crea un nuevo objeto Translator Dim TranslateText As New Translator() Pone el texto original en el traductor TranslateText.Text = txtInput.Text Hace el trabajo TranslateText.Translate() Muestra el resultado txtOutput.Text = TranslateText.Text End Sub

Visual C#
private void butTranslate_Click(object sender, System.EventArgs e){ //Crea un nuevo objeto Translator Translator TranslateText = new Translator(); //Pone el texto original en el traductor TranslateText.Text = txtInput.Text; //Hace el trabajo TranslateText.Translate(); //Muestra el resultado txtOutput.Text = TranslateText.Text; }

Cuando se examina el cdigo que genera Visual Studio para un formulario Web se observa que los controles de servidor se declaran como protegidos. De forma predeterminada los objetos control de servidor se configuran de modo que solo estn disponibles en el formulario Web actual y el los formularios Web derivados de ste. Herencia: quin deriva? La herencia es el proceso de basar una clase en otra. En este proceso una clase base proporciona mtodos, propiedades y otros miembros a una clase derivada. La ventaja de la herencia es que puede escribir y mantener el cdigo una sola vez en la clase base y reutilizarlo una y otra vez en clases derivadas. Cmo est de familiarizado con la herencia depende del lenguaje de programacin que haya estado utilizando. Visual Basic .NET introduce la herencia en la programacin Visual Basic. Es un enorme paso adelante para el lenguaje y el motivo de que muchas cosas tengan que cambiar entre versiones. Los formularios Windows y los tipos de datos ahora se heredan del marco de trabajo .NET en lugar de ser implementados mediante el motor Ruby de las versiones anteriores de Visual Basic. Ahora encontrar mucha mayor coherencia entre Visual Basic .NET y Windows Los programadores C# que estn familiarizados con C++ probablemente estn muy familiarizados con el concepto de herencia. Sin embargo, C# aade refinamientos que no se encuentran en la sintaxis C++, incluyendo las palabras clave interface, abstract y virtual. Cmo se especifique la herencia depende tambin del lenguaje de programacin. En Visual Basic .NET se usa la sentencia Inherits para que una nueva clase est basada en una existente. En C# se usa la definicin de clase. Las siguientes lneas muestran las diferentes sintaxis en ambos lenguajes. 36

Developing Web Applications

Visual Basic .NET


Public Class ClaseDerivada Inherits ClaseBase End Class

Visual C#
public class ClaseDerivada : ClaseBase { }

Visual Studio utiliza las palabras clave de la tabla 3.3 para crear clases base y derivar nuevas clases a partir de ellas. Las siguientes secciones explican como usar cada una de ellas.
Tabla 3. 3: Generalidades de las palabras clave de herencia
Visual Basic Usada para Basar una clase en otra, heredando los miembros de la clase base. Declarar que un miembro de la clase base se puede sustituir en la derivada Declarar que un miembro de la clase derivada sustituye a uno del mismo nombre en la clase base. new Declarar que un miembro de la clase derivada oculta a uno del mismo nombre en la clase base. abstract Declarar que una clase proporciona una plantilla para clases derivadas, Este tipo de clase se llama clase abstracta y no se puede instanciar. abstract Declarar que un miembro de una clase proporciona una plantilla para miembros derivados. Este tipo de miembro se denomina miembro abstracto y no se le pueden hacer llamadas. base Llamar a un miembro de la clase base desde dentro de la clase derivada. this Llamar a un miembro de la instancia actual de la clase. interface Crear un interface que define los miembros que debe proporcionar una clase. NombreClase : NombreInterface Usar una definicin de interface en una clase. Visual C#

Inherits Overridable Overrides Shadows MustInherit

ClaseDerivada: ClaseBase virtual override

MustOverride MyBase Me Interface Implements

Antes de poder aprender sobre la herencia con ms detalle debe comprender las dos cosas que no puede hacer con ella: No puede heredar de ms de una clase base en la definicin de una clase derivada. El concepto de herencia mltiple existe en muchos lenguajes de programacin orientada a objetos, pero en la prctica no es muy utilizado. Las clases base, sin embargo, se pueden derivar unas de otras de modo jerrquico. No puede derivar una clase formulario Web de una base formulario Web. Incluso aunque los formularios Web se definen como clases, Visual Studio no permite derivar nuevos formularios de los existentes. Sustituir, sobrecargar y ocultar miembros Una clase derivada hereda los miembros de su clase base. Si la clase derivada define un miembro con la misma firma, el miembro derivado sustituye al miembro base. La firma de un miembro incluye su nombre, lista de parmetros, tipos de parmetros y tipo de devolucin. Si una clase derivada define un miembro con el mismo nombre, pero una lista de parmetros, tipos de parmetros o tipo de devolucin diferentes, el miembro derivado sobrecarga u oculta el miembro base. Un miembro sobrecarga a otro miembro si el miembro base sigue estando disponible. Un miembro oculta a otro miembro si el miembro derivado reemplaza al miembro base. En el siguiente ejemplo la clase Sphere est basada en la clase Circle. En Visual Basic .NET los miembros que se pueden sustituir se deben declarar como Overridable (1), En visual C# se deben declarar como virtual (1), Esta es la clase Circle: Visual Basic .NET
Public Class Circle Private sxCenter, syCenter As Single Private sRadius As Single Public Property Top() As Single Get Top = sxCenter - sRadius End Get Set(ByVal Value As Single) sxCenter = Value + sRadius End Set End Property Public Property Left() As Single Get Left = syCenter - sRadius End Get Set(ByVal Value As Single) syCenter = Value + sRadius End Set End Property

37

MCAD/MCSD

Public Overridable Function Area() As Single Area = System.Math.PI * (sRadius ^ 2) End Function Public Function Perimeter() As Single Perimeter = 2 * sRadius * System.Math.PI End Function Public Property Radius() As Single Get Radius = sRadius End Get Set(ByVal Value As Single) sRadius = Value End Set End Property

' (1)

Public Overridable Sub Center(ByVal X As Single, ByVal Y As Single) ' (1) sxCenter = X syCenter = Y End Sub End Class

Visual C#
public class Circle{ float fxCenter, fyCenter, fRadius; // Constructor. public Circle(){ // Inicializa variables internas. fxCenter = 0; fyCenter = 0; fRadius = 0; } public float Top{ get{return fxCenter - fRadius;} set{fxCenter = value + fRadius;} } public float Left{ get{return fyCenter - fRadius;} set{fyCenter = value + fRadius;} } public virtual float Area(){ // (1) return (float)(System.Math.PI * Math.Pow((double)fRadius, 2)); } public float Perimeter(){ return 2 * fRadius * (float)System.Math.PI; } public float Radius{ get{return fRadius;} set{fRadius = value;} } public virtual void Center(float X, float Y){ fxCenter = X; fyCenter = Y; } } // (1)

La clase Sphere hereda todos los mtodos y propiedades definidos en Circle (1). Sphere sustituye el mtodo Area (2) porque la esfera utiliza una frmula diferente para su clculo. Sphere oculta el mtodo Center porque las esferas tienen una coordenada adicional (z) y no queremos que los usuarios accidentalmente den valores a X e Y sin drselo a Z. Observe que Sphere utiliza las palabras clave MyBase de Visual Basic o base de C# (4) para llamar al mtodo Center de la clase base desde el mtodo que lo oculta. Visual Basic .NET
Public Class Sphere Inherits Circle ' (1) Private sCenter As Single

38

Developing Web Applications

Public Overrides Function Area() As Single Area = 4 * System.Math.PI * (MyBase.Radius ^ 2) End Function Public Shadows Sub Center(ByVal X As Single, _ ByVal Y As Single, ByVal Z As Single) MyBase.Center(X, Y) ' (4) sCenter = Z End Sub Public Function Volume() As Single Volume = (4 / 3) * System.Math.PI * (Radius ^ 3) End Function Public Property Front() As Single Get Depth = sCenter - Radius End Get Set(ByVal Value As Single) sCenter = Value + MyBase.Radius End Set End Property End Class

' (2)

' (3)

Visual C#
public class Sphere : Circle{ float fCenter; // (1)

// Constructor. public Sphere(){ // Inicializa variable interna. fCenter = 0; } public override float Area(){ return (float)(4 * Math.PI * Math.Pow((double)base.Radius, 2)); } public new void Center(float X, float Y){ this.Center(X, Y, 0); } public void Center(float X, float Y, float Z){ base.Center(X, Y); // (4) fCenter = Z; } public float Volume(){ return (float)((4 / 3) * System.Math.PI * Math.Pow((double)base.Radius, 3)); } public float Front{ get{return fCenter - base.Radius; } set{fCenter = value + base.Radius; } } } // (2)

// (3)

Para ver como funciona la herencia, cree un nuevo objeto de cada tipo y llama a los mtodos y propiedades de ambos. El siguiente cdigo muestra las clases Sphere y Circle mostrando los valores que calculan en un formulario Web. Visual Basic .NET
Private Sub Page_Load(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles MyBase.Load Dim MyCircle As New Circle() MyCircle.Radius = 2 MyCircle.Center(10, 2) Response.Write("rea del Crculo: " & MyCircle.Area & "<br>") Response.Write("Circunferencia del crculo: " & _ MyCircle.Perimeter & "<br>")

39

MCAD/MCSD

Dim MySphere As New Sphere() MySphere.Radius = 10 MySphere.Center(10, 20, 25) Response.Write("Esfera Arriba: " & MySphere.Top & "<br>") Response.Write("Esfera Izquierda: " & MySphere.Left & "<br>") Response.Write("Esfera Delante: " & MySphere.Front & "<br>") Response.Write("Volumen Esfera: " & MySphere.Volume & "<br>") Response.Write("rea superficial Esfera: " & MySphere.Area & "<br>") Response.Write("Circunferencia Esfera: " & MySphere.Perimeter & "<br>") End Sub

Visual C#
private void Page_Load(object sender, System.EventArgs e){ Circle MyCircle = new Circle(); MyCircle.Radius = 2; MyCircle.Center(10, 2); Response.Write("rea del Crculo: " + MyCircle.Area() + "<br>"); Response.Write("Circunferencia del crculo: " + MyCircle.Perimeter() + "<br>"); Sphere MySphere = new Sphere(); MySphere.Radius = 10; MySphere.Center(10,20,25); Response.Write("Esfera Arriba: " + MySphere.Top + "<br>"); Response.Write("Esfera Izquierda: " + MySphere.Left + "<br>"); Response.Write("Esfera Delante: " + MySphere.Front + "<br>"); Response.Write("Volumen Esfera: " + MySphere.Volume() + "<br>"); Response.Write("rea superficial Esfera: " + MySphere.Area() + "<br>"); Response.Write("Circunferencia Esfera: " + MySphere.Perimeter() + "<br>"); }

En lo abstracto Visual Studio tambin permite definir clases abstractas. Una clase abstracta es una clase que define un interface para clases derivadas. Una clase abstracta esencialmente es un contrato que dice que todas las clases basadas en l deben proporcionar ciertos mtodos y propiedades. No puede crear objetos a partir de clases abstractas solo puede derivar nuevas clases de ellas. Las clases abstractas se declaran con las palabras clave MustInherit de Visual Basic o abstract de C#. Los mtodos y propiedades que debe implementar la clase derivada se declaran como MustOverride en Visual Basic o abstract en C#. La clase Shape es un ejemplo de clase abstracta: Visual Basic .NET
' Definicin de clase abstracta. Public MustInherit Class Shape Public MustOverride Property Top() As Single Public MustOverride Property Left() As Single Public MustOverride Function Area() As Single Public MustOverride Function Perimeter() As Single End Class

Visual C#
// Definicin de clase abstracta. public abstract class Shape{ public Shape(){} public abstract float Top{get; set;} public abstract float Left{get; set;} public abstract float Area(); public abstract float Perimeter(); }

Observe que los miembros MustOverride en Visual Basic o abstract en C# son solo definiciones no hay cuerpo de procedimiento porque estos procedimientos se definirn (sustituirn) en la clase derivada. La siguiente clase Circle demuestra cmo se hereda de una clase abstracta. En Visual Basic .NET la palabra clave Inherits declara que esta clase est basada en la clase base Shape (1). La palabra clave Overrides (2) es necesaria en cada una de las definiciones de miembros que sustituyen a miembros de la clase base. En C# la definicin de clase (1) declara que esta clase se basa en la clase base abstracta Shape. La palabra clave override (2) es necesaria en la declaracin de cada miembro que sustituye a un miembro de la clase base abstracta.

40

Developing Web Applications

Visual Basic .NET


Public Class Circle Inherits Shape ' (1) Private sxCenter, syCenter As Single Private sRadius As Single Public Overrides Property Top() As Single Get Top = sxCenter - sRadius End Get Set(ByVal Value As Single) sxCenter = Value + sRadius End Set End Property Public Overrides Property Left() As Single Get Left = syCenter - sRadius End Get Set(ByVal Value As Single) syCenter = Value + sRadius End Set End Property Public Overrides Function Area() As Single Area = 2 * System.Math.PI * (sRadius ^ 2) End Function Public Overrides Function Perimeter() As Single Perimeter = 2 * sRadius * System.Math.PI End Function Public Property Radius() As Single Get Radius = sRadius End Get Set(ByVal Value As Single) sRadius = Value End Set End Property Public Overridable Sub Center(ByVal X As Single, ByVal Y As Single) sxCenter = X syCenter = Y End Sub End Class ' (2)

Visual C#

public class Circle : Shape{ // (1) float fxCenter, fyCenter, fRadius; // Constructor. public Circle(){ // Inicializa variables internas. fxCenter = 0; fyCenter = 0; fRadius = 0; } public override float Top{ // (2) get{return fxCenter - fRadius; } set{fxCenter = value + fRadius; } } public override float Left{ get{return fyCenter - fRadius; } set{fyCenter = value + fRadius; } } public override float Area(){ return (float)(2 * System.Math.PI * Math.Pow((double)fRadius, 2)); } public override float Perimeter(){ return 2 * fRadius * (float)System.Math.PI; }

41

MCAD/MCSD

public float Radius{ get{return fRadius; } set{fRadius = value; } } public virtual void Center(float X, float Y){ fxCenter = X; fyCenter = Y; } }

3.1.4 Interfaces
Los interfaces son similares a las clases abstractas en que ambos proporcionan una plantilla que se puede usa para crear nuevas clases. La diferencia es que los interfaces no proporcionan la implementacin de ningn miembro base, mientras que las clases abstractas pueden implementar miembros comunes a todas las clases derivadas. Los interfaces se parecen ms a tipos que a clases. Cuando se implementa un interface concreto en una clase, las instancias de esta clase se pueden usar en lugar de cualquier argumento o variable declarado como del tipo del interface2. Por ejemplo, el siguiente cdigo declara un interface para los objetos forma creados anteriormente: Visual Basic .NET
Interface para todas las formas. Public Interface IFigure Property Top() As Single Property Left() As Single Function Area() As Single Function Perimeter() As Single End Interface

Visual C#
//Interface para todas las formas public interface IFigure{ float Top{get; set;} float Left{get; set;} float Area(); float Perimeter(); }

Para usar el interface implemntelo en una clase como se muestra aqu en negrita Visual Basic .NET
' Definicin de clase abstracta. Public MustInherit Class Shape Implements IFigure Public MustOverride Property Public MustOverride Property Public MustOverride Function Public MustOverride Function IFigure.Perimeter End Class

Top() As Single Implements IFigure.Top Left() As Single Implements IFigure.Left Area() As Single Implements IFigure.Area Perimeter() As Single Implements

Visual C#
public abstract class Shape : IFigure{ // Constructor. public Shape(){} public abstract float Top{get; set; } public abstract float Left{get; set; } public abstract float Area(); public abstract float Perimeter(); }

Como la clase abstracta Shape de este ejemplo implementa el interface IFigure, todas las clases derivadas de Shape heredan tambin la implementacin de IFigure. Esto significa que todos los objetos de los tipos Circle y Sphere, que derivan de Shape, se pueden usar como argumentos del tipo IFigure, como muestran las siguientes llamadas a procedimientos: Visual Basic .NET
Private Sub Page_Load(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles MyBase.Load ' Crea un crculo. Dim MyCircle As New Circle() MyCircle.Radius = 2 MyCircle.Center(10, 2) ' Crea una esfera. Dim MySphere As New Sphere() MySphere.Radius = 10 MySphere.Center(10, 20, 25)

Que yo sepa, esto sucede tambin cuando se hereda de una clase base. Desde siempre, una clase es un tipo. (N. del T.)

42

Developing Web Applications

' Muestra informacin sobre las formas. ShowShapeInfo(MySphere) ShowShapeInfo(MyCircle) End Sub ' Muestra la informacin de forma en el formulario Web. Sub ShowShapeInfo(ByVal Shape As IFigure) Response.Write("Arriba: " & Shape.Top & "<br>") Response.Write("Izquierda: " & Shape.Left & "<br>") Response.Write("Volumen: " & Shape.Volume & "<br>") Response.Write("Superficie: " & Shape.Area & "<br>") Response.Write("Permetro: " & Shape.Perimeter & "<br>") End Sub

Visual C#
private void Page_Load(object sender, System.EventArgs e){ // Crea un crculo. Circle MyCircle = new Circle(); MyCircle.Radius = 2; MyCircle.Center(10, 2); // Crea una esfera. Sphere MySphere = new Sphere(); MySphere.Radius = 10; MySphere.Center(10,20,25); // Muestra informacin sobre cada esfera. ShowShapeInfo(MySphere); ShowShapeInfo(MySphere); } // Muestra informacin de la forma en el formulario Web. private void ShowShapeInfo(IFigure Shape){ // Como el argumento Shape es un IFigure sabemos que tiene estos miembros. Response.Write("Arriba: " + Shape.Top + "<br>"); Response.Write("Izquierda: " + Shape.Left + "<br>"); Response.Write("Permetro: " + Shape.Perimeter() + "<br>"); Response.Write("Superficie: " + Shape.Area() + "<br>"); }

La clave es que todos los elementos definidos en el interface deben existir en cualquier clase que implemente el interface. Si se omite cualquier miembro Visual Studio genera un error en compilacin.

3.2 Espacios de nombres en una aplicacin Web


En esta leccin aprender como recorrer los espacios de nombres ASP.NET para encontrar los objetos que se usan para crear una aplicacin Web. Tambin ver como usar los objetos Application, Page, Request y Response en el cdigo. Estos cuatro objetos forman el ncleo de la programacin de aplicaciones Web.

3.2.1 Generalidades de los espacios de nombres Web


Las definiciones de clase para los objetos usados en aplicaciones Web residen en el espacio de nombres System.Web. La tabla 3.4 muestra la jerarqua del espacio de nombres y describe los tipos de definiciones de clase que se encuentran en cada uno. Use esta tabla como gua para buscar los objetos que realizan tareas concretas.
Tabla 3. 4: Jerarqua de espacios de nombres Web
Espacio de Nombres Contiene clases para

System.Web

Objetos Application, Browser, Cache, Cookies, Exception, Request, Response, Server y Trace. Estas clases se usan en la mayora de las tareas de programacin Web. El objeto Application definido en Global.asax se basa en la clase Application. System.Web.SessionState Objeto Session. Use esta clase para grabar y recuperar elementos en el estado de sesin. System.Web.Services Objeto WebService. Use esta clase para crear y usar servicios Web. System.Web.UI Objetos Control y Page. Use estas clases dentro de un formulario Web para crear y controlar el interface de usuario de la aplicacin Web. Los formularios Web estn basados en la clase Page. System.Web.UI.WebControls Todos los objetos control de servidor. Use estas clases dentro de formularios Web. System.Web.UI.HTMLControls Todos los objetos control HTML. Use estas clases dentro de formularios Web System.Web.Caching Objeto Cache. Use esta clase para controlar el cach de lado cliente para mejorar las prestaciones de las aplicaciones. System.Web.Mail Objetos MailMessage, MailAttachment y SmtpMail. Use estas clases para enviar mensajes de correo desde su aplicacin. System.Web.Security Objetos y mdulos de autenticacin. Use estas clases para autenticar usuarios y proporcionar seguridad dentro de su aplicacin.

Cuando se programa una aplicacin web se trata directamente con dos tipos de objetos derivados de clases de los espacios de nombres Web: 43

MCAD/MCSD

Objeto Application: Derivado de la clase HttpApplication. En la aplicacin, esta definicin reside en el archivo Global.asax. Objetos formulario Web: derivados de la clase Page, En la aplicacin, esta definicin reside en los mdulos de formulario Web. El siguiente cdigo muestra las declaraciones que genera Visual Studio para las clases Global y WebForm1. Estas clases las instancia automticamente el motor de ejecucin de ASP.NET. Visual Basic .NET
Public Class Global Inherits System.Web.HttpApplication End Class Public Class WebForm1 Inherits System.Web.UI.Page End Class

Visual C#
public class Global : System.Web.HttpApplication {} public class WebForm1 : Sytem.Web.UI.Page {}

Estos objetos Global y WebForm1 son los puntos de entrada que se usan para llegar a otros objetos Web en una aplicacin. Estos objetos, junto con Request y Response son los que se usan con mayor frecuencia en el cdigo. Las siguientes secciones explican cmo usar los objetos Application, Page, Request y Response para moverse entre otros objetos.

3.2.2 Uso del objeto Application


El objeto Application es un objeto de ms alto nivel en la jerarqua de objetos de la aplicacin Web. Use el objeto Application para configurar su aplicacin y para guardar informacin de estado. El objeto Application tiene propiedades y mtodos que proporcionan a otros objetos de la aplicacin, como muestra la figura 3.1. Cuando ASP.NET arranca una aplicacin instancia automticamente el objeto Global definido en Global.asax. Use los sucesos del objeto Global para configurar su aplicacin y para inicializar variables de estado a nivel de aplicacin.

Fig 3. 1: Objeto Application

La clase base HttpApplication proporciona las propiedades y mtodos para acceder a objetos subordinados del objeto Global. Estas propiedades y mtodos se muestran en la tabla 3.5. Use estas propiedades y mtodos para obtener otros objetos desde el objeto Application.
Tabla 3. 5: Propiedades y mtodos del objeto Application
Propiedad / Mtodo Se usa para Grabar elementos de datos en el estado de aplicacin Obtener Trace, Cache, Error y otros objetos para el contexto actual Acceso a mdulos HTTP. Leer una peticin y obtener objetos Browser, ClientCertificates, Cookies y Files para la peticin actual. Escribir texto o datos en una respuesta y obtener objetos Cache, Cookies y Output de la respuesta actual. Procesar peticiones y respuestas. El objeto Server proporciona mtodos auxiliares para codificar y decodificar URL,s. Grabar elementos de datos en el estado de sesin. Obtener informacin de autenticacin sobre el usuario que est haciendo la peticin actual. De forma predeterminada, las aplicaciones Web permiten acceso annimo.

Application Context Modules Request Response Server Session User

El siguiente cdigo usa los objetos Request y Browser disponibles desde el objeto Application para determinar si el navegador que hace la peticin es de versin 4.0 o posterior. Visual Basic .NET
Sub Application_BeginRequest(ByVal sender as Object, ByVal e as EventArgs) Se dispara al comienzo de cada peticin If Request.Browser.MajorVersion < 4 Then Desactiva caractersticas avanzadas End If End Sub

Visual C#
protected void Application_BeginRequest(Object sender, EventArgs e){ //Se dispara al comienzo de cada peticin if(Request.Browser.MajorVersion < 4){ //Desactiva caractersticas avanzadas } }

44

Developing Web Applications

3.2.3 Uso del objeto Page


El objeto Page controla el interface de la aplicacin. Este objeto tiene propiedades y mtodos que proporcionan acceso a otros objetos en el interface de usuario, como muestra la figura 3.2. Cuando un usuario solicita una pgina de la aplicacin ASP.NET instancia automticamente el formulario Web y muestra la pgina. Se aaden procedimientos de suceso al formulario para controlar el interface e interactuar con el usuario. La clase base Page proporciona los mtodos y propiedades centrales que se usan cuando se programan formularios Web. Estas propiedades y mtodos se muestran en la tabla 3.6.
Tabla 3.6: Propiedades y mtodos del objeto Page
Propiedad / Mtodo Se usa para Grabar elementos de datos en el estado de aplicacin Controlar la forma en que se guardan en cach las respuestas en el servidor. Obtener los controles de la pgina Leer una peticin y obtener los objetos Browser, ClientCertificates, Cookies y Files de la peticin actual Escribir texto o datos en la respuesta y obtener los objetos Cache, Cookies y Output de la respuesta actual Procesar peticiones y respuestas. El objeto Server proporciona mtodos auxiliares para codificar y decodificar URL,s Grabar elementos de datos en el estado de sesin Activar o desactivar el seguimiento de traza y escribir en el registro e traza

Application Cache Controls Request Response Server Session Trace

El siguiente cdigo aade un nuevo control al formulario Web en tiempo de ejecucin. Visual Basic .NET
Private Sub Page_Load(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles MyBase.Load Crea un nuevo control Dim txtNew As New TextBox() Establece el texto que se muestra en el control txtNew.Text = Un poco de texto Aade el control entre los elementos <form></form> FindControl(Form1).Controls.Add(txtNew) End Sub
Fig 3. 2: Objeto Page

Visual C#
private void Page_Load(object sender, System.EventArgs e){ //Crea un nuevo control TextBox txtNew = New TextBox(); //Establece texto para mostrar en el control txtNew.Text = Un poco de texto; //Aade el control entre los elementos <form></form>. FindControl[form1].Controls.Add(txtNew); }

3.2.4 Uso del objeto Request


El objeto Request contiene la informacin enviada por el navegador cliente cuando se solicita una pgina de la aplicacin. El objeto Request tiene propiedades y mtodos que proporcionan acceso a los otros objetos que componen la peticin, como muestra la figura 3.3. El objeto Request proporciona los mtodos y propiedades que se muestran en la tabla 3.7 para acceder a los objetos subordinados.
Tabla 3. 7: Propiedades y mtodos del objeto Request
Propiedad / Mtodo Se usa para Fig 3. 3: Objeto Request

Browser

Determina las posibilidades del navegador que hace la peticin. Las propiedades del navegador proporcionan el nmero de versin, determinan si es AOL, si soporta cookies, y otra informacin ClientCertificates Autentifica el cliente. Cookies Obtiene informacin procedente del cliente en forma de cookies Files Obtiene los archivos subidos por el cliente InputStream Lee y escribe los datos en bruto enviados al cliente

El siguiente cdigo usa el objeto Request para comprobar si el navegador soporta cookies y si existe una cookie concreta antes de grabar el valor de una cookie en el estado de sesin. 45

MCAD/MCSD

Visual Basic .NET


Private Sub Page_Load(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles MyBase.Load Se ejecuta la primera vez que se muestra la pgina If Not IsPostBack Then Comprueba si el navegador soporta cookies If Request.Browser.Cookies Then Comprueba si existe la cookie UName If Not IsNothing(Request.Cookies(UName)) Then Graba el valor de la cookie Session(User) = Request.Cookies(UName).Value End If End If End If End Sub

Visual C#
private void Page_Load(object sender, System.EventArgs e){ //Se ejecuta la primera vez que se muestra la pgina if(!IsPostBack) //Comprueba si el navegador soporta cookies if(Request.Browser.Cookies) //Comprueba si existe la cookie UName if(Request.Cookies[UName] != null) //Obtiene el valor de la cookie Session[User] = Request.Cookies[UName].Value; }

3.2.5 Uso del objeto Response


Use el objeto Response para dar forma a la respuesta enviada desde el servidor al navegador cliente. El objeto Response tiene propiedades y mtodos que proporcionan acceso a otros objetos que componen la respuesta, como muestra la figura 3.4. El objeto Response proporciona los mtodos y propiedades que se muestran en la tabla 3.8:
Tabla 3. 8: Propiedades y Mtodos del Objeto Response
Propiedad / Mtodo Se usa para Determina cmo almacena el servidor en cach las respuestas antes de enviarlas al cliente Configura el contenido de las cookies que se envan al cliente Obtiene o establece los datos en bruto enviados al cliente como respuesta.

Fig 3. 4: Objeto Response

Cache Cookies Output

El siguiente cdigo crea una cookie y la enva al cliente como parte de la respuesta. Visual Basic .NET
Private Sub Page_Load(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles MyBase.Load ' Se ejecuta la primera vez que se muestra la pgina. If Not IsPostBack Then ' Si el navegador soporta cookies. If Request.Browser.Cookies Then ' Crea una cookie. Dim cookUname As New HttpCookie("UName") cookUname.Value = "Wombat" ' Aade la cookie. Response.Cookies.Add(cookUname) End If End If End Sub

Visual C#
private void Page_Load(object sender, System.EventArgs e){ if(!IsPostBack) // Si el navegador soporta cookies. if (Request.Browser.Cookies){ // Crea una cookie. HttpCookie cookUname = new HttpCookie("UName"); cookUname.Value = "Wombat";

46

Developing Web Applications

// Aade la cookie. Response.Cookies.Add(cookUname); } }

3.3 Mantenimiento de informacin de estado


En esta leccin aprender cmo retener datos en un formulario Web entre peticiones. ASP.NET proporciona diferentes mecanismos para guardas datos de formularios, dependiendo de la naturaleza y alcance de la informacin.

3.3.1 Niveles de estado


Como se explic en el Captulo 2, Crear Aplicaciones de Formulario Web, los formularios Web se crean y se destruyen cada vez que un navegador cliente hace una peticin. Debido a esto las variables declaradas dentro de un formulario Web no mantienen su vale tras mostrar la pgina. Para resolver este problema ASP.NET proporciona las siguientes formas de mantener variables entre peticiones: Cadenas de Consulta: Se usan para pasar informacin en peticiones y respuestas como parte de una direccin Web. Las cadenas de consulta son visibles para el usuario, por lo que no deben contener informacin sensible, como contraseas. Cookies: Use las cookies para almacenar pequeas cantidades de informacin en un cliente. Los clientes podran rechazar las cookies, por lo que el cdigo tiene que anticipar esta posibilidad. Estado de Vista: ASP.NET almacena los elementos aadidos a la propiedad ViewState como campos ocultos en la pgina. Estado de Sesin: Use las variables Session para almacenar elementos que quiere mantener locales a la sesin (usuario) actual. Estado de Aplicacin: Use las variables Application para almacenar elementos que quiere que estn disponibles para todos los usuarios de la aplicacin.

3.3.2 Uso de cadenas de consulta


Las cadenas de consulta permiten enviar informacin adicional junto con una direccin. En HTML las cadenas de consulta aparecen tras un interrogante en un hiperenlace, en la forma:
<A HREF=WebForm1.aspx?UName=Wombat>Ejemplo de cadena de consulta</A>

Para enviar una cadena de consulta en el cdigo adala a la direccin de un mtodo Redirect. El siguiente procedimiento de suceso Click es equivalente al HTML anterior: Visual Basic .NET
Private Sub Button1_Click(ByVal sender as System.Object, _ ByVal e As System.EventArgs) Handles Button1.Click Vuelve a mostrar esta pgina con una cadena de consulta Server.Redirect(WebForm1.aspx?UName=Wombat) End Sub

Visual C#
private void Button1_Click(object sender, System.EventArgs e){ //Vuelve a mostrar esta pgina con una cadena de consulta Server.Redirect(WebForm1.aspx?UName=Wombat); }

Para recuperar una cadena de consulta en el cdigo use el mtodo QueryString del objeto Response. El siguiente cdigo muestra el elemento UName de la cadena de consulta creada en los ejemplos anteriores. Visual Basic .NET
Private Sub Page_Load(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles MyBase.Load Muestra la cadena de consulta Response.Write(Request.QueryString(UName)) End Sub

Visual C#
private void Page_Load(object sender, System.EventArgs e){ //Muestra la cadena de consulta Response.Write(Request.QueryString(UName)) }

3.3.3 Uso de cookies


Use cookies para almacenar pequeas cantidades de informacin en la mquina del cliente. Los sitios Web las usan a menudo para almacenar las preferencias del cliente u otra informacin especfica del cliente. Como las cookies pueden ser rechazadas es importante comprobar que el navegador las admite antes de intentar crearlas. 47

MCAD/MCSD

El siguiente cdigo comprueba si un navegador permite cookie y si lo hace graba las preferencias del usuario. Visual Basic .NET
Private Sub Page_Load(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles MyBase.Load Se ejecuta la primera vez que se muestra la pgina If Not IsPostBack Then Si el navegador soporta cookies If Request.Browser.Cookies Then Crea una Cookie Dim cookUPrefs As New HttpCookie(UPrefs) cookUPrefs.Value = Espaol Aade la cookie Response.Cookies.Add(cookUPrefs) End If End If End Sub

Visual C#
private void Page_Load(object sender, System.EventArgs e){ //Se ejecuta la primera vez que se muestra la pgina If(!IsPostBack) //Si el navegador soporta cookies If(Request.Browser.Cookies){ //Crea una cookie HttpCookie cookUPrefs = new HttpCookie(UPrefs); cookUPrefs.Value = Espaol; //Aade la cookie Response.Cookies.Add(cookUPrefs); } }

El siguiente cdigo comprueba la existencia de una cookie y la lee si existe: Visual Basic .NET
Private Sub Page_Load(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles MyBase.Load Se ejecuta la primera vez que se muestra la pgina If Not IsPostBack Then Comprueba si el navegador soporta cookies If Request.Browser.Cookies Then Comprueba si existe la cookie UPrefs If Not IsNothing(Request.Cookies(UPrefs)) Then Graba el valor de la cookie Session(Lang) = Request.Cookies(UPrefs).Value End If End If End If End Sub

Visual C#
private void Page_Load(object sender, System.EventArgs e){ //Se ejecuta la primera vez que se muestra la pgina if(!IsPostBack) //Comprueba si el navegador soporta cookies if(Request.Browser.Cookies) //Comprueba si existe la cookie UPrefs if(Request.Cookies[UPrefs] != null) //Graba el valor de la cookie Session[Lang] = Request.Cookies[UPrefs].Value; }

3.3.4 Uso del estado de vista


Use la propiedad ViewState para guardar datos en un campo oculto en una pgina. Como ViewState guarda los datos en la pgina, est limitado a elementos que se puedan serializar. Si quiere guardar elementos ms complejos tendr que convertirlos a y de una cadena. Por ejemplo, el siguiente cdigo aade texto de una caja de texto a celdas de una tabla en la pgina. Como no se pueden almacenar directamente objetos en ViewState es necesario almacenar las cadenas en el procedimiento Button1_Click y despus crear los controles fila de tabla a partir de las cadenas, como muestra el procedimiento Page_Load: 48

Developing Web Applications

Visual Basic .NET


Private Sub Button1_Click(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles Button1.Click ' Aade texto a ViewState ViewState.Add(ViewState.Count, TextBox1.Text) End Sub Private Sub Page_Load(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles MyBase.Load Dim iCount As Integer ' Para cada elemento del estado de vista For iCount = 0 To ViewState.Count Dim rowNew As New TableRow() Dim celNew As New TableCell() ' Configura el texto de la celda. celNew.Text = ViewState(iCount) ' Aade la celda a la fila. rowNew.Cells.Add(celNew) ' Aade la fila a la tabla Table1.Rows.Add(rowNew) Next End Sub

Visual C#
private void Button1_Click(object sender, System.EventArgs e){ // Aade texto al estado de vista. ViewState.Add(ViewState.Count.ToString(), TextBox1.Text); } private void Page_Load(object sender, System.EventArgs e){ if (IsPostBack) // Para cada elemento en ViewState foreach(StateItem staItem in ViewState.Values) TableRow rowNew = new TableRow(); TableCell celNew = new TableCell(); // Configura el texto de la celda. celNew.Text = staItem.Value.ToString(); // Aade la celda a la fila. rowNew.Cells.Add(celNew); // Aade la fila a la tabla. Table1.Rows.Add(rowNew); } }

ASP.NET codifica los datos ocultos que se almacenan en la pgina de forma que no son inteligibles para los usuarios. Si aade unos cuantos elementos a la tabla usando el cdigo anterior y despus selecciona Ver Fuente en su navegador, el HTML para el campo oculto es algo como esto:
</HEAD> <body MS_POSITIONING="GridLayout"> <form name="Form1" method="post" action="WebForm1.aspx" id="Form1"> <input type="hidden" name="__VIEWSTATE" value="dDwtMTMwNzIzMzU0Mzt0PHA8bDwwOzE7Mj szOzQ7PjtsPFxlO1RoaXMgaXMgc29tZSB0ZXh0O1RoaXMgaXMgc29tZSB0ZXh0O1RoaXMgaXMgc29tZSB0Z Xh0O1RoaXMgaXMgc29tZSB0ZXh0Oz4+Ozs+Oz4=" />

Usar los estados de aplicacin y de sesin Use Application y Session para guardar datos que quiera mantener durante el tiempo de vida de la aplicacin o de una sesin respectivamente. Puede almacenar cualquier tipo de datos en Application o Session, incluyendo objetos. Sin embargo, antes de usarlo debe considerar los siguientes puntos: Las variables de estado Application y Session se crean sobre la marcha, sin comprobacin de nombre o tipo. Debe limitar sus puntos de acceso a estas variables. El mantenimiento de estado de sesin afecta a las prestaciones. Se puede desactivar a niveles de aplicacin y pgina. Las variables de estado de aplicacin estn disponibles en el proceso actual, pero no entre procesos. Si se hace crecer una aplicacin para que corra en varios servidores o en varios procesadores dentro de un servidor, cada proceso tiene su propio Application. Los lmites de aplicacin establecidos por IIS determinan el alcance de Application.

49

MCAD/MCSD

Estructurar el acceso a variables de estado Las variables de estado Application y Session son potentes y, por tanto, amedrentadoras. Es fcil introducir en el cdigo errores al estilo de Basic si se usan de una forma no estructurada. Por ejemplo, el siguiente cdigo crea dos variables distintas en Application: Visual Basic .NET
Application(Uname) = Wombat Response.Write(Application(Unamme))

Visual C#
Application[Uname] = Wombat; Response.Write(Application[Unamme]);

La primera lnea crea una variable y le asigna un texto. La segunda lnea recupera una nueva variable, vaca y no muestra nada, sencillamente porque el nombre de variable est mal escrito. Aqu el problema es obvio, pero si ocurre en las profundidades de una estructura de decisin puede ser muy difcil de encontrar. Para mejorar este problema estructure su acceso a las variables de Application y Session. La forma ms fcil de hacerlo es declarar una variable a nivel de pgina para cada elemento que necesite, recupere los valores de Application y Session en el procedimiento de suceso Page_Load y grbelos en el procedimiento de suceso Page_Unload. Puede ser conveniente que la recuperacin y grabacin de variables de estado en un lugar coherente sea parte de sus normas de codificacin. El siguiente cdigo muestra la estructuracin del acceso a sus variables de estado. Visual Basic .NET
Public Class WebForm1 ' Declara una variable a nivel de pgina. Dim mstrUname As String Private Sub Page_Load(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles MyBase.Load ' Lee la variable de estado. mstrUname = Application("Uname") ' Modifica la variable mstrUname = "Wombat" ' Usa la variable. Response.Write(mstrUname) End Sub Private Sub Page_Unload(ByVal sender As Object, _ ByVal e As System.EventArgs) Handles MyBase.Unload ' Graba las variables de estado. Application("Uname") = mstrUname End Sub End Class

Visual C#
string mstrUname = ""; private void Page_Load(object sender, System.EventArgs e){ // Comprueba si existe la variable de estado. if(Application["Uname"] != null) // Obtiene la variable de estado. mstrUname = Application["Uname"].ToString(); // Modifica la variable mstrUname = "Wombat"; // Usa la variable. Response.Write(mstrUname); } private void Page_UnLoad(object sender, System.EventArgs e){ // Graba las variables de estado. Application["Uname"] = mstrUname; }

Importante: En Visual C# asegrese de comprobar si la variable de estado es null antes de llamar a cualquiera de sus mtodos, como ToString(). Si no lo hace recibir un error en tiempo de ejecucin si la variable no contiene un valor. Desactivar el estado de sesin ASP.NET mantiene de forma predeterminada el estado de sesin para cada pgina de la aplicacin. Si una pgina no precisa informacin de estado a nivel de sesin puede desactivarlo para mejorar las prestaciones. 50

Developing Web Applications

Para desactivar el estado de sesin para un formulario Web, en la ventana de propiedades del formulario Web de el valor False a EnableSessionState. Para desactivar el estado de sesin para toda una aplicacin, en el archivo Web.config de el valor False a la etiqueta <sessionstate mode=>, de la forma <sessionstate mode=false>.

3.4 Resumen
Los espacios de nombres organizan el cdigo y proporcionan acceso al cdigo del marco de trabajo .NET. Para usar un espacio de nombres desde fuera del proyecto establezca una referencia a l usando el dilogo Referencias del men Proyecto. Aada una sentencia Imports (Visual Basic) o using (C#) en el archivo fuente para proporcionar una forma abreviada de nombrar a los miembros del espacio de nombres en el cdigo. Las clases definen objetos dentro de un espacio de nombres. Puede basar una clase en otra usando herencia. Cuando se usa herencia la clase base proporciona sus miembros a la clase derivada, donde pueden ser sustituidos, sobrecargados u ocultados. Las aplicaciones Web usan los espacios de nombres System.Web y System.Web.UI. Estos espacios de nombres definen la mayora de los objetos que se usan en una aplicacin Web, incluyendo Application, Page, Request y Response. Estos cuatro objetos proporcionan acceso a la mayora de los objetos subordinados en una aplicacin Web. Como las variables ordinarias definidas en un formulario Web no son persistentes necesita grabar los datos voltiles entre peticiones. ASP.NET permite grabar elementos de datos mediante cadenas de consulta, cookies, ViewState, Session y Application.

3.5 Prctica: Usar objetos y grabar datos


En esta prctica crear la aplicacin Translator. Crear un formulario Web y un mdulo de clase. Crear una instancia de un objeto en el mdulo Global, grabar la instancia en Session y en el estado de vista desde el formulario Web.

3.5.1 Crear el interface de usuario


En este ejercicio crear el interface de usuario aadiendo controles de servidor al formulario Web. Para crear un nuevo proyecto de aplicacin Web 1. Abra un nuevo proyecto de aplicacin Web ASP.NET. En la caja de dilogo Nuevo Proyecto escriba el nombre Translator y pulse Aceptar. 2. En la ventana de propiedades cambie el nombre del archivo WebForm1.aspx a Translator.aspx. Para aadir controles al interface de usuario Aada los controles de la siguiente tabla, con las propiedades indicadas:
Control Tipo de Control Propiedad Valor

Label1 TextBox1 Button1

Label Text Box Button

Text Font ID TextMode ID Text

Traductor Universal Bold, Large txtSource Multicine butTranslate Traducir

3.5.2 Crear una clase Translator


En este ejercicio crear una clase Friend para contener la lgica y los datos de la aplicacin. Para aadir controles al interface de usuario 1. En el men Proyecto, seleccione Agregar Clase. Visual Studio muestra la caja de dilogo Agregar Nuevo Elemento. Llame a la clase TranslatorClass y pulse Aceptar. 2. En la ventana de cdigo aada el siguiente: Visual Basic .NET
Friend Class TranslatorClass Private mstrText As String Private mstrOriginal As String ' Controla el acceso a las variables a nivel de mdulo Public Property Text() As String Get Text = mstrText End Get

51

MCAD/MCSD

Set(ByVal Value As String) mstrText = Value ' Mantiene una copia del original para restaurar. mstrOriginal = Value End Set End Property ' Restaura el texto traducido al original. Public Sub Restore() mstrText = mstrOriginal End Sub ' Traduce el valor de la propiedad Text. Public Sub Translate() Dim strWord As String, intCount As Integer Dim arrWords() As String Dim bCaps As Boolean ' Convierte la cadena en array usando System.String. arrWords = mstrText.Split(" ") For intCount = 0 To UBound(arrWords) ' Comprueba si la palabra tiene mayscula. If LCase(arrWords(intCount)) <> arrWords(intCount) Then bCaps = True arrWords(intCount) = LCase(arrWords(intCount)) End If strWord = arrWords(intCount) ' Hace la traduccin. If strWord <> "" Then strWord = Right(strWord, Len(strWord) - 1) & _ Left(strWord, 1) & "ay" ' Vuelve a mayscula si es necesario. If bCaps Then strWord = UCase(Left(strWord, 1)) & _ Right(strWord, Len(strWord) - 1) End If End If ' Vuelve a almacenar en el array. arrWords(intCount) = strWord ' Restaura el indicador de mayscula. bCaps = False Next ' Reconstruye la cadena a partir del array. mstrText = String.Join(" ", arrWords) End Sub End Class

Visual C#
internal class TranslatorClass{ string mstrText, mstrOriginal; // Controla el acceso a las variables a nivel de clase. public string Text { get{return mstrText; } set{ mstrText = value; // Mantiene una copia del original para restaurar. mstrOriginal = value; } } // Restablece el texto traducido al original. public void Restore(){mstrText = mstrOriginal; }

52

Developing Web Applications

// Traduce el valor de la propiedad Text. public void Translate(){ string strWord; string[] arrWords; bool bCaps = false; // Convierte la cadena en array usando System.String. arrWords = mstrText.Split(' '); for(int intCount = 0; intCount <= arrWords.GetUpperBound(0); intCount++){ // Cambia a minsculas. strWord = arrWords[intCount].ToLower(); // Comprueba si la palabra lleva maysculas. if(!arrWords[intCount].Equals(strWord)) bCaps = true; // Hace la traduccin. if(strWord != "") { strWord = strWord.Substring(1,strWord.Length - 1) + strWord.Substring(0,1) + "ay"; // Vuelve a poner maysculas si es necesario. if(bCaps) strWord = strWord.Substring(0,1).ToUpper() + strWord.Substring(1, strWord.Length - 1); } // Vuelve a almacenar la palabra en el array. arrWords[intCount] = strWord; // Restablece el indicador de maysculas. bCaps = false; } // Reconstruye la cadena a partir del array. mstrText = String.Join(" ", arrWords); } }

3.5.3 Almacenar un objeto Translator en sesin


En este ejercicio aadir al archivo Global.asax el cdigo para inicializar una variable de estado de sesin que contenga el objeto TranslatorClass que usar el formulario Web. Para crear una variable de estado de sesin 1. En la ventana de proyecto pulse dos veces sobre el archivo Global.asax y despus pulse el enlace haga click aqu para cambiar a la vista de cdigos. 2. En la ventana de cdigo aada el siguiente procedimiento Session_Start: Visual Basic .NET
Sub Session_Start(ByVal sender As Object, ByVal e As EventArgs) Crea un nuevo objeto Translator Dim TransClass As New TranslatorClass() Almacena el objeto en una variable de estado de sesin Session(TransClass) = TransClass; End Sub

Visual C#
protected void Session_Start(Object sender, EventArgs e){ //Crea un nuevo objeto Translator TranslatorClass TransClass = new TranslatorClass(); //Almacena el objeto en una variable de estado de sesin Session[TransClass] = TransClass; }

3.5.4 Use el objeto TransClass en los sucesos del formulario Web


En este ejercicio aadir al formulario Web el cdigo para usar el objeto TransClass almacenado en la variable de estado de sesin. Tambin usar una variable booleana guardada en el estado de vista de la pgina para cambiar la funcin del botn de Traducir a Restablecer. Para crear una variable de estado de sesin 1. Abra el mdulo de cdigo del formulario en la ventana de cdigo 2. Declare una variable para guardar el objeto del estado de sesin. Visual Basic
Dim TransClass As TranslatorClass

Visual C#
TranslatorClass TransClass;

53

MCAD/MCSD

3. Aada el siguiente cdigo en el procedimiento de suceso Page_Load para asignar la variable de estado de sesin a la variable declarada en el punto anterior. Visual Basic
Private Sub Page_Load(ByVal sender As Sytem.Object, _ ByVal e as System.EventArgs) Handles MyBase.Load Lee la variable de sesin TransClass TransClass = Session(TransClass) End Sub

Visual C#
private void Page_Load(Object sender, System.EventArgs e){ //Se asegura de que existe la variable de sesin if(Session[TransClass] != null) //Lee la variable de sesin TransClass = (TranslatorClass)Session[TransClass]; }

4. Aada el siguiente cdigo al procedimiento de suceso but_Translate.Click: Visual Basic .NET


Private Sub butTranslate_Click(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles butTranslate.Click ' Declara un indicador booleano. Dim bSwitch As Boolean ' Lee el valor de ViewState y lo invierte. bSwitch = Not Viewstate("bSwitch") ' Guarda el nuevo valor en ViewState. ViewState("bSwitch") = bSwitch ' Usa el indicador para traducir o restablecer el texto. If bSwitch Then TransClass.Text = txtSource.Text ' Lee el texto. TransClass.Translate() ' Lo traduce txtSource.Text = TransClass.Text ' Muestra el texto. butTranslate.Text = "Restablecer" ' Cambia el texto del botn. Else TransClass.Restore() ' Restablece el texto original. txtSource.Text = TransClass.Text ' Muestra el texto. butTranslate.Text = "Traducir" ' Cambia el texto del botn. End If End Sub

Visual C#
private void butTranslate_Click(object sender, System.EventArgs e){ // Declara un indicador booleano. bool bSwitch; // Comprueba si existe la variable en ViewState. if(ViewState["bSwitch"] != null) // Lee el valor de ViewState y lo invierte. bSwitch = !(bool)ViewState["bSwitch"]; else // Configura el indicador. bSwitch = true; // Graba el nuevo valor en ViewState. ViewState["bSwitch"] = bSwitch; // Usa el indicador para traducir o restablecer el texto. if (bSwitch){ TransClass.Text = txtSource.Text; // Lee el texto. TransClass.Translate(); // Lo traduce. txtSource.Text = TransClass.Text; // Muestra el texto. butTranslate.Text = "Restablecer"; // Cambia el texto del botn. } else{ TransClass.Restore(); // Restablece el texto original. txtSource.Text = TransClass.Text; // Muestra el texto. butTranslate.Text = "Traducir"; // Cambia el texto del botn. } }

5. Ejecute y pruebe la aplicacin

54

Developing Web Applications

3.6 Resumen
Las siguientes preguntas estn pensadas para reforzar informacin clave presentada en este captulo. Si no es capaz de contestar una pregunta, repase la leccin apropiada e intente contestar de nuevo. Las respuestas a estas preguntas se pueden encontrar en el Captulo 16. 1. Cmo organiza el marco de trabajo .NET sus clases? 2. En Visual Basic .NET Cul es la diferencia entre un mdulo de clase y un mdulo de cdigo? 3. En Visual C#, Cmo se declara un mtodo para que est disponible sin tener que instanciar un objeto de la clase? 4. Cmo se llama a un miembro de la clase base desde dentro de una clase derivada? 5. Cules son los cuatro objeto principales usados en la programacin de aplicaciones Web? 6. Dnde grabara los siguientes elementos de datos de modo que sean persistentes entre peticiones a un formulario Web? Un control creado en tiempo de ejecucin Un objeto que proporciona servicio a todos los usuarios Preferencias de usuario

55

MCAD/MCSD

56

Developing Web Applications

4 Crear un interface de usuario


En este captulo aprender cmo usar los controles ASP.NET para crear un interface de usuario para aplicaciones de formularios Web con varias pginas. Aprender sobre los diferentes estilos de formularios Web, cmo elegir controles segn la tarea que quiera que ejecuten, cmo validar campos de datos y cmo desplazarse entre pginas Web en su aplicacin. Antes de comenzar deber estar familiarizado con los elementos bsicos de HTML y comprender el ciclo de vida de los formularios Web tal como se explica en el captulo 2, Crear Aplicaciones de Formulario Web.

4.1 Usar controles


Los controles son las herramientas para todas las tareas que se realizan sobre un formulario Web. Definen el aspecto del formulario y proporcionan una forma para obtener informacin y realizar tareas en beneficio del usuario. Visual Studio .NET incluye dos tipos diferentes de controles y dos formas de colocar estos controles en el formulario. En esta leccin aprender sobre estas diferencias y cmo se relacionan con las tareas de programacin principales.

4.1.1 Seleccionar una disposicin


Cuando se colocan controles en un formulario Web hay dos opciones para la forma en que se ordenan: Disposicin en Rejilla: Es la predeterminadas. Los controles se colocan exactamente donde se les pone y tienen posiciones absolutas en la pgina. Use esta disposicin para aplicaciones estilo Windows, en la que no se mezclan los controles con grandes cantidades de texto. Disposicin de Flujo: Coloca los controles en relacin con otros elementos de la pgina. Si se aaden elementos en tiempo de ejecucin los controles que se encuentran tras el nuevo se mueven hacia abajo. Use esta disposicin para aplicaciones tipo documento, en las que el texto y los controles estn entremezclados. Para establecer cmo se colocan los controles en una pgina: 1. Seleccione el formulario Web en la ventana de diseo 2. En la ventana de propiedades seleccione el objeto DOCUMENT 3. En la propiedad pageLayout de DOCUMENT seleccione el valor FlowLayout para disposicin de flujo o GridLayout para disposicin en rejilla. La opcin GridLayout se usa en formularios que tienen un aspecto fijo. FlowLayout se usa para formularios Web que incorporan texto y controles. Cuando se crean controles con GridLayout Visual Studio aade a cada control atributos de estilo que fijan su posicin, como muestra, en negrita, en la siguiente definicin de formulario:
<form action="webform1.aspx" method="post" enctype="multipart/form-data" runat="server" ID="Form1"> <h2>Upload and View Files on Server</h2> <INPUT id="filUpload" style="Z-INDEX: 101; LEFT: 86px; WIDTH: 347px; POSITION: absolute; TOP: 20px; HEIGHT: 27px" runat="server" type="file" size="38"> <asp:Button id="butUpload" style="Z-INDEX: 102; LEFT: 357px; POSITION: absolute; TOP: 60px" runat="server" Text="Upload" Width="74px" Height="31px"></asp:Button> <asp:ListBox id="lstServerFiles" style="Z-INDEX: 103; LEFT: 86px; POSITION: absolute; TOP: 79px" runat="server" Height="140px" Width="168px"></asp:ListBox> <asp:Button id="butView" style="Z-INDEX: 104; LEFT: 268px; POSITION: absolute; TOP: 178px" runat="server" Height="31px" Width="76px" Text="View"></asp:Button> <asp:Image id="imgView" style="Z-INDEX: 106; LEFT: 441px; POSITION: absolute; TOP: 24px" runat="server" Height="132px" Width="162px"></asp:Image> </form>

Cuando se crean controles con FlowLayout Visual Studio omite el atributo de estilo. Adems, puede crear controles pulsando dos veces sobre ellos en la caja de herramientas en lugar de usando arrastrar y soltar. Usar FlowLayout simplifica la mezcla de controles y texto en un formulario Web, especialmente cuando se edita el fuente del HTML, como muestra la siguiente definicin de formulario.

57

MCAD/MCSD

<form id="Form1" method="post" runat="server"> <h2>File Manager</h2> <p>To create a new file, type the name of the file below and click New.</p> <asp:Literal id="litNoFile" runat="server"></asp:Literal> <asp:TextBox id="txtNewFile" runat="server" width="191px"> </asp:TextBox> <asp:Button id="butNew" runat="server" Width="62px" Height="29px" Text="New"></asp:Button> <p>To edit a file, select the file from the list below and click Edit. Click Delete to delete the selected file. </p> <asp:Literal id="litNoneSelected" runat="server"></asp:Literal> <asp:ListBox id="lstFiles" runat="server" Width="252px" Height="161px"></asp:ListBox> <br> <asp:Button id="butEdit" runat="server" Width="62" Height="29" Text="Edit"></asp:Button> &nbsp;&nbsp; <asp:Button id="butDelete" runat="server" Width="62px" Height="29px" Text="Delete"></asp:Button> </form>

4.1.2 Elegir el control correcto


En un formulario Web puede elegir controles de servidor o controles HTML. Cul es la diferencia? Bsicamente, los controles de servidor son un sper conjunto de los controle HTML, y ofrecen las ventajas que muestra la tabla 4.1:
Tabla 4. 1: Controles de servidor frente a controles HTML
Caracterstica Sucesos de servidor Gestin de estado Adaptacin Propiedades Controles de servidor Lanzan sucesos especficos en el servidor Controles HTML Slo pueden lanzar sucesos de servidor a nivel de pgina (reenvo) Los datos introducidos en el control se mantienen Los datos no se mantienen, hay que grabarlos y restaurarlos entre peticiones. usando secuencias de comandos a nivel de pgina. Detectan automticamente el navegador y adaptan No hay adaptacin automtica. Hay que detectar el navegasu presentacin de forma acorde. dor mediante cdigo o usar el mnimo comn denominador. El marco de trabajo .NET proporciona un conjunto Solo atributos HTML de propiedades para cada control. Las propiedades permite n cambiar el aspecto del control y su comportamiento desde cdigo del servidor.

Entonces por qu usar otra cosa?. Porque los controles HTML tienen una correspondencia uno a uno con los elementos HTML estndar y proporcionan un control ms directo sobre lo que aparece en una pgina. Los controles HTML se usan por los siguientes motivos: Migracin desde versiones anteriores de ASP. Puede cargar una aplicacin ASP en Visual Studio y revisarla gradualmente en lugar de rescribirla completamente. Versiones previas de ASP solo soportaban elementos HTML, y estos elementos se convierten en controles HTML cuando se carga el proyecto en Visual Studio .NET No todos los controles precisan sucesos de servidor o control de estado. Esto es particularmente cierto cuando se hace vinculacin de datos. Los elementos vinculados normalmente se refrescan a partir del origen de datos con cada peticin en cada peticin, por lo que es ms eficiente no mantener informacin de estado para controles vinculados. Esto significa que puede usar controles HTML o desactivar la gestin de estado para los controles vinculados. Con controles HTML tiene control completo sobre la presentacin. ASP.NET ajusta el aspecto de los controles segn el navegador que hace la peticin. Los controles HTML no se ajustan, por lo que tiene control directo sobre su aspecto. Los controles de servidor y HTML proporcionan funcionalidades que se solapan. Por lo general es ms fcil trabajar con controles de servidor. La tabla 4.2 recoge los controles de servidor y HTML segn tareas.
Tabla 4. 2: Controles de Servidor Frente a Controles HTML
Tarea Mostrar texto Mostrar tablas Seleccionar de listas Ejecutar comandos Establecer valores Mostar imgenes Navegacin Agrupar controles Trabajar con fechas Mostrar anuncios Mostrar regla horizontal Controles de servidor Label, TextBox, Literal Table, DataGrid DropDownList, ListBox, DataList, Repeater Button, LinkButton, ImageButton CheckBox, CheckBoxList, RadioButton, RadioButtonList Image, ImageButton Hyperlink Panel, Placeholder Calendar AdRotator Literal Controles HTML Label, Text Field, Text Area, Password Field Table List Box, Dropdown Button, Reset Button, Submit Button Checkbox, Radio Button Image Ninguno (etiqueta <a> en texto) Flow Layout, Gris Layout Ninguno Ninguno Horizontal Rule

58

Developing Web Applications


Tarea Obtener nombres de ficheros del cliente Guardar datos en la pgina Validar datos Controles de servidor Ninguno (lo proporciona la gestin de estado) RequiredFieldValidator, CompareValidator, RangeValidator, RegularExpressionValidator, CustomValidator, ValidationSummary Controles HTML File Field Input Hidden Ninguno (a nivel pgina)

Las siguientes secciones describen las tareas de programacin principales que se ejecutan con controles para crear un interface de usuario.

4.1.3 Trabajar con texto


Hay muchas formas de mostrar texto en una pgina. Para texto de solo lectura, puede escribir directamente en el objeto Response, como en Response.Write(Un texto); puede usar un control Label; puede usar un control TextBox y dar a su propiedad ReadOnly el valor True; o puede usar un control Literal y componer el texto en HTML como hara con el mtodo Response.Write. Para mostrar texto modificable, en cambio, puede usar un control de servidor TextBox. El control TextBox tiene las propiedades clave de la tabla 4.3.
Tabla 4. 3: Propiedades del Control TextBox
Propiedad Se usa para Leer o escribir los datos del TextBox Mostrar texto en una sola lnea (SingleLine), varias lneas (MultiLine) o de contrasea (Password). Cuando tiene el valor Password la caja de texto muestra puntos en lugar de los caracteres escritos. Impedir que el usuario cambie el texto Cuando vale True la caja de texto lanza un suceso de envo TextChanged cuando el usuario sale de ella despus de cambiar su contenido. De forma predeterminada su valor es False y el suceso TextChanged se guarda en cach hasta que se produce otro suceso de envo.

Text TextMode ReadOnly AutoPostBack

Para ver los controles de texto en accin siga estos pasos para crear una pgina de conexin: 1. Inicie una nueva aplicacin Web con dos formularios llamados Webform1 y Webform2. 2. En Webform1 coloque los controles de la siguiente tabla, con los valores de propiedad que se indican: Control Propiedad Valor Label1 Text Nombre de Usuario Label2 Text Contrasea TextBox1 ID txtUser TextBox2 ID txtPassword TextMode Password Button1 ID butOK Text Aceptar 3. Aada el siguiente cdigo al procedimiento del suceso butOK_Click. Visual Basic .NET
Private Sub butOK_Click(ByVal sender As System.Object _ ByVal e As System.EventArgs) Handles butOk.Click If txtUser.Text = Invitado And txtPassword.Text = Amigo Then Response.Redirect(Webform2.aspx) Else txtPassword.Text = End If End Sub

Visual C#
private void butOK_Click(object sender, System.EventArgs e){ if((txtUser.Text = Invitado) && (txtPassword.Text == Amigo)) Response.Redirect(Webform2.aspx); else txtPassword.Text = ; }

4. Ejecute la aplicacin. Cuando entre el nombre de usuario y contrasea especificados en el cdigo se muestra Webform2.aspx. Observe que el valor Password en la propiedad TextMode hace que los caracteres introducidos sean reemplazados por un smbolo. Desde luego, normalmente no es una buena idea poner los nombres de usuario y contraseas en el cdigo. En el captulo 8 Mantener la Seguridad se mostrar la forma de grabar y recuperar contraseas en un archivo seguro en el servidor.

59

MCAD/MCSD

4.1.4 Trabajar con tablas y listas


El texto que se muestra en etiquetas y cajas de texto se coloca en un solo bloque. Para colocar el texto en filas y columnas necesita usar un control de tablas o de listas descritos en la tabla 4.4. Use los controles ListBox, DropDownList y Table para tablas dinmicas sencillas. Use controles DataGrid, DataList y Repeater para tablas y listas complejas que contienen otros controles o estn vinculadas con datos.
Tabla 4. 4: Controles de Lista y de Tabla de ASP.NET
Propiedad ListBox DropDownList Table DataGrid DataList Repeater Se usa para Muestra texto de solo lectura en una formato de lista desplazable sencilla Muestra texto de solo lectura en una lista desplegable sencilla Muestra texto y controles en filas y columnas. Los controles tabla permite construir tablas dinmicamente mediante cdigo usando colecciones TableRows y TableCells. Muestra texto en filas y columnas usando una plantilla para controlar su aspecto. Los controles DataGrid tienen capacidades de formato, ordenacin y paginacin incorporadas. Muestra filas de texto y controles usando una plantilla para controlar la apariencia. Los controles DataList tienen capacidades de formato y seleccin incorporadas. Muestra filas de otros controles usando una plantilla para controlar la apariencia. Los controles Repeater no incluyen las capacidades incorporadas en los controles DataGrid y DataList.

4.1.5 Aadir elementos a una lista o tabla en diseo


Los controles ListBox, DropDownList y Table permiten que se aadan elementos estticos en tiempo de diseo usando la caja de dilogo Editor de Coleccin: Para aadir elementos estticos a un control ListBox o DropDownList seleccione la propiedad Items en la ventana de propiedades y pulse el botn junto a (Coleccin). Para aadir elementos estticos a un control Table seleccione la propiedad Rows en la ventana de propiedades y pulse el botn junto a (Coleccin).

4.1.6 Aadir elementos a una lista o tabla en ejecucin


Para aadir elementos a una lista en tiempo de ejecucin use el mtodo Add de la coleccin Items. Por ejemplo, el siguiente cdigo aade a un control ListBox y un control DropDownList elementos introducidos en un TextBox. Visual Basic .NET
Private Sub butAdd_Click(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles butAdd.Click ListBox1.Items.Add(txtSource.Text) DropDownList1.Items.Add(txtSource.Text) End Sub

Visual C#
private void butAdd_Click(object sender, System.EventArgs e){ ListBox1.Items.Add(txtSource.Text); DropDownList1.Items.Add(txtSource.Text); }

Tanto el ListBox como el DropDownList almacenan automticamente los elementos que se les aaden en tiempo de ejecucin. Sin embargo, el control Table solo almacenar automticamente los datos para las celdas de tabla creadas en tiempo de diseo en el editor de colecciones. Para crear tablas y celdas adicionales en tiempo de ejecucin necesita reconstruir la tabla a partir de informacin almacenada en una variable de estado. Por ejemplo, el siguiente cdigo muestra elementos delimitados por coma introducidos en una caja de texto como celdas en una tabla, aadiendo filas a la tabla cada vez que el usuario pulsa el botn. Visual Basic .NET
Private Sub butAdd_Click(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles butAdd.Click Aade texto al ViewState de la pgina ViewState.Add(ViewState.Count, txtSource.Text) Reconstruye la tabla RebuildTable() End Sub Private Sub RebuildTable() Dim iCount1, iCount2 As Integer Dim arrWords As String() Dim strWords As String

60

Developing Web Applications

' Para cadena guardada en ViewState. For iCount1 = 0 To ViewState.Count - 1 Dim rowNew As New TableRow() ' Crea una nueva fila de tabla. strWords = ViewState(iCount1) ' Lee la cadena del ViewState. arrWords = Split(strWords, ",") ' Divide la lista en un array. For iCount2 = 0 To UBound(arrWords) ' Para cada elemento del array. Dim celNew As New TableCell() ' Crea una nueva celda de tabla. celNew.Text = arrWords(iCount2) ' Establece el texto de la celda. rowNew.Cells.Add(celNew) ' Aade la celda a la fila de tabla. Next Table1.Rows.Add(rowNew) ' Aade la fila a la tabla. Next End Sub

Visual C#
private void butAdd_Click(object sender, System.EventArgs e){ ListBox1.Items.Add(txtSource.Text); DropDownList1.Items.Add(txtSource.Text); // Aade texto al ViewState de la pgina. ViewState.Add(ViewState.Count, txtSource.Text); RebuildTable(); } private void RebuildTable(){ string[] arrWords; string strWords; TableRow rowNew; TableCell celNew; // Para cada cadena guardada en ViewState. for (int iCount1 = 0; iCount1 < ViewState.Count; iCount1++) { rowNew = new TableRow(); // Crea una nueva fila de tabla strWords = ViewState(iCount1); // Lee la cadena del ViewState. arrWords = Split(strWords, ","); // Divide la lista en un array. // Para cada elemento del array. for (int iCount2 = 0; iCount2 <= arrWords.GetUpperBound; iCount2++){ celNew = new TableCell(); // Crea una nueva celda de tabla. celNew.Text = arrWords[iCount2]; // Establece el texto de la celda. rowNew.Cells.Add(celNew); // Aade la celda a la fila de tabla. } Table1.Rows.Add(rowNew); // Aade la fila a la tabla. } }

4.1.7 Obtener el elemento seleccionado de una lista


Para obtener la seleccin actual en una lista use la propiedad SelectedItem. Por ejemplo, el siguiente cdigo muestra los elementos seleccionados de una caja de lista en una etiqueta en un formulario Web: Visual Basic .NET
Private Sub Page_Load(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles MyBase.Load ' Comprueba si hay un elemento seleccionado. If Not IsNothing(ListBox1.SelectedItem) Then ' Muestra el elemento seleccionado. Label1.Text = "El elemento seleccionado es: " & _ ListBox1.SelectedItem.Text Else Label1.Text = "No hay ningn elemento seleccionado." End If End Sub

Visual C#
private void Page_Load(object sender, System.EventArgs e){ // Comprueba si hay un elemento seleccionado. if (ListBox1.SelectedItem == null) Label1.Text = "No hay elemento seleccionado."; else // Muestra el elemento seleccionado. Label1.Text = "El elemento seleccionado es: " ListBox1.SelectedItem.Text; }

La propiedad SelectedItem devuelve un objeto; asegrese de comprobar si existe antes de intentar usarlo. 61

MCAD/MCSD

4.1.8 Usar vinculacin de datos sencilla con listas


Los controles pueden obtener sus valores de cualquier origen de datos de la aplicacin. Los orgenes de datos pueden ser cualquier dato pblico sea una tabla de base de datos, un array una propiedad o un objeto, o una expresin que combina varios elementos. A su nivel ms sencillo esto proporciona una forma fcil de inicializar los valores de cajas de lista y listas desplegables en un formulario Web. Para ver cmo funciona la vinculacin sencilla siga estos pasos: 1. Cree un formulario Web con una lista desplegable y este cdigo: Visual Basic .NET
' Elemento de datos pblico para DropDownList. Public arrData As String() = {"Este", "ese", "y", "el", "otro"} Private Sub Page_Load(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles MyBase.Load ' Vincula datos y controles en esta pgina. Page.DataBind() End Sub

Visual C#
public string[] arrData = {"Este", "ese", "y", "el", "otro"}; private void Page_Load(object sender, System.EventArgs e){ Page.DataBind() }

2. Seleccione la lista desplegable y pulse el botn junto a su propiedad DataBindings en la ventana de propiedades. Visual Studio muestra la caja de dilogo DataBindings. Esta caja de dilogo se utiliza para cargar elementos de cualquier origen de datos pblico en un control de tabla o de lista. 3. En la lista Propiedades enlazables seleccione la propiedad DataSource y marque la opcin Expresin de enlace predeterminada; escriba arrData en la caja de texto de la expresin. Cuando ejecute la aplicacin los elementos del array se mostrarn en la lista desplegable. Cuando se usa vinculacin de datos con un control de servidor, puede desactivar la gestin de estado para este control. Esto mejora las prestaciones porque el mtodo DataBind remplaza la gestin de estado automtica que proporciona ASP.NET. Para desactivar la gestin de estado para un control de servidor de el valor False a su propiedad EnableViewState.

4.1.9 Aadir elementos a DataGrid, DataList y Repeater


Use la vinculacin de datos para aadir elementos a los controles DataGrid, DataList y Repeater. Estos tres controles usan plantillas para definir su aspecto en tiempo de ejecucin. Una plantilla es un conjunto de elementos HTML, controles de servidor o ambos que se repetirn para cada elemento del control. Para aadir elementos a un control DataGrid, DataList o Repeater siga estos pasos: 1. Defina el origen de datos 2. Coloque el control DataGrid, DataList o Repeater y vinclelo con el origen de datos 3. Edite las plantillas en el control para aadir elementos HTML o controles de servidor que se repetirn dentro de la lista o rejilla 4. Configure las propiedades del control de servidor contenido en la lista o rejilla para vincular con los elementos de datos en el origen de datos del contenedor. El siguiente ejemplo muestra cmo aadir columnas plantilla a un DataGrid y cmo vincular los controles de estas columnas con un origen de datos sencillo. 1. Cree un origen de datos pblico en su aplicacin como hizo en el ejemplo anterior. Por ejemplo, este cdigo crea un array para probar un origen de datos sencillo. Visual Basic .NET
Elemento de datos pblico para un DataGrid Public arrData As String() = {"This", "that", "and", "the", "other"}

Visual C#
public string[] arrData= {"This", "that", "and", "the", "other"};

2. Coloque un control DataGrid en un formulario Web 3. Aada columnas plantilla al control seleccionndolo y pulsando en el enlace Generador de Propiedades bajo la ventana de propiedades. Visual Studio muestra la caja de dilogo Propiedades.

62

Developing Web Applications

4. En la caja de dilogo Propiedades seleccione Columnas, en la lista Columnas disponibles seleccione Columna plantilla y pulse el botn Agregar (>) para aadir una columna plantilla al control DataGrid. Para este ejemplo, aada dos columnas plantilla y pulse Aceptar. 5. En la ventana de propiedades seleccione la propiedad DataSource y especifique el origen de datos para el control. Para este ejemplo, escriba arrData, el array creado en el paso 1. 6. Cree la plantilla que se usar para mostrar datos en el control: pulse con el botn derecho sobre el control DataGrid, seleccione Editar plantilla y Columna(0). El aspecto del control cambia a modo de edicin. 7. Arrastre otros controles al formulario Web y colquelos en la plantilla para agregarlos al DataGrid. Para este ejemplo coloque un TextBox y arrstrelo a la columna 0. 8. En la ventana de propiedades, seleccione la propiedad DataBindings del control que acaba de aadir a la plantilla y pulse sobre el botn que aparece. Visual Studio muestra la caja de dilogo DataBindings. 9. En la lista Propiedades enlazables seleccione la propiedad que recibir el elemento de datos. Para este ejemplo seleccione Text. Seleccione Enlace simple, despliegue Container y pulse DataItem para especificar qu elemento de datos se pondr en la propiedad seleccionada. Pulse Aceptar para cerrar la caja de dilogo. 10. Edite la segunda plantilla de columna. Para ello pulse con el botn derecho sobre el control DataGrid, seleccione Editar plantilla y Columna (1). 11. Repita los pasos 4 a 7 para Columna(1). Para este ejemplo, coloque un botn en la plantilla Columna(1) del DataGrid. 12. Cuanto termine cierre la plantilla. Para ello pulse con el botn derecho sobre la plantilla y seleccione terminar edicin de plantilla. Visual Studio muestra los controles contenidos. Para cambiar cualquiera de las propiedades del control contenido edite la plantilla como se hizo en los ejemplos anteriores.

4.1.10 Ejecutar comandos


Los controles Button, LinkButton e ImageButton lanzan todos ellos sucesos de envo para ejecutar comandos. Un suceso de envo comienza una peticin desde el navegador, haciendo que el servidor procese los sucesos de la pgina. El procedimiento de suceso Click de un botn control se procesa despus de los sucesos de validacin y en cach de la pgina. Para ver el orden de los sucesos de una pgina coloque un TextBox, un ListBox y un Button en un formulario Web y aada este cdigo. Visual Basic .NET
Private Sub Page_Load(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles MyBase.Load Response.Write("Carga de pgina.<br>") ' Aade elementos a la caja de lista la primera vez que se carga la pgina. If Not IsPostBack Then ListBox1.Items.Add("Este") ListBox1.Items.Add("Ese") ListBox1.Items.Add("El otro") End If End Sub Private Sub TextBox1_TextChanged(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles TextBox1.TextChanged Response.Write("Texto cambiado.<br>") End Sub Private Sub ListBox1_SelectedIndexChanged(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles ListBox1.SelectedIndexChanged Response.Write("Elemento seleccionado.<br>") End Sub Private Sub Button1_Click(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles Button1.Click Response.Write("Botn pulsado.<br>") End Sub

Visual C#
private void Page_Load(object sender, System.EventArgs e){ Response.Write("Carga de pgina.<br>"); // Aade elementos a la caja de lista la primera vez que se carga la pgina. if (!IsPostBack){ ListBox1.Items.Add("Este"); ListBox1.Items.Add("Eso"); ListBox1.Items.Add("El otro"); } }

63

MCAD/MCSD

private void TextBox1_TextChanged(object sender, System.EventArgs e){ Response.Write("Texto cambiado.<br>"); } private void ListBox1_SelectedIndexChanged(object sender, System.EventArgs e){ Response.Write("Elemento seleccionado.<br>"); } private void Button1_Click(object sender, System.EventArgs e){ Response.Write("Botn pulsado.<br>"); }

Cuando se ejecuta el cdigo anterior la pgina muestra el orden de ejecucin de los sucesos. El procedimiento de suceso Click es el ltimo suceso de control que se procesa en la pgina. El uso del procedimiento de suceso Click de Button y LinkButton es directo. El control ImageButton proporciona una capacidad adicional. El argumento de suceso Click para un control incluye coordenadas X e Y del lugar donde ha pulsado el usuario en el control. La respuesta de imagen depende de donde se ha pulsado. Las imgenes que responden a pulsaciones de esta forma se denominan mapas de imagen. El siguiente cdigo usa los argumentos X e Y para calcular en que crculo se ha pulsado. Visual Basic .NET
Private Sub ImageButton1_Click(ByVal sender As System.Object, _ ByVal e As System.Web.UI.ImageClickEventArgs) Handles ImageButton1.Click Dim xOffset, yOffset, X, Y, Radius As Single Dim strMessage As String ' Calcula el radio del punto de pulsacin segn X e Y. xOffset = CSng(sender.width.value) / 2 yOffset = CSng(sender.height.value) / 2 X = System.Math.Abs(CSng(e.X) - xOffset) Y = System.Math.Abs(CSng(e.Y) - yOffset) Radius = System.Math.Sqrt((X ^ 2) + (Y ^ 2)) ' Configura el mensaje a mostrar. Select Case CInt(Radius) Case 0 To 21 strMessage = "en el crculo central." Case 22 To 42 strMessage = "en el segundo crculo." Case 43 To 64 strMessage = "en el tercer crculo." Case 65 To 86 strMessage = "en el cuarto crculo." Case Else strMessage = "fuera del crculo." End Select ' Muestra el mensaje. Label1.Text = "Ha pulsado " & strMessage End Sub

Visual C#
private void ImageButton1_Click(System.Object sender, System.Web.UI.ImageClickEventArgs e){ double xOffset, yOffset, X, Y, Radius; string strMessage; // Calcula el radio del punto de pulsacin a partir de X e Y. xOffset = Convert.ToDouble(ImageButton1.Width.Value) / 2; yOffset = Convert.ToDouble(ImageButton1.Height.Value) / 2; X = Math.Abs(Convert.ToDouble(e.X) - xOffset); Y = Math.Abs(Convert.ToDouble(e.Y) - yOffset); Radius = Math.Sqrt(Math.Pow(X, 2) + Math.Pow(Y, 2)); if (Radius < 22) strMessage = "en el circulo central."; else if ((Radius >= 22) && (Radius <= 42)) strMessage = "en Segundo crculo."; else if ((Radius > 42) && (Radius <= 64)) strMessage = "en tercer crculo."; else if ((Radius > 64) && (Radius <= 86)) strMessage = "en cuarto crculo."; else strMessage = "fuera del crculo."; // Muestra el mensaje. Label1.Text = "Ha pulsado " + strMessage; }

64

Developing Web Applications

4.1.11 Leer y escribir opciones


Use los controles RadioButton, RadioButtonList, CheckBox o CheckBoxList para obtener valores de opciones booleanas del usuario. Como con ListBox y DropDownList, use el editor de colecciones para aadir elementos a un RadioButtonList o CheckBoxList. Pulse la propiedad Items para mostrar el editor de propiedades para un control. Use la propiedad Checked para leer el estado de un CheckBox o RadioButton. Por ejemplo, el siguiente cdigo muestra si el control CheckBox1 est seleccionado. Visual Basic .NET
Private Sub Button1_Click(ByVal sender AS System.Object _ ByVal e as System.EventArgs) Handles Button1.Click Response.Write(CheckBox1 est & Checkbox1.Checked.ToString) End Sub

Visual C#
private void Button1_Click(object sender, System.EventArgs e){ Response.Write(CheckBox1 est + CheckBox1.Checked.ToString()); }

Cuando se coloca inicialmente un RadioButton en un formulario Web no interacta automticamente con los otros RadioButton del formulario en la forma en que lo hacen los controles OptionButton en un formulario Windows. Para que los controles interacten necesitar dar un valor a la propiedad GroupName de los botones. Cuando varios RadioButton tienen el mismo valor en la propiedad GroupName al seleccionar uno se elimina la seleccin de los dems. Para leer o modificar los valores de un control CheckBoxList o RadioButtonList use un bucle For Each para comprobar cada control de la lista. Los controles contenidos en un CheckBoxList no son CheckBox, como se podra esperar. Tanto CheckBoxList como RadioButtonList contienen elementos ListControl. Para determinar el estado de un ListControl use la propiedad Selected, como muestra el siguiente cdigo. Visual Basic .NET
Private Sub Button1_Click(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles Button1.Click Dim lstItem As ListItem For Each lstItem In RadioButtonList1.Items If lstItem.Selected Then Response.Write(lstItem.Text & " est seleccionado.<br>") End If Next End Sub

Visual C#
private void Button1_Click(object sender, System.EventArgs e){ foreach (ListItem lstItem in RadioButtonList1.Items) if (lstItem.Selected) Response.Write(lstItem.Text + " est seleccionado.<br>"); }

4.1.12 Mostrar grficos y avisos


Hay varias formas de mostrar grficos en un formulario Web: Como fondo: Use la propiedad Background del formulario Web para mostrar una imagen en toda la pgina. Use la propiedad BackgroundUrl del control Panel para mostrar una imagen de fondo en una zona de una pgina en lugar de la pgina completa. Como primer plano: Use el control Image para mostrar imgenes en primer plano Como botn: Use el control ImageButton para mostrar imgenes que respondan a sucesos de usuario. Vea la seccin Ejecutar Comandos, ms atrs, para un ejemplo de respuesta a sucesos de pulsacin en una imagen. Como anuncio: Use el control AdRotator para mostrar imgenes de una lista. Los anuncios mostrados por el control AdRotator contienen hiperenlaces con el sitio Web del anunciante. El control Image no responde a sucesos de usuario, pero permite mostrar grficos dinmicamente segn la entrada de otros controles de usuario. Para mostrar una imagen en un control Image en tiempo de ejecucin use la propiedad ImageUrl. Por ejemplo, el siguiente cdigo muestra una imagen cuando se pulsa un botn. Visual Basic .NET
Private Sub Button1_Click(ByVal sender as System.Object, _ ByVal e As System.EventArgs) Handles Button.Click Image1.ImageUrl = gondola.jpg End Sub

65

MCAD/MCSD

Visual C#
private void Button1_Click(object sender, System.EventArgs){ Image1.ImageUrl = gondola.jpg; }

Un uso habitual de los grficos es para anuncios la mayora de los anuncios en Internet se guardan como archivos .gif. Visual Studio incluye el control AdRotator para manejar las tareas asociadas con la presentacin de este tipo de anuncios. El control AdRotator usa un archivo XML para planificar los archivos que se mostrarn. El archivo XML almacena el URL de las imgenes de anuncio, el URL de la pgina que se mostrar si el usuario pulsa el anuncio, la prioridad del anuncio, y otras propiedades. En tiempo de ejecucin, el AdRotator selecciona uno de los anuncios indicados en este archivo y lo muestra en la pgina. Para usar el control AdRotator siga los pasos siguientes: 1. Coloque un control AdRotator en un formulario Web 2. Aada un archivo XML al proyecto actual y bralo 3. En la ventana de propiedades, seleccione la propiedad TargetSchema y seleccione AdRotator Schedule File. Visual Studio aade al archivo XML las siguientes lneas:
<Advertisements xmlns="http://schemas.microsoft.com/AspNet/ AdRotator-Schedule-File"> </Advertisements>

4. Aada una etiqueta <Ad> a la seccin <Advertisements> por cada anuncio que quiera mostrar. 5. Grabe el archivo XML y cambie al formulario Web en modo diseo 6. Seleccione el control AdRotator y configure la propiedad AdvertisementsFile con el archivo XML recin creado. Ahora edite el archivo XML para mostrar la informacin deseada. Por ejemplo, el siguiente archivo XML muestra dos anuncios diferentes
<?xml version="1.0" encoding="utf-8" ?> <Advertisements xmlns="http://schemas.microsoft.com/AspNet/ AdRotator-Schedule-File"> <Ad> <ImageUrl>../ads/sponsorad.gif</ImageUrl> <NavigateUrl>/ads/sponsorad.htm</NavigateUrl> <AlternateText>Click here to visit our sponsor.</AlternateText> <Keyword></Keyword> <Impressions>1</Impressions> </Ad> <Ad> <ImageUrl>../ads/net.gif</ImageUrl> <NavigateUrl>//www.gotdotnet.com</NavigateUrl> <AlternateText> ASP.NET tutorials and more.</AlternateText> <Keyword>ASP</Keyword> <Keyword>.NET</Keyword> <Impressions>5</Impressions> </Ad> </Advertisements>

Las etiquetas del esquema XML de AdRotator son las de la tabla 4.5
Tabla 4. 5: El Esquema AdRotator
Propiedad Ad ImageUrl NavigateUrl AlternateText Keyword Impressions Se usa para Comenzar la definicin de un anuncio. Direccin del anuncio que se muestra. Direccin a la que se va si el usuario pulsa sobre el anuncio. Texto que se muestra en una etiqueta de ayuda cuando el usuario detiene el ratn sobre el anuncio. Si no se puede mostrar ImageUrl se muestra este texto en su lugar. Nombre de categora que se usa para filtrar los anuncios que se muestran Nmero que representa la posibilidad de que se muestre un anuncio. Los anuncios con un nmero ms alto tienen mayor posibilidad de verse.

4.1.13 Agrupar controles


Coloque los controles en un grupo cuando quiera manipular una zona concreta de su formulario Web mediante cdigo. Por ejemplo, si quiere permitir que los usuario conecten con un sistema desde una regin de su pgina, y despus ocultar o desactivar esta zona cuando se hayan conectado. Use el control Panel para agrupar controles en un formulario Web. El uso del control Panel en un formulario Web es diferente de su uso en un formulario Windows. Por un lado, no puede colocar directamente controles en un control Panel; primero se colocan en el formulario Web y despus se arrastran al Panel. Por otra parte, el control

66

Developing Web Applications

Panel de formulario Web usa disposicin en flujo en lugar de rejilla; esto significa que no puede colocar un control en una posicin exacta en un panel. Nota: No es necesario colocar los RadioButton en un panel para que funcionen juntos, en cambio es necesario darles el mismo valor en su propiedad GroupName. Vea la seccin Leer y Escribir Opciones. Para colocar controles en un control Panel siga estos pasos: 1. Coloque los controles en el formulario Web 2. Arrastre los controles al control Panel en el orden en que quiera mostrarlo. Visual Studio colocar cada control inmediatamente tras el otro en secuencia. 3. Use retornos de carro y espacios para colocar los controles. El siguiente ejemplo utiliza un panel con dos controles de texto y un botn para pedir los datos de un usuario. Cuando el usuario se conecta, el panel se oculta. Visual Basic .NET
Private Sub butOK_Click(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles butOK.Click ' Si nombre/contrasea coinciden, oculta el panel y muestra el mensaje. If txtName.Text = "Invitado" And txtPassword.Text = "Amigo" Then pnlLogon.Visible = False Esta etiqueta no est en el panel lblWelcome.Text = "Bienvenido " & txtName.Text Else txtPassword.Text = "" vldPassword.Validate() End If End Sub

Visual C#
private void butOK_Click(object sender, System.EventArgs e){ // Si nombre/contrasea coinciden, oculta el panel y muestra el mensaje. if ((txtName.Text == "Invitado") && (txtPassword.Text == "Amigo")){ pnlLogon.Visible = False; //Esta etiqueta no est en el panel lblWelcome.Text = "Bienvenido " + txtName.Text; }else{ txtPassword.Text = ""; vldPassword.Validate(); } }

4.1.14 Obtener fechas


Para mostrar y obtener informacin de fechas use el control Calendar. Utilice su procedimiento de suceso SelectionChanged y las propiedades SelectedDate o SelectedDates. SelectionChanged es un suceso con envo, de modo que el siguiente cdigo muestra la fecha o fechas seleccionadas en cuanto cambia la seleccin: Visual Basic .NET
Private Sub Page_Load(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles MyBase.Load ' Muestra los datos actuales en la etiqueta para empezar. lblDate.Text = "Fecha actual: " & Date.Now.Date End Sub Private Sub calSource_SelectionChanged(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles calSource.SelectionChanged If calSource.SelectedDates.Count = 1 Then ' Si se ha seleccionado una fecha la muestra en una etiqueta. lblDate.Text = "Fecha seleccionada: " & calSource.SelectedDate Else ' Si se han seleccionado varias fechas, las muestra. lblDate.Text = "Fechas seleccionadas: " & calSource.SelectedDates(0) & _ " a " & calSource.SelectedDates(calSource.SelectedDates.Count - 1) End If End Sub

67

MCAD/MCSD

Visual C#
private void Page_Load(object sender, System.EventArgs e){ // Muestra la fecha actual. lblDate.Text = "Fecha actual: " + calSource.TodaysDate; } private void calSource_SelectionChanged(object sender, System.EventArgs e){ // Muestra la fecha actual. lblDate.Text = "Fecha actual: " + calSource.TodaysDate; if (calSource.SelectedDates.Count == 1) // Si se ha seleccionado una fecha, la muestra. lblDate.Text = "Fecha seleccionada: " + calSource.SelectedDate; else // Si se han seleccionado varias fechas las muestra. lblDate.Text = "Fechas seleccionadas: " + calSource.SelectedDates[0] + " a " + calSource.SelectedDates[calSource.SelectedDates.Count - 1]; }

4.1.15 Obtener archivos del cliente


Utilice el control File Field de HTML para subir archivos del cliente al servidor. El control HTML File Field en realidad es un control Text Field y un botn Submit con la etiqueta Examinar enlazados. Al pulsar el botn se ejecuta un dilogo incorporado que muestra el dilogo Elegir Archivo de Windows en el ordenador del cliente. Para recibir el archivo seleccionado en el servidor siga estos pasos: 1. Coloque un control File Field de HTML en un formulario Web. 2. Pulse con el botn derecho del ratn sobre el control y seleccione Ejecutar como Control del Servidor 3. Pulse con el botn derecho sobre el formulario y seleccione Ver Cdigo Fuente HTML. Visual Studio muestra el cdigo HTML del servidor Web. 4. Aada un atributo enctype a la etiqueta form. Este atributo establece el tipo MIME del formulario, y para subir un archivo es necesario tanto un tipo MIME multipart/form-data como un mtodo de formulario POST , como se ve a continuacin en negrita:
<form action=webform1.aspx method=post enctype=multipart/form-data runat=server ID=Form1>

5. Pulse con el botn derecho sobre el formulario Web y seleccione Ver diseo. Visual Studio muestra el formulario en modo de diseo 6. Aada un control Botn y un procedimiento de suceso Click para obtener y grabar el archivo seleccionado. Por ejemplo, el siguiente procedimiento graba el archivo en el servidor. Visual Basic .NET
Private Sub butUpload_Click(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles butUpload.Click Dim strFilename As String() ' Divide el nombre de archivo en partes. strFilename = filUpload.PostedFile.FileName.Split("\") ' Graba el archivo en el servidor con el nombre base. filUpload.PostedFile.SaveAs(Request.MapPath _ (Request.ApplicationPath) & "\" & strFilename(UBound(strFilename))) ' Aade el archivo a la lista de archivos del servidor. lstServerFiles.Items.Add(strFilename(UBound(strFilename))) ' Selecciona el primer elemento de la lista. lstServerFiles.SelectedIndex = 0 End Sub

Visual C#
private void butUpload_Click(object sender, System.EventArgs e){ // Obtiene el nombre del archivo completo. string strFilename = filUpload.PostedFile.FileName; // Obtiene el nombre base. strFilename = System.IO.Path.GetFileName(strFilename); // Graba el archivo en el servidor con el nombre base. filUpload.PostedFile.SaveAs(Request.MapPath(Request.ApplicationPath) + "\\" + strFilename); // Aade el archivo a la lista de archivos del servidor. lstServerFiles.Items.Add(strFilename); // Selecciona el primer elemento de la lista. lstServerFiles.SelectedIndex = 0; }

El mtodo PostedFile del control HTML File Field representa el archivo que se est subiendo. Puede usar la propiedad FileName y el mtodo SaveAs del objeto devuelto para grabar el archivo en el servidor, como muestra el 68

Developing Web Applications

cdigo precedente. El siguiente cdigo muestra una forma de recuperar el archivo del servidor. En este caso se muestra el archivo en el navegador. Visual Basic .NET
Private Sub butView_Click(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles butView.Click Dim strFilename As String ' Obtiene el nombre de archivo seleccionado. strFilename = lstServerFiles.SelectedItem.ToString ' Muestra como pgina Web. Response.Redirect(Request.ApplicationPath & "/" & strFilename) End Sub

Visual C#
private void butView_Click(object sender, System.EventArgs e){ // Obtiene el nombre de archivo seleccionado. string strFilename = lstServerFiles.SelectedItem.ToString(); // Muestra como pgina Web. Response.Redirect(Request.ApplicationPath + "/" + strFilename); }

4.2 Validar datos


Uno de los pasos ms importantes al obtener entradas de datos de un usuario es asegurarse de que los datos son vlidos. La validez viene determinada por una serie de criterios: Ha introducido algo el usuario? La entrada es del tipo de datos correcto (un nmero de telfono, por ejemplo)? Estn los datos dentro del rango exigido?. ASP.NET proporciona controles de validacin para ayudar a comprobar las entradas en formulario Web frente a estos y otros criterios antes de aceptar los elementos de datos. Esta leccin le ensea cmo usar los controles de validacin para capturar datos no vlidos y orientar al usuario para que corrija el problema.

4.2.1 Usar validacin


Los controles de validacin comprueban la validez de los datos introducidos por el usuario en controles de servidor asociados en el cliente antes de enviarlos al servidor. Esto es una mejora importante ante esquemas de validacin anteriores la mayor parte de los problemas de validacin se pueden capturar y corregir sin implicar una transmisin de ida y vuelta al servidor. La validacin en el cliente la proporciona una librera JScript llamada WebUIValidation.js, que se descarga al cliente por separado. Aunque existe un amplio soporte de JScript, el modelo de objetos de documento (DOM, Document Object Model) en que se basa la librera solo est disponible en Microsoft Explores 4.0 y posteriores. Por tanto, los controles de validacin tambin proporcionan automticamente validacin en el servidor. La validacin en el servidor se ejecuta siempre, se haya producido o no validacin en el cliente. Esta doble comprobacin asegura que la validacin personalizada se ejecuta correctamente y que no se ha esquivado la validacin en el cliente. Los controles de validacin comprueban el valor del control de servidor especificado en su propiedad ControlToValidate. La tabla 4.6 describe los seis controles de validacin.
Tabla 4. 6: Controles de validacin ASP.NET
Control RequiredFieldValidator CompareValidator RangeValidator RegularExpressionValidator CustomValidator ValidationSummary Se usa para Comprobar si un control contiene datos Comprobar si un elemento introducido corresponde con el introducido en otro control Comprobar si un elemento introducido se encuentra entre dos valores Comprobar si un elemento introducido corresponde a un formato concreto Comprobar la validez de un elemento introducido usando una secuencia de comandos de cliente, cdigo de servidor o ambos. Muestra los errores de validacin en un lugar nico, o una descripcin general de error de validacin.

Para usar los controles de validacin siga estos pasos: 1. Coloque un control de validacin en un formulario Web y de cmo valor de su propiedad ControlToValidate el nombre del control que quiere validar. Si est usando el control CompareValidator tambin deber especificar la propiedad ControlToCompare. 2. En la propiedad ErrorMessage del control de validacin escriba el mensaje que quiera mostrar al usuario si los datos no son vlidos. 3. Si quiere que el control de validacin muestre un mensaje diferente a ErrorMessage cuando se produzca un error escrbalo en su propiedad Text. Esta propiedad le permite indicar brevemente dnde se ha producido el error en el formulario, y mostrar el mensaje ErrorMessage, ms largo en el control ValidationSummary. 4. Coloque un control ValidationSummary en el formulario Web para mostrar los mensajes de error de los controles de validacin en un nico lugar. 5. Proporcione un control que lance un suceso de envo. Aunque la validacin se produce en el lado cliente, no comienza hasta que no se solicita el envo. 69

MCAD/MCSD

Para mostrar los mensajes de validacin en una caja de dilogo de el valor True a la propiedad ShowMessageBox de ValidationSummary.

4.2.2 Combinar validaciones


Un control de servidor puede tener varios validadotes. Por ejemplo, un TextBox para un nmero de telfono podra ser tanto obligatorio como con un formato concreto, por tanto puede ser comprobado por dos controles de validacin, un RequiredFieldValidator y un RegularExpressionValidator. Para escribir mensajes de error significativos cuando ms de un control de validacin comprueba un mismo control debe comprender las reglas de validacin de ASP.NET. Estas reglas pueden no tener un sentido obvio, pero hacen posible escribir mensajes de error que tratan problemas concretos. Por ejemplo, todos los controles de validacin salvo RequiredFieldValidator se consideran vlidos si estn en blanco. Esto posibilita proporcionar un mensaje de error si el control est en blanco, usando un RequiredFieldValidator, y un mensaje diferente cuando est fuera de rango o no tiene el formato correcto. Las reglas listadas en la tabla 4-7 se aplican a la conversin de datos para el CompareValidator:
Tabla 4. 7: Reglas de validacin de CompareValidator
Si el control Especificado en la propiedad ControlToValidate no se puede convertir al tipo de datos adecuado Especificado en la propiedad ControlToCompare no se puede convertir al tipo de datos adecuado El resultado es ... No vlido Vlido

En el segundo caso de la tabla 4-7 se debe proporcionar un control de validacin separado para el control especificado en la propiedad ControlToCompare para asegurarse de que es del tipo de datos adecuado.

4.2.3 Cancelar la validacin


Como la validacin se produce antes de que el servidor procese la pgina, un usuario se puede ver atrapado por la validacin, salvo que se proporcione una forma de cancelar la validacin sin en enviar. Para cancelar la validacin incluya un control HTML Submit que configure el atributo Page_ValidationActive, como muestra en negrita el siguiente fragmento de cdigo HTML:
<INPUT id=butCancel onclick=Page_ValidationActive=false type=submit value=Cancel>

La anterior definicin cancela la validacin y enva la pgina de vuelta al servidor. Puede comprobar si el usuario ha cancelado la operacin examinando la propiedad IsValid del objeto Page en el procedimiento de suceso Page_Load. Tiene que volver a validar la pgina porque la operacin de cancelacin de validacin pone IsValid a True. El siguiente cdigo muestra cmo comprobar si el usuario ha cancelado la validacin: Visual Basic .NET
Private Sub Page_Load(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles MyBase.Load ' Valida en caso de cancelacin por el usuario. If Page.IsPostBack Then Page.Validate() ' Comprueba si la pgina es vlida. If Not Page.IsValid Then ' El usuario ha cancelado la operacin, vuelve al inicio. Response.Redirect("default.htm") End If End If End Sub

Visual C#
private void Page_Load(object sender, System.EventArgs e){ // Valida en caso de cancelacin por el usuario. if (Page.IsPostBack){ Page.Validate(); if (!Page.IsValid) // El usuario ha cancelado la validacin. Response.Redirect("default.htm"); } }

4.2.4 Personalizar la validacin


Para ejecutar tipos de validacin complejos no contemplados por los controles de validacin estndar use un control CustomValidator y escriba el cdigo para realizar la validacin en el lado cliente y (opcionalmente) en el servidor.

70

Developing Web Applications

En el servidor, coloque el cdigo de validacin en el procedimiento de suceso ServerValidate. Los argumentos para este procedimiento proporcionan acceso al control que se valida. El siguiente procedimiento de suceso valida que el nmero introducido es primo: Visual Basic .NET
' Valida un nmero primo. Private Sub CustomValidator1_ServerValidate(ByVal source As System.Object, _ ByVal args As System.Web.UI.WebControls.ServerValidateEventArgs) _ Handles CustomValidator1.ServerValidate Try Dim iPrime, iCount As Integer ' Obtiene el valor de ControlToValidate (pasado como args) iPrime = Integer.Parse(args.Value) For iCount = 2 To iPrime \ 2 ' Si el nmero se puede dividir, no es primo, devuelve False. If iPrime Mod iCount = 0 Then args.IsValid = False Return End If Next ' Nmero primo, devuelve True. args.IsValid = True Return Catch ex As Exception ' Si hay un error en el anlisis devuelve False. args.IsValid = False Return End Try End Sub

Visual C#
private void vldtxtPrime_ServerValidate(object source, System.Web.UI.WebControls.ServerValidateEventArgs args){ try{ // Obtiene el valor de ControlToValidate(pasado como args). int iPrime = Int32.Parse(args.Value); for (int iCount = 2; iCount <= (iPrime / 2); iCount++){ // Si se puede dividir no es primo, devuelve False. if((iPrime % iCount) == 0){ args.IsValid = false; return; } // El nmero es primo, devuelve True. args.IsValid = true; return; } }catch(Exception e){ // Si hay un error en el anlisis devuelve False. args.IsValid = false; return; } }

Para proporcionar validacin en el cliente especifique una secuencia de comandos en la propiedad ClientValidatorFunction del control CustomValidator. La validacin en el cliente es opcional, y si se incluye debe mantener un cdigo similar en ambos lugares. La siguiente secuencia de comandos proporciona una versin para cliente de la validacin de nmero primo en el servidor: VBScript
<script language="vbscript"> Sub ClientValidate(source, arguments) For iCount = 2 To arguments.Value \ 2 ' Si el nmero es divisible no es primo, devuelve False. If arguments.Value Mod iCount = 0 Then arguments.IsValid = False Exit Sub End If Next arguments.IsValid = True End Sub </script>

71

MCAD/MCSD

JScript
<script language="jscript"> function ClientValidate(source, arguments){ for (var iCount = 2; iCount <= arguments.Value / 2; iCount++){ // Si el nmero es divisible no es primo, devuelve false. if ((arguments.Value % iCount) == 0){ arguments.IsValid = false; return false; } } // El nmero es primo, devuelve True. arguments.IsValid = true; return true; } </script>

4.3 Navegacin entre formularios


El enlace de informacin es la esencia de la Web. En una aplicacin de formularios Web los hiperenlaces y los mtodos de navegacin son lo que enlaza mltiples formularios entre si en una aplicacin coherente. ASP.NET proporciona varias formas de navegacin entre pginas de la aplicacin, y cada una de estas tcnicas produce unos efectos diferentes en trminos de cmo se muestra la pgina y cmo se intercambian datos entre pginas. En esta leccin aprender como usar cada una de las diferentes tcnicas de navegacin en cdigo y HTML.

4.3.1 Formas de navegar


ASP.NET proporciona cinco formas diferentes de navegar entre pginas en la aplicacin:
Tabla 4. 8: Navegacin entre Pginas
Mtodo de Navegacin Control HyperLink Se usa para Navegar a otra pgina Navegar a otra pgina desde cdigo. Es equivalente a pulsar un hiperenlace Finaliza el formulario Web actual y comienza la ejecucin de uno nuevo. Este mtodo solo funciona para navegar entre pginas de formulario web (.aspx) Comienza la ejecucin de un nuevo formulario Web mientras sigue mostrando la pgina Web actual. El contenido de ambos formularios se combina. Este mtodo solo funciona entre pginas de formulario Web (.aspx) Mtodo de secuencia de comandos que muestra una pgina en una nueva ventana de navegador en el cliente.

Response.Redirect Server.Transfer Server.Execute Window.Open

4.3.2 Uso de hiperenlaces y redireccin


Los controles de servidor Hyperlink responden a sucesos de pulsacin del usuario mostrando la pgina especificada en su propiedad NavigateUrl. El control Hyperlink no expone sucesos de usuario de lado servidor; si quiere interceptar un suceso de pulsacin en el cdigo use el control LinkButton o el control de servidor ImageButton. Para navegar desde un LinkButton o ImageButton use el mtodo Redirect del objeto Response: Visual Basic .NET
Private Sub LinkButton1_Click(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles LinkButton1.Click ' Muestra la siguiente pgina. Response.Redirect("PaginaSiguiente.aspx") End Sub

Visual C#
private void LinkButton1_Click(object sender, System.EventArgs e){ // Muestra la pgina siguiente. Response.Redirect("PaginaSiguiente.aspx"); }

4.3.3 Mtodo Transfer


El uso del mtodo Transfer es muy similar a ejecutar un hiperenlace o usar el mtodo Redirect, con una diferencia: Transfer puede retener informacin de la pgina de origen entre peticiones. Cuando se da el valor True a la propiedad preserveForm del mtodo Transfer la informacin de QueryString, ViewState y procedimiento resuceso estn disponibles en el formulario de destino. Para usar el mtodo Transfer con preserveForm a True primero debe dar el valor False al atributo EnableViewStateMac de la directiva Page del formulario Web. De forma predeterminada ASP.NET aplica un cdigo hash a la informacin de ViewState, y con este valor de atributo se desactiva esta codificacin para que la informacin se pueda leer en el formulario Web siguiente. La siguiente lnea muestra cmo desactivar la codificacin para que se pueda usar el ViewState en otra pgina. 72

Developing Web Applications

Visual Basic .NET


<%@ Page language="vb" EnableViewStateMac="false" Codebehind="RedirectNTransfer.aspx.vb" Inherits="vbNavigateSnippet.WebForm1" %>

Visual C#
<%@ Page language="c#" EnableViewStateMac="false" Codebehind="RedirectNTransfer.aspx.cs" AutoEventWireup="false" Inherits="csNavigateSnippet.WebForm1" %>

El siguiente procedimiento de suceso para un ImageButton muestra cmo se puede pasar informacin entre formularios con el mtodo Transfer. Visual Basic .NET
' Webform1.aspx Private Sub imgTransfer_Click(ByVal sender As System.Object, _ ByVal e As System.Web.UI.ImageClickEventArgs)Handles imgTransfer.Click ' Transfiere a otro formulario reteniendo ViewState. Server.Transfer("Webform2.aspx", True) End Sub

Visual C#
// Webform1.aspx private void ImageButton1_Click(object sender, System.Web.UI.ImageClickEventArgs e){ // Transfiere a otro formulario reteniendo ViewState. Server.Transfer("Webform2.aspx", true); }

Para recuperar la informacin de ViewState del formulario web de origen use el mtodo Form del objeto Request. El siguiente cdigo muestra el estado de un TextBox y las coordenadas X e Y del suceso de pulsacin del ImageButton de Webform1.aspx en Webform2.aspx: Visual Basic .NET
' Webform2.aspx Private Sub Page_Load(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles MyBase.Load Dim colForm As System.Collections.Specialized.NameValueCollection ' Obtiene los datos del formulario Web de origen. colForm = Request.Form ' Muestra el valor del TextBox de Webform1. Response.Write("TextBox1.Text: " & colForm.Item("TextBox1") & "<br>") ' Muestra las coordenadas de la pulsacin. Response.Write("ImageButton X, Y: " & colForm.Item("imgTransfer.x") & _ ", " & colForm.Item("imgTransfer.y") & "<br>") End Sub

Visual C#
// Webform2.aspx private void Page_Load(object sender, System.EventArgs e){ System.Collections.Specialized.NameValueCollection colForm; // Obtiene los datos del formulario Web de origen. colForm = Request.Form; // Muestra el valor del TextBox de Webform1. Response.Write("TextBox1.Text: " + colForm["TextBox1"] + "<br>"); // Muestra las coordenadas de la pulsacin. Response.Write("ImageButton X, Y: " + colForm["imgTransfer.x"] + ", " + colForm["imgTransfer.y"] + "<br>"); }

Nota: Los mtodos Transfer y Execute del objeto Server solo funcionan con formularios Web. Si intenta navegar a una pgina HTML usando uno de estos mtodos provocar un error en tiempo de ejecucin.

4.3.4 Mtodo Execute


Use el mtodo Execute para procesar un segundo formulario Web sin abandonar el primero. Esto permite dirigir los resultados de un formulario Web a una regin de la pgina actual. Como con el mtodo Transfer, Execute exige que el atributo EnableViewStateMac del formulario Web sea False para desactivar la aplicacin del hash a ViewState. Por ejemplo, el siguiente cdigo ejecuta el formulario Web Table.aspx y lo muestra en un control literal en la pgina actual. 73

MCAD/MCSD

Visual Basic .NET


Private Sub butExecute_Click(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles butExecute.Click Dim swrTarget As New System.IO.StringWriter() ' Ejecuta un formulario Web y almacena los resultados. Server.Execute("Table.aspx", swrTarget) ' Muestra el resultado en un control literal. litTable.Text = "<h2>Resultados de la tabla</h2>" & swrTarget.ToString End Sub

Visual C#
private void butExecute_Click(object sender, System.EventArgs e){ System.IO.StringWriter swrTarget = new System.IO.StringWriter(); // Ejecuta un formulario Web y almacena los resultados. Server.Execute("Table.aspx", swrTarget); // Muestra el resultado en un control literal. litTarget.Text = "<h2>Resultados de la tabla</h2>" + swrTarget.ToString(); }

El segundo argumento del mtodo Execute es opcional. Si lo omite el resultado se escribe en la pgina actual. El resultado es aditivo se muestra a la vez el resultado de las dos pginas y los controles de servidor de ambas pginas pueden responder a sucesos. Cuando combine formularios Web usando el mtodo Execute tenga en cuenta que cualquier suceso de envo que se produzca en el segundo formulario limpiar el primero. Por este motivo, la combinacin de formularios es til principalmente cuando el segundo no contiene controles que lancen sucesos de envo.

4.3.5 Mostrar una pgina en una nueva ventana


Para iniciar una nueva instancia del navegador use el mtodo Open de objeto de cliente Window. Solo puede hacerlo como parte de una secuencia de comandos de cliente, porque la nueva ventana se crea en el cliente. Sin embargo, hay formas de controlar el contenido y aspecto de la nueva ventana del navegador desde el servidor. En su forma ms sencilla, el mtodo Window.Open tiene la forma que se muestra en negrita en la siguiente definicin de un control de botn HTML:
<INPUT onclick="window.open('webform2.aspx')" type="submit" value="Nueva Ventana">

Para usar una variable como URL de destino cambie webform2.aspx por una etiqueta de datos:
<INPUT onclick="window.open('<%# urlDestino %>')" type="submit" value="Nueva Ventana">

Para actualizar el URL de destino desde el cdigo use una variable pblica y vinculacin de datos. El siguiente procedimiento de suceso Page_Load configura el URL de destino y lo actualiza mediante vinculacin de datos cuando se carga la pgina: Visual Basic .NET
Public urlTarget As String Private Sub Page_Load(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles MyBase.Load urlTarget = "webform2.aspx" Page.DataBind() End Sub

Visual C#
public string urlTarget; private void Page_Load(object sender, System.EventArgs e){ urlTarget = "webform2.aspx"; Page.DataBind(); }

Como el mtodo Window.Open recibe muchos argumentos diferentes para controlar los diferentes aspectos de la nueva ventana del navegador, puede crear una clase para manejar sus diferentes configuraciones. Las clases le permiten encapsular todas las opciones posibles, de forma que se pueden usar de forma orientada a objetos. El siguiente procedimiento de suceso Page_Load y definicin de clase muestran cmo controlar el tamao, situacin y URL de la nueva ventana mediante cdigo de servidor usando una clase llamada BrowserWindow. Visual Basic .NET
Public urlTarget As New BrowserWindow()

74

Developing Web Applications

Private Sub Page_Load(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles MyBase.Load With urlTarget ' Configura el URL de la nueva ventana. .URL = "HTMLPage1.htm" .Top = 100 .Left = 100 .Width = 400 .Height = 400 End With ' Actualiza el botn HTML. Page.DataBind() End Sub ' Clase que controla las nuevas ventanas creadas en la secuencia de comandos. ' Las opciones predeterminadas mostradas son las mismas del navegador. Public Class BrowserWindow ' Opciones de cadena: predeterminada en blanco. Public URL As String = "about:blank" ' Opciones enteras: 0 llama a predeterminado. Public Height As Integer = 0 Public Width As Integer = 0 Public Top As Integer = 0 Public Left As Integer = 0 ' Opciones tipo boolean, 0 es "no" 1, es "si" Public ChannelMode As Integer = 0 Public Directories As Integer = 1 Public FullScreen As Integer = 0 Public Location As Integer = 1 Public Resizable As Integer = 1 Public ScrollBars As Integer = 1 Public Status As Integer = 1 Public TitleBar As Integer = 1 Public ToolBar As Integer = 1 Public MenuBar As Integer = 1 End Class

Visual C#
public BrowserWindow urlTarget = new BrowserWindow(); private void Page_Load(object sender, System.EventArgs e){ urlTarget.URL = "Execute.aspx"; urlTarget.Top = 100; urlTarget.Left = 100; urlTarget.Width = 400; urlTarget.Height = 400; // Update HTML Button. Page.DataBind(); } // Clase que controla las nuevas ventanas creadas en la secuencia de comandos. // Las opciones predeterminadas mostradas son las mismas del navegador. public class BrowserWindow{ // Opciones de cadena: predeterminada en blanco. public string URL = "about:blank"; // Opciones enteras: 0 llama a predeterminado. public int Height = 0; public int Width = 0; public int Top = 0; public int Left = 0; // Opciones tipo boolean, 0 es "no" 1, es "si". public int ChannelMode = 0; public int Directories = 1; public int FullScreen = 0; public int Location = 1; public int Resizable = 1; public int ScrollBars = 1; public int Status = 1; public int TitleBar = 1; public int ToolBar = 1; public int MenuBar = 1; }

75

MCAD/MCSD

El cdigo HTML para un botn que usa estas opciones tendr el aspecto del siguiente ejemplo (la variable de servidor se muestra en negrita).
<INPUT type="button" value="Show New Window" onclick="window.open('<%# urlTarget.URL %>', null, 'height=<%# urlTarget.Height %>, width=<%# urlTarget.Width %>, top=<%# urlTarget.Top %>, left=<%# urlTarget.Left %>, channelmode=<%# urlTarget.ChannelMode %>, directories=<%# urlTarget.Directories %>,fullscreen=<%# urlTarget.FullScreen %>, location=<%# urlTarget.Location %>,menubar=<%# urlTarget.MenuBar %>, resizable=<%# urlTarget.Resizable %>,scrollbars=<%# urlTarget.ScrollBars %>, status=<%# urlTarget.Status %>,titlebar=<%# urlTarget.TitleBar %>, toolbar=<%# urlTarget.ToolBar %>')">

4.4 Resumen
Los controles de servidor proporcionan propiedades, mtodos y sucesos que se pueden usar en el cdigo de servidor. Los controles HTML proporcionan atributos y sucesos que se pueden usar en scripts que corren en el cliente. Para acceder a propiedades de un control HTML en cdigo de servidor aada un atributo runat=server a la definicin del control. ASP.NET realiza validacin de controles en el lado cliente inmediatamente antes de enviar el formulario al servidor. Una vez que la validacin de cliente tiene xito el formulario se valida de nuevo en el servidor antes de que se produzca el suceso Page_Load. Esto asegura que no se ha modificado el formulario en el cliente para esquivar la validacin y tambin garantiza que la validacin funcionar con navegadores anteriores al Internet Explorer 4.0. Para comprobar varias condiciones sobre un nico campo de datos use varios controles de validacin. Por ejemplo un TextBox que exige un nmero de telfono debe ser controlado por un RequiredFieldValidator y por un RegularExpressionValidator. Para navegar entre pginas de una aplicacin de formularios Web use una de las siguientes tcnicas (los mtodos de Server solo funcionan con formularios Web). Hiperenlaces Mtodo Response.Redirect Mtodo Server.Transfer Mtodo Server.Execute Procedimientos de secuencia de comandos de cliente Para realizar una accin en el navegador cliente debe usar una secuencia de comandos de cliente, por ejemplo, para abrir una pgina en una nueva ventana podra usar un botn HTML con un atributo onclick=window.open. Esto se debe a que las secuencias de comandos de cliente son el nico cdigo de una aplicacin de formularios Web que se ejecuta en el cliente.

4.5 Prctica: Editor de texto basado en Web


En esta prctica va a crear una aplicacin de formulario Web con varias pginas que permitir a los usuarios crear y editar archivos de texto archivados en el servidor. La aplicacin usa el nombre de conexin del usuario para determinar donde se almacenan los archivos. No hace un control de contrasea riguroso de hecho la contrasea siempre es Invitado. La autentificacin de contraseas se trata en el captulo 8, Mantenimiento de Seguridad. Importante: Para crear y borrar archivos la cuenta de usuario ASPNET debe tener derechos de modificacin y de escritura en el directorio raz de la aplicacin. De forma predeterminada esta cuenta solo tiene derechos de lectura y ejecucin. Par informacin sobre como asignar privilegios de seguridad en la carpeta de la aplicacin vea el captulo 9 Crear y Desplegar Aplicaciones Web.

4.5.1 Crear el formulario de registro


En este ejercicio crear el formulario Web que permitir a los usuarios registrarse en el editor de texto. El formulario Web utiliza validacin, disposicin de flujo, navegacin a otras pginas y el espacio de nombres System.IO para los servicios de directorio. Para iniciar la aplicacin y crear el formulario Web SignOn 1. Abra un nuevo proyecto de aplicacin ASP.NET. En el dilogo Nuevo Proyecto escriba el nombre EditorTextoWeb. 2. En la ventana de propiedades, cambie el nombre del archivo Webform1.aspx a SignOn.aspx. 3. En la ventana de propiedades seleccione el objeto DOCUMENT y cambie la propiedad pageLayout a FlowLayout. Despus de cambiar pageLayout a FlowLayout puede aadir controles pulsando dos veces sobre ello en la caja de herramientas. Si crea los controles en el orden en que aparecen en la pgina el proceso es rpido. La si76

Developing Web Applications

guiente tabla muestra los controles que debe crear en el orden adecuado, junto con los valores de sus propiedades. Propiedad Valor ID litNoAccount ID txtName ID vldtxtName ControlToValidate txtName ErrorMessage Por favor, escriba un nombre TextBox ID txtPassword RequiredFieldValidator ID vldtxtPassword ControlToValidate txtPassword ErrorMessage Por favor, escriba la contrasea RangeValidator ID vldtxtPasswordGuest ControlToValidate txtPassword ErrorMessage La contrasea es Invitado MinimumValue Invitado MaximumValue Invitado Button ID butSignOn Text Registro Despus de crear los controles y establecer sus propiedades cambie el diseador para ver el cdigo HTML de la pgina y edite la pgina en modo HTML, aadiendo texto y elementos HTML directamente. Para editar el formulario Web en modo HTML 1. Pulse con el botn derecho sobre el formulario Web y seleccione Ver cdigo fuente HTML. 2. Edite el formulario Web aadiendo el texto y etiquetas HTML que se muestran en negrita:
<form id="Form1" method="post" runat="server"> <h2>Bienvenido al Editor de Texto Web</h2> <asp:Literal id="litNoAccount" runat="server"></asp:Literal> <p>Por favor, regstrese</p> Nombre:<asp:TextBox id="txtName" runat="server" Width="165px"></asp:TextBox> <asp:RequiredFieldValidator id="vldtxtName" runat="server" ErrorMessage="Por favor, escriba un nombre." ControlToValidate="txtName"></asp:RequiredFieldValidator> <br> <br> Contrasea:<asp:TextBox id="txtPassword" runat="server" Width="163px" Height="21px" TextMode="Password"></asp:TextBox> <asp:RequiredFieldValidator id="vldtxtPassword" runat="server" ErrorMessage="Por favor, escriba la contrasea." ControlToValidate="txtPassword"></asp:RequiredFieldValidator> <br> <asp:RangeValidator id="vldtxtPasswordGuest" runat="server" ControlToValidate="txtPassword" ErrorMessage='La contrasea es "Invitado".' MaximumValue="Guest" MinimumValue="Guest"></asp:RangeValidator> <br> <br> <asp:Button id="butSignOn" runat="server" Text="Registro" Width="61px" Height="28px"></asp:Button> <p>Usuarios nuevos, pulsar <a href="NewAccount.aspx">aqu</a> para configurar una cuenta.</p> </form>

Control Literal TextBox RequiredFieldValidator

3.

Para ver el resultado de los cambios pulse con el botn derecho del ratn sobre el formulario Web y seleccione Ver diseo.

Cuando termine de editar el formulario Web cambie a la vista de diseo y pulse dos veces sobre el formulario para ver la ventana de cdigo. Escriba las siguientes sentencias antes de la definicin de clase del formulario: Visual Basic
Imports System.IO

Visual C#
using System.IO

Aada el siguiente cdigo en el procedimiento del suceso Click del botn:

77

MCAD/MCSD

Visual Basic .NET


Private Sub butSignOn_Click(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles butSignOn.Click Dim strPath As String 'Si el usuario existe hay un directorio con su nombre. strPath = Server.MapPath(Request.ApplicationPath) & "\" & txtName.Text If Directory.Exists(strPath) Then ' Configura las variables de sesin. Session("Path") = strPath Server.Transfer("FileManager.aspx") Else ' En caso contrario informa de que no encontr al usuario. litNoAccount.Text = "<p>No se encontr el nombre " & txtName.Text & _ "Compruebe el nombre o pulse <A href='NewAccount.aspx'>aqu</A>" & _ " si es un nuevo usuario.</p>" End If End Sub

Visual C#
private void butSignOn_Click(object sender, System.EventArgs e){ string strPath; // Si el usuario existe hay un directorio con su nombre. strPath = Server.MapPath(Request.ApplicationPath) + "\\" + txtName.Text; if(Directory.Exists(strPath)){ // Configura las variables de sesin. Session["Path"] = strPath; Server.Transfer("FileManager.aspx"); }else // En caso contrario informa de que no encontr al usuario. litNoAccount.Text = "<p>No se encontr el nombre " + txtName.Text + "Compruebe el nombre o pulse <A href='NewAccount.aspx'>aqu</A>" + " si es un nuevo usuario.</p>"; }

4.5.2 Crear el formulario NewAccount


En este ejercicio crear el formulario Web que crea una cuenta para un nuevo usuario. En esta aplicacin una cuenta consiste en un directorio en el raz de la aplicacin con el nombre del usuario. De nuevo, en este ejercicio no se proporciona seguridad; la seguridad se trata en el captulo 8. El formulario Web creado aqu utiliza validacin, disposicin en flujo, navegacin, controles HTML y el espacio de nombre System.IO para servicios de directorio. El formulario usa el nombre de usuario para crear un directorio para los archivos del usuario en el raz de la aplicacin en el servidor. Para crear el formulario Web NewAccount 1. Cree un nuevo formulario Web llamado NewAccount.aspx. 2. En la ventana de propiedades seleccione el objeto DOCUMENT y cambie su propiedad pageLayout a FlowLayout. 3. Aada controles y configure sus propiedades segn la siguiente tabla: Control Propiedad Valor Literal ID litNameExists TextBox ID txtName RequiredFieldValidator ID vldtxtName ControlToValidate txtName ErrorMessage Por favor escriba un nombre Button ID butCreate Text Crear Control HTML Button id butCancel value Cancelar 4. Cambie el formulario Web a vista HTML y aada el texto que se muestra en negrita:

78

Developing Web Applications

<form id="Form1" method="post" runat="server"> <h2>Crear una Cuenta</h2> <asp:Literal id="litNameExists" runat="server"></asp:Literal> <p>Actualmente no tiene una cuenta en el servidor.<br> Escriba a continuacin el nombre que quiere usar para registrarse y pulse Crear.</p> <asp:TextBox id="txtName" runat="server" Width="153px" Height="24px"></asp:TextBox> <asp:RequiredFieldValidator id="vldtxtName" runat="server" ErrorMessage="Por favor, escriba un nombre." ControlToValidate="txtName"> </asp:RequiredFieldValidator> <p> </p> <asp:Button id="butCreate" runat="server" Text="Crear" Width="67" Height="24"></asp:Button> &nbsp;&nbsp; <INPUT type="button" onclick="history.back()" value="Cancelar"></BUTTON> </form>

La ltima modificacin en el cdigo anterior, onclick=history.back() permite que el usuario cancele la operacin sin provocar validacin. Es importante usar aqu un control HTML porque no queremos que se procese en el servidor solo queremos volver al formulario SignOn. Cuando termine de editar el formulario Web vuelva a la vista de diseo y pulse dos veces sobre el botn Crear para ver la ventana de cdigo. Coloque la sentencia Imports o using antes de la definicin de la clase del formulario Web: Visual Basic .NET
Imports System.IO

Visual C#
using System.IO

Aada el siguiente cdigo al procedimiento de suceso butCreate_Click: Visual Basic .NET


Private Sub butCreate_Click(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles butCreate.Click Dim strPath As String 'Comprueba si el directorio existe. strPath = Server.MapPath(Request.ApplicationPath) & "\" & txtName.Text If Directory.Exists(strPath) Then ' Pide al usuario que escriba otro nombre. litNameExists.Text = "<p>El nombre " & txtName.Text & _ " ya existe. Por favor escriba uno diferente.</p>" Return Else Try Directory.CreateDirectory(strPath) ' Crea el directorio. Session("Path") = strPath ' Configura variable de sesin. Server.Transfer("FileManager.aspx") ' Va al admin de archivos. Catch ex As System.UnauthorizedAccessException Server.Transfer("NotAuthorized.aspx") End Try End If End Sub

Visual C#
private void butCreate_Click(object sender, System.EventArgs e){ string strPath; // Comprueba si el directorio existe. strPath = Server.MapPath(Request.ApplicationPath) + "\\" + txtName.Text; if (Directory.Exists(strPath)){ // Pide al usuario que escriba otro nombre. litNameExists.Text = "<p>El nombre " + txtName.Text + " ya existe. Por favor escriba uno diferente.</p>"; return;

79

MCAD/MCSD

}else { try{ Directory.CreateDirectory(strPath); // Crea el directorio. Session["Path"] = strPath; // Configura variable sesin. Server.Transfer("FileManager.aspx"); // Va al admin de archivos. }catch (System.UnauthorizedAccessException ex){ Server.Transfer("NotAuthorized.aspx"); } } }

4.5.3 Crear el formulario FileManager


En este ejercicio crear el formulario Web que permite a los usuarios crear, abrir y borrar archivos en sus cuentas del servidor. El formulario Web creado aqu usa vinculacin de datos, disposicin de flujo, navegacin, QueryString y el espacio de nombres System.IO para acceso a archivos. Para crear el formulario Web FileManager 1. Cree un nuevo formulario Web llamado FileManager.aspx. 2. En la ventana de propiedades seleccione el objeto DOCUMENT y cambie pageLayout a FlowLayout. 3. Aada controles y configure sus propiedades segn la siguiente tabla: Control Propiedad Valor Literal ID litNoFile TextBox ID txtNewFile Button ID butNew Text Nuevo Literal ID litNoneSelected ListBox ID lstFiles DataSource strFiles Button ID butEdit Text Editar Button ID butDelete Text Borrar 4. Cambie el formulario Web a HTML y aada el texto y etiquetas HTML que se muestran en negrita:
<form id="Form1" method="post" runat="server"> <h2>Administrador de Archivos</h2> <p>Para crear un nuevo archivo escriba el nombre y pulse Nuevo.</p> <asp:Literal id="litNoFile" runat="server"></asp:Literal> <asp:TextBox id="txtNewFile" runat="server" Width="191px"></asp:TextBox> <asp:Button id="butNew" runat="server" Width="62px" Height="29px" Text="Nuevo"></asp:Button> <p>Para editar un archivo seleccinelo en la lista y pulse Editar. Pulse Borrar para borrar el archivo seleccionado.</p> <asp:Literal id="litNoneSelected" runat="server"></asp:Literal> <asp:listbox id="lstFiles" runat="server" Width="252px" Height="161px" DataSource="<%# strFiles %>"></asp:listbox><br> <asp:Button id="butEdit" runat="server" Width="62" Height="29" Text="Edit"></asp:Button>&nbsp;&nbsp; <asp:Button id="butDelete" runat="server" Width="62px" Height="29px" Text="Delete"></asp:Button> </form>

5.

Cuando termine de editar el formulario Web vuelva a la vista de diseo y pulse dos veces sobre el botn Nuevo para ver la ventana de cdigo. Coloque las sentencias Imports o using antes de la definicin de clase del formulario Web. Visual Basic .NET
Imports System.IO

Visual C#
using System.IO

6.

Aada el siguiente cdigo a los procedimientos de suceso: Visual Basic .NET


Public strPath As String, strFiles As String()

80

Developing Web Applications

Private Sub Page_Load(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles MyBase.Load ' Obtiene la ruta. strPath = Session("Path") ' Si no es un suceso de envo. If Not IsPostBack Then Dim iCount As Integer 'Obtiene la lista de archivos en el directorio actual. strFiles = Directory.GetFiles(strPath) ' Obtiene los nombres cortos de los archivos. For iCount = 0 To UBound(strFiles) strFiles(iCount) = Path.GetFileName(strFiles(iCount)) Next End If ' Enlaza lstFiles con el array de archivos. lstFiles.DataBind() End Sub Private Sub butNew_Click(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles butNew.Click ' Si hay un nombre de archivo arranca el editor. If txtNewFile.Text <> "" Then Response.Redirect("EditFile.aspx?file=" & txtNewFile.Text) Else ' O presenta un mensaje. litNoFile.Text = "<p>Debe escribir el nombre del archivo.<p>" End If End Sub Private Sub butEdit_Click(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles butEdit.Click ' Si hay un nombre de archivo arranca el editor. If Not IsNothing(lstFiles.SelectedItem) Then Response.Redirect("EditFile.aspx?file=" & _ lstFiles.SelectedItem.ToString) Else ' Si no, muestra un mensaje. litNoneSelected.Text = "<p>Debe seleccionar un archivo.<p>" End If End Sub Private Sub butDelete_Click(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles butDelete.Click ' Si hay un nombre de archivo, arranca el editor. If Not IsNothing(lstFiles.SelectedItem) Then Try Dim filToDelete As File filToDelete.Delete(strPath & "\" & _ lstFiles.SelectedItem.ToString) lstFiles.Items.Remove(lstFiles.SelectedItem) Catch ex As System.Security.SecurityException Server.Transfer("NotAuthorized.aspx") End Try Else ' Si no, muestra un mensaje. litNoneSelected.Text = "<p>Debe seleccionar un archivo.<p>" End If End Sub

Visual C#
string strPath; public string[] strFiles;

81

MCAD/MCSD

private void Page_Load(object sender, System.EventArgs e){ // Obtiene la ruta. strPath = Session["Path"].ToString(); // Si no es un suceso de envo. if(!Page.IsPostBack){ // Obtiene la lista de archivos en el directorio actual. strFiles = Directory.GetFiles(strPath); // Obtiene los nombres cortos de los archivos. for (int iCount = 0; iCount <= strFiles.GetUpperBound(0); iCount++) strFiles[iCount] = Path.GetFileName(strFiles[iCount]); } // Vincula lstFiles con el array de archivos. lstFiles.DataBind(); } private void butNew_Click(object sender, System.EventArgs e){ //Si hay un nombre de archivo, arranca el editor. if (!(txtNewFile.Text == "")) Response.Redirect("EditFile.aspx?file=" + txtNewFile.Text); else // Si no, muestra un mensaje. litNoFile.Text = "<p>Debe escribir un nombre de archivo.<p>"; } private void butEdit_Click(object sender, System.EventArgs e){ // Si hay un nombre de archivo arranca el editor. if (lstFiles.SelectedItem == null) Response.Redirect("EditFile.aspx?file=" + lstFiles.SelectedItem.ToString()); else // Si no, muestra un mensaje. litNoneSelected.Text = "<p>Debe seleccionar un archivo.<p>"; } private void butDelete_Click(object sender, System.EventArgs e){ // Si hay un nombre de archivo, arranca el editor. if (lstFiles.SelectedItem != null) try{ File.Delete(strPath + "\\" + lstFiles.SelectedItem.ToString()); lstFiles.Items.Remove(lstFiles.SelectedItem); }catch(System.UnauthorizedAccessException ex){ Server.Transfer("NotAuthorized.aspx"); } else // Si no, muestra un mensaje. litNoneSelected.Text = "<p>Debe seleccionar un archivo.<p>"; }

4.5.4 Crear el formulario FileEditor


En este ejercicio crear el formulario Web que edita los archivos almacenados en el servidor en la cuenta del usuario. Este formulario usa la misma disposicin y tcnicas de programacin que los del apartado anterior. Para crear el formulario Web FileEditor 1. Cree un nuevo formulario Web llamado FileEditor.aspx. 2. En la ventana de propiedades seleccione el objeto DOCUMENT y cambie pageLayout a FlowLayout. 3. Aada controles y configure sus propiedades segn la siguiente tabla: Control Propiedad Valor TextBox ID txtEditFile TextMode Multiline Height 256px Width 448px Button ID butSave Text Grabar HTML Button id butCancel value Cancelar Button ID butExit Text Salir 4. 82 Cambie el formulario Web a vista HTML y aada el texto que se muestra en negrita:

Developing Web Applications

<form id="Form1" method="post" runat="server"> <h2>Editor de Ficheros</h2> <p>Modifique el fichero debajo. Pulse Grabar para guardar los cambios o Cancelar para descartarlos.</p> <asp:TextBox id="txtEditFile" runat="server" Width="448px" Height="253px" TextMode="MultiLine"></asp:TextBox> <p></p> <asp:Button id="butSave" runat="server" Width="65" Height="30" Text="Save"></asp:Button>&nbsp;&nbsp; <INPUT id="butCancel" onclick="history.back()" type="button" value="Cancelar" style="WIDTH: 65px; HEIGHT: 30px">&nbsp;&nbsp; <asp:Button id="butExit" runat="server" Width="65" Height="30" Text="Salir"></asp:Button> </form>

5.

Cuando termine de editar el formulario Web vuelva a la vista de diseo y pulse dos veces sobre el botn Grabar para ver la ventana de cdigo. Coloque las sentencias Imports o using antes de la definicin de clase del formulario Web. Visual Basic .NET
Imports System.IO

Visual C#
using System.IO

6.

Aada el siguiente cdigo a los procedimientos de suceso: Visual Basic .NET


Dim strPath, strFile As String Private Sub Page_Load(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles MyBase.Load ' Obtiene la ruta y el nombre de archivo. strPath = Session("Path") strFile = Request.QueryString("file") ' Si no es un suceso de envo. If Not IsPostBack Then Try ' Abre el archivo. strmEditFile = File.OpenText(strPath & "\" & strFile) ' Lee su texto. txtEditFile.Text = strmEditFile.ReadToEnd.ToString ' Cierra el archivo. strmEditFile.Close() Catch ex As System.IO.FileNotFoundException ' Si no existe, lo crea. File.CreateText(strPath + "\\" + strFile).Close() ' Vaca la caja de texto. txtEditFile.Text = "" Catch ex As System.UnauthorizedAccessException Server.Transfer("NotAuthorized.aspx") End Try End If End Sub Private Sub butExit_Click(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles butExit.Click If viewstate("changed") Then SaveFile() End If ' Vuelve al administrador de archivos. Response.Redirect("FileManager.aspx") End Sub Private Sub txtEditFile_TextChanged(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles txtEditFile.TextChanged ' Configura el indicador de cambiado. viewstate("changed") = True End Sub Private Sub butSave_Click(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles butSave.Click SaveFile() End Sub

83

MCAD/MCSD

Private Sub SaveFile() Dim strmEditWrite As StreamWriter ' Borra el archivo. File.Delete(strPath & strFile) ' Crea el archivo con el nuevo texto. strmEditWrite = File.CreateText(strPath & "\" & strFile) strmEditWrite.Write(txtEditFile.Text) strmEditWrite.Close() ' Restablece el indicador de cambiado. viewstate("changed") = False End Sub

Visual C#
string strPath, strFile; private void Page_Load(object sender, System.EventArgs e){ // Obtiene la ruta y nombre del archivo. Session["Path"] = "c:"; strPath = Session["Path"].ToString(); strFile = Request.QueryString["file"]; // Si no es un suceso de envo. if (! Page.IsPostBack){ StreamReader strmEditFile; try{ // Abre el archivo. strmEditFile = File.OpenText(strPath + "\\" + strFile); // Lee su texto. txtEditFile.Text = strmEditFile.ReadToEnd().ToString(); // Cierra el archivo. strmEditFile.Close(); }catch(FileNotFoundException ex){ // Si no existe, lo crea. File.CreateText(strPath + "\\" + strFile).Close(); // Limpia la caja de texto. txtEditFile.Text = ""; }catch(System.UnauthorizedAccessException ex){ Server.Transfer("NotAuthorized.aspx"); } } } private void butExit_Click(object sender, System.EventArgs e){ if (ViewState["Changed"].ToString() == "true") SaveFile(); // Vuelve al administrador de archivos. Response.Redirect("FileManager.aspx"); } private void txtEditFile_TextChanged(object sender, System.EventArgs e){ // Configura el indicador de cambio. ViewState["Changed"] = true.ToString(); } private void butSave_Click(object sender, System.EventArgs e){SaveFile();} void SaveFile(){ StreamWriter strmEditWrite; // Borra el archivo. File.Delete(strPath + strFile); // Crear el archivo con el nuevo texto. strmEditWrite = File.CreateText(strPath + "\\" + strFile); strmEditWrite.Write(txtEditFile.Text); strmEditWrite.Close(); // Restablece el indicador de cambio. ViewState["Changed"] = false.ToString(); }

4.5.5 Crear el formulario Web NonAuthorized


Como se mencion al inicio de esta prctica, debe autorizar a la cuenta de usuario ASPNET para que cree y borre archivos en la carpeta raz de la aplicacin. Si no otorga estos permisos todos los intentos de crear, grabar o borrar archivos provocarn un error System.UnauthorizedAccessException. El cdigo de los ejercicios anteriores trata este error usando bloques de manejo de excepciones Try ... Catch / try ... catch. Si se produce el error el Editor de Texto Web muestra un formulario Web con instrucciones. 84

Developing Web Applications

1. 2.

Cree un nuevo formulario Web llamado NonAuthorized.aspx. Cambie a modo HTML y aada el siguiente texto al formulario Web:
<h2>No est autorizado para esta peticin.</h2> <p> Este error se produce cuando la cuenta de usuario ASPNET no est autorizada Para acceder, crear o modificar una carpeta o archivo en el servidor. Utilice el Explorador de Windows para configurar los permisos en el directorio de proyecto de modo que permita que la cuenta de usuario ASPNET modifique, lea y escriba archivos. </p> <a href="SignOn.aspx">Volver a Registro.</a>

4.6 Repaso
Las siguientes preguntas estn pensadas para reforzar informacin clave mostrada en este captulo. Si no es capaz de contestar a una pregunta repase la leccin correspondiente e intente de nuevo. Las respuestas se pueden encontrar en el captulo 16. 1. Cul es la diferencia principal entre el control de servidor Button y el control HTML Button? 2. Cmo se consigue que varios controles RadioButton interacten en un formulario Web de forma que solo se pueda seleccionar uno a la vez? 3. Por qu ASP.NET realiza la validacin en el cliente y en el servidor? 4. Qu tipos de validacin debera utilizar para comprobar que un usuario ha introducido un nmero de cliente correcto? 5. Qu es incorrecto en la siguiente lnea de cdigo? Visual Basic .NET
Server.Transfer(Default.htm)

Visual C#
Server.Transfer(Default.htm)

6. Por qu no se puede abrir una nueva ventana de navegador mediante cdigo de servidor?

85

MCAD/MCSD

86

Developing Web Applications

5 ADO.NET.
En este captulo aprender como usar para leer y modificar datos almacenados en bases de datos OLE y SQL desde formularios Web. Aprender sobre las herramientas de datos incluidas en Visual Studio .NET y cmo usarlas para crear conexiones con, obtener registros de y ejecutar comandos sobre bases de datos. Tambin aprender cmo mostrar datos en un formulario Web usando tanto vinculacin de datos como cdigo. Finalmente aprender cmo usar transacciones para mantener la integridad de una base de datos. Para completar las lecciones de este captulo deber: Tener instalado en su ordenador Microsoft Data Engine (MSDE) o SQL Server 2000 en su ordenador. Visual Studio .NET instala MSDE como parte de su instalacin predeterminada. Instalar la base de datos SQL Contacts (Contacts.mdf) desde el CD-ROM que acompaa al libro. Esta base de datos se usa en los ejemplos de este captulo. Estar familiarizado con los elementos bsicos del lenguaje Transact-SQL. Para encontrar informacin sobre este lenguaje vea el tema Referencia del Lenguaje Transact-SQL en la ayuda de SQL Server.

5.1 Acceso a datos con ADO.NET


Visual Studio .NET proporciona acceso a bases de datos mediante el conjunto de herramientas y espacios de nombres conocidos colectivamente como ADO.NET. El acceso a datos en ADO.NET est estandarizado de forma que en su mayor parte es independiente del origen de datos una vez establecida una conexin con una base de datos se usa un conjunto coherente de objetos, propiedades y mtodos, independientemente del tipo de base de datos que se est usando. En esta leccin aprender cmo usar ADO.NET para conectar con una base de datos y cmo leer, modificar y borrar registros de la base de datos. Las lecciones de este captulo usan la base de datos Contacts (Contacts.mdf) incluida en el CD-ROM de acompaamiento para todos sus ejemplos. Asegrese de instalar esta base de datos antes de intentar probar los ejemplos.

5.1.1 ADO.NET
En ADO.NET hay tres capas para el acceso a datos: Almacn de datos fsico: Puede ser una base de datos OLE, una base de datos SQL o un archivo XML. Proveedor de datos: Consiste en los objetos Connection y Command que crear la representacin de los datos en memoria. Conjunto de datos: Representacin en memoria de las tablas y relaciones con las que se trabaja en la aplicacin. La capa proveedor de datos proporciona la abstraccin entre el almacn de datos fsico y el conjunto de datos con el que se trabaja en el cdigo. Despus de crear el conjunto de datos no importa de donde procede o donde est almacenado. Esta arquitectura se denomina desconectada porque el conjunto de datos es independiente del almacn de datos. En ADO.NET hay dos formas de conexiones con base de datos:
Fig. 5. 1: Objetos Connection y Command

Usar un objeto OleDbConnection para conectar con una base de datos local: Las conexiones con bases de datos OLE usan el objeto OleDbDataAdapter para ejecutar comandos y recuperar datos. Usar un objeto SqlDbConnection para conectar con una base de datos de servidor: Las conexiones con bases de datos SQL usan el objeto SqlDbDataAdapter para ejecutar comandos y recuperar datos. Adems de estas conexiones con bases de datos, puede acceder directamente a archivos XML desde conjuntos de datos usando los mtodos ReadXML y WriteXML del objeto DataSet. Los archivos XML son representaciones estticas de conjuntos de datos. ADO.NET usa XML para todas sus transferencias a travs de Internet. ADO.NET proporciona sus objetos, propiedades y mtodos mediante los tres espacios de nombres descritos en la tabla 5.1. Los espacios de nombres System.Data.SqlClient y System.Data.OleDb proporcionan funcionalidades equivalentes para bases de datos SQL y OLE respectivamente.
Tabla 5. 1: Espacios de Nombres ADO.NET
Espacio de Nombres Proporciona Clases, tipos y servicios para crear y acceder a conjuntos de datos y sus objetos subordinados. Clases y tipos para acceder a bases de datos Microsoft SQL Server Clases y tipos para acceder a bases de datos OLE.

System.Data System.Data.SqlClient System.Data.OleDb

87

MCAD/MCSD

Cuando se trabaja con bases de datos en cdigo necesitar aadir declaraciones Imports o using al principio del mdulo de cdigo. Para acceder a una base de datos mediante ADO.NET siga estos pasos: 1. 2. 3. 4. 5. Crear una conexin con la base de datos usando un objeto conexin. Llamar a un comando para crear un DataSet usando un objeto adaptador. Usar el objeto DataSet en el cdigo para mostrar los datos o cambiar elementos de la base de datos. Llamar a un comando para actualizar la base de datos desde el DataSet usando un objeto adaptador. Cerrar la conexin con la base de datos, si la abri explcitamente en el paso 2 usando el mtodo Open. Al llamar a un comando sin llamar primero al mtodo Open abre y cierra implcitamente la conexin con cada peticin. Las siguientes secciones discuten cada uno de estos pasos con ms detalle.

5.1.2 Conectar con una base de datos


Use el explorador de servidores para conectar con una base de datos en Visual Studio. Para conectar con una base de datos en el entorno de diseo de Visual Studio siga estos pasos: 1. En el men Ver seleccione Explorador de Servidores. 2. En la barra de herramientas del Explorador de Servidores pulse el botn Conectar con base de datos. Visual Studio .NET muestra el dilogo Propiedades de vnculo de datos. 3. Pulse la lengeta Proveedor para seleccionar el tipo de base de datos para la conexin. El proveedor predeterminado es Microsoft OLE DB Provider for SQL Server. Esta es la opcin correcta si su base de datos corre bajo Microsoft SQL Server. Para acceder a un tipo de base de datos diferente seleccione el proveedor adecuado. Por ejemplo, para acceder directamente a una base Microsoft Access 2000 seleccione Microsoft Jet 4.0 OLE DB Provider. 4. Pulse la lengeta Conexin para especificar la base de datos con la cual conectar. Al cambiar el proveedor en el paso 3 cambian las opciones de conexin. 5. Introduzca las opciones de conexin y pulse Probar conexin para asegurarse de que la configuracin es correcta. Cuando la configuracin sea correcta pulse Aceptar. Visual Studio aade la conexin al servidor de datos al Explorador de Servidores. 6. Al pulsar el signo ms (+) en el Explorador de Servidores se expanden elementos. Para ver las tablas en una conexin de base de datos expanda los elementos bajo la conexin y expanda los elementos bajo Tablas. 7. Para aadir un elemento a la aplicacin arrstrelo desde el explorador y sultelo en el formulario Web. Por ejemplo, arrastre la tabla Contacts. Cuando suelte la tabla en el formulario Web Visual Studio crea los objetos conexin y adaptador con la configuracin adecuada. Importante: Las aplicaciones Web se ejecutan bajo la cuenta de usuario ASP.NET. El administrador de la base de datos deber configurar esta cuenta y otorgarle permisos antes de que la aplicacin tenga acceso a la base de datos. Para bases de datos Access debe otorgar a la cuenta de usuario ASP.NET permisos sobre el archivo de base de datos usando las opciones de seguridad de archivos de Windows.

5.1.3 Crear un conjunto de datos


Utilice los objetos conexin y adaptador creados en el paso 7 de la seccin anterior para crear un conjunto de datos. Para crear un conjunto de datos en modo diseo siga estos pasos: 1. Pulse con el botn derecho sobre el objeto adaptador de datos y seleccione Generar conjunto de datos. Visual Studio muestra el dilogo Generar conjunto de datos. 2. Seleccione las tablas que se aadirn al conjunto de datos y pulse Aceptar. Visual Studio crea un nuevo objeto DataSet y lo aade al formulario Web. Para ver los datos del conjunto de datos en modo diseo pulse con el botn derecho sobre el objeto DataSet y seleccione Ver esquema. Visual Studio muestra el conjunto de datos en la ventana del diseador XML.

5.1.4 Mostrar un conjunto de datos


Para mostrar un conjunto de datos en un formulario Web en tiempo de ejecucin siga estos pasos: 1. Aada al formulario un control para mostrar el conjunto de datos, por ejemplo un DataGrid. 2. Configure el conjunto de datos como origen de datos del control. Por ejemplo, para el control DataGrid pulse sobre el enlace Generador de propiedades bajo la ventana de propiedades, seleccione el objeto DataSet como valor de la propiedad DataSource y una de sus tablas como valor de DataMember.

88

Developing Web Applications

3. Configure las columnas que mostrar el control. Para el control DataGrid pulse el elemento Columnas en la caja de dilogo Propiedades, quite la marca de Crear columnas automticamente en tiempo de ejecucin, y aada las columnas que se van a mostrar de la lista Columnas disponibles. Pulse Aceptar cuando termine. 4. Aada al procedimiento de suceso Page_Load cdigo para rellenar el conjunto de datos a partir del adaptador de datos y vincular los datos del objeto DataSet al control. Por ejemplo, el siguiente cdigo muestra los datos en el control DataGrid creado en los pasos anteriores. Visual Basic .NET
Private Sub Page_Load(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles MyBase.Load ' Rellena el conjunto de datos. SqlDataAdapter1.Fill(DataSet1) ' Actualiza el DataGrid. DataGrid1.DataBind() End Sub

Visual C#
private void Page_Load(object sender, System.EventArgs e){ // Rellena el conjunto de datos. sqlDataAdapter1.Fill(DataSet1); // Actualiza el DataGrid. DataGrid1.DataBind(); }

5. Ejecute la aplicacin. Cuando se carguen los datos debe ver una tabla con los mismos. Consejo: Como est rellenando el conjunto de datos y vinculando los datos con el control DataGrid en el suceso Page_Load no necesita mantener informacin de estado para el control DataGrid. Desactivar la informacin de estado mejora las prestaciones porque no es necesario guardar los datos del DataGrid en el ViewState de la pgina entre peticiones. De el valor False a la propiedad EnableViewState para desactivar el mantenimiento de estado para el control.

5.1.5 Cambiar registros en la base de datos


El DataSet es el objeto central de ADO.NET. Los aadidos, borrados o cambios a los registros de una base de datos por lo general se hacen mediante un objeto DataSet. Para cambiar registros por medio de un objeto DataSet siga estos pasos: 1. Obtenga un objeto DataSet como se describe en las secciones anteriores. 2. Modifique el DataSet. 3. Actualice la base de datos con el DataSet llamando al mtodo Update del adaptador de datos. Para obtener los elementos de datos de un DataSet use las colecciones Tables, Rows y Columns.
Fig. 5. 2: Colecciones del DataSet

5.1.6 Cmo hace referencia a objetos ADO.NET


Cuando se crean objetos conexin, adaptador y conjunto de datos en modo diseo se activa el tipado de datos para estos objetos. Esto significa que puede usar los nombres especficos del esquema de base de datos para identificar tablas, filas y campos. Este es un gran cambio respecto a ADO, que solo proporciona referencias sin tipo a los objetos de datos. Las siguientes lneas de cdigo equivalentes muestran una referencia con tipo frente a una referencia sin tipo a un objeto de una base de datos. Visual Basic .NET
' Referencia con tipo a la columna HomePhone de la tabla Contacts. DataSet1.Contacts.HomePhoneColumn.Caption = "@Home" ' Referencia sin tipo a la misma columna. DataSet1.Tables("Contacts").Columns("HomePhone").Caption = "@Home"

Visual C#
// Referencia con tipo a la columna HomePhone de la tabla Contacts. DataSet1.Contacts.HomePhoneColumn.Caption = "@Home"; // Referencia sin tipo a la misma columna. DataSet1.Tables["Contacts"].Columns["HomePhone"].Caption = "@Home";

89

MCAD/MCSD

La primera lnea no solo es ms sencilla de leer y escribir, sino que tambin es mucho menos propensa a errores, puesto que Visual Studio comprueba los tipos de datos mientras se trabaja, marcando cualquier error como referencia no reconocida. En general debe usar referencias con tipos cuando trabaje con objetos de datos. La excepcin a esta regla se produce cuando no se conoce el objeto especfico con el que se est trabajando. Normalmente esta situacin se produce cuando se proporciona el origen de datos en tiempo de ejecucin en lugar de en tiempo de diseo. La informacin de tipos para objetos de datos procede del esquema XML que genera Visual Studio cuando se crea un conjunto de datos en modo de diseo. Para ver informacin de tipo para un conjunto de datos pulse con el botn derecho sobre el conjunto de datos en la ventana de diseo y seleccione Ver esquema. Visual Studio muestra el conjunto de datos en el diseador XML. Puede usar el diseador XML para aadir elementos, especificar claves nicas y ver o cambiar los tipos de datos de elementos en un conjunto de datos.

5.1.7 Aadir, cambiar y borrar filas


Para aadir, cambiar o borrar filas en el objeto Table de DataSet use la coleccin Rows. Para aadir un registro a un conjunto de datos cree un nuevo objeto Row y adalo a la coleccin Rows, como muestra este cdigo: Visual Basic .NET
' Usa conexin, adaptador y conjunto de datos creados en modo diseo. Private Sub butAddRow_Click(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles butAddRow.Click ' Crea un nuevo objeto fila para la tabla Contacts. Dim rowNew As DataSet1.ContactsRow = DataSet1.Contacts.NewRow ' Aade datos a las columnas de la fila. rowNew.ContactID = 42 rowNew.FirstName = "Danielle" rowNew.LastName = "Tiedt" rowNew.WorkPhone = "(111) 555-1212" ' Aade la fila al conjunto de datos. DataSet1.Contacts.Rows.Add(rowNew) End Sub

Visual C#
// Usa conexin, adaptador y conjunto de datos creados en modo diseo. private void butAddRow_Click(object sender, System.EventArgs e){ // Crea un nuevo objeto fila para la tabla Contacts. DataSet1.ContactsRow rowNew = (DataSet1.ContactsRow)DataSet1.Contacts.NewRow(); // Aade datos a las columnas de la fila. rowNew.ContactID = 42; rowNew.FirstName = "Danielle"; rowNew.LastName = "Tiedt"; rowNew.WorkPhone = "(111) 555-1212"; }

Para cambiar una fila en un conjunto de datos obtenga un objeto Row de la tabla usando el mtodo FindBy y haga los cambios a los campos de la fila, como muestra este cdigo: Visual Basic .NET
' Usa conexin, adaptador y conjunto de datos creados en modo diseo. Private Sub butChangeRow_Click(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles butChangeRow.Click ' Declara un objeto fila. Dim rowChange As DataSet1.ContactsRow ' Obtiene la fila a modificar mediante su clave principal. rowChange = DataSet1.Contacts.FindByContactID(42) ' Cambia un campo de la fila. rowChange.WorkPhone = "(111) 555-9000" End Sub

Visual C#
// Usa conexin, adaptador y conjunto de datos creados en modo diseo. private void butChangeRow_Click(object sender, System.EventArgs e){ // Declara un objeto fila. DataSet1.ContactsRow rowChange; // Obtiene la fila a cambiar mediante su clave Principal.

90

Developing Web Applications

rowChange = DataSet1.Contacts.FindByContactID(42); // Cambia un campo de la fila. rowChange.WorkPhone = "(111) 555-9000"; }

Para borrar una fila de un conjunto de datos obtenga un objeto Row de la tabla usando el mtodo FindBy y brrelo usando su mtodo Delete: Visual Basic .NET
' Usa conexin, adaptador y conjunto de datos creados en modo diseo. Private Sub butDeleteRow_Click(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles butDeleteRow.Click ' Declara un objeto fila. Dim rowDelete As DataSet1.ContactsRow ' Obtiene la fila a borrar. rowDelete = DataSet1.Contacts.FindByContactID(42) ' Borra la fila. rowDelete.Delete() End Sub

Visual C#
// Usa conexin, adaptador y conjunto de datos creados en modo diseo. private void butDeleteRow_Click(object sender, System.EventArgs e){ // Declara un objeto fila. DataSet1.ContactsRow rowDelete; // Obtiene la fila a borrar rowDelete = DataSet1.Contacts.FindByContactID(42); // Borra la fila. rowDelete.Delete(); }

5.1.8 Actualizar la base de datos desde el conjunto de datos


Para actualizar la base de datos con los cambios hechos en un objeto DataSet use el mtodo Update del adaptador de datos. Normalmente querr hacer esto despus de que se hayan procesado todos los sucesos de control en una pgina; por tanto, el mtodo Update normalmente se llama desde el suceso Page_PreRender, como se muestra aqu: Visual Basic .NET
' Usa conexin, adaptador y conjunto de Private Sub Page_PreRender(ByVal sender ByVal e As System.EventArgs) Handles ' Actualiza la base de datos con los SqlDataAdapter1.Update(DataSet1) End Sub datos creados en modo diseo. As Object, _ MyBase.PreRender cambios del conjunto de datos.

Visual C#
// Usa conexin, adaptador y conjunto de datos creados en modo diseo. private void Page_PreRender(object sender, System.EventArgs e) { // Actualiza la base de datos con los cambios del conjunto de datos. sqlDataAdapter1.Update(DataSet1); }

Cuando actualiza una base de datos desde un conjunto de datos ADO.NET sigue estos pasos: 1. Determina los cambios al conjunto de datos comprobando la propiedad RowState de cada objeto DataRow. Los valores posibles son Added, Deleted, Modified, Unchanged o Detached. 2. Llama a las propiedades InsertCommand, DeleteCommand o UpdateCommand del objeto adaptador para hacer los cambios necesarios en la base de datos. 3. Restablece las propiedades RowState de los objetos DataRow actualizados a Unchanged. Las propiedades InsertCommand, DeleteCommand y UpdateCommand del objeto adaptador se generan automticamente a partir de la propiedad SelectCommand del objeto cuando se crea un conjunto de datos a partir de un adaptador de datos en modo diseo. Cada una de estas propiedades representa un objeto OleCommand o SqlCommand. Los objetos comando tienen las siguientes propiedades que determinan cmo se ejecutan: La propiedad CommandText contiene la sentencia SQL o el nombre del procedimiento almacenado. La propiedad CommandType determina cmo se ejecuta el comando mediante las siguientes opciones: El valor Text ejecuta el comando como sentencia SQL (predeterminado). El valor StoredProcedure ejecuta el comando como procedimiento almacenado en la base de datos. El valor TableDirect devuelve la tabla completa. Solo se aplica a proveedores de datos NET para OLE DB. 91

MCAD/MCSD

Puede cambiar el contenido del conjunto de datos y cmo se actualiza cambiando las sentencias SQL utilizadas por estos objetos comando. Para ver o modificar estos comandos siga estos pasos: 1. En la ventana de propiedades pulse dos veces sobre la propiedad comando que quiere modificar. Esto expande la lista de propiedades que se aplican al objeto comando. 2. Seleccione la propiedad CommandText del comando y pulse el botn elipsis a la derecha de su valor. Visual Studio muestra el dilogo Generador de consultas. 3. Seleccione las columnas que se incluirn en el comando marcando las cajas junto a los nombres de los campos de datos en el panel tabla, o escriba directamente la sentencia SQL en el panel de comando. Cuando termine pulse Aceptar.

5.1.9 Crear una conexin en tiempo de ejecucin


La creacin de objetos de datos en modo de diseo es una gran forma de aprender sobre el acceso de datos en ADO.NET porque Visual Studio genera las opciones de propiedades de los objetos conexin y adaptador. La configuracin de algunas propiedades, como ConnectionString, puede ser difcil y confusa sin la ayuda del modo diseo. Despus de crear una conexin en modo diseo puede cortar y pegar las opciones de propiedades para crear conexiones similares mediante cdigo. El uso de objetos de acceso a datos mediante cdigo sigue la misma secuencia que en modo diseo: 1. 2. 3. 4. 5. Crear el objeto conexin Crear un objeto adaptador Crear un objeto conjunto de datos Llamar a mtodos del objeto adaptador para llenar o actualizar el conjunto de datos Usar vinculacin de datos u otra tcnica para mostrar los datos del conjunto de datos. Por ejemplo, el siguiente cdigo crea objetos de datos y muestra datos de un proveedor SQL: Visual Basic .NET
Private Sub Page_Load(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles MyBase.Load ' (1) Crear la conexin. Dim sqlconnectContactMgmt As New SqlConnection _ ("server=(local);database=Contacts;Trusted_Connection=yes") ' (2) Crear un adaptador de datos. Dim sqladaptContactMgmt As New _ SqlDataAdapter("select * from Contacts", sqlconnectContactMgmt) ' (3) Crear un conjunto de datos. Dim dsContacts As New DataSet() ' (4) Rellenar el conjunto de datos. sqladaptContactMgmt.Fill(dsContacts, "Contacts") ' (5) Mostrar la tabla en una rejilla mediante vinculacin de datos. DataGrid1.DataSource = dsContacts.Tables("Contacts").DefaultView DataGrid1.DataBind() End Sub

Visual C#
private void Page_Load(object sender, System.EventArgs e){ // (1) Crear la conexin. SqlConnection sqlconnectContactMgmt = new SqlConnection ("server=(local);database=Contacts;Trusted_Connection=yes"); // (2) Crear un adaptador de datos. SqlDataAdapter sqladaptContactMgmt = new SqlDataAdapter("select * from Contacts", sqlconnectContactMgmt); // (3) Crear un conjunto de datos. DataSet dsContacts = new DataSet(); // (4) Rellenar el conjunto de datos. sqladaptContactMgmt.Fill(dsContacts, "Contacts"); // (5) Mostrar la tabla en una rejilla mediante vinculacin de datos. DataGrid1.DataSource = dsContacts.Tables["Contacts"].DefaultView; DataGrid1.DataBind(); }

5.1.10 Actualizar una Conexin en tiempo de ejecucin


Como se mencion anteriormente en esta seccin ADO.NET usa las propiedades InsertCommand, DeleteCommand y UpdateCommand para actualizar la base de datos desde el conjunto de datos. Cuando se crea una adaptador de datos en tiempo de ejecucin es necesario generar estas propiedades entes de llamar al mtodo Update del objeto adaptador. 92

Developing Web Applications

Para generar las propiedades InsertCommand, DeleteCommand y UpdateCommand en tiempo de ejecucin siga estos pasos: 1. Configure el SelectCommand del objeto adaptador. ADO.NET usa la propiedad CommandText del SelectCommand para generar las opciones para InsertCommand, DeleteCommand y UpdateCommand. 2. Cree un objeto generador de comando par el objeto adaptador. El objeto generador de comando depende del proveedor de datos, por lo que tiene dos formas: OleDbCommandBuilder y SqlCommandBuilder. El siguiente cdigo conecta con una base de datos (1), crea un conjunto de datos (2), genera comandos (3), modifica el conjunto de datos (4) y actualiza la base de datos segn estos cambios (5): Visual Basic .NET
Private Sub Page_Load(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles MyBase.Load ' (1) Crea la conexin. Dim ContactMgmt As New SqlConnection _ ("server=(local);database=Contacts;Trusted_Connection=yes") ' Crea un adaptador. Dim adptContactMgmt As New _ SqlDataAdapter("select * from Contacts", ContactMgmt) ' (2) Crea un conjunto de datos. Dim dsContacts As New DataSet() ' Configura el comando de seleccin. adptContactMgmt.SelectCommand.CommandText = "SELECT * FROM Contacts" ' (3) Crea comandos de insercin, borrado y actualizacin automticamente. Dim cmdContactMgmt As SqlCommandBuilder = New _ SqlCommandBuilder(adptContactMgmt) ' (4) Crea una nueva fila. Dim rowInsert As DataRow = dsContacts.Tables("Contacts").NewRow ' Aade datos a los campos de la fila. rowInsert("ContactID") = 42 rowInsert("FirstName") = "Danielle" rowInsert("LastName") = "Tiedt" rowInsert("WorkPhone") = "(555) 555-1212" ' Aade la fila al conjunto de datos. dsContacts.Tables("Contacts").Rows.Add(rowInsert) ' (5) Actualiza la base de datos. adptContactMgmt.Update(dsContacts.Tables("Contacts")) End Sub

Visual C#
private void Page_Load(object sender, System.EventArgs e){ // (1) Crea la conexin. SqlConnection ContactMgmt = new SqlConnection("server=(local);database=Contacts;Trusted_Connection=yes"); // Crea un adaptador. SqlDataAdapter adptContactMgmt = new SqlDataAdapter ("select * from Contacts", ContactMgmt); // (2) Crea un conjunto de datos. DataSet dsContacts = new DataSet(); // Configura el comando de seleccin. adptContactMgmt.SelectCommand.CommandText = "SELECT * FROM Contacts"; // (3) Crea comandos de insercin, borrado y actualizacin automticamente. SqlCommandBuilder cmdContactMgmt = new SqlCommandBuilder(adptContactMgmt); // (4) Crea una nueva fila. DataRow rowInsert = dsContacts.Tables["Contacts"].NewRow(); // Aade datos a los campos de la fila. rowInsert["ContactID"] = 42; rowInsert["FirstName"] = "Danielle"; rowInsert["LastName"] = "Tiedt"; rowInsert["WorkPhone"] = "(222) 555-1212"; // Aade la fila al conjunto de datos. dsContacts.Tables["Contacts"].Rows.Add(rowInsert); // (5) Actualiza la base de datos. adptContactMgmt.Update(dsContacts.Tables["Contacts"]); }

El mtodo Update del cdigo precedente necesita que se cree primero el objeto SqlCommandBuilder. Al crear este objeto se proporciona la configuracin de la propiedad InsertCommand que el objeto adaptador usa para aadir la nueva fila a la base de datos.

93

MCAD/MCSD

5.2 Usar conjuntos de datos en formularios Web


La mayor parte de los controles de servidor ASP.NET soportan vinculacin de datos, que es una forma de enlazar datos de la aplicacin, como conjuntos de datos, a propiedades de un control. En concreto, los controles de servidor DataGrid y DataList estn diseados especficamente para que la presentacin de un conjunto de datos en un formulario Web sea sencilla y eficiente. En esta leccin aprender cmo mostrar un conjunto de datos en un formulario Web usando DataGrid, DataList y otros controles de servidor. Aprender cmo seleccionar registros de un conjunto de datos en un formulario Web y cmo ejecutar comandos SQL en una base de datos desde procedimientos de suceso de un control.

5.2.1 Mostrar un conjunto de datos en un DataGrid


La forma ms sencilla de mostrar un conjunto de datos en un formulario web es mediante un control DataGrid usando vinculacin de datos. Siga estos pasos: 1. 2. 3. 4. Cree los objetos conexin, adaptador y conjunto de datos como se describe en la seccin anterior. Aada un control DataGrid al formulario web Use como valor de la propiedad DataSource del DataGrid el nombre del conjunto de datos. Aada en el suceso Page_Load del formulario Web el cdigo para rellenar el conjunto de datos a partir del adaptador y vincular los datos del conjunto de datos con el DataGrid.

Por ejemplo, el siguiente procedimiento de suceso crea un conjunto de datos a partir de la tabla Contacts de la base de datos Contacts y lo muestra en un control DataGrid: Visual Basic .NET
Private Sub Page_Load(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles MyBase.Load ' Rellena el conjunto de datos. adptContacts.Fill(dsContacts) ' Vincula el conjunto de datos con el control DataGrid. grdContacts.DataBind() End Sub

Visual C#
private void Page_Load(object sender, System.EventArgs e){ // Rellena el conjunto de datos. adptContacts.Fill(dsContacts); // Vincula los datos con el control DataGrid. grdContacts.DataBind(); }

El procedimiento anterior muestra todas las columnas del conjunto de datos sin darles ningn formato. Por lo general esto no es lo que se quiere; por ejemplo, la columna Birthdate incluye la hora adems de la fecha. Para seleccionar las columnas que quiere mostrar y dar formato a los datos siga estos pasos: 1. Pulse el enlace Generador de propiedades en la ventana Propiedades. Visual Studio muestra el dilogo Propiedades del DataGrid. 2. Seleccione el elemento Columnas en el lado izquierdo del dilogo para seleccionar las columnas del conjunto de datos que se van a mostrar y darles formato. Visual Studio muestra las propiedades de columnas. Para mostrar columnas concretas del conjunto de datos siga estos pasos: 1. Quite la marca de la caja Crear columnas automticamente en tiempo de ejecucin. Esto limita las columnas del DataGrid a las que se seleccionen. 2. Seleccione la columna en la lista Columnas disponibles y pulse el botn Aadir (>) para aadirla a la lista Columnas seleccionadas.. Para dar formato a los datos de una columna: 1. Seleccione la columna a la que quiere dar formato en la lista Columnas seleccionadas. 2. Escriba la expresin de formato en la caja de texto Expresin de formato de datos. La expresin de formato tiene la forma {0:expresionformato}, donde expresionformato es una de las expresiones de formato predefinidas del marco de trabajo Microsoft .NET, tal como se describen en los temas Cadenas de Formato de Fecha y Hora, Cadenas de Formato Numrico y Personalizar Cadenas de Formato de la ayuda de Visual Studio .NET. El dilogo Propiedades de DataGrid se usa para determinar todos los aspectos de la apariencia y comportamiento del DataGrid, incluyendo el formato de las cabeceras de columna, determinando cmo recorre (pagina) los registros, dnde se muestran bordes o lneas, y mucho ms.

94

Developing Web Applications

5.2.2 Mostrar un conjunto de datos en un DataList


Utilice un control DataList para mostrar informacin de un conjunto de datos como una lista de filas, en lugar de filas y columnas de un DataGrid. Para mostrar un conjunto de datos en un control DataList siga estos pasos: 1. 2. 3. 4. Cree los objetos conexin, adaptador y conjunto de datos como se describe en la leccin anterior. Aada un control DataList al formulario Web. Use el nombre del conjunto de datos como valor de la propiedad DataSource del DataList. Aada al suceso Page_Load del formulario Web para rellenar el conjunto de datos a partir del adaptador y para vincular los datos del conjunto de datos con el DataGrid. 5. Edite las plantillas de encabezado, elemento y separador del control DataList para crear su aspecto. El control DataList utiliza plantillas para determinar el contenido de sus encabezados, pies y filas. Estas plantillas se editan para aadir literales y controles y vincularlos con elementos del conjunto de datos. El DataList proporciona tres categoras diferentes de plantillas para controlar los diferentes aspectos de su apariencia. Plantillas de encabezado y pie. Incluyen el ttulo y lneas que aparecen en la parte superior e inferior del DataList. Plantillas de elemento. Determinan los contenidos de la filas en la lista de datos y permiten alternar el aspecto de las filas pares, impares, seleccionadas o en edicin. Plantillas de separadores. Aaden lnea u otros separadores entre filas. Para editar una plantilla de un DataList: 1. Pulse con el botn derecho sobre el control DataList y seleccione Editar plantilla, seleccione la plantilla que quiere editar en la lista. 2. Cuando el DataList est en modo de edicin cambia de aspecto. Escriba el texto que quiere que aparezca en la plantilla y aada los controles que desee. 3. Para mostrar un elemento del conjunto de datos en la plantilla aada un control a la plantilla y pulse sobre la elipsis a la derecha de a propiedad DataBindings del control. Visual Studio muestra el dilogo DataBindings para el control. 4. Cuando termine de editar las plantillas del control DataList pulse con el botn derecho sobre el DataList y seleccione Terminar edicin de plantilla. La vinculacin de datos para los controles de la plantilla de elemento de un control DataList puede ser una sencilla vinculacin con un elemento del contenedor, o puede ser una expresin compleja usando el mtodo Eval. Por ejemplo, la siguiente expresin de vinculacin personalizada combina el nombre y el apellido en un solo control. Visual Basic .NET
DataBinder.Eval(Container, DataItem.FirstName) & & _ DataBinder.Eval(Container, DataItem.LastName)

Visual C#
DataBinder.Eval(Container, DataItem.FirstName) + + DataBinder.Eval(Container, DataItem.LastName);

Realmente, cuando se crea una plantilla de DataList con vinculacin de datos lo que crea Visual Studio en el HTML del formulario Web es un mtodo Eval de DataBinder. En ocasiones es ms sencillo editar las plantillas directamente en HTML que mediante el procedimiento descrito anteriormente. Para editar las plantillas de un DataList directamente en HTML pulse con el botn derecho sobre el formulario Web y seleccione Ver cdigo fuente HTML. Visual Studio muestra el formulario Web en modo HTML. Por ejemplo, el siguiente HTML muestra un control DataList que contiene nombre, cumpleaos y telfono del conjunto de datos Contacts:
<asp:DataList id="dlstContacts" runat="server" DataSource="<%# dsContacts %>"> <HeaderTemplate> <h2>Informacin de Contacto <HR width="100%" SIZE="1"></h2> </HeaderTemplate> <FooterTemplate><HR></FooterTemplate>

95

MCAD/MCSD

<ItemTemplate> <asp:Label id="lblName" runat="server" Text='<%# DataBinder.Eval(Container, DataItem.FirstName") + " " +DataBinder.Eval(Container, "DataItem.LastName") %>'></asp:Label> &nbsp; Fecha de Nacimiento: <asp:Label id="lblBirthdate" runat="server" Text='<%# DataBinder.Eval (Container, "DataItem.Birthdate", "{0:d}") %>'></asp:Label> &nbsp; Telfono de trabajo: <asp:Label id="lblWorkPhone" runat="server" Text='<%# DataBinder.Eval (Container, "DataItem.WorkPhone") %>'></asp:Label> </ItemTemplate> <SeparatorTemplate><HR>SeparatorTemplate> </asp:DataList>

Para mostrar los datos del conjunto de datos en el control anterior rellene el conjunto de datos a partir del adaptador y vincule el control DataList en el procedimiento de suceso Page_Load: Visual Basic .NET
Private Sub Page_Load(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles MyBase.Load ' Rellena el conjunto de datos. adptContacts.Fill(dsContacts) ' Vincula el conjunto de datos con el control DataList. dlstContacts.DataBind() End Sub

Visual C#
private void Page_Load(object sender, System.EventArgs e){ // Rellena el conjunto de datos. adptContacts.Fill(dsContacts); // Vincula los datos con el control DataList. dlstContacts.DataBind(); }

5.2.3 Mostrar datos en otros controles de lista


Desde luego, puede vincular los elementos de un conjunto de datos con cualquier control de lista en un formulario Web. Los controles DataGrid y DataList son solo dos de las formas ms verstiles de mostrar un conjunto de datos. Para mostrar elementos de un conjunto de datos en un control ListBox, DropDownList, CheckBoxList o RadioButtonList siga estos pasos: 1. En la propiedad DataSource del control ponga el nombre del conjunto de datos. 2. En la propiedad DataText del control indique el miembro del conjunto de datos que se mostrar en la propiedad Text del elemento de lista. 3. En la propiedad DataValue del control indique el miembro del conjunto de datos que se devolver en la propiedad Value del elemento de lista. 4. Mediante cdigo, rellene el conjunto de datos a partir del adaptador y vincule el control El siguiente cdigo HTML muestra las configuraciones de propiedades para un control DropDownList vinculado con el conjunto de datos Contacts:
<asp:DropDownList id="drpContacts" runat="server" Width="384px" Height="22px" DataSource="<%# dsContacts %>" DataTextField='LastName' DataValueField="ContactID"></asp:DropDownList>

El siguiente cdigo rellena el conjunto de datos y vincula los datos con el DropDownList. Visual Basic .NET
Private Sub Page_Load(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles MyBase.Load ' Rellena el conjunto de datos. adptContacts.Fill(dsContacts) ' Vincula los datos con el control. drpContacts.DataBind() End Sub

96

Developing Web Applications

Visual C#
private void Page_Load(object sender, System.EventArgs e){ // Rellena el conjunto de datos. adptContacts.Fill(dsContacts); // Vincula el conjunto de datos con el control DataList. dlstContacts.DataBind(); }

En tiempo de ejecucin el DropDownList muestra una lista de los apellidos de la tabla Contacts y la propiedad SelectedItem.Value devuelve el ContactID, que es til para buscar otra informacin sobre el individuo, La limitacin es que solo puede incluir un valor en cada una de las propiedades DataText y DataValue. Si quiere incluir el nombre y apellido del contacto en la lista desplegable tiene que hacerlo mediante cdigo. El siguiente procedimiento para el suceso Page_Load aade el nombre y apellido a la lista desplegable e incluye ContactID como propiedad Value de cada elemento de lista. Visual Basic .NET
Private Sub Page_Load(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles MyBase.Load ' Se ejecuta la primera vez que se muestra la pgina. If Not IsPostBack Then ' Rellena el conjunto de datos Contacts. adptContacts.Fill(dsContacts) ' Para cada fila de la tabla ... Dim drowItem As dsContacts.ContactsRow For Each drowItem In dsContacts.Contacts ' Crea un nuevo elemento de lista. Dim lstNew As New ListItem() lstNew.Text = drowItem.FirstName & " " & drowItem.LastName lstNew.Value = drowItem.ContactID ' Aade el elemento de lista a la lista desplegable. drpContacts.Items.Add(lstNew) Next End If End Sub

Visual C#
private void Page_Load(object sender, System.EventArgs e){ // Se ejecuta la primera vez que se muestra la pgina. if (!IsPostBack){ // Rellena el conjunto de datos Contacts. adptContacts.Fill(dsContacts); // Para cada fila de la tabla... foreach (dsContacts.ContactsRow drowItem in dsContacts.Contacts) { // Crea un nuevo elemento de lista. ListItem lstNew = new ListItem(); lstNew.Text = drowItem.FirstName + " " + drowItem.LastName; lstNew.Value = drowItem.ContactID.ToString(); // Aade el elemento de lista a la lista desplegable. drpContacts.Items.Add(lstNew); } } }

5.2.4 Seleccionar registros concretos


El DropDownList creado en la seccin anterior es til para seleccionar elementos de la tabla Calls en la base de datos Contacts. Como ContactsID es una clave nica puede usarlo para seleccionar el registro de la tabla Calls correspondiente a un contacto concreto. El siguiente cdigo crea un conjunto de datos que contiene las llamadas para el contacto seleccionado en el DropDownList. Visual Basic .NET
Private Sub drpContacts_SelectedIndexChanged(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles drpContacts.SelectedIndexChanged ' Cuando se selecciona un contacto muestra sus llamadas. adptCalls.SelectCommand.CommandText = "SELECT * FROM Calls" & _ " WHERE ContactID =" & drpContacts.SelectedItem.Value ' Limpia el conjunto de datos. dsCalls.Clear adptCalls.Fill(dsCalls)

97

MCAD/MCSD

' Muestra los resultados en una rejilla de datos. grdCalls.DataBind() End Sub

Visual C#
private void drpContacts_SelectedIndexChanged(object sender, System.EventArgs e){ // Cuando se selecciona un contacto muestra sus llamadas. adptCalls.SelectCommand.CommandText = "SELECT * FROM Calls" + " WHERE ContactID =" + drpContacts.SelectedItem.Value; // Limpia el conjunto de datos. dsCalls.Clear(); adptCalls.Fill(dsCalls); // Muestra los resultados en una rejilla de datos. grdCalls.DataBind(); }

En tiempo de ejecucin, el formulario Web muestra una lista de las llamadas para el contacto seleccionado en la lista desplegable.

5.2.5 Ejecutar comandos sobre una base de datos


Adems de trabajar con conjuntos de datos puede ejecutar comandos directamente sobre la conexin con la base de datos. El objeto conexin proporciona tres mtodos para comandos: ExecuteScalar. Ejecuta comandos de consulta que devuelve un nico valor, como contar el nmero de registros de una tabla. ExecuteNonQuery. Ejecuta comandos que cambian la base de datos pero no devuelven un valor concreto. Esto incluye aadir y borrar elementos de una base de datos. El mtodo ExecuteNonQuery devuelve el nmero de filas afectadas por el comando. ExecuteReader. Lee registros de la base de datos secuencialmente. Para usar estos mtodos siga estos pasos: 1. 2. 3. 4. 5. Cree una conexin con la base de datos. Abra la conexin. Cree un objeto comando que contenga el comando SQL o procedimiento almacenado a ejecutar. Ejecute el mtodo sobre el objeto comando. Cierre la conexin.

5.2.6 Devolver un valor desde una base de datos


La leccin 1 mostr cmo aadir filas a y eliminar filas de una base y cmo actualizar despus la base de datos a partir del conjunto de datos, pero pas por alto un importante detalle: a menudo es necesario recuperar informacin de la base de datos antes de poder aadir un registro. El ejemplo ms comn de esto es cuando un registro incluye un campo de clave nica, como ContactsID en la base de datos Contacts. Debe obtener un valor nico antes para cada registro antes de poder aadirlo a la base de datos. Hay varias formas de obtener un nuevo valor de clave nica de una base de datos. Tal vez el ms directo sea crear un objeto comando y usar el mtodo ExecuteScalar para devolver un valor. Hay dos tipos de objetos comando: Los objetos SqlCommand ejecutan comandos sobre conexiones con bases de datos SQL. Los objetos OleDbCommand ejecutan comandos sobre conexiones con bases de datos OLE. El siguiente cdigo usa un objeto SqlCommand para recuperar el nmero ms alto usado por ContactID, incrementa el valor y usa el nmero como clave nica para una nueva fila de la tabla Contact: Visual Basic .NET
' Usa conexin, adaptador y conjunto de datos creados en modo diseo. Private Sub butAddRow_Click(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles butAddRow.Click ' Obtiene un ContactID nico. Dim intID As Integer Dim cmdNewID As New SqlCommand("SELECT MAX(ContactID)" & _ " FROM Contacts", ContactMgmt) ' Abre la conexin con la base de datos. ContactMgmt.Open() intID = CInt(cmdNewID.ExecuteScalar())

98

Developing Web Applications

' Crea un nuevo objeto fila para la tabla Contacts. Dim rowNew As dsContacts.ContactsRow = dsContacts.Contacts.NewRow ' Aade datos a los campos de la fila. rowNew.ContactID = intID + 1 rowNew.FirstName = "Max" rowNew.LastName = "Benson" rowNew.WorkPhone = "(111) 555-1212" ' Aade la fila al conjunto de datos. dsContacts.Contacts.AddContactsRow(rowNew) ' Cierra la conexin con la base de datos. ContactMgmt.Close() End Sub

Visual C#
private void butAddRow_Click(object sender, System.EventArgs e){ // Obtiene un ContactID nico. int intID; SqlCommand cmdNewID = new SqlCommand("SELECT MAX(ContactID)" + " FROM Contacts", ContactMgmt); // Abre la conexin con la base de datos. ContactMgmt.Open(); intID = (int)sqlcommNewID.ExecuteScalar(); // Crea un nuevo objeto fila para la tabla Contacts. dsContacts.ContactsRow rowNew = (dsContacts.ContactsRow) dsContacts.Contacts.NewRow(); // Aade datos a los campos de la fila. rowNew.ContactID = intID + 1; rowNew.FirstName = "Max"; rowNew.LastName = "Benson"; rowNew.WorkPhone = "(111) 555-1212"; // Aade la fila al conjunto de datos. dsContacts.Contacts.AddContactsRow(rowNew); // Cierra la conexin con la base de datos. ContactMgmt.Close(); }

El mtodo ExecuteScalar se puede usar con cualquier sentencia SQL que devuelva un nico valor. Para ejecutar otros tipos de sentencias utilice los mtodos ExecuteNonQuery o ExecuteReader.

5.2.7 Cambiar registros directamente en la base de datos


El mtodo ExecuteNonQuery ejecuta comandos que no devuelven un conjunto de datos, como INSERT, DELETE o UPDATE de SQL. Por ejemplo, el siguiente cdigo usa ExecuteNonQuery para borrar una fila directamente Visual Basic .NET
Private Sub butDelete_Click(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles butDelete.Click Dim intRows As Integer ' Crea un objeto comando. Dim cmdDeleteRow As New SqlCommand("DELETE ROW " & _ " FROM Contacts WHERE ContactID=1", ContactMgmt) ' Abre la conexin con la base de datos. ContactMgmt.Open() ' Ejecuta el comando. intRows = cmdDeleteRow.ExecuteNonQuery() ' Muestra el nmero de registros borrados. Response.Write("Registros Borrados : " & intRows) ' Cierra la conexin. ContactMgmt.Close() End Sub

Visual C#
private void butDeleteRow_Click(object sender, System.EventArgs e){ int intRows; // Crea un objeto comando. SqlCommand cmdDeleteRow = new SqlCommand("DELETE ROW" + " FROM Contacts WHERE ContactID=1", ContactMgmt); // Abre la conexin con la base de datos. ContactMgmt.Open(); // Ejecuta el comando. intRows = cmdDeleteRow.ExecuteNonQuery();

99

MCAD/MCSD

// Muestra el nmero de registros borrados. Response.Write("Registros Borrados: " + intRows.ToString()); // Cierra la conexin. ContactMgmt.Close(); }

El mtodo ExecuteNonQuery acta directamente sobre la conexin con la base de datos. No pasa por medio de adaptador o un conjunto de datos. Si hace cambios a una tabla en la base de datos mediante ExecuteNonQuery debe actualizar los conjuntos de datos afectados por estos cambios llamando al mtodo Fill del adaptador.

5.2.8 Recuperar registros directamente de la base de datos


El mtodo ExecuteReader ejecuta comandos que devuelven registros, como SELECT de SQL. Los registros se devuelven en un objeto lector de datos, que es una especie de versin de solo lectura de un conjunto de datos. Como el mtodo ExecuteReader acta directamente sobre la conexin con la base de datos hay dos versiones del objeto lector de datos: OleDbDataReader y SqlDataReader. El uso de ExecuteReader para crear objetos lectores de datos proporciona mejores prestaciones que la creacin de un conjunto de datos a partir de un adaptador, pero no da mucha flexibilidad. Los objetos lectores de datos son de solo lectura y solo se leen hacia delante, un registro cada vez. Los conjuntos de datos permiten obtener los registros en cualquier orden y, ms importante, permiten escribir cambios en la base de datos. El siguiente cdigo obtiene todas las llamadas para un contacto y muestra las lneas de tema de cada llamada en un formulario Web usando un objeto lector de datos y ExecuteReader: Visual Basic .NET
Private Sub butShowCalls_Click(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles butShowCalls.Click ' Crea un objeto comando. Dim cmdGetCalls As New SqlCommand("SELECT * FROM Calls" & _ " WHERE ContactID=3", ContactMgmt) ' Abre la conexin. ContactMgmt.Open() ' Crea un objeto lector de datos. Dim dreadCalls As SqlDataReader ' Ejecuta el comando. dreadCalls = cmdGetCalls.ExecuteReader() ' Muestra los registros. Do While dreadCalls.Read() Response.Write(dreadCalls.GetString(4)) Loop ' Cierra el lector. dreadCalls.Close() ' Cierra la conexin con la base de datos. ContactMgmt.Close() End Sub

Visual C#
private void butShowCalls_Click(object sender, System.EventArgs e){ // Crea un objeto comando. SqlCommand cmdGetCalls = new SqlCommand("SELECT * FROM Calls" + " WHERE ContactID=3", ContactMgmt); // Abre la conexin. ContactMgmt.Open(); // Crea un objeto lector de datos. SqlDataReader dreadCalls; // Ejecuta el comando. dreadCalls = cmdGetCalls.ExecuteReader(); // Muestra los registros while (dreadCalls.Read()) Response.Write(dreadCalls.GetString(4)); // Cierra el lector. dreadCalls.Close(); // Cierra la conexin. ContactMgmt.Close(); }

El objeto lector de datos es un conjunto de registros de lectura hacia delante, de modo que el mtodo Read lee cada lnea siguiente hasta que llega al final del conjunto de registros. Un objeto lector bloquea la conexin con la base de datos mientras est en ejecucin, por lo que hay que llamar a su mtodo Close cuando se termina de leer los registros, como se muestra en el ejemplo. 100

Developing Web Applications

5.3 Proceso de transacciones


ADO.NET permite agrupar operaciones de base de datos en transacciones. Un transaccin es un grupo de comandos que cambian los datos almacenados en una base de datos. La transaccin, que se trata como una sola unidad, asegura que los comandos se manejan de modo todo o nada si falla uno de los comandos fallan todos, y cualesquiera datos que hayan sido escritos en la base de datos por estos comandos se recuperan a su estado anterior. De esta forma las transacciones mantienen la integridad de una base de datos. En esta leccin aprender cmo implementar procesamiento de transacciones para conjuntos de datos y bases de datos en una aplicacin Web

5.3.1 Transacciones
Como ya se ha dicho, una transaccin es un grupo de comandos de base de datos que se tratan como una unidad. Los programadores de base de datos determinan qu comandos pertenecen a una transaccin usando la prueba ACID: los comandos de base de datos deben ser atmicos, coherentes, aislados y permanentes (atomic, consistent, isolated, durable). Los comandos pertenecen a una transaccin si son: Atmicos. En otras palabras, componen una sola unidad de trabajo. Por ejemplo, si un cliente se muda querr que el operador de datos cambie todos los campos de direccin del cliente como una sola unidad, en lugar de cambiar primero la calle, luego la ciudad y despus el estado. Coherentes. Todas las relaciones entre datos en una base de datos se mantienen correctamente. Por ejemplo, si la informacin de cliente usa una tasa de impuestos de la tabla autonmica, la autonoma introducida para el cliente debe existir en la tabla de tasas de impuestos. Aislados. Los cambios que hagan otros clientes no pueden afectar a los que estn en curso. Por ejemplo, si dos operadores de datos intentan hacer un cambio en el mismo cliente a la vez pueden pasar dos cosas: o se aceptan los cambios de un operador y se informa al otro de que sus cambios no se han hecho, o se notifica a ambos que sus cambios no se han hecho. En ninguno de los dos casos se deja al cliente en un estado indeterminado. Permanentes. Una vez que se hace un cambio, se mantiene. Si se produce un fallo de corriente o un error del sistema antes de que se complete el conjunto de comandos, una vez que se rearranca el sistema los cambios se deshacen y se devuelven los datos a su estado original. El procesamiento de transacciones es particularmente importante para las aplicaciones Web que usan acceso a datos, puesto que estas aplicaciones se encuentran distribuidas entre varios clientes. En una aplicacin Web las bases de datos son un recurso compartido, y tener muchos clientes repartidos sobre un rea amplia puede arrastrar estos problemas clave: Competencia por los recursos. Varios clientes pueden intentar cambiar el mismo registro a la vez. Este problema empeora al crecer el nmero de clientes. Fallos inesperados. Internet no es la red ms fiable que existe, incluso aunque la aplicacin Web y el servidor Web sean 100% fiables. Los clientes pueden ser desconectados inesperadamente por los proveedores de servicio, por sus mdem o por fallos de corriente. Ciclo de vida de la aplicacin Web. Las aplicaciones Web no siguen el mismo ciclo de vida que las aplicaciones Windows los formularios Web solo duran un instante, y un cliente puede abandonar la aplicacin en cualquier momento sencillamente escribiendo una nueva direccin en su navegador. El procesamiento de transacciones sigue estos pasos: 1. 2. 3. 4. Comenzar una transaccin Procesar comandos de base de datos Comprobar errores Si hay errores, restablecer la base de datos a su estado al comienzo de la transaccin, si no, consignar la transaccin en la base de datos. En ADO.NET las transacciones se manejan de formas diferentes, dependiendo del nivel: Los conjuntos de datos proporcionan procesamiento de transacciones mediante los mtodos RejectChanges y Update. Los conjuntos de datos tambin proporcionan un mtodo AcceptChanges que restablece el estado de los registros como sin cambios. Las objetos conexin proporcionan procesamiento de transacciones mediante el objeto transaccin. Los objetos transaccin hacen un seguimiento de los comandos ejecutados sobre una base de datos y proporcionan los mtodos Rollback, Commit y Save para restablecer el estado de la base de datos, consignar cambios o crear un punto de restauracin dentro de una transaccin, respectivamente. El espacio de nombres System.EnterpriseServices proporciona transacciones a nivel empresarial mediante la clase ContextUtil. Las transacciones a nivel empresarial usan el coordinador de transacciones distribuidas (DTC: Distributed Transactions Coordinator) que incluye SQL Server para seguir transacciones entre varios formularios Web y entre varios componentes COM+. 101

MCAD/MCSD

5.3.2 Transacciones de conjunto de datos


Los conjuntos de datos proporcionan procesamiento de transacciones implcito, puesto que no se hacen los cambios en la base de datos hasta que no se llama al mtodo Update del objeto adaptador de datos. Esto permite ejecutar una serie de comandos sobre los datos y seleccionar un punto en el que estos cambios se hacen permanentes en la base de datos. Si se produce un error durante el mtodo Update ninguno de los cambios del conjunto de datos se hace en la base de datos. En este punto, puede intentar corregir el error y reintentar el mtodo Update, o puede deshacer los cambios pendientes en el conjunto de datos mediante su mtodo RejectChanges. Por ejemplo, el siguiente cdigo muestra la lista de contactos en un control DataGrid y permite que el usuario borre filas pulsando Delete en el DataGrid: Visual Basic .NET
Private Sub Page_Load(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles MyBase.Load ' Comprueba si es la primera vez que se muestra la pgina. If Not IsPostBack Then ' En la primera presentacin rellena el conjunto de datos. adptContacts.Fill(dsContacts) ' Graba el conjunto de datos como variable de estado. Session("dsContacts") = dsContacts Else ' En posteriores obtiene el conjunto de datos de la variable de estado. dsContacts = Session("dsContacts") End If ' Vincula con el conjunto de datos. grdContacts.DataBind() End Sub Private Sub grdContacts_ItemCommand(ByVal source As Object, _ ByVal e As System.Web.UI.WebControls.DataGridCommandEventArgs) _ Handles grdContacts.ItemCommand ' Si se ha pulsado el botn Delete. If e.CommandName = "Delete" Then Dim intContactID ' Obtiene el ContactID de la dila seleccionada. intContactID = _ CInt(grdContacts.Items(e.Item.ItemIndex).Cells(3).Text) Dim rowDelete As dsContacts.ContactsRow ' Obtiene la fila a borrar del conjunto de datos. rowDelete = dsContacts.Contacts.FindByContactID(intContactID) ' Borra la fila. rowDelete.Delete() ' Refresca la rejilla de datos. grdContacts.DataBind() End If End Sub

Visual C#
private void Page_Load(object sender, System.EventArgs e){ // Comprueba si es la primera vez que se muestra la pgina. if (!IsPostBack){ // La primera vez rellena el conjunto de datos. adptContacts.Fill(dsContacts); // Graba el conjunto de datos como variable de estado. Session["dsContacts"] = dsContacts; }else // Las siguientes obtiene los datos de la variable de estado. dsContacts = (dsContacts)Session["dsContacts"]; // Vincula con el conjunto de datos. grdContacts.DataBind(); } private void grdContacts_ItemCommand(object sender, System.Web.UI.WebControls.DataGridCommandEventArgs e){

102

Developing Web Applications

// Si se ha pulsado el botn Delete. if (e.CommandName == "Delete"){ int intContactID; // Obtiene el ContactID de la fila seleccionada. intContactID = Convert.ToInt16 (grdContacts.Items[e.Item.ItemIndex].Cells[3].Text); dsContacts.ContactsRow rowDelete; // Obtiene la fila a borrar del Conjunto de datos. rowDelete = dsContacts.Contacts.FindByContactID(intContactID); // Borra la fila. rowDelete.Delete(); // Refresca la rejilla de datos. grdContacts.DataBind(); } }

El siguiente procedimiento de suceso para los botones Restore y Commit permiten que el usuario restablezca el conjunto de datos a su estado previo o, como alternativa, actualice la base de datos con los borrados que se hicieron en el cdigo anterior. Visual Basic .NET
Private Sub butRestore_Click(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles butRestore.Click ' Restablece el conjunto de datos a su estado original. dsContacts.RejectChanges() ' Refresca la rejilla de datos. grdContacts.DataBind() End Sub Private Sub butCommit_Click(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles butCommit.Click ' Actualiza la base de datos a partir del conjunto de datos. adptContacts.Update(dsContacts) ' Graba los cambios en la variable de estado. Session("dsContacts") = dsContacts ' Refresca la rejilla de datos. grdContacts.DataBind() End Sub

Visual C#
private void butRestore_Click(object sender, System.EventArgs e){ // Restablece el conjunto de datos a su estado original. dsContacts.RejectChanges(); // Refresca la rejilla de datos. grdContacts.DataBind(); } private void butCommit_Click(object sender, System.EventArgs e){ int intRows; // Actualiza la base de datos a partir del conjunto de datos. intRows = adptContacts.Update(dsContacts); // Graba los cambios en la variable de estado. Session["dsContacts"] = dsContacts; // Refresca la rejilla de datos. grdContacts.DataBind(); }

El mtodo RejectChanges en el procedimiento de suceso butRestore_Click anterior devuelve el conjunto de datos a su estado anterior al borrado de la fila. El mtodo AcceptChanges del conjunto de datos es el inverso a RejectChanges restablece la propiedad DataRowState de todas las filas cambiadas en un conjunto de datos a Unchanged y elimina las filas borradas. El mtodo AcceptChanges impide que el mtodo Update haga estos cambios en la base de datos, porque Update usa la propiedad DataRowState de las filas para determinar qu filas debe modificar en la base de datos. Por este motivo, el mtodo AcceptChanges solo es til cuando no se tiene intencin de actualizar la base de datos a partir del conjunto de datos.

5.3.3 Transacciones de base de datos


Puede manejar las transacciones a nivel base de datos mediante un objeto transaccin. Como en ADO.NET hay dos tipos de conexiones con base de datos, tambin hay dos tipos de objetos transaccin: SqlTransaction y OleDbTransaction. 103

MCAD/MCSD

Para usar cualquiera de estos dos tipos de transacciones siga estos pasos: 1. Abra una conexin con la base de datos 2. Cree el objeto transaccin usando el mtodo BeginTransaction del objeto conexin 3. Cree objetos comando que se controlarn mediante esta transaccin, asignando a la propiedad Transaction de cada objeto comando al nombre de la transaccin creada en el paso 2. 4. Ejecute los comandos. Como el objetivo del procesamiento de transacciones es detectar y corregir errores antes de que se escriban los datos en la base de datos, normalmente esto se hace como parte de una estructura de manipulacin de errores. 5. Consigne los cambios en la base de datos o restablezca su estado, dependiendo del xito de los comandos. 6. Cierre la conexin con la base de datos. El siguiente cdigo usa un DataGrid para mostrar una lista de contactos de la base de datos Contacts. El DataGrid incluye una columna de botones que permite al usuario borrar contactos. La funcin DeleteContact usa una transaccin para asegurarse de que se borran las llamadas a un contacto si se borra este contacto. Esto ayuda a asegurar la integridad de la base de datos. Visual Basic .NET
Private Sub Page_Load(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles MyBase.Load adptContacts.Fill(dsContacts) ' Rellena el conjunto de datos. grdContacts.DataBind() ' Vincula el conjunto de datos. End Sub Private Sub grdContacts_ItemCommand(ByVal source As Object, _ ByVal e As System.Web.UI.WebControls.DataGridCommandEventArgs) _ Handles grdContacts.ItemCommand ' Si se ha pulsado el botn Delete. If e.CommandName = "Delete" Then Dim intContactID ' Obtiene el Contactad de la fila seleccionada. intContactID = _ CInt(grdContacts.Items(e.Item.ItemIndex).Cells(3).Text) ' Borra la informacin del contacto. lblStatus.Text = DeleteContact(intContactID) End If adptContacts.Fill(dsContacts) ' Refresca el conjunto de datos. grdContacts.DataBind() ' Refresca el DataGrid. End Sub Function DeleteContact(ByVal intContactID As Integer) As String ' Abre la conexin con la base de datos. ContactMgmt.Open() ' Declara un objeto transaccin. Dim transDelete As SqlTransaction ' Crea la transaccin. transDelete = ContactMgmt.BeginTransaction(IsolationLevel.ReadCommitted) ' Crea el comando para borrar de la tabla Contacts. Dim cmdDelete As New SqlCommand("DELETE FROM Contacts WHERE ContactID=" & _ intContactID, ContactMgmt, transDelete) ' Ejecuta los comandos. Try Dim intRows As Integer ' Borra la fila de la tabla Contacts. intRows = cmdDelete.ExecuteNonQuery() ' Borra las llamadas para este ContactID. cmdDelete.CommandText = "DELETE FROM Calls WHERE ContactID=" & intContactID intRows = intRows + cmdDelete.ExecuteNonQuery() ' Consigna la transaccin. transDelete.Commit() ' Devuelve el mensaje de xito. Return intRows & " Borrados." Catch ' Restablece el estado de la base de datos si hubo un error. transDelete.Rollback() ' Devuelve un mensaje de error. Return "No se pudo borrar el contacto." Finally ' Cierra la base de datos. ContactMgmt.Close() End Try End Function

104

Developing Web Applications

Visual C#
private void Page_Load(object sender, System.EventArgs e){ adptContacts.Fill(dsContacts); // Rellena el conjunto de datos. grdContacts.DataBind(); // Vincula el conjunto de datos. } private void grdContacts_ItemCommand(object sender, System.Web.UI.WebControls.DataGridCommandEventArgs e){ // Si se puls el botn Delete. if (e.CommandName == "Delete"){ int intContactID; // Obtiene el ContactID de la fila seleccionada. intContactID = Convert.ToInt16(grdContacts.Items [e.Item.ItemIndex].Cells[3].Text); // Borra la informacin del contacto. lblStatus.Text = DeleteContact(intContactID); } adptContacts.Fill(dsContacts); // Refresca el conjunto de datos. grdContacts.DataBind(); // Refresca la rejilla de datos. } string DeleteContact(int intContactID){ // Abre la conexin con la base de datos. ContactMgmt.Open(); // Declara un objeto transaccin. SqlTransaction transDelete; // Crea la transaccin. transDelete = ContactMgmt.BeginTransaction(IsolationLevel.ReadCommitted); // Crea el comando para borrar de la tabla Contacts. SqlCommand cmdDelete = new SqlCommand("DELETE FROM Contacts WHERE ContactID=" + intContactID.ToString(), ContactMgmt, transDelete); // Ejecuta los comandos. try{ int intRows; // Borra la fila de la tabla Contacts. intRows = cmdDelete.ExecuteNonQuery(); // Borra las llamadas para este ContactID. cmdDelete.CommandText = "DELETE FROM Calls WHERE ContactID=" + intContactID.ToString(); intRows = intRows + cmdDelete.ExecuteNonQuery(); // Consigna la transaccin. transDelete.Commit(); // Devuelve el mensaje de xito. return intRows.ToString() + " borrados."; }catch{ // Restablece el estado de la base de datos si hubo un error. transDelete.Rollback(); // Devuelve un mensaje de error. return "No se pudo borrar el contacto."; }finally // Cierra la base de datos. ContactMgmt.Close(); }

El objeto transaccin determina cmo se manejan los cambios concurrentes en una base de datos mediante la propiedad IsolationLevel. El nivel de proteccin vara como especifican las opciones de la tabla 5.2.
Tabla 5. 2: Opciones de nivel de aislamiento
Nivel Comportamiento No bloquea los registros que se estn leyendo. Esto significa que un cambio sin consignar se puede leer y ser anulado por otro cliente, causando una copia local de un registro que no es coherente con lo que est almacenado en la base de datos. Esto se denomina lectura sucia porque los datos no son coherentes. Se comporta igual que ReadUncommitted, pero comprueba el nivel de aislamiento de otras transacciones pendientes durante una operacin de escritura, de modo que las transacciones con nivel de aislamiento ms restrictivo no se sobrescriben. Bloquea los registros que se estn leyendo y libera el bloqueo tan pronto como se han ledo. Esto impide que se lean los cambios antes de que se consignen, pero no impide que otros clientes aadan, borren o modifiquen registros durante la transaccin. Es el nivel de aislamiento predeterminado. Bloquea los registros que se estn leyendo y mantiene el bloqueo hasta que se completa la transaccin. Esto asegura que los datos que se estn leyendo no cambian durante la misma. Bloquea el conjunto de datos completo y mantiene el bloqueo hasta que se completa la transaccin. Esto asegura que los datos y su orden dentro de la base de datos no cambian durante la transaccin.

ReadUncommitted Chaos ReadCommitted RepeatableRead Serializable

105

MCAD/MCSD

Las conexiones con bases de datos SQL proporcionan una capacidad de transaccin que no est disponible para las conexiones con bases de datos OLE: la posibilidad de crear puntos de restauracin dentro de una transaccin. Los puntos de restauracin permiten devolver la base de daos a una posicin concreta dentro de la transaccin actual. Para crear un punto de restauracin dentro de una transaccin SQL use el mtodo Save: Visual Basic .NET
transDelete.Save("FirstStep")

Visual C#
transDelete.Save("FirstStep");

Para devolver una transaccin SQL a un punto de restauracin especifique el nombre del punto en el mtodo Rollback. Visual Basic .NET
transDelete.Rollback("FirstStep")

Visual C#
transDelete.Rollback("FirstStep");

5.3.4 Transacciones de empresa


Como las transacciones de empresa pueden abarcar varios formularios Web o incluso varios componentes dentro de una aplicacin distribuida ASP.NET proporciona una forma para que los formularios Web trabajen con DTC. Para usar DTC desde un formulario Web siga estos pasos: 1. Inicie una nueva transaccin o contine una existente configurando el atributo transaction del documento. Por ejemplo, la siguiente directiva @Page inicia una nueva transaccin.
<% Page Language=vb AutoEventWireup=false CodeBehind=PageTransactions.aspx.vb Inherits=vbTransactionSnippet.PageTransactions Transactions=RequiresNew %>

2. Aada al proyecto una referencia al espacio de nombres System.EnterpriseServices. 3. Use los mtodos SetAbort y SetComplete de la clase ContextUtil para cambiar el estado de la transaccin como sea necesario. 4. Use los sucesos CommitTransaction y AbortTransaction de la clase Page para responder a los cambios en el estado de la transaccin. Para ms informacin sobre DTC vea la ayuda en lnea de Visual Studio.

5.4 Resumen
ADO.NET incluye tres componentes clave usados para la mayor parte del acceso a datos: conexin con base de datos, adaptador de datos y conjunto de datos. Para acceder a una base de datos siga estos pasos: Cree una conexin con la base de datos. Cree un conjunto de datos usando un objeto adaptador. Use el conjunto de datos para mostrar datos o cambiar elementos en la base de datos. Actualice la base de datos a partir del conjunto de datos. Cierre la conexin con la base de datos. ADO.NET proporciona conjuntos de datos con tipo. Los conjuntos de datos con tipo usan nombres y tipos de datos explcitos que ayudan a evitar errores durante la programacin. Utilice vinculacin de datos para mostrar rpidamente conjuntos de datos en formularios Web mediante DataGrid, DataList u otros controles de lista. Cree objetos comando para ejecutar sentencias SQL directamente sobre una base de datos. Los objetos comando pueden devolver un nico valor (ExecuteScalar), modificar la base de datos (ExecuteNonQuery) o devolver datos (ExecuteReader). Las transacciones agrupan los comandos de base de datos de forma que tienen xito o fracasan de modo todo o nada. Esto asegura que los cambios no se hacen de forma parcial, preservando la integridad de la base de datos. Para determinar qu comandos se deben incluir en una transaccin use la prueba ACID. Una transaccin debe ser atmica, coherente, aislada y permanente (atomic, isolated, consistent, durable) Para usar una transaccin siga estos pasos: Comience la transaccin Ejecute comandos y haga cambios que son parte de la transaccin Compruebe errores

106

Developing Web Applications

Si se producen errores deshaga los cambios (roll back). Si no se producen errores consigne los cambios. Esto termina la transaccin. Maneje las transacciones de conjunto de datos usando el mtodo Update para consignar los cambios y el mtodo RejectChanges para deshacerlos (roll back) Maneje las transacciones con base de datos usando los mtodos Commit y Rollback del objeto transaccin.

5.5 Prctica: Aplicacin de gestin de contactos


En esta prctica crear una aplicacin Web con varias pginas que usa una base de datos para almacenar informacin de contactos y llamadas. La aplicacin permite aadir contactos, ver y aadir llamadas hechas por un contacto y aadir nuevos tipos de contacto. Esta aplicacin usa la base de datos Contacts (Contacts.mdb) incluida en el CD-ROM del libro. La aplicacin de gestin de contactos muestra estos conceptos clave: Navegacin. Los usuarios navegan desde una pgina central de conmutacin a pginas de tareas especficas. Una vez que los usuarios terminan una tarea vuelven a la pgina de conmutacin. Conexin de datos central. Los componentes de conexin con base de datos, adaptador de datos y conjunto de datos residen en el archivo Global.asax y se inicializan una vez por usuario. Estos objetos se comparten entre formularios Web usando variables de estado de sesin. Transacciones de conjunto de datos. Todos los cambios en la base de datos se procesan mediante conjuntos de datos, y todas las actualizaciones estn contenidas dentro de estructuras de manejo de errores. Si una actualizacin falla, el usuario puede intentar de nuevo o cancelar la operacin sin daar la integridad de la base de datos. Controles vinculados y no vinculados. Las llamadas se muestran utilizando un control DataList que contiene controles etiqueta vinculados con datos. Los contactos se muestran en una lista desplegable usando cdigo en lugar de vinculacin de datos. Comandos de base de datos. La aplicacin obtiene valores de clave nicos ejecutando comandos sobre la base de datos.

5.5.1 Inicie un proyecto y cree el formulario SwichtBoard


En este ejercicio va a iniciar un nuevo proyecto y crear el formulario Web usado para navegar a otros formularios Web de la aplicacin. Este formulario es muy sencillo y no contiene cdigo ejecutable. 1. Cree un nuevo proyecto de aplicacin Web ASP.NET llamado ContactManagement. 2. Cambie el nombre de Webform1.aspx a SwitchBoard.aspx y muestre el formulario en modo HTML. 3. Escriba el siguiente cdigo HTML entre las etiquetas <form> y </form>
<h2>Conmutador de Gestin de Contactos</h2> <P>Qu quiere hacer? </P> <P><a href="Calls.aspx">Ver/Aadir llamadas.</a></P> <P><a href="AddContact.aspx">Aadir un contacto.</a></P> <P><a href="DeleteContact.aspx">Borrar un contacto.</a></P> <P><a href="ContactTypes.aspx">Aadir un tipo de contacto.</a></P>

5.5.2 Aadir componentes de base de datos


La aplicacin de gestin de contactos realiza acceso a la base de datos desde diferentes formularios Web. Los componentes de conexin, adaptador y conjunto de datos se aaden al archivo Global.asax y se graban como variables de estado de sesin de modo que se puede acceder a ellos desde los formularios Web respectivos. Todos los formularios Web, y todos los usuarios de los formularios Web, comparten una nica conexin con la base de datos. Esto conserva recursos y facilita el mantenimiento de las configuraciones de conexin y de adaptador durante el desarrollo de la aplicacin porque todos los componentes de base de datos estn en un nico lugar. 1. Abra el archivo Global.asax y pulse el enlace Explorador de servidores. Visual Studio muestra el explorador de servidores. 2. Pulse el botn Conectar con base de datos en la ventana del explorador de servidores. Visual Studio muestra la caja de dilogo Propiedades de vnculo de datos. 3. Seleccione el nombre del servidor SQL Server donde est instalada la base de datos Contacts, seleccione la opcin Usar la seguridad Integrada de Windows NT y escriba Contacts en le la caja de texto Seleccione la base de datos del servidor. Pulse Probar conexin para comprobar la configuracin y pulse Aceptar cuando termine. Visual Studio aade la conexin con la base de datos al Explorador de Servidores. 4. En la ventana del Explorador de Servidores, expanda los elementos bajo la conexin de datos recin creada pulsando en el signo ms a la izquierda de la conexin de datos Contacts.dbo y haga lo mismo con el subelemento tablas. Arrastre las tablas Calls, ContactTypes y Contacts del Explorador de Soluciones a la pgina Global.asax. Visual Studio aade un componente de conexin con base de datos y componentes adaptador de datos para cada una de las tablas. 107

MCAD/MCSD

5. Cada adaptador de datos representa a una de las tablas arrastradas a la pgina. Pulse con el botn derecho sobre uno de los adaptadores y seleccione Generar conjunto de datos. Visual Studio muestra el dilogo Generar conjunto de datos 6. Escriba el nombre del conjunto de datos en la caja de texto Nuevo. Use un nombre correspondiente a la tabla que representa (por ejemplo, dsCalls para la tabla Calls), seleccione Agregar este conjunto de datos al diseador y pulse Aceptar. Visual Studio aade el conjunto de datos a la pgina Global.asax. Nota: Cuando Visual Studio aade un conjunto de datos aade un nmero al nombre que se le da. Para eliminar el nmero hay que editar el nombre en la ventana de propiedades. 7. Repita los pasos 5 y 6 para cada adaptador de datos 8. Pulse dos veces sobre la pgina Global.asax en la ventana de cdigo para ver el cdigo de la pgina. Aada el siguiente procedimiento de suceso Session_Start para crear las variables de estado de sesin que se usarn en los formularios Web para acceder a los componentes de base de datos: Visual Basic .NET
Sub Session_Start(ByVal sender As Object, ByVal e As EventArgs) ' Conexin con la base de datos. Session("ContactMgmt") = SqlConnection1 ' Adaptadores de datos. Session("adptCalls") = SqlDataAdapter1 Session("adptContactTypes") = SqlDataAdapter2 Session("adptContacts") = SqlDataAdapter3 ' Conjunto de datos. Session("dsCalls") = dsCalls Session("dsContactTypes") = dsContactTypes Session("dsContacts") = dsContacts End Sub

Visual C#
protected void Session_Start(Object sender, EventArgs e){ // Conexin con la base de datos. Session["ContactMgmt"] = sqlConnection1; // Adaptadores de datos. Session["adptCalls"] = sqlDataAdapter1; Session["adptContactTypes"] = sqlDataAdapter2; Session["adptContacts"] = sqlDataAdapter3; // Conjuntos de datos. Session["dsCalls"] = dsCalls; Session["dsContactTypes"] = dsContactTypes; Session["dsContacts"] = dsContacts; }

5.5.3 Crear el formulario AddContact


La aplicacin permite a los usuarios aadir informacin sobre nuevos contactos por medio del formulario Web AddContact. Este formulario es una entrada de datos sencilla con cajas de texto para cada uno de los elementos de datos de un registro de la tabla Contacts. 1. Aada al proyecto un nuevo formulario Web llamado AddContact.aspx 2. En la ventana de propiedades, seleccione el objeto DOCUMENT y de a la propiedad pageLayout el valor FlowLayout. 3. Aada al formulario Web los controles de la tabla siguiente, con la configuracin que se indica. Control Propiedad Configuracin TextBox ID txtFirstName TextBox ID txtLastName TextBox ID txtAddress TextMode Multiline TextBox ID txtCity DropDownList ID drpStates DataSource arrState TextBox ID txtZIP TextBox ID txtHomePhone TextBox ID txtWorkPhone TextBox ID txtNotes TextMode Multiline DropDownList ID drpContactTypes Button ID butAdd Text Aadir Button ID butCancel Text Cancelar 108

Developing Web Applications

Propiedad Configuracin ID litStatus Text Volver a Conmutador NavigateUrl SwitchBoard.aspx 4. Escriba directamente en la pgina Web texto para identificar los campos. Utilice retornos de carro para iniciar nuevas lneas3. 5. Pulse dos veces sobre el formulario Web para mostrar la ventana de cdigo y aada la siguiente sentencia Imports o using en la parte superior del mdulo. Visual Basic .NET
Imports System.Data.SqlClient

Control Literal Hyperlink

Visual C#
using System.Data.SqlClient;

6. El formulario Web AddContact usa los componentes de base de datos creados en Global.asax en la seccin 5.5.2. Para usar estos componentes en el formulario Web declare variables a nivel de clase y recupere las referencias a los componentes de las variables de estado en las que estn almacenados. El siguiente cdigo muestra cmo hacerlo: Visual Basic .NET
Dim ContactMgmt As SqlConnection Dim adptContactTypes As SqlDataAdapter Dim adptContacts As SqlDataAdapter Dim dsContacts As New dsContacts() ' Estas variables son pblicas para la vinculacin de datos. Public dsContactTypes As New dsContactTypes() Public arrState As String() = {"AL", "AK", "AR", "AZ", "CA", "CO", "CT", _ "DE", "FL", "GA", "HI", "ID", "IL", "IN", "IA", "KS", "KY", "LA", _ "MA", "ME", "MD", "MI", "MN", "MO", "MS", "MT", "NC", "ND", "NE", _ "NH", "NJ", "NM", "NV", "NY", "OH", "OK", "OR", "PA", "RI", "SC", _ "SD", "TN", "TX", "UT", "VA", "VT", "WA", "WI", "WY"} Private Sub Page_Load(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles MyBase.Load ' Obtiene la conexin y adaptadores del estado de sesin. ContactMgmt = Session("ContactMgmt") adptContactTypes = Session("adptContactTypes") adptContacts = Session("adptContacts") ' Rellena el conjunto de datos ContactType. adptContactTypes.Fill(dsContactTypes) ' Rellena el conjunto de datos Contacts. adptContacts.Fill(dsContacts) ' Vincula datos rellena las listas drpContactTypes y drpStates. drpContactTypes.DataBind() drpStates.DataBind() End Sub

Visual C#
SqlConnection ContactMgmt; SqlDataAdapter adptContactTypes; SqlDataAdapter adptContacts; dsContacts dsContacts = new dsContacts(); // Estas variables son pblicas para la vinculacin de datos. public dsContactTypes dsContactTypes = new dsContactTypes(); public string[] arrState = {"AL", "AK", "AR", "AZ", "CA", "CO", "CT", "DE", "FL", "GA", "HI", "ID", "IL", "IN", "IA", "KS", "KY", "LA", "MA", "ME", "MD", "MI", "MN", "MO", "MS", "MT", "NC", "ND", "NE", "NH", "NJ", "NM", "NV", "NY", "OH", "OK", "OR", "PA", "RI", "SC", "SD", "TN", "TX", "UT", "VA", "VT", "WA", "WI", "WY"}; private void Page_Load(object sender, System.EventArgs e){ // Obtiene la conexin y adaptadores del estado de sesin. ContactMgmt = (SqlConnection)Session["ContactMgmt"]; adptContactTypes = (SqlDataAdapter)Session["adptContactTypes"]; adptContacts = (SqlDataAdapter)Session["adptContacts"]; // Rellena el conjunto de datos ContactType. adptContactTypes.Fill(dsContactTypes, "Contact_Types"); // Rellena el conjunto de datos Contacts. adptContacts.Fill(dsContacts); //Asigna el conjunto de datos tipos de contactos a su lista
3

Consejo del traductor: utilice una tabla estndar HTML para dar un aspecto ms ordenado al formulario.

109

MCAD/MCSD

//Nota: las cuatro siguientes lneas no figuran en el original, pero sin //ellas no se carga la lista de tipos de contactos. drpContactTypes.DataSource = dsContactTypes; drpContactTypes.DataMember = "Contact_Types"; drpContactTypes.DataTextField = "ContactType"; drpContactTypes.DataValueField = "ContactTypeID"; // Vincula datos rellena las listas drpContactTypes y drpStates. drpContactTypes.DataBind(); drpStates.DataBind(); }

7. Cada contacto de la tabla Contacts est identificado est identificado por un ContactID. Esta es la clave principal de la tabla, por lo que debe ser nica para cada contacto. Por tanto, antes de poder aadir un contacto al conjunto de datos Contact debe obtener de la base de datos un ContactID nico. Aada a la clase del formulario Web la siguiente funcin auxiliar para obtener este ID nico antes de aadir el contacto. Visual Basic .NET
' Devuelve un ContactID nico nuevo. Private Function GetNewContactID() As Integer Dim cmdNewID As New SqlCommand("SELECT MAX(ContactID)" " FROM Contacts", ContactMgmt) ContactMgmt.Open() ' Abre la conexin con la Dim intID As Integer ' Obtiene el ID ms alto. ' Se asegura de que el registro existe. If Not (cmdNewID.ExecuteScalar() Is DBNull.Value) Then intID = CInt(cmdNewID.ExecuteScalar()) ' Obtiene Else intID = 0 ' En caso End If ' Cierra la conexin. ContactMgmt.Close() ' Devuelve un ID nuevo (mayor en uno que el ms alto). Return intID + 1 End Function & _ base de datos.

el nmero ms alto. contrario ID cero.

Visual C#
// Devuelve un ContactID nico nuevo. int GetNewContactID(){ SqlCommand cmdNewID = new SqlCommand("SELECT " + "MAX(ContactID) FROM Contacts", ContactMgmt); ContactMgmt.Open(); // Abre la conexin con la base de datos. int intID; // Obtiene el ID ms alto. // Se asegura de que el registro existe. if (cmdNewID.ExecuteScalar() != DBNull.Value) intID = (int)cmdNewID.ExecuteScalar(); // Obtiene el nmero ms alto. else intID = 0; // En caso contrario ID cero. // Cierra la conexin ContactMgmt.Close(); // Devuelve un ID nuevo (mayor en uno que el ms alto). return intID + 1; }

8. Aada el siguiente procedimiento de suceso butAdd_Click para aadir la informacin del nuevo contacto a la base de datos. Visual Basic .NET
Private Sub butAdd_Click(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles butAdd.Click ' Crea una nueva fila para el conjunto de datos. Dim rowNew As dsContacts.ContactsRow rowNew = dsContacts.Contacts.NewContactsRow()

110

Developing Web Applications

' Aade datos a la fila. rowNew.ContactID = GetNewContactID() rowNew.FirstName = txtFirstName.Text rowNew.LastName = txtLastName.Text rowNew.Address = txtAddress.Text rowNew.City = txtCity.Text rowNew.StateOrProvince = drpStates.SelectedItem.Text rowNew.PostalCode = txtZip.Text rowNew.HomePhone = txtHomePhone.Text rowNew.WorkPhone = txtWorkPhone.Text rowNew.Notes = txtNotes.Text rowNew.ContactTypeID = drpContactTypes.SelectedItem.Value ' Aade la fila al conjunto de datos. dsContacts.Contacts.AddContactsRow(rowNew) Try ' Modifica la base de datos. adptContacts.Update(dsContacts) ' Indica el xito. litStatus.Text = rowNew.FirstName & " " & rowNew.LastName & _ " aadido con xito.<br>" ' Vuelve a mostrar la pgina para limpiar los campos. Server.Transfer("AddContact.aspx") Catch ex As Exception litStatus.Text = "Se ha producido el error:<br>" & ex.Message & _ "<br>" & "Corrija el error y pulse Aadir para aadir " & _ "el contacto o pulse Cancelar para abortar. <br> " End Try End Sub

Visual C#
private void butAdd_Click(object sender, System.EventArgs e){ // Crea una nueva fila para el conjunto de datos. dsContacts.ContactsRow rowNew; rowNew = dsContacts.Contacts.NewContactsRow(); // Aade datos a la fila. rowNew.ContactID = GetNewContactID(); rowNew.FirstName = txtFirstName.Text; rowNew.LastName = txtLastName.Text; rowNew.Address = txtAddress.Text; rowNew.City = txtCity.Text; rowNew.StateOrProvince = drpStates.SelectedItem.Text; rowNew.PostalCode = txtZip.Text; rowNew.HomePhone = txtHomePhone.Text; rowNew.WorkPhone = txtWorkPhone.Text; rowNew.Notes = txtNotes.Text; rowNew.ContactTypeID = Convert.ToInt16(drpContactTypes.SelectedItem.Value); // Aade la fila al conjunto de datos. dsContacts.Contacts.AddContactsRow(rowNew); try{ // Modifica la base de datos. adptContacts.Update(dsContacts); // Indica el xito. litStatus.Text = rowNew.FirstName + " " + rowNew.LastName + " aadido con xito.<br>"; // Vuelve a mostrar la pgina para limpiar los campos. Server.Transfer("AddContact.aspx"); }catch (Exception ex){ litStatus.Text = "Se ha producido el error:<br>" + ex.Message + "<br>" + "Corrija el error y pulse Aadir para aadir el contacto o pulse " + "Cancelar para abortar.<br>"; } }

9. Aada el procedimiento de suceso butCancel_Click para permitir que el usuario cancele la operacin y limpie las cajas de texto del formulario. Visual Basic .NET
Private Sub butCancel_ServerClick(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles butCancel.ServerClick ' Vuelve a mostrar la pgina para limpiar las cajas de texto. Server.Transfer("AddContact.aspx") End Sub

111

MCAD/MCSD

Visual C#
private void butCancel_ServerClick(object sender, System.EventArgs e){ // Vuelve a mostrar la pgina para limpiar las cajas de texto. Server.Transfer("AddContact.aspx"); }

5.5.4 Crear el formulario Calls


El formulario Web Calls permite que el usuario introduzca y vea llamadas telefnicas de un contacto. Usa un control DataList para ver las llamadas telefnicas para un contacto seleccionado en una lista desplegable, y contiene los controles que aaden una llamada en un control Panel para que se puedan ocultar y . 1. Aada al proyecto un nuevo formulario Web llamado Calls.aspx. 2. Aada al formulario los controles que muestra la siguiente tabla con las configuraciones que se indican. Coloque los controle que siguen al control Panel dentro del panel de modo que se pueda controlar con facilidad su presentacin en tiempo de ejecucin. Control Propiedad Configuracin DropDownList ID drpContacts Button ID butView Text Ver llamada Button ID butAddCall Text Aadir Llamada Panel4 ID pnlAdd TextBox ID txtDate TextBox ID txtTime TextBox ID txtSubject TextBox ID txtNotes TextMode Multiline Button ID butOkAdd Button ID butCancelAdd Literal ID litError 3. Abra la lengeta Datos de la Caja de herramientas y arrastre un componente DataSet al formulario Web. Visual Studio muestra el dilogo Agregar conjunto de datos con la opcin Conjunto de datos con tipo seleccionada. 4. En la lista desplegable Nombre seleccione el conjunto de datos con tipo llamado ContactManagement.dsCalls y pulse aceptar. Visual Studio aade el conjunto de datos al formulario Web. 5. Aada un control DataList de la lengeta Web Forms de la Caja de herramientas al formulario Web bajo el panel. Configure sus propiedades y edite sus plantillas como indica la siguiente tabla: Control Propiedad Configuracin DataList ID dlstCalls DataSource dsCalls

HeaderTemplate
Texto Ordinario Lnea HTML Ninguna Ninguna Ninguna ID (DataBindings) ID (DataBindings) Ninguna ID (DataBindings) Ninguna ID (DataBindings) Llamadas <HR> <HR> lblDate Usando el dilogo DataBindings seleccione Container.DataItem. CallDate del rbol Enlace simple. Seleccione el formato {0:d} lblTime Usando el dilogo DataBindings seleccione Container.DataItem. CallTime del rbol Enlace simple. Seleccione el formato {0:t} Asunto: lblSubject Usando el dilogo DataBindings seleccione Container.DataItem. Subject del rbol Enlace simple. Notas: lblNotes Usando el dilogo DataBindings seleccione Container.DataItem. Notes del rbol Enlace simple. <HR>

FooterTemplate
Lnea HTML

ItemTemplate
Label

Label

Texto ordinario Label

Texto ordinario Label

SeparatorTemplate
Lnea HTML
4

Ninguna

El panel debera tener visible = false para que inicialmente no se vea (N. del T.)

112

Developing Web Applications

6. Copie el control Hyperlink de la parte inferior del formulario AddContact a la parte inferior del formulario Calls. Para copiar el control seleccinelo y pulse CTRL+C. Para pegar la copia en el formulario Calls pulse sobre el formulario en modo diseo y pulse CTRL+V. 7. Pulse dos veces sobre el formulario Web Calls para ver la ventana de cdigo y aada la siguiente sentencia Imports o using en la parte superior del mdulo. Visual Basic .NET
Imports System.Data.SqlClient

Visual C#
using System.Data.SqlClient;

8. El formulario Web Calls usa los componentes de datos del archivo Global.asax, de modo que es necesario recuperar referencias a estos componentes de las variables de estado creadas en la seccin 5.5.2. Las siguientes declaraciones y procedimiento de suceso Page_Load recuperan referencias a los componentes de datos y los hacen disponibles para el cdigo del formulario: Visual Basic .NET
Dim Dim Dim Dim ContactMgmt As SqlConnection adptContacts As SqlDataAdapter adptCalls As SqlDataAdapter dsContacts As New dsContacts()

Private Sub Page_Load(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles MyBase.Load ' Obtiene variables de estado de sesin. ContactMgmt = Session("ContactMgmt") adptContacts = Session("adptContacts") adptCalls = Session("adptCalls") dsCalls = Session("dsCalls") dsContacts = Session("dsContacts") ' Se ejecuta la primera vez que se muestra la pgina. If Not IsPostBack Then ' Rellena el conjunto de datos Contacts. adptContacts.Fill(dsContacts) ' Por cada fila de la tabla ... Dim rowNext As dsContacts.ContactsRow For Each rowNext In dsContacts.Contacts ' Crea un nuevo elemento de lista. Dim lstNew As New ListItem() lstNew.Text = rowNext.FirstName & " " & rowNext.LastName lstNew.Value = rowNext.ContactID ' Aade el elemento a la lista desplegable. drpContacts.Items.Add(lstNew) Next ' Selecciona el primer elemento de la lista. drpContacts.SelectedIndex = 0 End If End Sub

Visual C#
SqlConnection ContactMgmt; SqlDataAdapter adptContacts; SqlDataAdapter adptCalls; dsContacts dsContacts = new dsContacts(); private void Page_Load(object sender, System.EventArgs e){ // Obtiene variables de estado de sesin. ContactMgmt = (SqlConnection)Session["ContactMgmt"]; adptContacts = (SqlDataAdapter)Session["adptContacts"]; adptCalls = (SqlDataAdapter)Session["adptCalls"]; dsCalls = (dsCalls)Session["dsCalls"]; dsContacts = (dsContacts)Session["dsContacts"];

113

MCAD/MCSD

// Se ejecuta la primera vez que se muestra la pgina. if (!IsPostBack){ // Rellena el conjunto de datos Contacts. adptContacts.Fill(dsContacts); // Por cada fila de la tabla... foreach (dsContacts.ContactsRow rowNext in dsContacts.Contacts){ // Crea un nuevo elemento de lista. ListItem lstNew = new ListItem(); lstNew.Text = rowNext.FirstName + " " + rowNext.LastName; lstNew.Value = rowNext.ContactID.ToString(); // Aade el elemento a la lista desplegable. drpContacts.Items.Add(lstNew); } // Selecciona el primer elemento de la lista. drpContacts.SelectedIndex = 0; } }

9. El formulario Web Calls modifica el conjunto de datos Calls en tiempo de ejecucin. Necesita aadir el siguiente cdigo al procedimiento de suceso Page_PreRender para almacenar el conjunto de datos de nuevo en la variable de estado despus de que se finalice el procesamiento de la pgina. (El suceso PreRender es el ltimo que se procesa antes de mostrar la pgina). Visual Basic .NET
Private Sub Page_PreRender(ByVal sender As Object, _ ByVal e As System.EventArgs) Handles MyBase.PreRender ' Graba el conjunto de datos en el estado de sesin. Session("dsCalls") = dsCalls End Sub

Visual C#
private void Page_PreRender(object sender, System.EventArgs e){ // Graba el conjunto de datos en el estado de sesin. Session["dsCalls"] = dsCalls; }

10. Aada el siguiente cdigo para los procedimientos de suceso de pulsacin de los botones Ver y Aadir. Visual Basic .NET
Private Sub butView_Click(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles butView.Click ' Configura el comando de seleccin para el conjunto de datos. adptCalls.SelectCommand.CommandText = "SELECT * FROM Calls " & _ "WHERE ContactID=" & drpContacts.SelectedItem.Value ' Limpia el conjunto de datos. dsCalls.Clear ' Rellena el conjunto de datos. adptCalls.Fill(dsCalls) ' Vincula con el control DataList dlstCalls.DataBind() End Sub Private Sub butAddCall_Click(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles butAddCall.Click ' Configura los valores iniciales de fecha y hora. txtDate.Text = Now.ToShortDateString() txtTime.Text = Now.ToShortTimeString() ' Hace visible el panel de aadir llamada. pnlAdd.Visible = True ' Desactiva los botones y la lista desplegable. butView.Enabled = False butAddCall.Enabled = False drpContacts.Enabled = False End Sub

Visual C#
private void butView_Click(object sender, System.EventArgs e){ // Configura el comando de seleccin para el conjunto de datos. adptCalls.SelectCommand.CommandText = "SELECT * FROM Calls " + "WHERE ContactID=" + drpContacts.SelectedItem.Value; dsCalls.Clear(); // Limpia el conjunto de datos. adptCalls.Fill(dsCalls); // Rellena el conjunto de datos. dlstCalls.DataBind(); // Vincula con el control DataList }

114

Developing Web Applications

private void butAddCall_Click(object sender, System.EventArgs e){ // Configura los valores iniciales de fecha y hora. txtDate.Text = System.DateTime.Now.ToShortDateString(); txtTime.Text = System.DateTime.Now.ToShortTimeString(); // Hace visible el panel de aadir llamada pnlAdd.Visible = true; // Desactiva los botones y la lista desplegable. butView.Enabled = false; butAddCall.Enabled = false; drpContacts.Enabled = false; }

11. Aada la siguiente funcin auxiliar para obtener un nuevo valor de CallID. Como CallID es la clave principal de la tabla Calls necesita un valor nico dentro de la base de datos, como se muestra aqu: Visual Basic .NET
' Devuelve un nuevo CallID nico. Private Function GetCallID() As Integer Dim cmdNewID As New SqlCommand("SELECT MAX(CallID) FROM Calls", ContactMgmt) ContactMgmt.Open() ' Abre la conexin. Dim intID As Integer ' Obtiene el ID ms alto. ' Se asegura de que el registro existe. If Not (cmdNewID.ExecuteScalar() Is DBNull.Value) Then intID = CInt(cmdNewID.ExecuteScalar()) ' Obtiene el nmero ms alto. Else intID = 0 ' O le da el valor cero. End If ContactMgmt.Close() ' Cierra la conexin. ' Devuelve un nuevo ID, superior en uno al ms alto. Return intID + 1 End Sub

Visual C#
int GetCallID() { SqlCommand cmdNewID = new SqlCommand("SELECT MAX(CallID)FROM Calls", ContactMgmt); ContactMgmt.Open(); // Abre la conexin. int intID; // Obtiene el ID ms alto. // Se asegura de que el registro existe. if (cmdNewID.ExecuteScalar() != DBNull.Value) intID = (int)cmdNewID.ExecuteScalar(); // Obtiene el nmero ms alto. else intID = 0; // O le da el valor cero. // Cierra la conexin ContactMgmt.Close(); // Devuelve un nuevo ID, superior en uno al ms alto. return intID + 1; }

12. Aada el siguiente cdigo a los procedimientos de suceso de los botones Aceptar y Cancelar. Estos procedimientos de suceso son muy similares a los usados para aadir o cancelar en la tabla Contacts del ejercicio anterior. Visual Basic .NET
Private Sub butOKAdd_Click(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles butOKAdd.Click Dim rowNew As dsCalls.CallsRow rowNew = dsCalls.Calls.NewCallsRow rowNew.ContactID = drpContacts.SelectedItem.Value rowNew.CallID = GetCallID() rowNew.CallDate = txtDate.Text rowNew.CallTime = txtDate.Text & " " & txtTime.Text rowNew.Subject = txtSubject.Text rowNew.Notes = txtNotes.Text ' Aade la fila al conjunto de datos Calls. dsCalls.Calls.AddCallsRow(rowNew)

115

MCAD/MCSD

Try adptCalls.Update(dsCalls) ' Oculta el panel aadir llamada. pnlAdd.Visible = False ' Limpia los campos. txtSubject.Text = "" txtNotes.Text = "" ' Activa los otros controles. butView.Enabled = True butAddCall.Enabled = True drpContacts.Enabled = True Catch ex As Exception ' Muestra el error. litError.Text = "Se ha producido el siguiente error: <br>" & _ ex.Message & "<br>" & "Corrija el error e intente de nuevo, " & _ o pulse Cancelar.<br>" End Try End Sub Private Sub butCancelAdd_Click(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles butCancelAdd.Click ' Oculta el panel Aadir llamada. pnlAdd.Visible = False ' Limpia los campos. txtSubject.Text = "" txtNotes.Text = "" ' Activa los otros controles. butAddCall.Enabled = True drpContacts.Enabled = True End Sub

Visual C#
private void butOKAdd_Click(object sender, System.EventArgs e){ dsCalls.CallsRow rowNew; rowNew = dsCalls.Calls.NewCallsRow(); rowNew.ContactID = Convert.ToInt16(drpContacts.SelectedItem.Value); rowNew.CallID = GetCallID(); rowNew.CallDate = Convert.ToDateTime(txtDate.Text); rowNew.CallTime = Convert.ToDateTime(txtDate.Text + " " + txtTime.Text); rowNew.Subject = txtSubject.Text; rowNew.Notes = txtNotes.Text; // Aade la fila al conjunto de datos Calls. dsCalls.Calls.AddCallsRow(rowNew); try{ adptCalls.Update(dsCalls); pnlAdd.Visible = false; // Oculta el panel aadir llamada. txtSubject.Text = ""; // Limpia los campos. txtNotes.Text = ""; butView.Enabled = true; // Activa los otros controles. butAddCall.Enabled = true; drpContacts.Enabled = true; }catch (Exception ex){ // Muestra el error. litError.Text = " Se ha producido el siguiente error:<br>" + ex.Message + "<br>" + " Corrija el error e intente de nuevo, o pulse Cancelar<br>"; } } private void butCancelAdd_Click(object sender, System.EventArgs e) { // Oculta el panel Aadir llamada. pnlAdd.Visible = false; // Limpia los campos. txtSubject.Text = ""; txtNotes.Text = ""; // Activa los otros controles. butAddCall.Enabled = true; drpContacts.Enabled = true; }

116

Developing Web Applications

5.5.5 Crear los formularios DeleteContact y ContactTypes


Hasta ahora esta prctica ha mostrado cmo crear formularios Web paso a paso. Ahora es el momento de que vuele solo. Cree los formularios DeleteContact y ContactTypes por si mismo. Estos formularios Web deben realizar las siguientes tareas: Use los componentes de datos del archivo Global.asax Realice operaciones sobre la base de datos. El formulario DeleteContact debe permitir a los usuarios borrar contactos de la base de datos. El formulario ContactTypes debe permitir a los usuarios ver y aadir nuevos tipos de contactos. Use transacciones de conjunto de datos, como se muestra en los formularios AddContact y Calls. Proporcione un modo de volver al formulario SwitchBoard. Cuando termine, compare sus resultados con la aplicacin Contact Management incluida en el CD-ROM.

5.6 Repaso
Las siguientes preguntas estn pensadas para reforzar informacin clave mostrada en este captulo. Si no es capaz de contestar a una pregunta repase la leccin correspondiente e intente de nuevo. Las respuestas se pueden encontrar en el captulo 16. 1. Qu pasos debe seguir y qu objetos debe usar para encontrar rpidamente el nmero de registros en una tabla de base de datos? 2. En qu se diferencian los conjuntos de datos sin tipo de los conjuntos de datos con tipo, y cuales son las ventajas de los conjuntos de datos con tipo? 3. Cmo se reutiliza un componente de conexin de base de datos en una aplicacin Web? 4. Explique las diferencias entre manejar transacciones a nivel base de datos y a nivel conjunto de datos.

117

MCAD/MCSD

118

Developing Web Applications

6 Capturar y corregir errores


En este captulo aprender cmo tratar con los problemas que aparecen en su aplicacin como resultado de circunstancias externas. Este captulo le ayudar a anticipar, identificar y tratar estos tipos de problemas en su aplicacin de modo eficaz. Las lecciones 1 y 2 tratan las dos tcnicas principales para tratar con estos tipos de problemas de programacin dentro de una aplicacin Web ASP.NET. La leccin 3 explica cmo controlar una aplicacin durante las pruebas o despus de que se haya desplegado para asegurar que los problemas se han tratado correctamente. Para completar las lecciones de este captulo debe: Estar familiarizado con los aspectos bsicos del lenguaje de programacin Visual Basic o C#. Esto incluye familiaridad con los conceptos de variables, procedimientos, estructuras de decisin y alcance. Vea los temas de ayuda Cambios en el Lenguaje Visual Basic o Recorrido del Lenguaje C# en Visual Studio .NET. Comprender cmo crear una aplicacin Web bsica usando formularios Web, controles de servidor y procedimientos de suceso que se introdujeron en el Captulo 2, Crear Aplicaciones de Formulario Web. Haber completado la aplicacin Contact Management tratada en el Captulo 5, Almacenar y Recuperar Datos con ADO.NET. La prctica final de este captulo ampla este ejemplo con tratamiento de excepciones.

6.1 Uso del manejo de excepciones


Las excepciones son circunstancias inusuales que se producen dentro de la lgica de una aplicacin. En la documentacin de Visual Studio a menudo se intercambian los trminos excepcin y error porque se usan las mismas tcnicas para manejar ambas situaciones. En esta leccin aprender las diferentes tcnicas de programacin que puede usar para controlar excepciones en una aplicacin Web. Esta leccin trata solo las tcnicas modernas que proporcionan Visual Studio .NET y ASP.NET. No trata sintaxis de control de excepciones antiguas como On Error, que an soporta Visual Basic .NET.

6.1.1 Tcnicas de control de excepciones


Cuando se produce un problema no anticipado en una aplicacin Web, es inmediatamente aparente para el usuario, que generalmente ver un mensaje de error. Cuando sucede esto el usuario se queda bloqueado lo nico que puede hacer es pulsar Atrs en su navegador e intentar de nuevo. El programador es responsable de anticipar estas situaciones y tratarlas en su cdigo antes de que se produzcan. El proceso para tratar con estos tipos de situaciones se llama control de excepciones. Los errores con los que no se trata en el cdigo se llaman excepciones no controladas y son los que aparecen ante el usuario. Hay dos aproximaciones diferentes para manejar excepciones en una aplicacin Web: Utilizar bloques de control de excepciones para tratar con estas dentro del alcance de un procedimiento. Esta tcnica se denomina control de excepciones estructurado (SEH, estructured exception handling) en la documentacin de Visual Studio Usar sucesos de error para tratar con excepciones dentro del alcance de un objeto.

6.1.2 Usar bloques de control de excepciones


Utilice bloques de control de excepciones para encerrar sentencias que pueden fallar debido a condiciones externas. Un ejemplo habitual es el acceso a ficheros. Cuando se intenta grabar un archivo en un servidor pueden producirse una serie de problemas: el disco puede estar lleno, el nombre de fichero puede estar ya en uso, o puede que la ruta para grabar el fichero no exista. Para tratar con estos posibles problemas encierre las sentencias de acceso a archivos en un bloque de control de excepciones. La tabla 6-1 describe las palabras clave usadas para crear un bloque de control de excepciones.
Tabla 6. 1: Palabras clave de control de excepciones
Visual C# Basic .NET Se usa para Comenzar una estructura de control de errores. Si una sentencia que siga a esta palabra clave provoca una excepcin el flujo de control pasa inmediatamente a la siguiente sentencia Catch/catch Recupera cualquier excepcin que se haya producido y la gestiona. Cuando el flujo de control pasa a un bloque Catch/catch se procesan las sentencias contenidas en el bloque para corregir el error o manejar la excepcin de alguna otra forma. Procesa las sentencias que se deben ejecutar como parte del bloque de control de excepciones tanto si se produce un error como si no. Finaliza un bloque de control de excepciones. Provoca una excepcin. Use esta palabra dentro del bloque de control de excepciones para pasar inmediatamente el flujo de control a la sentencia Catch/catch.

Try

try

Catch Finally End Try Throw

catch finally N/A throw

119

MCAD/MCSD

La forma ms sencilla de comprender el uso combinado de estas palabras clave es un ejemplo. Imagine un formulario Web que permite seleccionar un archivo de su mquina para subir al servidor. Cuando se sube el archivo se aade a una caja de lista. Cuando el usuario introduce un nombre de archivo y pulsa Subir pueden darse una serie de condiciones de excepcin: El archivo puede no existir en el ordenador cliente La conexin Internet puede fallar durante la subida El archivo puede ser demasiado grande para subirlo en Internet El servidor puede no tener suficiente espacio en disco para el archivo.

Para controlar estas situaciones imprevisibles, encierre las sentencias que pueden causar estas condiciones en un bloque de control de excepciones, como muestra el siguiente cdigo: Visual Basic .NET
Private Sub butUpload_Click(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles butUpload.Click Dim strFilename As String = fileUpload.PostedFile.Filename ' Divide el nombre de archivo en partes. strFilename = System.IO.Path.GetFilename(strFilename) Try ' (1) Comprueba si el archivo tiene longitud cero (no existe). If filUpload.PostedFile.ContentLength = 0 Then Throw New System.IO.FileNotFoundException() End If ' (2) Graba el archivo en el servidor usando su nombre base. filUpload.PostedFile.SaveAs(Request.MapPath(Request.ApplicationPath) & _ "\" & strFilename) ' Aade el archivo a la lista de archivos del servidor. lstFiles.Items.Add(strFilename) ' Selecciona el primer elemento de la lista. lstFiles.SelectedIndex = 0 Catch ex As Exception ' (3) Controla las posibles excepciones. litError.Text = "<p>SE ha producido el error:</p>" & ex.Message & "<br>" Finally ' (4) Ejecuta limpieza. ' Reinicia el campo Archivo. filUpload.Value = "" End Try End Sub

Visual C#
private void butUpload_Click(object sender, System.EventArgs e){ string strFilename = filUpload.PostedFile.FileName; // Divide el nombre de archivo en partes. strFilename = System.IO.Path.GetFileName(strFilename); try{ // (1) Comprueba si el archivo tiene longitud cero (no existe). if (filUpload.PostedFile.ContentLength == 0) throw new System.IO.FileNotFoundException(); // (2) Graba el archivo en el servidor usando su nombre base. filUpload.PostedFile.SaveAs(Request.MapPath(Request.ApplicationPath) + "\\" + strFilename); // Aade el archivo a la lista de archivos del servidor. lstFiles.Items.Add(strFilename); // Selecciona el primer elemento de la lista. lstFiles.SelectedIndex = 0; }catch (Exception ex) // (3) Controla las posibles excepciones. litError.Text = "<p>Se ha producido el error:</p>" + ex.Message + "<br>"; finally // (4) Ejecuta limpieza. // Reinicia el campo Archivo. filUpload.Value = ""; }

Cuando se ejecuta el cdigo anterior sigue estos pasos: 1. Comprueba si existe el fichero en la mquina cliente. Si el archivo introducido tiene longitud cero, el archivo no existe, de modo que el cdigo causa una System.IO.FileNotFoundException y el flujo pasa inmediatamente al paso 3. 2. Graba el archivo en el servidor. Si tiene xito, el flujo de control contina aadiendo el nombre del archivo a la ListBox. Si falla, el flujo de control pasa al paso 3, saltndose la ListBox. 120

Developing Web Applications

3. Controla la excepcin. En este caso, las excepciones se controlan sencillamente mostrndolas en un control Literal en el formulario Web. Si no se ha producido ninguna excepcin, el flujo de control se salta este paso y va directamente al 4. 4. Limpieza final. Estas sentencias son el ltimo paso en el bloque de control de excepciones. La palabra clave Catch/catch puede interceptar excepciones generales, como muestra el ejemplo anterior, o puede interceptar y responder de forma diferente a tipos de excepciones concretos, como muestra este fragmento: Visual Basic .NET
Try ' Algunas sentencias... Catch ex As System.IO.FileNotFoundException litError.Text = "<p>El archivo no existe.</p>" Catch ex As System.IO.IOException litError.Text = "<p>No se puede grabar el archivo en el servidor.</p>" Catch ex As System.Net.WebException litError.Text = "<p>Error de Internet durante la subida.</p>" Catch ex As Exception litError.Text = "<p>Se ha producido el error:</p>" & ex.Message & "<br>" End Try

Visual C#
try{ // Algunas sentencias... } catch (System.IO.FileNotFoundException ex) litError.Text = "<p> El archivo no existe.</p>"; catch (System.IO.IOException ex) litError.Text = "<p> No se puede grabar el archivo en el servidor.</p>"; catch (System.Net.WebException ex) litError.Text = "<p> Error de Internet durante la subida.</p>"; catch (Exception ex) litError.Text = "<p> Se ha producido el error:</p>" + ex.Message + "<br>";

El cdigo anterior ejecuta cuatro sentencias diferentes dependiendo de si la excepcin es FileNotFoundException, IOException, WebException o cualquier otro tipo de excepcin. Como las sentencias Catch se procesan secuencialmente, debe ponerlas en orden, de la excepcin ms especfica a la ms general. Por ejemplo, el siguiente fragmento de cdigo nunca ejecutar las sentencias para System.IO.IOException, System.IO.FileNotFoundException o System.Net.WebException, porque estos errores los captura primero el tipo de excepcin general Exception: Visual Basic .NET
Catch ex As Exception litError.Text = "<p>Se ha producido el error:</p>" & ex.Message & "<br>" Catch ex As System.IO.FileNotFoundException litError.Text = "<p>El archivo no existe.</p>" Catch ex As System.IO.IOException litError.Text = "<p>No se puede grabar el archivo en el servidor.</p>" Catch ex As System.Net.WebException litError.Text = "<p>Error de Internet durante la subida.</p>"

Visual C#
catch (Exception ex) litError.Text = "<p> Se ha producido el error:</p>" + ex.Message + "<br>"; catch (System.IO.FileNotFoundException ex) litError.Text = "<p> El archivo no existe.</p>"; catch (System.IO.IOException ex) litError.Text = "<p> No se puede grabar el archivo en el servidor.</p>"; catch (System.Net.WebException ex) litError.Text = "<p> Error de Internet durante la subida.</p>";

El marco de trabajo .NET incluye tipos de excepcin especficos con las clases individuales. Esto significa que no hay una nica lista completa de tipos de excepcin en la documentacin de .NET. En su lugar debe usar el dilogo Excepciones de Visual Studio .NET para ver los tipos de excepcin concretos, como describe el siguiente procedimiento. 1. En el men Depurar seleccione Excepciones. Visual Studio muestra el dilogo Excepciones. 2. Pulse el signo ms a la izquierda de los elementos de la lista para ver las excepciones que proporciona.

121

MCAD/MCSD

6.1.3 Causar excepciones


Como ha visto en la seccin anterior, la palabra clave Throw/throw se usa para causar una excepcin concreta. Esta tcnica es til para mostrar cmo funciona el control de excepciones, pero provoca la pregunta para qu querremos provocar una excepcin en una aplicacin del mundo real?. El control de excepciones es una forma de implementar un cierto tipo de lgica en la aplicacin. Sencillamente est especificando una serie de situaciones que no son normalmente parte del curso de los sucesos de la aplicacin y diciendo: Esto son excepciones. Esto permite dejar aparte la complejidad de tratar con estas excepciones, simplificando de esta forma la lgica principal de la aplicacin. Por ejemplo, en el ejemplo FileUpload a continuacin es razonable causar la excepcin FileNotFoundException si el archivo subido tiene longitud cero. De lo contrario es muy difcil determinar si un archivo existe en la mquina cliente antes de subirlo. FileNotFoundException es una excepcin estndar del espacio de nombres System.IO, y es descriptiva de lo que sucede. Visual Basic .NET
Private Sub butUpload_Click(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles butUpload.Click Dim strFilename As String = filUpload.PostedFile.Filename ' Divide el nombre de archivo en partes. strFilename = System.IO.Path.GetFilename(strFilename) Try ' Comprueba si el archivo tiene longitud cero (no existe). If filUpload.PostedFile.ContentLength = 0 Then Throw New System.IO.FileNotFoundException() End If ' Graba el archivo en el servidor con su nombre. filUpload.PostedFile.SaveAs(Request.MapPath(Request.ApplicationPath) & _ "\" & strFilename) ' Aade el archivo a la lista de archivos del servidor. lstFiles.Items.Add(strFilename) ' Selecciona el primer elemento de la lista. lstFiles.SelectedIndex = 0 ' Controla posibles excepciones. Catch ex As System.IO.FileNotFoundException litError.Text = "<p>El archivo no existe.</p>" Catch ex As System.IO.IOException litError.Text = "<p>No se pudo grabar el archivo en el servidor.</p>" Catch ex As System.Net.WebException litError.Text = "<p>Error de Internet durante la subida del archivo.</p>" Catch ex As Exception litError.Text = "<p>Se produjo el error:</p>" & ex.Message & "<br>" ' Limpieza. Finally ' Reinicia el campo Archivo. filUpload.Value = "" End Try End Sub

Visual C#
private void butUpload_Click(object sender, System.EventArgs e){ string strFilename = filUpload.PostedFile.FileName; // Divide el nombre de archivo en partes. strFilename = System.IO.Path.GetFileName(strFilename); try{ // (1) Comprueba si el archivo tiene longitud cero (no existe). if (filUpload.PostedFile.ContentLength == 0) throw new System.IO.FileNotFoundException(); // (2) Graba el archivo en el servidor con su nombre. filUpload.PostedFile.SaveAs(Request.MapPath(Request.ApplicationPath) + "\\" + strFilename); // Aade el archivo a la lista de archivos del servidor. lstFiles.Items.Add(strFilename); // Selecciona el primer elemento de la lista. lstFiles.SelectedIndex = 0; }

122

Developing Web Applications

// (3) Controla posibles excepciones. catch (System.IO.FileNotFoundException ex) litError.Text = "<p> El archivo no existe.</p>"; catch (System.IO.IOException ex) litError.Text = "<p> No se pudo grabar el archivo en el servidor.</p>"; catch (System.Net.WebException ex) litError.Text = "<p> Error de Internet durante la subida del archivo.</p>"; catch (Exception ex) litError.Text = "<p> Se produjo el error:</p>" + ex.Message + "<br>"; // (4) Limpieza. finally // Reinicia el campo Archivo. filUpload.Value = ""; }

6.1.4 Definir nuevas excepciones


En algunos casos querr provocar en su aplicacin una excepcin que no tenga un equivalente descriptivo en el marco de trabajo .NET. En estos casos deber crear una nueva excepcin del tipo ApplicationException. Por ejemplo, el siguiente fragmento de cdigo causa una excepcin que indica que el usuario ya est conectado: Visual Basic .NET
Throw New ApplicationException("El usuario ya est conectado")

Visual C#
throw new ApplicationException("El usuario ya est conectado);

Para controlar esta excepcin utilice la siguiente sentencia: Visual Basic .NET
Catch ex As ApplicationException

Visual C#
catch(ApplicationException ex)

La clase ApplicationException proporciona las mismas caractersticas que la clase Exception estndar. Sencillamente proporciona una forma de diferenciar entre las excepciones definidas en el marco de trabajo .NET y las definidas en la aplicacin. Si est creando una gran aplicacin o si est creando componentes utilizados por otras aplicaciones querr definir sus propias clases de excepcin basadas en la clase ApplicationException. Por ejemplo, el siguiente cdigo define una clase para UserLoggedOnException. Visual Basic .NET
Public Class UserLoggedOnException Inherits ApplicationException ' Constructor de Excepcin. Sub New(Optional ByVal Message As String = "El usuario ya est conectado.", _ Optional ByVal Inner As Exception = Nothing) MyBase.New(Message, Inner) End Sub End Class

Visual C#
public class UserLoggedOnException : System.ApplicationException { // Constructor de Excepcin (sobrecargado) public UserLoggedOnException() : this("El usuario ya est conectado ", null){} public UserLoggedOnException(string message) : this(message, null){} public UserLoggedOnException(string message, Exception inner) : base(message, inner){} }

La clase UserLoggedOnException anterior hereda sus propiedades y mtodos de la clase base ApplicationException. La nueva clase proporciona solamente su propio constructor para configurar el mensaje predeterminado que muestra. Este es un mtodo estndar.

6.1.5 Uso de sucesos de error


Otra forma de controlar excepciones es mediante los sucesos de error incorporados a los objetos Web. Cuando se produce una aplicacin no controlada en una aplicacin Web ASP.NET lanza los sucesos que se describen en la tabla 6.2. 123

MCAD/MCSD

Tabla 6. 2: Sucesos de control de excepciones


Procedimiento de Se produce cuando suceso Page_Error Se produce una excepcin sin controlar en la pgina. Este procedimiento reside en el formulario Web. Global_Error Se produce una excepcin sin controlar en la aplicacin. Este procedimiento reside en el archivo Global.asax. Application_Error Se produce una excepcin sin controlar en la aplicacin. Este procedimiento reside en el archivo Global.asax.

Los sucesos de error permiten controlar excepciones para todo un objeto en un lugar nico centralizado. Es diferente al uso de bloques de control de excepciones, que controlan las excepciones dentro del procedimiento en el que suceden. Puede usar los sucesos de error de las siguientes formas: Como sustitutos de los bloques de control de excepciones. Como los sucesos de error se producen fuera del alcance del procedimiento donde se produjo el error, tiene menos informacin sobre los pasos que llevan a la excepcin, y por tanto menos capacidad de corregir la condicin de error por el usuario. Sin embargo, es adecuado para tareas donde no se podr corregir la excepcin en el cdigo. Como complemento de los bloques de control de excepciones. Los sucesos de error pueden proporcionar un ltimo punto de defensa centralizado contra las excepciones no previstas o controladas en algn otro lugar. Usando las dos tcnicas de control de excepciones juntas se asegura de capturar todas las excepciones antes de que el usuario las vea, mostrar un mensaje razonable, e incluso registrar el error para mejorar la aplicacin. Cuando controle excepciones en sucesos de error use el objeto Server para obtener informacin sobre lo que ha sucedido. El objeto Server proporciona los mtodos que muestra la tabla 6.3 para trabajar con excepciones.
Tabla 6. 3: mtodos de control de excepciones de objeto Server
Mtodo Se usa para Obtiene la ltima excepcin producida en el servidor. Elimina la ltima excepcin producida en el servidor. La llamada a ClearError controla la excepcin, de modo que no lanza sucesos de error posteriores ni aparece al usuario en el navegador.

GetLastError() ClearError()

Para controlar una excepcin en un suceso de error siga estos pasos: 1. En el procedimiento de suceso Page_Error, Global_Error o Application_Error obtenga la excepcin que se produjo usando el mtodo GetLastError. 2. Haga algo con la excepcin, como mostrar un mensaje al usuario, corregir el problema o escribir un registro de error. 3. Elimine la excepcin usando ClearError. 4. Vuelva a mostrar la pgina Web. El procesamiento de una pgina Web se detiene inmediatamente cuando se produce una excepcin, de forma que los controles de servidor y otros elementos de la pgina podran no mostrarse despus de procesar la excepcin. El siguiente cdigo muestra estos pasos: Visual Basic .NET
Private Sub Page_Error(ByVal sender As Object, _ ByVal e As System.EventArgs) Handles MyBase.Error Dim ex As Exception = Server.GetLastError() ' Obtiene el error. Session("Error") = ex.Message() ' Almacena el mensaje de error. Server.ClearError() ' Elimina el error. Response.Redirect("ErrorEvents.aspx") ' De vuelta a esta pgina. End Sub

Visual C#
private void Page_Error(object sender, System.EventArgs e){ Exception ex = Server.GetLastError(); // Obtiene el error. Session["Error"] = ex.Message; // Almacena el mensaje de error. Server.ClearError(); // Elimina el error. Response.Redirect("ErrorEvents.aspx"); // Redirige de vuelta a esta pgina. }

El cdigo anterior almacena el mensaje de excepcin como variable de estado Session antes de limpiar la excepcin de modo que se pueda mostrar el mensaje cuando se recargue la pgina mediante el mtodo Redirect. El siguiente cdigo muestra el mensaje de excepcin grabado cuando se vuelve a mostrar la pgina:

124

Developing Web Applications

Visual Basic .NET


Private Sub Page_Load(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles MyBase.Load ' Muestra el error, si lo hay. If Session("Error") <> Nothing Then litError.Text = "<p>Se produjo el error:</p>" & Session("Error") & "<br>" ' Limpia la variable de estado de sesin. Session("Error") = Nothing End If End Sub

Visual C#
private void Page_Load(object sender, System.EventArgs e){ // Muestra el error, si lo hay. if(Session["Error"] != null){ litError.Text = "<p> Se produjo el error:</p>" + Session["Error"].ToString(); // Limpia la variable de estado de sesin. Session["Error"] = null; } }

6.2 Usar pginas de error


La leccin 6.1 proporcion tcnicas para controlar excepciones que ocurren en el servidor que ejecuta la aplicacin Web. Sin embargo, como las aplicaciones Web corren sobre Internet, hay toda una clase de excepciones que no se pueden detectar desde el cdigo. Para interceptar estos errores y proporcionar la mejor respuesta posible necesita usar pginas de error. En esta leccin aprender como usar pginas de error en ASP.NET para interceptar errores HTTP y responder ante ellos a nivel aplicacin y pgina.

6.2.1 Control de excepciones relacionadas con internet


Cuando un usuario ejecuta una aplicacin Web desde su navegador se pueden producir una serie de excepciones fuera del alcance de la verdadera aplicacin. Por ejemplo, se pueden producir errores de servidor cuando se agota el tiempo de espera para una respuesta del usuario, o la pgina solicitada puede no encontrarse en el servidor. Las pginas de error son pginas .htm o .aspx en el servidor a las que se redirige al usuario cuando se produce una excepcin no controlada. ASP.NET permite definir pginas de error a dos niveles: Especificar opciones de pgina de error a nivel aplicacin en la seccin customErrors del archivo Web.config. Estas opciones determinan la pgina que se muestra para errores HTTP concretos. Especificar una pgina de error para un formulario Web concreto en el atributo ErrorPage de la directiva Page. Esta opcin determina la pgina de error que se muestra si el formulario Web encuentra una excepcin no controlada.

6.2.2 Pginas de error a nivel de aplicacin


Internet Information Service (IIS) de Microsoft define las pginas de error que se muestran de forma predeterminada para respuestas HTTP especficas. Para ver o cambiar la configuracin de pgina de error para una aplicacin en IIS siga estos pasos: 1. Pulse con el botn derecho sobre el directorio de aplicacin Web y seleccione Propiedades. IIS muestra el dilogo Propiedades. 2. Pulse sobre la lengeta Errores personalizados. IIS muestra la configuracin de pginas de error para cdigos de respuesta HTTP especficos. 3. Seleccione el cdigo de respuesta cuya pgina de error quiere cambiar y pulse Modificar propiedades. IIS muestra el dilogo Propiedades de asignacin de errores. 4. Pulse Examinar para reemplazar la pgina de error por una pgina de su propio directorio de aplicacin. Pulse Aceptar cuando termine. Al usar IIS para cambiar las pginas de error a nivel aplicacin los cambios se hacen en el servidor donde est desplegada la aplicacin. Si se cambia de servidor habr que repetir estos cambios. Como alternativa, puede hacer que la configuracin de pginas de error a nivel de aplicacin sea parte de la aplicacin usando el archivo Web.config del proyecto. Para especificar las pginas que se mostrarn si se producen errores HTTP especficos no controlados en una aplicacin Web use la seccin customErrors del archivo Web.config. Los errores HTTP estn identificados por un cdigo de estado definido en la especificacin HTTP 1.1. ASP.NET recoge estos cdigos de estado en la enumeracin HTTPStatusCode. Algunos de los ms habituales se recogen en la tabla 6-4. 125

MCAD/MCSD

Tabla 6. 4: Cdigos de estado HTTP habituales


Valor 200 204 301 302 400 401 403 404 408 500 503 505 Miembro HTTPStatusCode OK NoContent Moved, MovedPermanently Found, Redirect BadRequest Unauthorized Forbidden NotFound RequestTimeOut InternalServerError ServiceUnavailable HttpVersionNotSupported Indica La peticin ha tenido xito La peticin he tenido xito, pero la respuesta est intencionadamente en blanco. La peticin se est redirigiendo a otra direccin La peticin se est redirigiendo a otra direccin El servidor no puede comprender la peticin El recurso solicitado necesita una autorizacin que no ha sido proporcionada con la peticin. El servidor rechaza cumplir la peticin El recurso solicitado no existe en el servidor. El cliente no envi una peticin antes de que terminara el tiempo de espera de peticin del servidor. Se ha producido un error genrico en el servidor. El servidor est temporalmente no disponible El servidor no da soporte a la versin de HTTP solicitada.

Para mostrar una pgina concreta en respuesta a uno o ms de estos cdigos de estado incluya un etiqueta <error> en la seccin customErrors del archivo Web.config de su aplicacin. Por ejemplo, la siguiente seccin customErrors especifica una pgina de error predeterminada, junto con tres pginas de error diferentes para cdigos de respuesta HTTP concretos:
<customErrors mode="On" defaultRedirect="ErrDefault.aspx"> <error statusCode="401" redirect="ErrUnauthorized.aspx" /> <error statusCode="404" redirect="ErrPageNotFound.aspx" /> <error statusCode="500" redirect="ErrServer.htm" /> </customErrors>

EL campo mode de customErrors debe tener el valor on para ver las pginas de error mientras se depura la aplicacin en la mquina local. Si se le da el valor RemoteOnly (predeterminado) se mostrarn las pginas designadas cuando se acceda a la aplicacin desde una mquina cliente, pero no cuando se acceda de modo local.

6.2.3 Pginas de error a nivel de pgina


Para mostrar una pgina concreta cuando se produzca una excepcin no controlada en un formulario Web use el atributo ErrorPage del objeto Page. Puede usar los mtodos GetLastError y ClearError del objeto Server desde la pgina de error, como se mostr anteriormente para los sucesos de error. Por ejemplo, el siguiente HTML establece el atributo ErrorPage para un formulario Web. Visual Basic .NET
<%@ Page Language="vb" AutoEventWireup="false" Codebehind="WebForm1.aspx.vb" Inherits="vbExceptionSnippet.WebForm1" errorPage="errDefault.aspx"%>

Visual C#
<%@ Page language="c#" Codebehind="ErrorPage.aspx.cs" AutoEventWireup="false" Inherits="csErrorPageSnippet.WebForm1" errorPage="ErrDefault.aspx"%>

A continuacin, el siguiente cdigo provoca una excepcin cuando el usuario pulsa butError. Visual Basic .NET
' Webform1.aspx Private Sub butError_Click(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles butError.Click ' Causa excepcin. Throw New System.Net.WebException() End Sub

Visual C#
// Webform1.aspx private void butError_Click(object sender, System.EventArgs e){ // Causa excepcin. throw new System.Net.WebException(); }

Cuando se produce una excepcin se muestra la pgina ErrDefault.aspx, que describe el error al usuario usando el siguiente cdigo. Visual Basic .NET
' ErrDefault.aspx Private Sub Page_Load(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles MyBase.Load ' Muestra el error producido. litError.Text = "<p>Se ha producido el error:</p>" & _ Server.GetLastError.Message

126

Developing Web Applications

' Limpia el error. Server.ClearError() End Sub

Visual C#
// ErrDefault.aspx private void Page_Load(object sender, System.EventArgs e){ // Muestra el error producido. litError.Text = "<p>Se ha producido el error:</p>" + Server.GetLastError().Message; // Limpia el error. Server.ClearError(); }

6.3 Registro de excepciones


Mientras se desarrolla la aplicacin es una buena idea usar registro de excepciones para proporcionar un medio de seguimiento de las mismas. Un registro de excepciones es una lista de excepciones controladas que se producen durante la ejecucin de la aplicacin. El repaso peridico del registro de excepciones le ayuda a comprobar que las excepciones se estn controlando correctamente, no se estn produciendo con demasiada frecuencia y no estn impidiendo a los usuarios que realicen tareas con su aplicacin. En esta leccin aprender cmo usar las caractersticas de seguimiento de ASP.NET para implementar el registro de excepciones en su aplicacin.

6.3.1 Usar seguimiento para registrar errores


El seguimiento es una tcnica para registrar sucesos, como las excepciones, en una aplicacin. Siempre ha habido formas de registrar los errores de una aplicacin normalmente abriendo un archivo y escribiendo en l los mensajes de error pero el seguimiento ofrece ventajas significativas. Estandarizacin. Incorporar el seguimiento en el marco de trabajo .NET asegura que las tcnicas de programacin son las mismas en todas las aplicaciones que se desarrollen con l. Soporte Web Incorporado. ASP.NET ampla las herramientas del marco de trabajo .NET incluyendo informacin relativa a las prestaciones y comportamiento de las peticiones Web. Configuracin. Puede activar y desactivar el seguimiento usando opciones del archivo de configuracin de la aplicacin. No necesita recompilar la aplicacin. Prestaciones. Cuando estn desactivadas, las sentencias de seguimiento no afectan a las prestaciones. Para usar seguimiento en una aplicacin Web siga estos pasos: 1. Active el seguimiento. 2. Escriba en el registro de seguimiento. 3. Lea el registro de seguimiento. Las seccione siguientes proporcionan detalles sobre estos pasos.

6.3.2 Activar y desactivar el seguimiento


El seguimiento se puede activar y desactivar para una aplicacin Web completa o para una pgina individual. Para activar el seguimiento para toda una aplicacin, de el valor True al atributo Enabled del elemento <trace> en el archivo Web.config. Para activar el seguimiento para una nica pgina de el valor True a la propiedad Trace del objeto DOCUMENT. De forma predeterminada la salida de seguimiento se muestra al final de cada pgina Web. Aunque esto es adecuado para depurado, por lo general cuando empiece a probar una aplicacin terminada querr escribir el seguimiento en un archivo de registro. Para escribir el seguimiento en un archivo para toda la aplicacin de el valor False al atributo PageOutput del elemento <trace>. ASP.NET escribe la salida de seguimiento en un archivo Trace.axd en el directorio raz de la aplicacin. El elemento <trace> incluye un atributo RequestLimits para determinar cuantas peticiones de pgina escribir en el registro. Por ejemplo, la siguiente lnea de un archivo Web.config activa el seguimiento para la aplicacin y escribe las 20 primeras peticiones en el archivo Trace.axd.
<trace enabled="true" requestLimit="20" pageOutput="false" traceMode="SortByTime" localOnly="true" />

La escritura de los mensajes de seguimiento en un archivo de registro no afecta al seguimiento configurado a nivel de pgina. Cuando la propiedad Trace de un objeto DOCUMENT tiene el valor True todos los mensajes de seguimiento para esta pgina se muestran en la misma. 127

MCAD/MCSD

Para escribir mensajes de seguimiento en un archivo solo para las pginas seleccionadas de una aplicacin siga estos pasos: 1. En el elemento <trace> del archivo Web.config de la aplicacin de el valor True al atributo Enabled y el valor False al atributo PageOutput. 2. De el valor False a la propiedad Trace del objeto DOCUMENT en cada pgina que quiera excluir del seguimiento. Cuando se ha establecido la propiedad Trace de un objeto DOCUMENT a True o False no se puede restablecer la opcin predeterminada desde la ventana de propiedades de Visual Studio, sino que debe editar el HTML del formulario Web para eliminar el campo trace del elemento Page. El siguiente cdigo muestra en negrita el texto que debe borrar. Visual Basic .NET
<%@ Page Language="vb" AutoEventWireup="false" Codebehind="Trace.aspx.vb" Inherits="vbErrorLogSnippet.WebForm1" trace="True" %>

Visual C#
<%@ Page language="c#" Codebehind="WebForm1.aspx.cs" AutoEventWireup="false" Inherits="csTracing.WebForm1" trace="True"%>

6.3.3 Escribir mensajes en el registro de seguimiento


El objeto Trace proporciona los mtodos Write y Warn que permiten escribir mensajes en la informacin de seguimiento. Los dos mtodos son idnticos con una excepcin: los mensajes escritos con Write se muestran en negro, mientras que los escritos con Warn se muestran en rojo. Por ejemplo, el siguiente cdigo escribe informacin sobre excepciones no controladas en el registro de seguimiento usando el mtodo Warn, por lo que se ven en rojo. Visual Basic .NET
Private Sub Page_Error(ByVal sender As Object, _ ByVal e As System.EventArgs) Handles MyBase.Error ' escribe un mensaje en el registro de seguimiento. Trace.Warn("Error", "", Server.GetLastError()) ' Limpia el error de modo que la aplicacin puede continuar. Server.ClearError() ' Vuelve a mostrar la pgina. Response.Redirect("Trace.aspx") End Sub

Visual C#
private void Page_Error(object sender, System.EventArgs e){ // Escribe un mensaje en la registro de seguimiento. Trace.Warn("Error", "", Server.GetLastError()); // Limpia el error de modo que la aplicacin puede continuar. Server.ClearError(); // Vuelve a mostrar la pgina. Response.Redirect("Trace.aspx"); }

En algunos casos querr realizar algunas acciones adicionales cuando el seguimiento est activo, por ejemplo, especificar informacin de usuario. La propiedad IsEnabled del objeto Trace permite ejecutar este cdigo condicionalmente, de modo que no afecta a las prestaciones cuando el seguimiento est desactivado. Por ejemplo, el siguiente cdigo aade informacin de navegador al mensaje de seguimiento si este est activado. Visual Basic .NET
Private Sub Page_Error(ByVal sender As Object, _ ByVal e As System.EventArgs) Handles MyBase.Error If Trace.IsEnabled Then Dim strMessage As String If Request.Browser.AOL Then strMessage = "Navegador AOL" Else strMessage = "Navegador no AOL" End If Trace.Warn("Error", strMessage, Server.GetLastError()) End If Server.ClearError() Response.Redirect("Trace.aspx") End Sub

128

Developing Web Applications

Visual C#
private void Page_Error(object sender, System.EventArgs e){ if (Trace.IsEnabled){ string strMessage; if (Request.Browser.AOL) strMessage = "Navegador AOL"; else strMessage = "Navegador no AOL"; Trace.Warn("Error", strMessage, Server.GetLastError()); } Server.ClearError(); Response.Redirect("Trace.aspx"); }

6.3.4 Leer el registro de seguimiento


De forma predeterminada la salida de seguimiento se muestra en la parte inferior de cada pgina Web que tiene el seguimiento activado. Como se mencion anteriormente, si el atributo PageOutput del elemento <trace> del archivo Web.config tiene el valor False la salida de seguimiento se escribe en el archivo Trace.axd en el directorio raz de la aplicacin en lugar de mostrarse en la pgina. Puede ver este archivo sencillamente pidindolo en su navegador. Por ejemplo, puede usar el enlace:
<A href="Trace.axd">Ver Seguimiento</A>

De forma predeterminada solo puede ver Trace.axd desde el servidor local en la que corre la aplicacin. Si quiere verlo desde una mquina remota, como cuando se depura en remoto, de el valor False al atributo localOnly del elemento <trace> en el archivo Web.config:
<trace Enabled="true" requestLimit="20" pageOutput="false" traceMode="SortByTime" localOnly="false" />

El seguimiento ASP.NET se detiene despus de que el servidor recibe el nmero de peticiones HTTP indicado en el atributo requestLimit del elemento <trace>. Para limpiar la lista y comenzar el seguimiento de nuevo pulse el enlace Borrar rastro actual en la parte superior derecha de la pgina Trace.axd. Este enlace vuelve a mostrar Trace.axd pasndole la cadena de consulta clear=1

6.4 Resumen
El control de excepciones proporciona un modo de tratar con sucesos no usuales en un programa. Cada una de las diferentes tcnicas de control de excepciones proporciona una forma de dejar aparte la complejidad del trato con estos sucesos no usuales de modo que no oculten la lgica principal de la aplicacin. Los bloques de control de excepciones usan las palabras clave Try, Catch, Finally (Visual Basic .NET) o try, catch, finally (C#) Capture las excepciones en orden de ms especfica a ms general. Use la palabra clave Throw (Visual Basic .NET) o throw (C#) para causar una interrupcin intencionada. Los sucesos de error controlan las excepciones en un procedimiento de suceso separado. Use los mtodos GetLastError y ClearError para controlar excepciones en estos sucesos de error. Las pginas de error controlan excepciones que se producen fuera de la aplicacin Web a causa de problemas relacionados con Internet. Vigile las excepciones que controla su aplicacin escribiendo mensajes en el registro de seguimiento usando los mtodos Write y Warn del objeto Trace. Active el seguimiento a nivel de aplicacin configurando los atributos del elemento <trace> en el archivo Web.config. Active el seguimiento a nivel de pgina configurando el atributo Trace en la directiva Page de un formulario Web.

6.5 Prctica: Aadir control de excepciones a una aplicacin


En esta prctica aadir caractersticas de control de excepciones a la aplicacin Contact Management ya existente. Cuando se introdujo esta aplicacin en el Captulo 5 usaba algunos bloques de control de excepcione sencillos para enfrentarse a problemas que podan surgir al actualizar registros en la base de datos. Esta leccin ampla estos bloques para tratar con tipos concretos de errores de datos e implementa seguimiento para ver cmo se controlan los errores.

6.5.1 Ampliar el control de errores


La aplicacin Contact Management trata con excepciones de base de datos de una forma muy sencilla: Si se encuentra una excepcin muestra el error y deja que el usuario cancele la operacin. Por ejemplo, vea el cdigo para el suceso butAdd_Click del formulario AddContact, apartado 5.5.3, paso 8. 129

MCAD/MCSD

Para crear un control de excepciones ms detallado edite las sentencias Catch/catch en la aplicacin para controlar las siguientes excepciones posibles: ConstraintException. Esta excepcin se produce si se viola la excepcin de clave nica de un conjunto de datos. En la prctica esto puede suceder si dos usuarios aaden un contacto en el mismo instante y ambos obtienen el mismo ContactID. Cuando el segundo usuario intenta actualizar la base de datos se produce una ConstraintException porque el primero ya ha aadido un contacto con este Contactad. Para resolver esta situacin, obtenga otro ContactID e intente actualizar de nuevo, como se muestra a continuacin. Visual Basic .NET
' Se produce si el ContactID no es nico. Catch ex As ConstraintException rowNew.ContactID = GetNewContactID() ' Obtiene otro ID. Try ' Intenta de nuevo. adptContacts.Update(dsContacts) ' Indica xito. litStatus.Text = rowNew.FirstName & " " & rowNew.LastName & _ " aadido con xito.<br>" Catch litStatus.Text = "No se pudo aadir el registro. Pulse Aadir para " & _ " intentar de nuevo o Cancelar para terminar." End Try

Visual C#
// Se produce si el ContactID no es nico. catch (ConstraintException ex){ rowNew.ContactID = GetNewContactID(); // Obtiene otro ID. try{ // Intenta de nuevo. adptContacts.Update(dsContacts); // Indica xito. litStatus.Text = rowNew.FirstName + " " + rowNew.LastName + " aadido con xito.<br>"; }catch litStatus.Text = " No se pudo aadir el registro. Pulse Aadir para " + " intentar de nuevo o Cancelar para terminar."; }

DBConcurrencyException. Esta excepcin se puede producir si un usuario intenta actualizar la base de datos mientras otro usuario tiene acceso exclusivo. En este caso es mejor notificar al primer usuario que la actualizacin no se ha realizado y permitir que vuelva a enviar los cambios, como muestra el cdigo: Visual Basic .NET
' La base de datos puede estar bloqueada por otra sesin. Permite reintentar. Catch ex As DBConcurrencyException litStatus.Text = "La base de datos est bloqueada. " & _ "Espere unos segundos y pulse de nuevo Aadir."

Visual C#
// La base de datos puede estar bloqueada por otra sesin. Permite reintentar. catch (DBConcurrencyException ex) litStatus.Text = " La base de datos est bloqueada. " +_ "Espere unos segundos y pulse de nuevo Aadir.";

DataException. Es la excepcin general para asuntos relacionados con datos. Controle esta excepcin como forma de interceptar problemas en los que puede que no haya pensado. El siguiente cdigo muestra un mensaje al usuario y registra la excepcin para verla en el registro como herramienta de diagnstico. Visual Basic .NET
' Excepcin de datos genrica, informa. Catch ex As DataException litStatus.Text = "Se ha producido un error de base de datos:<br>" & _ ex.Message & "<br>" & "Corrija el error y pulse Aadir para " & _ "aadir el contacto o pulse Cancel para terminar.<br>" Trace.Warn("Error", "Excepcin de datos", ex) End Try

130

Developing Web Applications

Visual C#
// Excepcin de datos genrica, informa. catch(DataException ex){ litStatus.Text = " Se ha producido un error de base de datos:<br>" + ex.Message + "<br>" + " Corrija el error y pulse Aadir para " + "aadir el contacto o pulse Cancel para terminar.<br>"; Trace.Warn("Error", "Excepcin de datos", ex); }

Estos cambios en butAdd_Click dejan sin controlar las excepciones que no estn relacionadas con datos. Para cubrir los objetivos de esta prctica controlaremos estas posibles excepciones en sucesos de error.

6.5.2 Aadir un suceso de error


Tras controlar las posibles excepciones de datos en el procedimiento de suceso butAdd_Click del formulario Web AddContacts debe proporcionar una forma de controlar y registrar excepciones no anticipadas mediante el procedimiento de suceso Error. Esto sirve a dos cometidos: Impide que el usuario vea mensajes de error tcnicos y los reemplaza por informacin ms til. Mantiene informacin sobre excepciones no anticipadas en un registro que se puede usar como herramienta de diagnstico que le ayude a determinar si necesita controlar otras excepciones. 1. Aada al formulario Web un procedimiento de suceso Page_Error que trate con todas las dems excepciones en la pgina. El siguiente cdigo graba informacin sobre la excepcin en el registro de seguimiento, crea un mensaje de error para presentar y limpia el error de modo que la aplicacin pueda continuar: Visual Basic .NET
Private Sub Page_Error(ByVal sender As Object, ByVal e As _ System.EventArgs) Handles MyBase.Error ' Escribe el error en el registro. Trace.Warn("Error", "Suceso de Error", Server.GetLastError()) ' Guarda un mensaje para mostrar como variable de sesin. Session("Error") = "<p>Se ha producido un error inesperado. " & _ "Intente de nuevo.</p>" ' Limpia el error. Server.ClearError() ' Vuelve a mostrar la pgina. Response.Redirect("AddContact.aspx") End Sub

Visual C#
private void Page_Error(object sender, System.EventArgs e){ // Escribe el error en el registro. Trace.Warn("Error", "Suceso de Error", Server.GetLastError()); // Guarda un mensaje para mostrar como variable de sesin. Session["Error"] = "<p> Se ha producido un error inesperado. " + "Intente de nuevo.</p>"; // Limpia el error Server.ClearError(); // Vuelve a mostrar la pgina. Response.Redirect("AddContact.aspx"); }

2. Modifique el procedimiento de suceso Page_Load para mostrar el mensaje de error que se ha grabado como variable de sesin. Para ello aada a este suceso las lneas siguientes, al final del mismo, a continuacin de la sentencia drpStates.DataBind() Visual Basic .NET
' Si ha habido un error sin controlar lo muestra. If Session("Error") <> "" Then litStatus.Text = Session("Error") Session("Error") = Nothing ' Reinicia el mensaje de error. End If End Sub

Visual C#
// Si ha habido un error sin controlar lo muestra. if(Session["Error"] != null){ litStatus.Text = Session["Error"].ToString(); Session["Error"] = null; // Reinicia el mensaje de error. } }

131

MCAD/MCSD

6.5.3 Crear y ver el registro de seguimiento


Los ejercicios 1 y 2 escribieron en el registro de seguimiento mensajes que le ayudan a capturar errores no anticipados cuando la gente empieza a usar su aplicacin. Para hacer estos mensajes visibles active el seguimiento y aada a su aplicacin un enlace para mostrar el registro de seguimiento. 1. Modifique el archivo Web.config para activar el seguimiento. El siguiente elemento <trace> activa el seguimiento, graba la salida como Trace.axd, aumenta el nmero de peticiones registradas a 20 y permite que el registro se vea de forma remota.
<trace enable="true" requestLimit="20" pageOutoput="false" traceMode="SortByTime" localOnly="false" />

2. Aada al formulario Web SwitchBoard un enlace para mostrar condicionalmente el registro de seguimiento. El siguiente HTML crea el enlace como un control de servidor Hyperlink de modo que puede mostrarlo u ocultarlo en tiempo de ejecucin, dependiendo del valor del elemento <trace>.
<asp:Hyperlink NavigateUrl="Trace.axd" ID="hypTrace" runat="server" text="Ver registro de seguimiento" Visible="false"></asp:Hyperlink>

3. Aada el siguiente cdigo al procedimiento de suceso Page_Load del formulario Web SwitchBoard para mostrar el enlace del registro de seguimiento. Visual Basic .NET
Private Sub Page_Load(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles MyBase.Load ' Muestra el enlace de seguimiento si ste est activado. If Trace.IsEnabled Then hypTrace.Visible = True End If End Sub

Visual C#
private void Page_Load(object sender, System.EventArgs e){ // Muestra el enlace de seguimiento si ste est activado. if (Trace.IsEnabled) hypTrace.Visible = true; }

6.5.4 Ampliar el control de excepciones a otros formularios Web


Hasta ahora esta prctica le ha mostrado cmo aadir control de excepciones paso a paso. Ahora es el momento de que lo haga por si mismo. Ample el control de excepciones a los formularios Calls, DeleteContact y ContactTypes. Estos formularios Web deben: Controlar las posibles excepciones de datos usando bloques de control de excepciones como se mostr en el ejercicio 6.5.1. Aadir sucesos Error para capturar y registrar excepciones no anticipadas como se mostr en el ejercicio 6.5.2. Cuando termine compare sus resultados con la aplicacin Contact Management incluida en el CD.

6.6 Repaso
Las siguientes preguntas estn pensadas para reforzar informacin clave mostrada en este captulo. Si no es capaz de contestar a una pregunta repase la leccin correspondiente e intente de nuevo. Las respuestas se pueden encontrar en el captulo 16. 1. Explique por qu es importante el control de excepciones en una aplicacin terminada. 2. Indique dos aproximaciones al control de excepciones en aplicaciones Web ASP.NET 3. Describa el cometido de la pginas de error y por qu son necesarias. 4. Explique por qu el seguimiento ayuda con el control de excepciones.

132

Developing Web Applications

7 Programacin avanzada de formularios Web


En este captulo aprender cmo realizar algunas tareas de programacin avanzada que no encajan con claridad en ninguna otra categora. Aunque puede crear aplicaciones Web sin conocer los temas que trata este captulo, las lecciones que contiene son una parte importante de la corriente principal de la programacin Web y le ayudarn a completar su conjunto de habilidades. Para completar las lecciones de este captulo necesitar: Soltura en la creacin de aplicaciones Web usando controles y cdigo de servidor. Tener alguna experiencia con un lenguaje de secuencias de comandos, como VBScript o JScript. Si nunca ha usado un lenguaje de secuencias de comandos consulte los temas relativos a VBScript p JScript en la ayuda en lnea de Visual Studio antes de comenzar con la leccin 4 de este captulo.

7.1 Guardar y recuperar informacin del usuario


Las aplicaciones Web que necesitan que los usuarios registren informacin pueden recuperar esta informacin cada vez que un usuario concreto vuelve a visitar el sitio web. Por ejemplo, un sitio web de compras puede registrar la informacin de envos y facturacin del cliente y recuperarla para utilizar los datos de direccin cada vez que el cliente hace un nuevo pedido.

7.1.1

Identificar usuarios de la aplicacin Web

Las aplicaciones Web pueden identificar a los usuarios exigiendo que introduzcan un nombre e usuario y una contrasea cada vez que visitan el sitio Web. Tambin pueden identificarlos mediante informacin almacenada en sus ordenadores en forma de cookies. Las Cookies son pequeos archivos que una aplicacin web puede escribir en el ordenador cliente. La ventaja de usar cookies es que la interaccin es invisible al usuario. Los usuarios no tienen que registrarse cada vez que visitan el sitio Web; su informacin aparece automticamente cuando es necesaria. La desventaja es que los usuarios pueden configurar sus ordenadores para que no acepten cookies. A algunos usuarios no les gusta la idea de que los sitios Web almacenen informacin en sus ordenadores y posiblemente usen esta informacin para seguir sus movimientos en Internet. Por tanto, antes de intentar usar cookies hay que comprobar si el usuario las acepta. Puede utilizar dos aproximaciones cuando almacene y recupere informacin mediante cookies: Almacene toda la informacin del usuario en una cookie en la mquina cliente. Esta aproximacin es til cuando la informacin del usuario es sencilla y no es necesaria en el servidor para otras tareas. Almacene una clave identificativa en la mquina cliente y recupere la informacin del usuario de un origen de datos en el servidor usando esta clave. Es la mejor aproximacin para almacenar informacin ms amplia. Las siguientes secciones describe cmo grabar y recuperar informacin del usuario usando estas aproximaciones.

7.1.2
1. 2. 3. 4. 5.

Almacenar nformacin de suario en el cliente

Para almacenar una cookie en la mquina cliente: Compruebe si el cliente soporta cookies usando la propiedad Cookies del objeto Browser. Si el cliente soporta cookies, compruebe si ya existe usando la coleccin Cookies del objeto Request. Si la cookie no existe an cree un nuevo objeto cookie usando la clase HttpCookie. Configure las propiedades Value y Expiration del objeto cookie. Aada el objeto cookie a la coleccin Cookies del objeto Response.

El siguiente procedimiento de suceso Page_Load muestra los pasos anteriores creando una cookie que hace un seguimiento de la ltima visita del usuario a una pgina Web. El cdigo comprueba si el usuario acepta cookies y aade una si es la primera vez que el usuario visita la pgina o la actualiza si ya la ha visitado antes. Visual Basic .NET
Private Sub Page_Load(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles MyBase.Load ' (1) Comprueba si el navegador acepta cookies. If Request.Browser.Cookies Then ' (2) Si la cookie no existe... If Request.Cookies("LastVisit") Is Nothing Then ' (3) Crea la cookie. Dim cookLastVisit As New HttpCookie("LastVisit", Now.ToString())

133

MCAD/MCSD

' (4) Configura la expiracin a maana. cookLastVisit.Expires = DateTime.Now.AddDays(1) ' (5) Aade a la coleccin de cookies. Response.Cookies.Add(cookLastVisit) ' Muestra un mensaje. Response.Write("Esta es su primera visita.") Else ' Obtiene la cookie. Dim cookLastVisit As HttpCookie = Request.Cookies("LastVisit") ' Muestra un mensaje con la hora de la ltima visita. Response.Write("Su ltima visita a la pgina fue en: " & _ cookLastVisit.Value) ' Actualiza la cookie en el cliente. Response.Cookies("LastVisit").Value = Now.ToString() Response.Cookies("LastVisit").Expires = DateTime.Now.AddDays(1) End If Else Response.Write("Su navegador no acepta cookies.") End If End Sub

Visual C#
private void Page_Load(object sender, System.EventArgs e){ // (1) Comprueba si el navegador acepta cookies. if (Request.Browser.Cookies){ // (2) Si la cookie no existe... if (Request.Cookies["LastVisit"] == null){ // (3) Crea la cookie. HttpCookie cookLastVisit = new HttpCookie("LastVisit", DateTime.Now.ToString()); // (4) Configura la expiracin a maana. cookLastVisit.Expires = DateTime.Now.AddDays(1); // (5) Aade a la coleccin de cookies. Response.Cookies.Add(cookLastVisit); // Muestra un mensaje. Response.Write("Esta es su primera visita."); }else { // Obtiene la cookie. HttpCookie cookLastVisit = Request.Cookies["LastVisit1"]; // Muestra un mensaje con la hora de la ltima visita. Response.Write("Su ltima visita a la pgina fue en: " + cookLastVisit.Value); // Actualiza la cookie en el cliente. Response.Cookies["LastVisit"].Value = DateTime.Now.ToString(); Response.Cookies["LastVisit"].Expires = DateTime.Now.AddDays(1); } } else Response.Write("Su navegador no acepta cookies."); }

Sobre las cookies Las cookies diferencian maysculas y minsculas. Por ejemplo, LastVisit no es la misma cookie que ultimaVisita. La propiedad Expires determina cundo puede la mquina cliente descartar la cookie. De forma predeterminada, las cookies expiran cuando termina la sesin de un usuario. Si se da a Expires el valor DateTime.MaxValue la cookie nunca expira. Puede eliminar una cookie de la mquina cliente dando a Expires el valor de la hora actual. Por ejemplo, el siguiente cdigo elimina la cookie LastVisit de la mquina cliente. Visual Basic .NET
Private Sub butRemoveCookie_Click(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles butRemoveCookie.Click ' Configura la cookie para expiracin inmediata. Response.Cookies("LastVisit").Expires = DateTime.Now End Sub

Visual C#
private void butRemoveCookie_Click(object sender, System.EventArgs e){ // Configura la cookie para expiracin inmediata. Response.Cookies["LastVisit"].Expires = DateTime.Now; }

134

Developing Web Applications

Uso de claves dentro de cookies Puede grabar hasta 4096 bytes de informacin en una nica cookie, y puede identificar informacin dentro de una cookie usando claves. Por ejemplo, el siguiente cdigo guarda informacin de nombre y direccin del usuario como cookie con claves individuales. Visual Basic .NET
Private Sub butOK_Click(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles butOK.Click ' Crea una cookie. Dim cookUserInfo As New HttpCookie("UserInfo") ' Rellena las claves con los datos del formulario. cookUserInfo("FirstName") = txtFirstName.Text cookUserInfo("LastName") = txtLastName.Text cookUserInfo("Street") = txtStreet.Text cookUserInfo("City") = txtCity.Text cookUserInfo("State") = drpState.SelectedItem.Value cookUserInfo("ZIP") = txtZIP.Text ' Configura la caducidad. cookUserInfo.Expires = DateTime.Now.AddDays(30) ' Aade la cookie. Response.Cookies.Add(cookUserInfo) End Sub

Visual C#
private void butOK_Click(object sender, System.EventArgs e){ // Crea una cookie. HttpCookie cookUserInfo = new HttpCookie("UserInfo"); // Rellena las claves con los datos del formulario. cookUserInfo["FirstName"] = txtFirstName.Text; cookUserInfo["LastName"] = txtLastName.Text; cookUserInfo["Street"] = txtStreet.Text; cookUserInfo["City"] = txtCity.Text; cookUserInfo["State"] = drpState.SelectedItem.Value; cookUserInfo["ZIP"] = txtZIP.Text; // Configura la caducidad. cookUserInfo.Expires = DateTime.Now.AddDays(30); // Aade la cookie. Response.Cookies.Add(cookUserInfo); }

Para obtener los valores de las claves almacenadas en una cookie sencillamente use el nombre de la clave, como muestra el cdigo siguiente: Visual Basic .NET
Private Sub butGetData_Click(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles butGetData.Click ' Obtiene la cookie. Dim cookUserInfo As HttpCookie = Request.Cookies("UserInfo") ' Rellena los campos. txtFirstName.Text = cookUserInfo("FirstName") txtLastName.Text = cookUserInfo("LastName") txtStreet.Text = cookUserInfo("Street") txtCity.Text = cookUserInfo("City") drpState.SelectedItem.Value = cookUserInfo("State") txtZIP.Text = cookUserInfo("ZIP") End Sub

Visual C#
private void butGetData_Click(object sender, System.EventArgs e){ // Obtiene la cookie. HttpCookie cookUserInfo = Request.Cookies["UserInfo"]; // Rellena los campos. txtFirstName.Text = cookUserInfo["FirstName"]; txtLastName.Text = cookUserInfo["LastName"]; txtStreet.Text = cookUserInfo["Street"]; txtCity.Text = cookUserInfo["City"]; drpState.SelectedItem.Value = cookUserInfo["State"]; txtZIP.Text = cookUserInfo["ZIP"]; }

135

MCAD/MCSD

7.1.3

Almacenar informacin de usuario en el servidor

Para almacenar informacin del usuario en el servidor en lugar de la mquina cliente utilice cookies como dispositivo de identificacin para almacenar y recuperar informacin del usuario en el servidor. Puede almacenar informacin del usuario en el servidor usando una base de datos, un archivo XML o cualquier otro tipo de almacn de datos. Para almacenar informacin del usuario en el servidor siga estos pasos 1. 2. 3. 4. Cree una clave nica para identificar al usuario. Grabe la clave nica en el ordenador del usuario como cookie Cree un archivo en el servidor para almacenar la informacin del usuario Grabe la informacin del usuario en el servidor usando la clave nica como ndice.

7.1.4

Crear claves nicas para identificar usuarios

El marco de trabajo Microsoft .NET proporciona un espacio de nombres System.GUID para crear identificadores nicos globales (Globally Unique Identifier, GUID). Un GUID es un entero de 128 bits que sirve como identificador nico entre redes. Puede usar los GUID como claves nicas para identificar todo tipo de cosas, incluyendo usuarios. El siguiente cdigo crea un GUID y lo almacena como cookie en la mquina cliente. Visual Basic .NET
Private Sub butOK_Click(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles butOK.Click ' Obtiene la cookie de la peticin. Dim cookUserID As HttpCookie = Request.Cookies("UserID") ' Si no existe, la crea. If cookUserID Is Nothing Then ' Crea una nueva cookie con un nuevo GUID. cookUserID = New HttpCookie("UserID", System.Guid.NewGuid().ToString()) cookUserID.Name = "UserID" End If ' Configura la caducidad. cookUserID.Expires = DateTime.Now.AddDays(30) ' Aade la cookie a la respuesta. Response.Cookies.Add(cookUserID) ' Graba la informacin del usuario de los datos del formulario. SetUserInfo(cookUserID.Value) End Sub

Visual C#
private void butOK_Click(object sender, System.EventArgs e){ // Obtiene la cookie de la peticin. HttpCookie cookUserID = Request.Cookies["UserID"]; // Si no existe, la crea. if (cookUserID == null) // Crea una nueva cookie con un nuevo GUID. cookUserID = new HttpCookie("UserID", System.Guid.NewGuid().ToString()); // Configura la caducidad. cookUserID.Expires = DateTime.Now.AddDays(30); // Aade la cookie a la respuesta. Response.Cookies.Add(cookUserID); // Graba la informacin del usuario de los datos del formulario. SetUserInfo(cookUserID.Value); }

7.1.5

Crear un archivo para guardar informacin del usuario

La utilidad de guardar informacin de usuario es ser capaz de recuperar esta informacin rpidamente la siguiente vez que el usuario visite la aplicacin Web. Como estos usuarios ya estn identificados por una clave nica (el GUID creado en la seccin anterior) tiene sentido intentar acceder a sus datos mediante un conjunto de datos. Los conjuntos de datos incluyen un mtodo Find para recuperar filas de datos mediante su clave nica. Usar un conjunto de datos significa que el archivo creado en el servidor debe ser una base de datos o un archivo XML. XML proporciona una forma de guardar datos estructurados en un archivo sin la complejidad o sobrecarga de una base de datos, de modo que para algo tan sencillo como informacin de nombre y direccin de un usuario resulta ms rentable. Para crear un archivo XML para almacenar informacin de usuario siga estos pasos:

136

Developing Web Applications

1. Cree en Visual Studio un archivo XML que contenga datos de prueba para cada uno de los campos que quiera registrar sobre el usuario. 2. Genere un esquema XML para el archivo. El esquema XML permite que el conjunto de datos haga referencia a los datos contenidos en el archivo por su nombre. 3. Especifique un campo clave dentro del esquema XML. Esto permite encontrar los registros usando este campo con el mtodo Find del conjunto de datos. 4. Lea el esquema y el archivo XML en un conjunto de datos.

7.1.6

Crear un archivo XML

Para crear un archivo XML en Visual Studio seleccione Agregar Nuevo Elemento en el men Proyecto y seleccione Archivo XML en la lista Plantillas. Los archivos XML son muy parecidos a archivos HTML; sin embargo, los elementos y atributos XML diferencian maysculas y minsculas y usan una sintaxis estricta. Para identificar elementos de datos en un archivo XML se usan las etiquetas <elemento> y </elemento>. El siguiente ejemplo muestra un archivo XML para almacenar informacin del nombre y direccin del usuario.
<?xml version="1.0" standalone="yes"?> <USERS xmlns="http://tempuri.org/UserPrefs.xsd"> <USER> <FIRSTNAME>Joan</FIRSTNAME> <LASTNAME>Reddington</LASTNAME> <STREET>436 Atlantic Ave.</STREET> <CITY>Melbourne Beach</CITY> <STATE>FL</STATE> <ZIP>32401</ZIP> <ID>79844302-6d86-4520-ac64-c8c3240e21a9</ID> </USER> </USERS>

7.1.7

Crear un esquema XML

Para usar un archivo XML con un conjunto de datos debe crear primero un esquema XML para el conjunto de datos. Un esquema XML es una descripcin de los elementos de datos que contiene el archivo XML. Proporciona los nombres de los elementos, sus tipos, si hay campo clave y otra informacin. Para crear un esquema XML a partir de un archivo XML seleccione Crear esquema en el men XML mientras se est mostrando el archivo XML en la ventana de diseo. Visual Studio crea un archivo de esquema que describe el archivo XML.

7.1.8

Especificar un campo clave

A un archivo XML se le aade una clave principal para permitir bsquedas. Siga estos pasos: 1. Pulse con el botn derecho sobre el elemento que ser la clave, seleccione Agregar y Nueva clave. Visual Studio muestra el dilogo Editar clave. 2. Seleccione la marca Clave principal del conjunto de datos y pulse Aceptar. Esto permite usar el mtodo Find del objeto DataSet para recuperar filas del conjunto de datos usando el valor de este elemento.

7.1.9

Leer XML en un conjunto de datos

Cuando se ha creado esquema y un archivo XML puede leer estos archivos en un conjunto de datos usando los mtodos ReadXmlSchema y ReadXml. El siguiente cdigo muestra una funcin auxiliar que devuelve un conjunto de datos creado a partir del archivo UserInfo. Visual Basic .NET
Function GetUserData() As DataSet ' Configura la ruta del archivo y esquema XML. Dim strPath As String = Server.MapPath(Request.ApplicationPath) ' Declara un conjunto de datos. Dim dsUsers As New DataSet() ' Aplica el esquema XML al conjunto de datos. dsUsers.ReadXmlSchema(strPath & "\UserInfo.xsd") ' Lee el XML en el conjunto de datos. dsUsers.ReadXml(strPath & "\UserInfo.xml") Return dsUsers End Function

137

MCAD/MCSD

Visual C#
private DataSet GetUserData(){ // Configura la ruta del archivo y esquema XML. string strPath = Server.MapPath(Request.ApplicationPath); // Declara un conjunto de datos. DataSet dsUsers = new DataSet(); // Aplica el esquema XML al conjunto de datos. dsUsers.ReadXmlSchema(strPath + "\\UserInfo.xsd"); // Lee el XML en el conjunto de datos. dsUsers.ReadXml(strPath + "\\UserInfo.xml"); return dsUsers; }

7.1.10 Guardar informacin del usuario en el servidor


Para guardar informacin del usuario en el servidor dentro de un archivo XML use el mtodo SaveXML del objeto conjunto de datos. El siguiente procedimiento SetUserInfo usa el procedimiento GetUserData de la seccin anterior para obtener un conjunto de datos de un archivo XML y despus usa el mtodo Find para averiguar si el ID de usuario existe en el conjunto de datos. Si no lo encuentra, aade una fila para el usuario antes de configurar los valores de los campos de esta fila a partir de los controles de servidor de un formulario Web. Finalmente, escribe todo el conjunto de datos de vuelta al servidor. Visual Basic .NET
Sub SetUserInfo(ByVal UserID As String) ' Configura la ruta del archivo y del esquema XML. Dim strPath As String = Server.MapPath(Request.ApplicationPath()) ' Obtiene el conjunto de datos de usuarios. Dim dsUsers As DataSet = GetUserData() ' Localiza la fila en el conjunto de datos. Dim rowUser As DataRow = dsUsers.Tables("User").Rows.Find(UserID) ' Si no encuentra la fila crea una nueva. If rowUser Is Nothing Then rowUser = dsUsers.Tables("User").NewRow dsUsers.Tables("User").Rows.Add(rowUser) End If ' Graba datos de los campos. rowUser("FirstName") = txtFirstName.Text rowUser("LastName") = txtLastName.Text rowUser("Street") = txtStreet.Text rowUser("City") = txtCity.Text rowUser("State") = drpState.SelectedItem.Text rowUser("ZIP") = txtZIP.Text rowUser("ID") = UserID ' Escribe el XML desde el conjunto de datos. dsUsers.WriteXml(strPath & "\UserInfo.xml") End Sub

Visual C#
private void SetUserInfo(string UserID){ // Configura la ruta del archivo y del esquema XML. string strPath = Server.MapPath(Request.ApplicationPath); // Obtiene el conjunto de datos de usuarios. DataSet dsUsers = GetUserData(); // Localiza la fila en el conjunto de datos. DataRow rowUser = dsUsers.Tables["User"].Rows.Find(UserID); // Si no encuentra la fila crea una nueva. if (rowUser == null){ rowUser = dsUsers.Tables["User"].NewRow(); dsUsers.Tables["User"].Rows.Add(rowUser); } // Graba datos de los campos. rowUser["FirstName"] = txtFirstName.Text; rowUser["LastName"] = txtLastName.Text; rowUser["Street"] = txtStreet.Text; rowUser["City"] = txtCity.Text; rowUser["State"] = drpState.SelectedItem.Text; rowUser["ZIP"] = txtZIP.Text; rowUser["ID"] = UserID; // Escribe el XML desde el conjunto de datos. dsUsers.WriteXml(strPath + "\\UserInfo.xml"); }

138

Developing Web Applications

7.1.11 Recuperar informacin de usuario del DataSet


Para recuperar informacin de usuario del archivo XML use el procedimiento GetUserData para crear un conjunto de datos a partir del archivo XML, y use el mtodo Find para recuperar la fila que corresponde al ID del usuario. El siguiente procedimiento GetUserInfo recupera informacin del conjunto de datos y la usa para rellenar los controles de servidor en un formulario Web. Visual Basic .NET
Sub GetUserInfo(ByVal UserID As String) ' Obtiene el conjunto de datos de usuarios. Dim dsUsers As Data.DataSet = GetUserData() ' Localiza la fila en el conjunto de datos. Dim rowUser As Data.DataRow = dsUsers.Tables("User").Rows.Find(UserID) ' Si no encuentra el usuario, sale. If rowUser Is Nothing Then Exit Sub ' Aade datos a los campos del formulario. txtFirstName.Text = rowUser.Item("FirstName") txtLastName.Text = rowUser.Item("LastName") txtStreet.Text = rowUser.Item("Street") txtCity.Text = rowUser.Item("City") drpState.SelectedItem.Text = rowUser.Item("State") txtZIP.Text = rowUser.Item("ZIP") End Sub

Visual C#
void GetUserInfo(string UserID){ // Obtiene el conjunto de datos de usuarios. DataSet dsUsers = GetUserData(); // Localiza la fila en el conjunto de datos. DataRow rowUser = dsUsers.Tables["User"].Rows.Find(UserID); // Si no encuentra el usuario, sale. if (rowUser == null) return; // Aade datos a los campos del formulario. txtFirstName.Text = rowUser["FirstName"].ToString(); txtLastName.Text = rowUser["LastName"].ToString(); txtStreet.Text = rowUser["Street"].ToString(); txtCity.Text = rowUser["City"].ToString(); drpState.SelectedItem.Text = rowUser["State"].ToString(); txtZIP.Text = rowUser["ZIP"].ToString(); }

7.2 Enviar correo


Puede enviar correo desde una aplicacin Web de dos formas distintas, dependiendo de desde donde quiere enviarlo. Usar el protocolo mailto: para enviar correo desde el cliente. Esta tcnica usa el sistema de correo del cliente y es til para obtener realimentacin para un sitio Web, proporcionar soporte tcnico u otras tareas que precisan una respuesta al correo del usuario. Usar las clases MailMessage y SmtpMail para enviar corro desde el servidor. Esta tcnica usa el sistema de correo del servidor, que es til para informe de errores automatizado, crear correo annimo u otras tareas que no necesariamente precisan una direccin de correo para respuesta del cliente.

7.2.1 Enviar correo desde un cliente


Para enviar correo usando el sistema de correo del cliente cree un enlace usando el protocolo mailto. Por ejemplo, el siguiente HTML muestra un enlace que crea un nuevo mensaje con una lnea de asunto y un cuerpo de mensaje:
<A href="mailto:alguien@microsoft.com?SUBJECT=Envo desde un cliente&BODY=Cuerpo de texto del mensaje.">Enviar correo</A>

Cuando el usuario pulsa sobre el enlace el navegador abre la aplicacin de correo y crea un mensaje. Puede usar el protocolo mailto en lugar de cualquier URL de destino en un control de servidor o HTML. Por ejemplo, el siguiente HTML define un control de servidor Hyperlink que enva un mensaje de correo.
<asp:HyperLink ID="hypMail" NavigateUrl="mailto:alguient@microsoft.com?SUBJECT= Correo desde un Formulario Web;BODY=Cuerpo del mensaje." Runat="server"> Enviar correo.</asp:HyperLink>

Tambin puede usar el protocolo mailto como parte de un mtodo Redirect en cdigo, pero tiene el efecto secundario de mostrar una pgina en blanco en el navegador a la vez que crea el mensaje de correo. 139

MCAD/MCSD

Las partes del mensaje de correo se especifican usando la claves que soporta el protocolo mailto. Estas claves se incluyen dentro de una cadena de consulta, separadas por ampersands (&), y son las que se describen en la tabla 7.1
Tabla 7. 1: Claves soportadas por el protocolo mailto
Clave SUBJECT CC BCC BODY Especifica Texto que aparece en la lnea de asunto del mensaje Lista de direcciones a las que copiar el mensaje. Si hay varias direcciones se separan con punto y coma (;) Lista de direcciones a las que enviar copia ciega del mensaje. Si hay varias direcciones se separan con punto y coma (;) Texto del mensaje

El protocolo mailto no proporciona una clave para anexar archivos; sin embargo, el usuario puede anexarlos manualmente cuando se abra la ventana de mensaje. Si quiere que el usuario anexe un archivo (como un registro de error o algn otro informe), coloque las instrucciones correspondientes en el cuerpo del mensaje.

7.2.2 Enviar correo desde el servidor


Cuando se enva correo desde el servidor ASP.NET no arranca el sistema de correo del cliente para permitir que el usuario componga el mensaje a enviar, aadir anexos o validar direcciones. El mensaje se compone mediante cdigo y se enva de una de dos formas. Puede enviar un mensaje sencillo usando el mtodo Send de la clase SmtpMail. Puede crear un mensaje ms complejo usando la clase MailMessage y enviar el mensaje usando el mtodo Send de SmtpMail. Ambas clases, SmtpMail y MailMessage, son parte del espacio de nombres System.Web.Mail del marco de trabajo .NET, de modo que tendr que aadir una referencia al mismo (Imports o using) al mismo al inicio de su mdulo para facilitar el acceso. No es necesario crear una instancia de la clase SmtpMail antes de usarla. Para enviar un mensaje sencillo basta con usar el mtodo Send: Visual Basic .NET
SmtpMail.Send ("alguien@microsoft.com", "jesse@contoso.com", "Lnea de Asunto", "Texto del mensaje.")

Visual C#
SmtpMail.Send ("alguien@microsoft.com", "jesse@contoso.com", "Lnea de Asunto", "Texto del mensaje.");

La lnea de cdigo precedente enva inmediatamente un mensaje desde alguien@microsoft.com a jesse@contoso.com. Estos dos valores, de y a son necesarios, aunque el mtodo Send no los valida. La clase SmtpMail enva correo usando el servidor SMTP local de forma predeterminada. Para usar un servidor diferente configure la propiedad SmtpServer. El mtodo Send por si solo es adecuado para mensajes de texto sencillos, pero para enviar un mensaje con formato o con anexos necesita crear un objeto basado en la clase MailMessage y usar el mtodo Send de SmtpMail para enviarlo, como en el cdigo siguiente. Visual Basic .NET
Private Sub butMail_Click(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles butMail.Click Dim mailNew As New MailMessage() ' Crea el mensaje. mailNew.From = "someone@microsoft.com" ' Configura las propiedades. mailNew.To = "jesse@contoso.com" mailNew.Subject = "Este es el texto del asunto." mailNew.Body = "Este es el texto del mensaje." Dim atcItem As New _ ' Crea un anexo. MailAttachment(Server.MapPath(Request.ApplicationPath) & "\joey.jpg") mailNew.Attachments.Add(atcItem) ' Lo anexa al mensaje. SmtpMail.Send(mailNew) ' Enva el mensaje. End Sub

140

Developing Web Applications

Visual C#
private void butSendMail_Click(object sender, System.EventArgs e){ MailMessage mailNew = new MailMessage(); // Crea el mensaje. mailNew.From = "someone@microsoft.com"; // Configura las propiedades. mailNew.To = "jesse@contoso.com"; mailNew.Subject = " Este es el texto del asunto."; mailNew.Body = " jesse@contoso.com."; MailAttachment atcItem = new MailAttachment // Crea un anexo. (Server.MapPath(Request.ApplicationPath) + "\\joey.jpg"); mailNew.Attachments.Add(atcItem); // Lo anexa al mensaje. SmtpMail.Send(mailNew); // Enva el mensaje. }

El cdigo anterior crea un mensaje, configura sus propiedades, le anexa un archivo y lo enva. Como en el ejemplo anterior con Send, las propiedades From y To son obligatorias, pero no se validan.

7.3 Uso de marcos


Los marcos son partes de una pgina Web que puede usar ara mostrar otras pginas Web. Se usan marcos para mostrar varias regiones que se desplazan y comportan de forma independiente entre si. En esta leccin aprender cmo crear marcos con Visual Studio y cmo controlar los marcos.

7.3.1 Crear marcos en Visual Studio


Para crear marcos en Visual Studio siga estos pasos: 1. Cree un conjunto de marcos 2. Cree las pginas que mostrar en los marcos 3. Configure la pgina web para que muestre los marcos en el conjunto de marcos

7.3.2 Crear un conjunto de marcos


Para crear un conjunto de marcos en Visual Studio siga estos pasos: 1. En el men Proyecto, seleccione Agregar nuevo elemento, Visual Studio muestra el dilogo Agregar nuevo elemento. 2. En la lista de plantillas seleccione Conjunto de marcos, escriba el nombre de la pgina Web en el cuadro Nombre y pulse Abrir. Visual Studio muestra el dilogo Seleccione una plantilla de conjunto de marcos. 3. Seleccione el tipo de marcos que quiere crear y pulse Aceptar. Visual Studio crea la pgina Web como archivo htm y la abre en el diseador.

7.3.3 Crear pginas y aadirlas al conjunto de marcos


Despus de crear el conjunto de marcos puede mostrar pginas HTML o formularios Web en cada uno de los marcos del conjunto. Aunque los conjuntos de trabajo son archivos HTML las pginas que se muestren dentro de ellos pueden ser tanto HTML como formularios Web. Despus de crear las pginas que va a mostrar en los marcos asocie cada marco con una pgina: 1. Pulse con el botn derecho sobre el marco que quiere asociar con una pgina y seleccione Establecer pgina para marco. Visual Studio muestra el dilogo Pgina de seleccin. 2. Seleccione en la lista Contenido la pgina que quiere mostrar y pulse Aceptar. Visual Studio aade la pgina seleccionada al marco. 3. Repita los pasos 1 y 2 para cada uno de los marcos. Cuando termine, el conjunto de marcos mostrar cada una de las pginas en el marco correspondiente. Visual Studio no puede mostrar correctamente el formulario Web en el conjunto de marcos en modo de diseo los marcos aparecern con mensajes de error o con controles extraos. Sin embargo, en tiempo de ejecucin se mostrar correctamente. Puede ver el marco de trabajo en tiempo de ejecucin de dos formas: Establecer el conjunto de marcos como pgina de inicio de la aplicacin Web e iniciar la aplicacin. Navegar al conjunto de marcos en tiempo de ejecucin desde un enlace o usando el mtodo Redirect en el cdigo.

7.3.4 Comprobar el soporte del navegador para marcos


Antes de empezar a hacer un uso intensivo de marcos en su aplicacin debe saber que las primeras versiones de algunos navegadores no los soportaban. Si un cliente que utiliza uno de estos navegadores solicita una pgina que contiene marcos el navegador mostrar una pgina en blanco o se bloquear.

141

MCAD/MCSD

Para detectar si un navegador soporta marcos antes de mostrar un conjunto de marcos use la propiedad Frames del objeto Browser. Por ejemplo, el siguiente cdigo muestra o un conjunto de marcos o una pgina HTML sencilla, dependiendo del soporte para marcos del navegador. Visual Basic .NET
Private Sub butDisplayPage_Click(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles butDisplayPage.Click ' Si el navegador cliente soporta marcos muestra el conjunto de marcos. If Request.Browser.Frames Then Server.Transfer("frames.htm") ' Si no, muestra una versin diferente. Else Server.Transfer("noframes.htm") End If End Sub

Visual C#
private void butDisplayPage_Click(object sender, System.EventArgs e){ // Si el navegador cliente soporta marcos muestra el conjunto de marcos. if (Request.Browser.Frames) Server.Transfer("frames.htm"); // Si no, muestra una versin diferente. else Server.Transfer("noframes.htm"); }

Tambin puede crear contenido alternativo dentro de <HTML> segn el soporte para marcos usando el elemento <NOFRAMES>. Este elemento lo soporta Internet Explores en versiones 3.0 y posteriores y es parte de la especificacin HTML 4.0. El cdigo que genera Visual Studio cuando se crea un conjunto de marcos contiene automticamente un elemento <NOFRAMES> de esta forma:
<frameset rows="64,*"> <frame name="banner" src="Banner.aspx" scrolling="no" noresize> <frameset cols="150,*"> <frame name="contents" src="Contents.aspx"> <frame name="main" src="Body.aspx"> </frameset> <noframes> <p>This HTML frameset displays multiple Web pages. To view this frameset, use a Web browser that supports HTML 4.0 and later.</p> </noframes> </frameset>

Puede modificar el texto para proporcionar contenido alternativo o una versin sin marcos de la pgina.

7.3.5 Apuntar a un marco desde un enlace


Cada marco de un conjunto de marcos acta como una ventana de navegador independiente. Una vez que se muestra una pgina en un marco los enlaces de esta pgina se muestran dentro del mismo marco. Para enlazar entre pginas mostradas en marcos aada un atributo TARGET al enlace. Por ejemplo, el siguiente HTML muestra unas serie de enlaces dirigidos al marco principal (main) del conjunto:
<h3>Contenido</h3> <P><A href="Cuerpo1.aspx" target="main">Cuerpo 1</A></P> <P><A href="Cuerpo2.aspx" target="main">Cuerpo 1</A></P> <P><A href="Cuerpo3.aspx" target="main">Cuerpo 1</A></P>

Cuando se pulsa sobre alguno de estos enlaces el contenido del marco llamado main cambia. No se puede apuntar a un marco usando Redirect, Transfer o Execute en el cdigo. Para navegar entre marcos solo puede usar enlaces HTML o controles de servidor Hyperlink.

7.4 Secuencias de comandos de cliente


ASP.NET proporciona un conjunto completo de herramientas de programacin para crear aplicaciones Web que corren en el servidor, de modo que por qu preocuparse de las secuencias de comandos en el cliente?. Porque las secuencias de comandos tienen acceso directo al navegador del cliente, lo que hace posible hacer cosas que no se pueden hacer desde el servidor. Por ejemplo, puede usar secuencias de comandos de cliente para:

142

Developing Web Applications

Controlar la ventana del navegador. No puede controlar el navegador desde el cdigo de servidor. Para abrir nuevas ventanas, establecer el foco dentro de una ventana, navegar entre marcos, navegar dentro del historial y ejecutar otras tareas relacionadas con el navegador debe usar secuencias de comandos de cliente. Responder inmediatamente a sucesos de paso del ratn. El cdigo de servidor solo puede responder a sucesos despus de que se enve la pgina al servidor; el cdigo de cliente puede responder a los sucesos de pgina cuando se producen. Iniciar el sistema de correo del cliente. Vea la leccin 2 de este captulo. En esta leccin aprender cmo aadir secuencias de comandos a formularios Web y pginas HTML en Visual Studio para crear cdigo que se ejecute en el ordenador cliente.

7.4.1 Antes de usar secuencias de comandos


Las secuencias de comandos de cliente causan tres temas de los que hay que estar precavidos. No todos los navegadores soportan secuencias de comandos. Solo Internet Explorer soporta VBScript. Las secuencias de comandos provocan problemas de seguridad. Como no todos los navegadores soportan secuencias de comandos, debe comprobar las posibilidades del navegador antes de mostrar pginas que contengan secuencias de comandos de cliente. El siguiente procedimiento de suceso Page_Load comprueba si un navegador soporta secuencias de comandos y si no lo hace redirige a los usuarios a una pgina que recomienda la descarga de una nueva versin. Visual Basic .NET
Private Sub Page_Load(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles MyBase.Load If Request.Browser.VBScript Then Response.Redirect("VBScripts.htm") Exit Sub ElseIf Request.Browser.JavaScript Then Response.Redirect ("JScripts.htm") Else Response.Redirect("NoScripts.htm") End If End Sub

Visual C#
private void Page_Load(object sender, System.EventArgs e){ if (Request.Browser.VBScript) Response.Redirect("VBScripts.htm"); else if (Request.Browser.JavaScript) Response.Redirect("JScripts.htm"); else Response.Redirect("NoScripts.htm"); }

Otro tema a tener en cuenta con las secuencias de comandos de cliente es la seguridad. Este tema tiene dos aspectos. Primero, las secuencias de comandos no son seguras las puede ver o copiar cualquiera que visite la aplicacin. Segundo, las secuencias de comandos pueden potencialmente transmitir virus; por tanto, algunos usuarios configuran sus navegadores para que desactiven las secuencias de comandos. Las propiedades VBScript y JavaScript del objeto Browser devolvern True incluso aunque se desactiven las secuencias de comandos. Para comprobar si estn activadas hay que ser un poco listo. El siguiente HTML comprueba si las secuencias de comandos estn activadas intentando ejecutar una. Si estn activadas se redirige al usuario a otra pgina y nunca ve el mensaje:
<html> <script> window.navigate("scripts.aspx") </script> <!-- Si las secuencias de comandos estn activadas, lo siguiente no se ve --> <head> <title>Scripts</title> </head> <body MS_POSITIONING="FlowLayout"> <h2>Secuencias de Comandos Desactivadas.</h2> <p>Sus opciones de seguridad especifican que su navegador no ejecute sentencias de comandos, por tanto no podr ver la pgina solicitada. Reactive las secuencias de comandos e intntelo de nuevo.</p> </body> </html>

143

MCAD/MCSD

7.4.2 Seleccionar un lenguaje de secuencias de comandos


Las secuencias de comandos se pueden escribir en VBScript o en JScript. Los lenguajes de secuencias de comandos se diferencias de los compilados, como Visual Basic .NET o C#, en: No son compilados. Los interpreta el navegador en tiempo de ejecucin. Son un subconjunto seguro de su lenguaje madre. No permiten crear o borrar archivos en el disco del usuario ni realizar tareas con riesgo evidente de colgar el ordenador del usuario.. VBScript y JScript con funcionalmente equivalentes se diferencian solo en la sintaxis y las palabras clave. En general, los programadores de C# estn ms cmodos usando JScript porque sigue los convenios de C; los programadores Visual Basic estn ms cmodos con VBScript porque estn muy relacionados. Sin embargo, solo Internet Explorer soporta VBScript, por lo que si su aplicacin tiene que correr en otros navegadores deber usar JScript. Si es programador de Visual Basic probablemente no le gustar el hecho de que JScript diferencia maysculas y minsculas. En JScript todas las palabras clave, variables, referencias a objeto, mtodos y propiedades se deben escribir usando correctamente maysculas y minsculas. Para ms informacin sobre lenguajes de secuencia de comandos vea los temas de la ayuda de Visual Basic relativos a JScript y VBScript.

7.4.3 DOM
El modelo de objetos de documento (DOM, Document Object Model) se compone de los objetos que proporciona el navegador para usar en las secuencias de comandos. Estos objetos permiten controlar la ventana del navegador, la pgina (o documento) actual y objetos de la pgina. La figura 7.1 muestra los objetos que proporciona DOM. La explicacin de todos los objetos en DOM est fuera del alcance de este libro. Sin embargo, hay una gran cantidad de informacin en el tema de Referencia DHTML de la ayuda de Visual Studio. Este tema y las referencias a las que enlaza son parte de la ayuda en lnea de Web Workshop.

Fig 7. 1: Jerarqua de Objetos DOM

7.4.4 Aadir secuencias de comandos en lnea


Las pginas Web pueden incluir secuencias de comandos en lnea como parte de su contenido o como procedimientos que se ejecutan en respuesta a sucesos. Las secuencias de comandos en lnea se ejecutan en el momento en que el navegador las encuentra. El ltimo ejemplo de la seccin anterior 7.4.1 muestra este funcionamiento redirigiendo al navegador a una nueva pgina si permite secuencias de comandos. Si se ejecuta correctamente la secuencia de comandos el usuario nunca ve el mensaje relativo a la desactivacin de secuencias de comandos. Si una secuencia de comandos en lnea hace referencia a un elemento de la pgina este elemento debe aparecer antes de que la secuencia de comandos lo nombre. Por ejemplo, el siguiente HTML muestra dos cajas de texto y usa una secuencia de comandos para mover el cursor a la segunda. VBScript
<HTML> <body language="vbscript"> <form id="Form1" method="post" runat="server"> <P><asp:TextBox id="txtFirstName" Runat="server"></asp:TextBox></P> <P><asp:TextBox id="txtLastName" Runat="server"></asp:TextBox></P> <script>window.document.all("txtLastName").focus()</script> </form> </body> </HTML>

144

Developing Web Applications

JScript
<HTML> <body language="javascript"> <form id="Form1" method="post" runat="server"> <P><asp:TextBox id="txtFirstName" Runat="server"></asp:TextBox></P> <P><asp:TextBox id="txtLastName" Runat="server"></asp:TextBox></P> <script>window.document.all["txtLastName"].focus()</script> </form> </body> </HTML>

Las secuencias de comandos en lnea tambin se pueden usar como atributos de elementos HTML que ejecutan acciones, como el control HTML Button. Por ejemplo, el siguiente HTML crea un botn que abre una pgina de ayuda en una nueva ventana.
<button id="butHelp" onclick="window.open('help.aspx', 'help', 'height=200,width=300')">Ayuda</button>

Observe que la secuencia de comandos anterior es independiente de lenguaje. En otras palabras, funcionar tanto si el atributo language del elemento <body> es VBScript como si es JScript. Para usar un lenguaje de secuencia de comandos diferente al establecido en el elemento <body> debe usar el atributo language del elemento <script>. Por ejemplo, la siguiente secuencia de comandos muestra una lista de niveles de encabezado: VBScript
<HTML> <script language="vbscript"> For i = 1 to 6 document.write("<h" & i & ">") document.write("H" & i) document.write("</h" & i & "><br>") Next </script> </HTML>

JScript
<HTML> <script language="javascript"> for (i = 1; i <= 6; i++){ document.write("<h" + i + ">"); document.write("H" + i); document.write("</h" + i + "><br>"); } </script> </HTML>

7.4.5 Respuesta a sucesos con secuencia de comandos


Las secuencias de comandos tambin definen procedimientos que responden a sucesos de pgina, como carga de la ventana, pulsacin de botones y paso del ratn sobre objetos. Para crear un procedimiento de suceso de secuencia de comandos siga estos pasos: 1. Usando Visual Studio cree o abra la pgina en la que quiere incluir las secuencias de comandos de cliente. La pgina puede ser un formulario Web (.aspx) o una pgina HTML (.htm). 2. Cambie a la vista HTML de la pgina. 3. En la lista desplegable en la parte superior izquierda de la pgina seleccione el objeto para el que quiere aadir el procedimiento 4. En la lista desplegable de la parte superior derecha de la pgina seleccione el suceso al que quiere que el cdigo responda. 5. Visual Studio crea un bloque de secuencia de comandos que contiene un procedimiento de suceso vaco, como este. VBScript
<script id=clientEventHandlersVBS language=vbscript> <!-Sub butRunScript_onmouseover End Sub --> </script>

145

MCAD/MCSD

JScript
<script id=clientEventHandlersJS language=javascript> <!-function butRunScript_onmouseover() {} //--> </script>

El cdigo que se aada al procedimiento de suceso se ejecutar cuando se produzca el suceso de pgina. Por ejemplo, el siguiente cdigo cambia el cursor del ratn al smbolo de mano cuando el usuario mueve el cursor por encima. VBScript
Sub butRunScript_onmouseover butRunScript.style.cursor = "hand" End Sub

JScript
function butRunScript_onmouseover() { butRunScript.style.cursor = "hand"; }

Los procedimientos de cliente pueden detectar una amplia variedad de sucesos, incluyendo pulsacin de teclas, sucesos de paso de ratn, pulsaciones, cargas y descargas. A diferencia de los sucesos de servidor, los sucesos de cliente no proporcionan argumentos directamente. En su lugar se usa el mtodo event del objeto window para obtener valores. Por ejemplo, el siguiente procedimiento para el suceso mousemove muestra las coordenadas del cursor en la barra de estado del navegador. VBScript
Sub document_onmousemove window.status = window.event.clientX & ", " & window.event.clientY End Sub

JScript
function window_onmousemove() { window.status = window.event.clientX + ", " + window.event.clientY; }

El cdigo de los procedimientos de cliente puede obtener y establecer los valores que muestran los controles de servidor y HTML de la pgina. Esto significa que puede obtener valores del usuario y proporcionar respuestas sin enviar la pgina de vuelta al servidor. Por ejemplo, el siguiente cdigo HTML define una pgina que juega un sencillo juego con el usuario sin ningn envo al servidor. VBScript
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> <html> <head> <title>EventScript</title> <meta name="vs_defaultClientScript" content="VBScript"> <meta name="vs_targetSchema" content="http://schemas.microsoft.com/intellisense/ie5"> <meta name="GENERATOR" content="Microsoft Visual Studio.NET 7.0"> <meta name="ProgId" content="VisualStudio.HTML"> <meta name="Originator" content="Microsoft Visual Studio.NET 7.0"> <script id="clientEventHandlersVBS" language="vbscript"> Sub butRunScript_onclick ' Muestra un mensaje en un rea de texto. sMessage = "Estoy pensando un nmero entre 0 y 9. " sMessage = sMessage & "Pulse una tecla numrica para adivinar." txtMessage.value = sMessage ' Inicializa el generador de nmeros aleatorios. Randomize ' Obtiene un nmero aleatorio y lo guarda en un campo oculto. hidNumber.value = Int(9 * Rnd) End Sub

146

Developing Web Applications

Sub document_onkeypress ' Si la tecla corresponde al nmero, muestra el mensaje de xito. if (window.event.keyCode - 48) = CInt(hidNumber.value) then txtMessage.value = "Correcto!" ' Si no, indica la respuesta correcta. else txtMessage.value = "Fall. El nmero era: " & hidNumber.value end if End Sub </script> </head> <body MS_POSITIONING="FlowLayout"> <p><textarea id="txtMessage"></textarea></p> <P><INPUT type="button" id="butRunScript" value="Ejecutar Script" NAME="butRunScript"></P> <INPUT id="hidNumber" type="hidden" name="Hidden1"> </body> </html>

JScript
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" > <HTML> <HEAD> <META NAME="GENERATOR" Content="Microsoft Visual Studio 7.0"> <TITLE></TITLE> <meta name="vs_defaultClientScript" content="JavaScript"> <meta name="vs_targetSchema" content="http://schemas.microsoft.com/intellisense/ie5"> <meta name="GENERATOR" content="Microsoft Visual Studio.NET 7.0"> <meta name="ProgId" content="VisualStudio.HTML"> <meta name="Originator" content="Microsoft Visual Studio.NET 7.0"> <script id=clientEventHandlersJS language=javascript> <!-function window_onkeypress() { // Si la tecla corresponde al nmero, muestra mensaje de xito. if ((window.event.keyCode - 48) == parseInt(hidNumber.value)) txtMessage.value = "Correcto!"; // Si no, indica la respuesta correcta. else txtMessage.value = " Fall. El nmero era: " + hidNumber.value; } function butRunScript_onclick() { // Muestra un mensaje en un rea de texto. sMessage = " Estoy pensando un nmero entre 0 y 9. " + " Pulse una tecla numrica para adivinar."; txtMessage.value = sMessage; // Obtiene un entero aleatorio. hidNumber.value = Math.round(9 * Math.random()); } //--> </script> </HEAD> <BODY language=javascript onmousemove="return window_onmousemove()" onkeypress="return window_onkeypress()"> <p><textarea id="txtMessage" style="WIDTH: 200px; HEIGHT: 88px" rows="5" cols="22" NAME="txtMessage"></textarea></p> <P><INPUT type="button" id="butRunScript" value="Ejecutar Script" NAME="butRunScript" language=javascript onmouseover="return butRunScript_onmouseover()" onclick="return butRunScript_onclick()"> </P> <P><INPUT id="hidNumber" type="hidden" name="Hidden1"></P> </BODY> </HTML>

7.5 Consumir servicios Web XML


Los servicios Web XML son componentes de lgica de negocio a los que se puede acceder en Internet. Consumir un servicio Web sencillamente significa utilizarlo desde una aplicacin. En esta leccin aprender como localizar un servicio Web, hacer referencia a l y usarlo desde una aplicacin Web. 147

MCAD/MCSD

7.5.1 Encontrar servicios Web XML


Los servicios Web XML se hacen pblicos en Internet usando un registro de descripcin, descubrimiento e integracin universal (UDDI, Universal Description, Discovery and Integration) . Actualmente Microsoft e IBM administran los dos nodos UDDI disponibles. Los negocios registran sus servicios Web en estos nodos de forma que los clientes (Vd. y yo) pueden localizar los servicios Web que quieren usar. Hay muchas formas diferentes para buscar servicios Web XML en Internet. La forma ms sencilla es seleccionar Servicios Web XML en la pgina Inicio de Visual Studio .NET. El elemento Servicios Web XML en la pgina de inicio le permite localizar servicios Web XML por categora general o por tarea que realiza, como calendario, financiera, matemtica o clima. Los botones de opcin Buscar en sobre la caja Categora permite buscar servicios Web XML puestos en produccin (presumiblemente depurados y probados) o an en desarrollo.

7.5.2 Usar un servicio Web XML


Usar un servicio Web es muy similar a usar un componente .NET o COM. Se establece una referencia a la clase, se crea una instancia de un objeto a partir de la clase y despus se usan los mtodos y propiedades de la clase desde el cdigo. Hay varias formas de establecer una referencia a un servicio Web XML desde Visual Studio .NET. Tal vez la ms sencilla sea hacerlo desde la pgina de inicio: 1. Localice el servicio Web que quiere utilizar pulsando el enlace Servicios Web XML en la pgina Inicio. 2. Pulse el enlace Agregar como referencia Web al proyecto actual bajo la descripcin del servicio. Visual Studio aade una referencia en la seccin Referencias Web del Explorador de soluciones, Para usar la referencia en el cdigo: 1. Cree un nuevo objeto a partir de la clase del servicio Web. El nombre de clase del servicio Web se muestra en la carpeta Referencias Web del Explorador de soluciones. 2. Use las propiedades y mtodos del servicio Web a partir del nuevo objeto. Las caractersticas de autocompletar y de inspector de objetos de Visual Studio funcionan con las clases de servicio Web, por lo que el uso de sus propiedades y mtodos es igual que el de cualquier otra clase. Nota: El siguiente ejemplo depende de la disponibilidad de un sitio Web de un tercero. En el momento de escribirse este libro este sitio estaba disponible, pero no se puede garantizar su disponibilidad futura. Por ejemplo, el siguiente cdigo usa el servicio Web de comprobacin de tarjetas de crdito CDYNE para validar un nmero de tarjeta de crdito escrito en una caja de texto. Visual Basic .NET
Private Sub butCheck_Click(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles butCheck.Click Dim wsCheck As New com.cdyne.secure.LUHNChecker() Dim wsValid As com.cdyne.secure.ReturnIndicator wsValid = wsCheck.CheckCC(txtNumber.Text) lblMsg.Text = wsValid.CardType & " " & wsValid.CardValid.ToString() End Sub

Visual C#
private void butCheck_Click(object sender, System.EventArgs e){ com.cdyne.secure.LUHNChecker wsCheck = new com.cdyne.secure.LUHNChecker(); com.cdyne.secure.ReturnIndicator wsValid; wsValid = wsCheck.CheckCC(txtNumber.Text); lblMsg.Text = wsValid.CardType + " " + wsValid.CardValid.ToString(); }

7.5.3 Uso de servicios Web XML desde secuencias de comando de cliente


En algunos casos tiene ms sentido llamar a un servicio Web XML desde secuencias de comandos de cliente que desde el cdigo de servidor. Un servicio Web XML puede tardar mucho tiempo en responder no tiene sentido hacer que el servidor espere la respuesta cuando lo nico que va a hacer es pasarla al cliente. Para usar un servicio Web XML desde secuencias de comandos de cliente siga estos pasos: 1. Cree una clase de estilo para el comportamiento WebService (Webservice.htc) 2. Aada a la pgina un elemento HTML que use la clase creada en el paso 1. 3. Escriba procedimientos de secuencia de comandos para inicializar y llamar a los mtodos del servicio Web XML usando el comportamiento.

148

Developing Web Applications

El siguiente HTML crea una clase de estilo webservice, la inicializa y llama a un servicio Web para mostrar una cita diaria cuando el usuario pulsa Mostrar cita. VBScript
<HTML> <HEAD> <title>WebForm2</title> <style>.webservice { BEHAVIOR:url(webservice.htc) }</style> <script language="VBScript"> Dim iCallID Sub init(control, wsAddress, name) control.useService wsAddress, name End Sub Function getResult() if window.event.result.error And _ (iCallID = window.event.result.id) Then Dim xfaultcode, xfaultstring, xfaultsoap xfaultcode = window.event.result.errorDetail.code xfaultstring = window.event.result.errorDetail.string xfaultsoap = window.event.result.errorDetail.raw ' Muestra informacin del error. alert("Error " & xfautlcode & " " & xfaultstring & " " & _ xfaultSoap) Else getResult = window.event.result.value End If End Function Sub getQuote() ' Inicializa el servicio Web en el control seleccionado. init ws, "http://webservice.effective-web.net/globalself/ globalselfDailyThought.WSDL", "DailyQuote" ' Llama a un mtodo dentro del servicio Web iCallID = ws.DailyQuote.callService("getTodaysQuote") ' onresult Muestra el resultado en el elemento div ws. End Sub </script> </HEAD> <body> <form id="WebForm2" method="post" runat="server"> <h2>Uso de servicios Web desde cdigo de cliente </h2> <div id="ws" class="webservice" onresult="ws.innerText = getResult()"></div><br> <input type="button" onclick="getQuote()" value="Ver Cita"> </form> </DIV> </body> </HTML>

JScript
<HTML> <HEAD> <title>WebForm2</title> <style> .webservice { BEHAVIOR:url(webservice.htc) }</style> <script language="JScript"> var iCallID; function init(control, wsAddress, name){ control.useService(wsAddress, name); } function getResult(){ if((event.result.error)&&(iCallID==event.result.id)) { var xfaultcode = event.result.errorDetail.code; var xfaultstring = event.result.errorDetail.string; var xfaultsoap = event.result.errorDetail.raw; // Muestra informacin de error. alert("Error " + xfautlcode + " " + xfaultstring + " " + xfaultSoap); }

149

MCAD/MCSD

else return event.result.value; } function getQuote(){ // Inicializa el servicio Web en el control seleccionado. init(ws, "http://webservice.effective-web.net/globalself/ globalselfGlobalSelf.WSDL", "DailyQuote"); // Llama a un mtodo del servicio Web. iCallID = ws.DailyQuote.callService("getTodaysQuote"); // onresult muestra el resultado en el elemento div ws. } </script> </HEAD> <body> <form id="WebForm2" method="post" runat="server"> <h2>Uso de servicios Web desde cdigo de cliente.</h2> <div id="ws" class="webservice" onresult="ws.innerText = getResult();"> </div><br> <input type="button" onclick="getQuote()" value="Ver Cita"> </form></DIV> </body> </HTML>

Para ms informacin sobre el uso de servicios Web XML desde cdigo cliente vea la ayuda de Visual Studio, tema Comportamiento WebService.

7.6 Resumen
Las cookies le permiten guardar informacin sobre un usuario concreto de modo invisible. Se pueden usar para guardar la informacin directamente en el ordenador del usuario o indirectamente mediante un identificador nico que se utiliza para recuperar informacin de usuario desde un conjunto de datos almacenado en el servidor. Use la propiedad Cookies del objeto Browser para comprobar si un navegador acepta cookies antes de intentar crearlas. Use la coleccin Cookies del objeto Request para recuperar una cookie del usuario. Use la coleccin Cookies del objeto Response para crear o modificar una cookie en el ordenador del usuario. Para borrar una cookie en el ordenador del usuario de el valor Now a la propiedad Expires del objeto Cookie. Use el protocolo mailto: para crear un mensaje que se enviar desde el sistema de correo del usuario. El protocolo mailto: se usa como parte de un enlace. Use las clases MailMessage y SmtpMail para componer y enviar mensajes desde el sistema de correo del servidor. Los marcos permiten mostrar varias pginas en una sola ventana del navegador. La presentacin y desplazamiento de cada marco se controla por separado. Use la propiedad Frames del objeto Browser para comprobar si un navegador acepta marcos antes de mostrarlos. Los enlaces en un marco pueden mostrar una pgina en otro marco usando el atributo target. Solo puede controlar los marcos desde enlaces o secuencias de comandos de cliente. Las secuencias de comandos de cliente permiten controlar la ventana del navegador, responder inmediatamente a sucesos que no provocan el envo y realizar otras tareas que no son posibles en cdigo de servidor. Use las propiedades VBScript o JavaScript del objeto Browser para comprobar si el navegador soporta secuencias de comandos. Use una secuencia de prueba en lnea que redirija a los usuario para comprobar si el usuario ha desactivado las secuencias de comandos mediante las opciones de seguridad del navegador. Aada procedimientos de suceso de secuencia de comandos a una pgina HTML para responder a sucesos que se produzcan en el cliente en lugar de en el servidor.

7.7 Prctica: Uso de caractersticas avanzadas


En esta prctica va a crear una aplicacin que muestra varias pginas usando marcos. Esta aplicacin permite al usuario seleccionar un color de fondo para la aplicacin, componer y enviar correo desde el servidor y jugar a un juego sencillo. Esta prctica realiza las siguiente tareas clave: Prueba las capacidades del navegador para asegurarnos de que soporta marcos, cookies y secuencias de comandos. Guarda cookies en el ordenador del usuario y las recupera para configurar el color de fondo de la aplicacin. Enva correo desde el servidor usando objetos MailMessage y SmtpMail. Muestra pginas en marcos y controla la presentacin de estos marcos desde una pgina Contents.

150

Developing Web Applications

7.7.1 Comprobar el soporte de caractersticas avanzadas


En este ejercicio va a crear una pgina predeterminada para la aplicacin que comprueba si el navegador del usuario acepta cookies, puede mostrar marcos y puede ejecutar secuencias de comandos. Si cualquiera de estas caractersticas no est disponible se muestra el mensaje adecuado. Una pgina predeterminada es la que muestra IIS si el usuario llega al directorio de la aplicacin Web sin especificar una pgina concreta. IIS utiliza los nombres Default.htm y Default.aspx para la pgina predeterminada, salvo que se cambien para la aplicacin mediante IIS. 1. Aada a la aplicacin un formulario Web llamado Default.aspx y haga que sea la pgina de inicio de la aplicacin. 2. Aada al formulario Web el siguiente procedimiento de suceso Page_Load. Visual Basic .NET
Private Sub Page_Load(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles MyBase.Load ' Crea un indicador para saber si se han desactivado caractersticas. Dim bProceed As Boolean = True ' Comprueba si el navegador acepta cookies. If Request.Browser.Cookies = False Then Response.Write("Su navegador no acepta cookies.<br>" & _ "Cambie su configuracin de seguridad para permitirlas.<br><br>") bProceed = False End If ' Comprueba si soporta secuencias de comandos. If Request.Browser.JavaScript = False Then Response.Write("Su navegador no soporta secuencias de comandos." & _ "Actualice a una versin ms actual.<br><br>") bProceed = False End If ' Comprueba si el navegador soporta VBScript. If Request.Browser.VBScript = False Then Response.Write("Su navegador no soporta VBScript.<br>" & _ "Instale Explorer.<br><br>") bProceed = False End If ' Si pasa las pruebas, comprueba si las secuencias de comandos estn ' activadas probando a ejecutar una. If bProceed Then ' Si estn desactivadas se ignora esta lnea; si estn activadas se ' muestra el conjunto de marcos. Response.Write("<script>window.navigate('frameset.htm')</script>") Response.Write("La configuracin de seguridad de su navegador ha " & _ "desactivado las secuencias de comandos.<br> Cambie esta " & _ "configuracin.<br><br>") End If End Sub

Visual C#
private void Page_Load(object sender, System.EventArgs e){ // Crea un indicador para saber si se han desactivado caractersticas. bool bProceed = true; // Comprueba si acepta cookies. if (!Request.Browser.Cookies){ Response.Write("Su navegador no acepta cookies.<br>" + "Cambie su configuracin de seguridad para permitirlas.<br><br>"); bProceed = false; } // Comprueba si el navegador soporta secuencias de comandos. if (!Request.Browser.JavaScript){ Response.Write("Su navegador no soporta secuencias de comandos.<br>" + "Cambie a una versin ms actual.<br><br>"); bProceed = false; } // Comprueba si el navegador soporta VBScript. if (!Request.Browser.VBScript){ Response.Write("Su navegador no soporta VBScript.<br>" + "Instale Internet Explorer.<br><br>"); bProceed = false; }

151

MCAD/MCSD

// Si pasa las pruebas, comprueba si las secuencias de comandos estn // activadas probando a ejecutar una. if (bProceed) { // Si estn desactivadas se ignora esta lnea; si estn activadas se // muestra el conjunto de marcos. Response.Write("<script>window.navigate('frameset.htm')</script>"); Response.Write("La configuracin de seguridad de su navegador ha " + "desactivado las secuencias de comandos.<br> Cambie esta " + "configuracin.<br><br>"); } }

3. Aada el siguiente contenido HTML al formulario Web:


<p>Esta aplicacin Web utiliza caractersticas que no estn disponibles en su navegador o que han sido desactivadas mediante la configuracin de seguridad. No puede ejecutar esta aplicacin hasta que no actualice su navegador tal como se ha descrito anteriormente. A continuacin pulse <a href="default.aspx"> aqu</a> para probar de nuevo.</p>

Cuando se carga la pgina que se ha creado con los pasos anteriores comprueba cada una de las caractersticas avanzadas que un navegador puede o no soportar. Si hay problemas con el uso de alguna de ellas la pgina muestra un aviso de advertencia. Si no encuentra problemas, el usuario no ve la pgina predeterminada. En su lugar se le redirige inmediatamente al conjunto de marcos, que muestra las otras pginas de la aplicacin.

7.7.2 Almacenar informacin de usuario


En este ejercicio va a crear un formulario Web que permite que el usuario seleccione un color de fondo. El formulario recuerda la seleccin del usuario entre sesiones guardando en segundo plano una cookie en la mquina del usuario. 1. Cree un nuevo formulario Web llamado Background.aspx. 2. Aada a la pgina un control de servidor DropDownList que contenga elementos de lista para varios colores. Este paso es probablemente ms fcil en modo HTML que en modo diseo, porque en HTML puede copiar y pegar para crear los elementos rpidamente. El siguiente HTML muestra la definicin del DropDownList y sus elementos:
<asp:dropdownlist id="drpBackground" AutoPostBack="True" Runat="server" Width="128px"> <asp:ListItem Value="White">Blanco</asp:ListItem> <asp:ListItem Value="Silver">Gris</asp:ListItem> <asp:ListItem Value="LightSteelBlue">Azul acero claro</asp:ListItem> <asp:ListItem Value="Honeydew">Verde claro</asp:ListItem> <asp:ListItem Value="Azure">Azuln</asp:ListItem> <asp:ListItem Value="Linen">Lino</asp:ListItem> <asp:ListItem Value="MintCream">Crema de menta</asp:ListItem> </asp:dropdownlist>

3. Modifique el elemento <body> del formulario web para indicar un color de fondo usando una vinculacin con la lista desplegable: <body bgColor="<%# drpBackground.SelectedItem.Value %>"> 4. Aada el siguiente cdigo al procedimiento de suceso Page_Load para comprobar una cookie, crearla si no existe o establecer el color de fondo segn la cookie si existe. El procedimiento de suceso Page_Load tambin realiza vinculacin de datos para que la pgina actualice el color de fondo. Visual Basic .NET
Private Sub Page_Load(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles MyBase.Load ' Primera presentacin If IsPostBack = False Then ' Si la cookie no existe la crea. If Request.Cookies("BackgroundColor") Is Nothing Then ' Crea una cookie con el color de fondo predeterminado. Dim cookBackground As New HttpCookie("BackgroundColor", "0") ' Configura la cookie para que caduque en un da. cookBackground.Expires = DateTime.Now.AddDays(1) ' Aade la cookie al objeto respuesta. Response.Cookies.Add(cookBackground) Else

152

Developing Web Applications

' Obtiene el color de fondo del usuario a partir de la cookie. drpBackground.SelectedIndex = _ CInt(Request.Cookies("BackgroundColor").Value) End If End If ' Actualiza la vinculacin para establecer el color de fondo Page.DataBind() End Sub

Visual C#
private void Page_Load(object sender, System.EventArgs e){ // Primera presentacin if (!IsPostBack){ // Si la cookie no existe la crea. if (Request.Cookies["BackgroundColor"] == null){ // Crea una cookie con el color de fondo predeterminado. HttpCookie cookBackground = new HttpCookie("BackgroundColor", "0"); // Configura la cookie para que caduque en un da. cookBackground.Expires = DateTime.Now.AddDays(1); // Aade la cookie al objeto respuesta. Response.Cookies.Add(cookBackground); }else // Obtiene el color de fondo del usuario a partir de la cookie. drpBackground.SelectedIndex = Convert.ToInt16(Request.Cookies ["BackgroundColor"].Value); } // Actualiza la vinculacin para establecer el color de fondo Page.DataBind(); }

5. Aada el siguiente cdigo para actualizar la cookie mediante el objeto Response cuando el usuario seleccione un color de fondo de la lista desplegable: Visual Basic .NET
Private Sub drpBackground_SelectedIndexChanged( _ ByVal sender As System.Object, ByVal e As System.EventArgs) Handles _ drpBackground.SelectedIndexChanged ' Registra la seleccin de color en una cookie. Dim cookBackground As New HttpCookie("BackgroundColor") ' Configura el valor de la cookie. cookBackground.Value = drpBackground.SelectedIndex ' Configura la caducidad de la cookie. cookBackground.Expires = DateTime.Now.AddDays(1) ' Aade la cookie al objeto respuesta. Response.Cookies.Add(cookBackground) End Sub

Visual C#
private void drpBackground_SelectedIndexChanged(object sender, System.EventArgs e){ // Registra la seleccin de color en una cookie. HttpCookie cookBackground = new HttpCookie("BackgroundColor"); // Configura el valor de la cookie. cookBackground.Value = drpBackground.SelectedIndex.ToString(); // Configura la caducidad de la cookie. cookBackground.Expires = DateTime.Now.AddDays(1); // Aade la cookie al objeto respuesta. Response.Cookies.Add(cookBackground); }

7.7.3 Crear un formulario Web para correo


En este ejercicio va a crear un formulario Web que permitir componer y enviar un mensaje de correo desde el servidor. 1. Cree un nuevo formulario Web y llmelo Mail.aspx 2. Aada el texto y los controles de servidor que se muestran en el siguiente HTML:

153

MCAD/MCSD

<P> De:&nbsp;&nbsp;&nbsp; <asp:TextBox ID="txtFrom" Runat="server" Width="376px"></asp:TextBox> <asp:RequiredFieldValidator ID="vldtxtFrom" ControlToValidate="txtFrom" Runat="server" ErrorMessage="Campo indispensable."> </asp:RequiredFieldValidator> <br> A:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <asp:TextBox ID="txtTo" Runat="server" Width="377px"></asp:TextBox> <asp:RequiredFieldValidator ID="vldTo" ControlToValidate="txtTo" Runat="server" ErrorMessage="Campo indispensable."> </asp:RequiredFieldValidator> <br> Asunto: <asp:TextBox ID="txtSubject" Runat="server" Width="376px"></asp:TextBox> </P> <asp:TextBox ID="txtMessage" Runat="server" TextMode="MultiLine" Width="432px" Height="208px"></asp:TextBox> <br> <asp:Button ID="butSend" Runat="server" Text="Enviar"></asp:Button> <input type="reset" id="butReset" value="Cancelar"> <br> <asp:literal id="litStatus" runat="server"></asp:literal>

Los controles RequiredFieldValidator son necesarios porque antes de poder enviar el mensaje se deben establecer las propiedades From y To del objeto MailMessage. 3. Aada la sentencia Imports o using para poder utilizar el espacio de nombres System.Web.Mail. 4. Aada al procedimiento de suceso butSend_Click el siguiente cdigo para crear un objeto MailMessage y enviar el mensaje desde el servidor: Visual Basic .NET
Private Sub butSend_Click(ByVal sender As System.Object, + ByVal e As System.EventArgs) Handles butSend.Click Dim msgMail As New MailMessage() ' Crea el mensaje. msgMail.From = txtFrom.Text ' Configura las propiedades. msgMail.To = txtTo.Text msgMail.Subject = txtSubject.Text msgMail.Body = txtMessage.Text SmtpMail.Send(msgMail) ' Enviar mensaje. txtTo.Text = "" ' Limpia los campos. txtSubject.Text = "" txtMessage.Text = "" litStatus.Text = "<p>Mensaje enviado.</p>" ' Muestra el xito. End Sub

Visual C#
private void butSend_Click(object sender, System.EventArgs e){ MailMessage msgMail = new MailMessage(); // Crea el mensaje. msgMail.From = txtFrom.Text; // Configura las propiedades msgMail.To = txtTo.Text; msgMail.Subject = txtSubject.Text; msgMail.Body = txtMessage.Text; SmtpMail.Send(msgMail); // Enviar mensaje. txtTo.Text = ""; // Limpia los campos. txtSubject.Text = ""; txtMessage.Text = ""; litStatus.Text = "<p>Mensaje enviado.</p>"; // Muestra el xito. }

5. Aada al procedimiento de suceso Page_Load el siguiente cdigo para limpiar el mensaje de estado si el usuario cancela el envo de un mensaje tras enviar con xito otro anterior. Visual Basic .NET
Private Sub Page_Load(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles MyBase.Load litStatus.Text = "" ' Limpia el mensaje de estado. End Sub

Visual C#
private void Page_Load(object sender, System.EventArgs e){ litStatus.Text = ""; // Limpia el mensaje de estado. }

154

Developing Web Applications

7.7.4 Crear un interface de usuario basado en marcos


En este ejercicio va a crear un conjunto de marcos que contiene regiones para una tabla de contenidos, una pancarta y un cuerpo. Crear la pgina de tabla de contenidos que mostrar las pginas seleccionadas en el marco de cuerpo y actualizar el marco de pancarta usando una secuencia de comandos. 1. Cree una nueva pgina HTML llamada Contents.htm 2. Aada a esta pgina los siguientes enlaces:
<a href="Background.aspx" target="main" onclick="ShowBanner('Elegir Fondo')"> Elegir Fondo</a><br> <a href="Mail.aspx" target="main" onclick="ShowBanner('Enviar correo desde el servidor')">Enviar Correo</a><br> <a href="Game.htm" target="main" onclick="ShowBanner('Jugar')">Jugar</a><br>

3. Aada el siguiente procedimiento de secuencia de comandos a la pgina: VBScript


<script language="vbscript"> ' Actualiza el texto en el marco de pancarta. Sub ShowBanner(Message) ' Escribe texto en el marco de pancarta. parent.frames("banner").document.write("<h2>" & Message & "</h2>") ' Cierra el documento para que el siguiente texto reemplace al actual. parent.frames("banner").document.close End Sub </script>

JScript
<script language="javascript"> // Actualiza el texto en el marco de pancarta. function ShowBanner(Message){ // Escribe texto en el marco de pancarta. parent.frames["banner"].document.write("<h2>" + Message + "</h2>"); // Cierra el documento para que el siguiente texto reemplace al actual. parent.frames["banner"].document.close(); } </script>

4.

5. 6. 7. 8.

Esta secuencia de comandos muestra un ttulo en el marco de pancarta del conjunto de marcos a partir de cada uno de los enlaces creados en el paso anterior. Cree un conjunto de marcos para mostrar las pginas del proyecto. En el men Proyecto seleccione Agregar nuevo elemento, seleccione Conjunto de marcos en la lista Plantillas y llame al archivo Frameset.htm. Al pulsar Abrir Visual Studio muestra el dilogo Seleccione una plantilla de conjunto de marcos. Seleccione la plantilla Pancarta y Contenido y pulse Aceptar. Visual Studio muestra un nuevo conjunto de marcos vaco en la ventana de diseo. Pulse con el botn derecho del ratn en el marco ms a la izquierda y seleccione Establecer pgina para marco. Visual Studio muestra el dilogo Pgina de seleccin. Seleccione Contents.htm y pulse aceptar para mostrar la pgina Contents en el marco. Haga que el conjunto de marcos sea la pgina de inicio de la aplicacin. En el explorador de soluciones pulse con el botn derecho sobre el archivo Frameset.htm y seleccione Establecer como pgina de inicio.

7.7.5 Prctica extra con secuencias de comandos y cookies


Los ejercicios 1 a 4 han recorrido las tareas aprendidas en este captulo. Ahora siga por si mismo intentando completar las siguientes tareas que amplan la aplicacin de caractersticas avanzadas. Aada una secuencia de comandos Window_OnLoad a la pgina Contents para mostrar un mensaje de bienvenida en el marco de pancarta la primera vez que se muestra la pgina. Aada el formulario Web Adivine el Nmero creado en el apartado 7.4.5 a la aplicacin. Cree en el formulario de correo una cookie para recordar el campo De introducido por el cliente. Use el color de fondo seleccionado en la pgina correspondiente para cambiar el fondo de todas las pginas del conjunto de marcos. Cuando termine compare sus resultados con la aplicacin Advanced Features incluida en el CD.

7.8 Repaso
Las siguientes preguntas estn pensadas para reforzar informacin clave mostrada en este captulo. Si no es capaz de contestar a una pregunta repase la leccin correspondiente e intente de nuevo. Las respuestas se pueden encontrar en el captulo 16. 1. Escriba el HTML para un enlace que enve correo cuando el usuario lo pulse 155

MCAD/MCSD

2. Muestre el cdigo que escribe una cookie que contiene el nombre de usuario Rob Young y la fecha actual en el ordenador del usuario. Configure la cookie para que permanezca en el ordenador 30 das. 3. Por qu no puede abrir una ventana de navegador desde cdigo de servidor?. Cmo podra mostrar una pgina en una nueva ventana con una secuencia de comandos de cliente? 4. Cmo mostrara una pgina en un marco desde un enlace en otro marco?.

156

Developing Web Applications

8 Mantener la seguridad
En este captulo aprender cmo controlar el acceso a su aplicacin Web usando las tres tcnicas que proporciona ASP.NET para identificar a los usuarios y permitir que tengan acceso a la aplicacin. Tambin aprender cmo asegurar los datos transmitidos sobre Internet de forma que otros no puedan leerlos. Este captulo no proporciona una gua completa de seguridad en redes o en servidor. Este es amplio tema que abarca una gran cantidad de informacin conceptual o especfica del sistema. Lo que hace este captulo es proporcionar una gua prctica para implementar seguridad en una aplicacin Web usando ASP.NET. Para completar las lecciones de este captulo deber Tener acceso a dos ordenadores en una red Windows. Puede ser una red sencilla basada en grupos de trabajo, pero es mejor una basada en dominio. Tener privilegios de administrador en un ordenador que funcione como servidor en la red. Si no tiene acceso a una red Windows puede realizar la mayora de las tareas de este captulo usando un nico ordenador y ejecutando la aplicacin localmente, como se hace en el modo de depuracin de Visual Studio, pero no podr comprobar verdaderamente la autenticacin de mltiples usuarios.

8.1 Autenticar y autorizar usuarios


Autenticacin es el proceso de identificar usuarios. Autorizacin es el proceso de permitir el acceso a los usuario en base a su identidad. Juntas, la autenticacin y la autorizacin proporcionan los medios para mantener la aplicacin Web segura frente a intrusos. En esta leccin aprender cmo maneja ASP.NET los usuarios annimos y ver ls diferentes formas en que puede identificar y autorizar usuarios. Esta informacin le ayudar a seleccionar una estrategia de autentificacin segn el tipo de aplicacin que est creando.

8.1.1 Acceso por uuarios annimos


El acceso annimo es la forma en que funcionan la mayora de los sitios Web pblicos los sitios que contienen informacin permiten que cualquiera vea la informacin, de modo que no autentifican a los usuarios. Las aplicaciones Web ASP.NET proporcionan acceso annimo a los recursos en el servidor por medio de la impersonificacin. La impersonificacin es el proceso de asignar una cuenta de usuario a un usuario desconocido. De forma predeterminada, la cuenta de acceso annima se llama IUSR_nombremaquina. Esta cuenta se usa para controlar el acceso a los recursos en el servidor. Para ver o cambiar los privilegios de acceso de la cuenta de usuario annima use el elemento Administracin de equipos como indican los siguientes pasos. 1. Entre en el ordenador como administrador. 2. En el men Inicio, Configuracin, Herramientas administrativas seleccione Administracin de equipos para ejecutar la consola de administracin. 3. En la lista de la izquierda seleccione Usuarios locales y grupos y despus la carpeta Usuarios para mostrar la lista de usuarios autorizados en este ordenador. 4. En la lista de usuarios a la derecha pulse dos veces sobre la cuenta de usuario annimo llamada IUSR_nombremaquina. La consola de administracin muestra las propiedades de la cuenta. 5. Pulse sobre la lengeta Miembro de para ver los grupos a los que pertenece la cuenta. De forma predeterminada los usuarios annimos pertenecen al grupo Invitados, que tiene privilegios limitados. Bajo la configuracin predeterminada ASP.NET usa la cuenta ASPNET para ejecutar la aplicacin Web. Esto significa que si la aplicacin intenta realizar tareas que no estn incluidas en los privilegios de la cuenta ASPNET se producir una excepcin de seguridad y se denegar el acceso. El nombre de cuenta tambin se mostrar en el registro de sucesos de seguridad en el visor de sucesos. El acceso de los usuarios annimos se restringe configurando los permisos de archivo de Windows. Para estar seguro su servidor debe usar el sistema de archivos NT (NTFS). Los anteriores sistemas de ficheros FAT o FAT32 no proporcionan seguridad a nivel de fichero. Para ms informacin sobre la configuracin de permisos de fichero Windows consulte los temas de ayuda de Windows relacionados con seguridad.

8.1.2 Acceso por usuarios autenticados


Como se indic anteriormente el acceso annimo es adecuado para informacin pblica. Pero si su aplicacin contiene informacin privada o realiza tareas restringidas como realizar pedidos querr autenticar y autorizar usuarios individuales. Hay tres formas principales de autenticar y autorizar usuarios dentro de una aplicacin Web ASPNET:

157

MCAD/MCSD

Autenticacin Integrada de Windows. Identifica y autoriza a los usuarios en base a la lista de usuarios del servidor. El acceso a los recursos en el servidor se autoriza o deniega en base a los privilegios de la cuenta del usuario. Esto funciona igual que la seguridad habitual de redes Windows. Autenticacin por Formularios. Dirige a los usuarios a un formulario Web de conexin que recoge su nombre y contrasea y lo autentica contra una lista o base de datos de usuarios mantenida por la aplicacin. Autenticacin Passport. Dirige a los nuevos usuarios a un sitio alojado por Microsoft de modo que pueden registrar un nico nombre de usuario y contrasea que autorizar su acceso a mltiples sitios Web. A los usuarios existentes se les pide su nombre y contrasea Passport, que la aplicacin autentica contra la lista de usuarios de Microsoft Passport. Cada una de estas aproximaciones, junto con el acceso annimo, tienen diferentes ventajas. Estos mtodos estn adaptados a diferentes tipos de aplicaciones Web, como resume la tabla 8.1.
Tabla 8. 1: Tipos deaplicacin Web y tcnicas de autenticacin
Tipo de Aplicacin Aplicacin Internet Pblica Aplicacin Web Intranet Aplicacin Web corporativa privada Aplicacin Web comercial Mltiples aplicaciones Web comerciales Tipo de autenticacin Annimo Integrada de Windows Integrada de Windows Formularios Passport Descripcin Mtodo de acceso comn para la mayora de sitios Web. No es necesaria identificacin y los recursos restringidos se aseguran mediante los permisos de archivo NTFS. La autenticacin de Windows autentica a los usuarios mediante el controlador de dominio. Los usuarios de red tienen acceso a los recursos de aplicaciones Web como determinan sus privilegios de usuario en el servidor. Los usuarios corporativos pueden acceder a la aplicacin web usando sus nombres de usuarios y contraseas de la red corporativa. Las cuentas de usuario se administran usando las herramientas de seguridad en red de Windows. Las aplicaciones que necesitan recoger informacin para envo y facturacin deben implementar la autenticacin por formularios para obtener y almacenar informacin de cliente. La autenticacin Passport permite que los usuarios se registren una sola vez mediante una autoridad central. La identidad del usuario est disponible a cualquier aplicacin que use el SDK de Passport. La informacin de cliente se mantiene en un perfil Passport en lugar de una base de datos local.

Las siguientes secciones describen cmo autenticar y autorizar a los usuarios usando cada una de las tres tcnicas.

8.1.3 Autenticacin con archivos HTM y HTML


Los tres mtodos de autenticacin ASP.NET se aplican a archivos que son parte de la aplicacin Web. Esto incluye formularios Web (.aspx), mdulos (.asax) y otros recursos procesados por medio del ejecutable de la aplicacin. Esto no incluye automticamente pginas HTML (.htm o .html). Estas pginas las administra IIS, no ASP.NET. Si quiere autenticar a usuarios que accede a pginas HTML dentro de su aplicacin usando los modos de autenticacin Windows, Forms o Passport debe asignar estos archivos al ejecutable ASP.NET siguiendo estos pasos: 1. En IIS, pulse con el botn derecho del ratn sobre la carpeta que contiene la aplicacin Web y seleccione Propiedades. IIS muestra el dilogo Propiedades. 2. Pulse sobre la lengeta Directorio virtual y el botn Configuracin. IIS muestra el dilogo Configuracin de aplicacin. 3. Pulse Agregar. IIS muestra el dilogo Agregar o modificar asignacin de extensin para aplicacin. 4. Pulse Examinar y seleccione el archivo aspnet_isapi.dll. Este archivo se encuentra en el directorio del marco de trabajo .NET, cuya ruta ser similar a C:\Windows\Microsoft.NET\Framework\numeroversion\ 5. Escriba .htm en la caja de texto Extensin y pulse Aceptar. 6. Repita los pasos 3 a 5 para la extensin .html. Cuando termine pulse Aceptar para cerrar los dilogos de IIS .

8.2 Autenticacin de Windows


La autenticacin de Windows usa las caractersticas de seguridad integradas en los sistemas operativos Windows NT y XP para autenticar y autorizar usuarios de aplicaciones Web. La ventaja de la autenticacin Windows es que la aplicacin Web puede usar exactamente el mismo esquema de seguridad que se aplica a la red corporativa los nombres de usuario, contraseas y permisos son los mismos para los recursos de red y para las aplicaciones Web.

8.2.1 Activar la autenticacin Windows


La autenticacin Windows es el mtodo predeterminado cuando se crea un nuevo proyecto de aplicacin Web. Para ver cmo funciona siga estos pasos. 1. Cree un nuevo proyecto de aplicacin Web. En un proyecto Visual Basic .NET cambie el elemento de autorizacin para que sea como el siguiente. En un proyecto Visual C# aada este elemento de autorizacin:
<authorization> <deny users="?" </authorization> />

158

Developing Web Applications

2. Aada la siguiente definicin de tabla HTML al formulario Web de inicio de la aplicacin:


<TABLE id="tblUser" > <TR> <TD>Autenticado</TD> <TD><span runat="server" id="spnAuthenticated"></span></TD> </TR> <TR> <TD>Nombre de usuario</TD> <TD><span runat="server" id="spnUserName"></span></TD> </TR> <TR> <TD>Tipo de Autenticacin</TD> <TD><span runat="server" id="spnAuthenticationType"></span></TD> </TR> </TABLE>

3. Cambie el formulario Web a modo diseo y alada el siguiente cdigo al mdulo de cdigo del formulario Web: Visual Basic .NET
Private Sub Page_Load(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles MyBase.Load spnAuthenticated.InnerText = User.Identity.IsAuthenticated spnUserName.InnerText = User.Identity.Name spnAuthenticationType.InnerText = User.Identity.AuthenticationType End Sub

Visual C#
private void Page_Load(object sender, System.EventArgs e){ spnAuthenticated.InnerText = User.Identity.IsAuthenticated.ToString(); spnUserName.InnerText = User.Identity.Name; spnAuthenticationType.InnerText = User.Identity.AuthenticationType; }

4. Ejecute la aplicacin. Cuando se ejecuta el proyecto en local ASP.NET autentica al usuario utilizando el nombre que se utiliz para entrar en Windows. Cuando se ejecuta de forma remota (como en Internet) ASP.NET muestra un dilogo de conexin para pedir el nombre de usuario y contrasea. Si el nombre de usuario y contrasea estn autorizados en el dominio de red ASP.NET autentica al usuario y le autoriza el uso de la aplicacin. La aplicacin se ejecuta utilizando los permisos de la cuenta del usuario. Cuando se autoriza a un usuario ASP.NET emite un certificado de autorizacin en forma de una cookie que persiste durante el tiempo de la sesin del usuario. La sesin de usuario termina cuando el navegador se cierra o cuando la sesin alcanza el tiempo lmite de inactividad. La autenticacin integrada de Windows trabaja mejor en una red basada en dominio. Las redes que usan grupos de trabajo en lugar de dominios tienen un uso ms limitado de las caractersticas de seguridad de red. Las redes basadas en dominio usan un controlador de dominio para identificar y autorizar a los usuarios de la red. Una de las ventajas principales de la autenticacin integrada de Windows es que los usuarios que estn conectados a la red no tienen que volver a conectarse de nuevo para acceder a la aplicacin Web; se les autentica automticamente. Otra ventaja es que los usuarios corporativos pueden usar los mismos nombres de usuario y contraseas de red cuando acceden al sitio Web de forma remota desde casa o durante viajes. La autenticacin integrada de Windows tambin permite establecer otra capa de seguridad permitiendo o prohibiendo usuarios o grupos de usuarios concretos. Adems, la autorizacin integrada de Windows se superpone a caractersticas similares que se encuentran en IIS. Las siguientes secciones describen estos temas con ms detalle.

8.2.2 Permitir o denegar el acceso a usuarios concretos.


Cuando la aplicacin usa la autenticacin integrada de Windows ASP.NET comprueba la lista de autorizacin del archivo Web.config del proyecto para ver qu usuarios de la red tienen permitido el acceso a la aplicacin. Los caracteres asterisco (*) e interrogacin (?) tienen un significado especial en la lista de autorizacin: el carcter * significa todos los usuarios; el carcter ? indica usuarios no autorizados. Por ejemplo, la siguiente lista de autorizacin en Web.config exige que todos los usuarios estn autenticados:
<authorization> <deny users="?" /> <!-- niega usuario no autenticados --> </authorization>

Para restringir el acceso a usuarios especficos indique sus nombres separados por comas en un elemento <allow>. Cuando ASP.NET comprueba la lista de autorizaciones en Web.config acepta la primera correspondencia 159

MCAD/MCSD

que coincide. Asegrese de terminar la lista de autorizaciones con un elemento <deny> para todos los usuarios no aceptados, por ejemplo:
<authorization> <allow users="Deanna Meyer, Michael Emanuel" /> <!-- Autoriza dos usuarios --> <deny users="*" /> <!-- Niega todos los dems --> </authorization>

La lista de autorizacin anterior solo concede el acceso a dos usuarios, a todos los dems se les deniega. Adems, los dos usuarios autorizados deben tener cuenta con este nombre en el dominio de red.

8.2.3 Autorizacin basada en rol


La autorizacin basada en rol permite identificar grupos de usuarios para permitir o denegar el acceso segn su rol en la organizacin. En Windows NT y XP los roles corresponden con nombres usados para identificar grupos de usuarios. Windows define varios grupos incorporados, como son Administradores, Usuarios e Invitados. Puede ver, modificar o aadir grupos usando la consola de Administracin de equipos. Para permitir o denegar el acceso a ciertos grupos de usuarios aada el elemento <roles> a la lista de autorizacin del archivo Web.config de la aplicacin Web. Por ejemplo, la siguiente lista de autorizacin solo concede acceso a los usuarios conectados como administradores de red:
<authorization> <allow roles="Administradores" /> <!-- Permite a Administradores. --> <deny users="*" /> <!-- Niega todos los dems. --> </authorization>

8.2.4 Obtener la identidad del usuario


Una vez que un usuario est autenticado y autorizado la aplicacin puede obtener informacin sobre l usando la propiedad Identity del objeto User. La propiedad Identity devuelve un objeto que incluye informacin de nombre y rol del usuario, como muestra el siguiente cdigo: Visual Basic .NET
Private Sub Page_Load(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles MyBase.Load spnAuthenticated.InnerText = User.Identity.IsAuthenticated spnUserName.InnerText = User.Identity.Name spnAuthenticationType.InnerText = User.Identity.AuthenticationType End Sub

Visual C#
private void Page_Load(object sender, System.EventArgs e){ spnAuthenticated.InnerText = User.Identity.IsAuthenticated.ToString(); spnUserName.InnerText = User.Identity.Name; spnAuthenticationType.InnerText = User.Identity.AuthenticationType; }

Adems, el objeto User proporciona el mtodo IsInRole para determinar el rol del usuario actual: Visual Basic .NET
If User.IsInRole("Administradores") Then Hace algo End If

Visual C#
if(User.IsInRole("Administradores")) // Hace algo.

Estos mtodos y propiedades se pueden usar junto con el suceso AuthorizeRequest del mdulo Global para personalizar el proceso de autorizacin del usuario. Por ejemplo, puede usar este mtodo par comprobar el nombre del usuario en un archivo de usuarios en lugar de usar la lista de Web.config.

8.2.5 Configuracin de IIS y autenticacin Windows


La configuracin de autorizacin de Web.config se solapa con las opciones disponibles en IIS. Si se configura la autorizacin tanto en Web.config como en IIS, se evala primero la configuracin de IIS y despus la de Web.config. Por lo general, esto significa que se aplica la opcin ms restrictiva. Para ver la configuracin de autorizacin en IIS siga estos pasos: 1. En la consola de IIS, pulse con el botn derecho sobre la carpeta de la aplicacin Web y seleccione Propiedades. IIS muestra el dilogo de propiedades de la aplicacin.

160

Developing Web Applications

2. Pulse la lengeta Seguridad de directorios y el botn Modificar en el grupo Control de autenticacin y acceso annimo. IIS muestra el dilogo Mtodos de autenticacin El botn Modificar del primer grupo de opciones controla el acceso annimo por usuarios no autenticados. Quitar la marca es equivalente a especificar <deny users=?> en Web.config. Est muy recomendado permitir que IIS controle la contrasea para la cuenta annima, pero puede ser necesario no hacerlo si la aplicacin est distribuida entre varios servidores. Las marcas del segundo grupo del dilogo permiten que la aplicacin use la autenticacin Bsica o Implcita adems de la autenticacin Windows. Estos mtodos proporcionan menos seguridad que la autenticacin Windows, de formularios o Passport y se implementan mediante IIS en lugar de ASP.NET. Puede activar varios mtodos de autenticacin por medio de IIS. Si se activan varios mtodos, puede detectar el que se ha utilizado usando el mtodo AuthenticationType del objeto Identity. Para ms informacin sobre los modos de autenticacin Bsico e Implcito consulte la ayuda de IIS.

8.3 Autenticacin por formularios


La autenticacin por formularios muestra automticamente un formulario Web designado para recoger informacin de nombre de usuario y contrasea. El cdigo asociado con este formulario autentica y autoriza a los usuarios en base a listas de usuarios guardadas en el archivo Web.config de la aplicacin o en una base de datos de usuarios separada. La ventaja de la autenticacin por formularios es que los usuarios no tienen que ser miembros de una red basada en dominio para tener acceso a la aplicacin. Otra ventaja es que muchas aplicaciones Web en concreto sitios comerciales en que los usuarios piden productos quieren tener acceso a la informacin del usuario. La autenticacin por formularios hace que estos tipos de aplicaciones sean ms fciles de crear.

8.3.1 Activar la autenticacin por formularios


La autenticacin por formularios permite crear su propia base de datos de usuarios y validar la identidad de estos usuarios cuando visitan el sitio Web. Para usar la autenticacin por formularios para identificar y autorizar usuarios siga estos pasos: 1. 2. 3. 4. 5. En Web.config establezca el modo de autenticacin como Forms. Cree un formulario Web para recoger la informacin de conexin Cree un archivo o base de datos para almacenar los nombres de usuario y contraseas Escriba cdigo para agregar nuevos usuarios al archivo o base de datos de usuarios Escriba cdigo para autenticar a los usuarios contra el archivo o base de datos de usuarios.

Cuando alguien accede a una aplicacin Web que usa autenticacin por formularios ASP.NET muestra el formulario de conexin especificado en Web.config. Una vez que un usuario est autorizado ASP.NET emite un certificado de autorizacin en forma de cookie que persiste el tiempo especificado en la configuracin de autenticacin en Web.config. La diferencia entre la autenticacin integrada de Windows y la autenticacin por formularios es que en la segunda la aplicacin realiza todas las tareas de autenticacin y autorizacin. El programador debe crear formularios Web y cdigo para recoger los nombres de usuario y contraseas y comprobarlos contra una lista de usuarios autorizados. La autenticacin por formularios usa las clases que se encuentran en el espacio de nombres System.Web.Security. Para usar estas clases en el cdigo debe aadir la sentencia Imports o using al comienzo de cada mdulo que realice autenticacin. Las siguientes secciones describen cmo implementar la autenticacin por formularios en la aplicacin siguiente los pasos generales indicados anteriormente en esta seccin.

8.3.2 Establecer el modo de autenticacin por formulario


El modo de autenticacin de una aplicacin se establece en el elemento <authorization> del archivo Web.config. Para que la aplicacin utilice autenticacin por formulario haga los siguientes cambios:
<authentication mode="Forms" > <!-- Establece el modo de autenticacin --> <forms loginUrl="LogIn.aspx" ><!-- Especifica un formulario de conexin --> <credentials passwordFormat="Clear"> <!-- Crea una lista de usuarios --> <user name="June" password="JuneBug"/> <user name="Walter" password="Halifax"/> </credentials> </forms> </authentication>

161

MCAD/MCSD

<authorization> <deny users="?" /> <!-- niega a todos los usuarios no autenticados --> </authorization>

El anterior fragmento de Web.config muestra un ejemplo simplificado de autenticacin por formularios que usa la mayor parte de las opciones predeterminadas e incluye una lista de usuarios. La tabla 8-2 indica todos los posibles atributos para los elementos que componen las opciones de configuracin de autenticacin por formularios:
Tabla 8. 2: Opciones de configuracin de autenticacin por formulario en Web.config
Elemento <authentication> <forms> Atributo Descripcin Use el valor Forms para establecer la autenticacin por formulario. Establece el nombre de la cookie en que se almacena la credencial del usuario. El valor predeterminado es .authaspx. Si hay en el servidor ms de una aplicacin que use esta forma de autenticacin deber especificar un nombre diferente para cada una. Establece el nombre del formulario Web que se muestra si el usuario no ha sido autenticado. Si se omite, el predeterminado es Default.aspx. Establece cmo protege ASP.NET la cookie de autorizacin almacenada en la mquina del usuario. El predeterminado es All, que encripta y valida los datos. Otros valores posibles son Encryption, Validation y None Establece el tiempo en minutos que persiste la cookie de autorizacin. El valor predeterminado es 30. ASP.NET renueva la cookie automticamente si recibe una peticin del usuario y ha pasado ms de la mitad del tiempo asignado. Establece la ruta donde se almacena la cookie en la mquina del usuario. El predeterminado es una barra invertida (\) Establece el algoritmo que se utiliza para encriptar la contrasea de usuario. El predeterminado es SHA1. Otros posibles valores son MD5 y Clear, que anula la encriptacin. Indica el nombre de un usuario Establece la contrasea del usuario.

mode name loginUrl protection timeout path

<credentials> <users>

passwordFormat name password

El elemento <credentials> permite almacenar la lista de usuarios en el archivo Web.config. Esto es cmodo para autenticacin sencilla, en la que un administrador aade nuevos usuarios y establece sus contrasear, pero no es la mejor aproximacin si quiere que los usuarios configuren sus propias cuentas o mantengan sus contraseas. En estos casos querr crear un archivo o base de datos de usuarios para almacenar los nombres de usuario y sus contraseas encriptadas. Usar una base de datos tiene la ventaja aadida de que permite almacenar todo tipo de informacin adicional sobre el usuario, como informacin de envo e historial de pedidos. La siguiente seccin muestra como autenticar usuarios usando credenciales almacenadas en Web.config. Las secciones posteriores muestran el mtodo ms avanzado (y ms complicado) de usar una base de datos.

8.3.3 Crear un formulario Web de conexin


Para autenticar a los usuarios mediante autenticacin por formularios necesita crear un formulario Web que permita que los usuarios se conecten. Este formulario se identifica mediante el nombre indicado en el elemento <forms> en Web.config. El formulario de conexin puede ser tan sencillo como un par de cajas de texto y un botn, o puede aparecer dentro de otra pgina con contenido no seguro. Cuando el usuario pulsa el botn correspondiente la aplicacin autentica su nombre de usuario y contrasea, emite un certificado de autenticacin y permite el acceso al resto de la aplicacin, como muestra el cdigo siguiente. Visual Basic .NET
' Incluya esta lnea al comienzo del mdulo. Imports System.Web.Security Private Sub butSignOn_Click(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles butSignOn.Click ' Autentica nombre/contrasea en <credentials>. If FormsAuthentication.Authenticate(txtUserName.Text, txtPassword.Text) Then ' Si lo encuentra va a la pgina de inicio. FormsAuthentication.RedirectFromLoginPage(txtUserName.Text, True) Else ' Si no, elimina la contrasea. txtPassword.Text = "" ' Si es el tercer intento, muestra la pgina de acceso denegado. If CInt(ViewState("Tries")) > 1 Then Response.Redirect("Denied.htm") Else ' Si no, incrementa el nmero de intentos. ViewState("Tries") = CInt(ViewState("Tries")) + 1 End If End If End Sub

162

Developing Web Applications

Visual C#
// Incluya esta lnea al comienzo del mdulo. using System.Web.Security; private void butSignOn_Click(object sender, System.EventArgs e){ // Autentica nombre/contrasea en <credentials>. if (FormsAuthentication.Authenticate(txtUserName.Text, txtPassword.Text)) // Si lo encuentra va a la pgina de inicio. FormsAuthentication.RedirectFromLoginPage(txtUserName.Text, true); else{ // Si no, elimina la contrasea. txtPassword.Text = ""; // Si es el tercer intento, muestra la pgina de acceso denegado. if (System.Convert.ToInt32(ViewState["Tries"]) > 1) Response.Redirect("Denied.htm"); else // Si no, incrementa el nmero de intentos. ViewState["Tries"] = System.Convert.ToInt32(ViewState["Tries"]) + 1; } }

Hay algunas cuestiones importantes acerca del cdigo anterior. La clase FormsAuthentication es parte del espacio de nombres System.Web.Security, de modo que debe incluir o importar el espacio de nombres o calificar completamente las referencias a la clase. El mtodo Autentcate de la clase FormsAuthentication comprueba el nombre de usuario y la contrasea contra la lista de usuarios del elemento <credentials> de Web.config. El mtodo RedirectFromLoginPage de la clase FormsAuthentication muestra la pgina de inicio de la aplicacin. Si los campos de peticin de datos estn en la pgina de inicio de la aplicacin deber desactivarlos o indicar de alguna otra forma que la conexiona tenido xito. Si el nombre de usuario y la contrasea no son vlidos el cdigo permite al usuario dos intentos ms antes de mostrar una pgina de acceso denegado. Esta es una pgina HTML en lugar de un formulario Web, ya que se denegar el acceso a todos los formularios Web de la aplicacin. Si redirige al usuario a otra pgina de esta forma asegrese de que est fuera del alcance de la aplicacin. Use la clase FormsAuthentication para desconectar cuando el usuario termine con la aplicacin o cuando quiera eliminar la cookie de autenticacin de su mquina. Por ejemplo, el siguiente cdigo termina el acceso del usuario a la aplicacin y exige que vuelva a conectarse para obtener acceso de nuevo. Visual Basic .NET
Imports System.Web.Security Private Sub butSignOut_Click(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles butSignOut.Click ' Elimina la cookie de autenticacin. FormsAuthentication.SignOut() ' Vuelve a la misma pgina. Response.Redirect("UserInfo.aspx") End Sub

Visual C#
using System.Web.Security; private void butSignOut_Click(object sender, System.EventArgs e){ // Elimina la cookie de autenticacin. FormsAuthentication.SignOut(); // Redirect Vuelve a la misma pgina. Response.Redirect("UserInfo.aspx"); }

8.3.4 Autenticar usuarios con una base de datos


Las secciones anteriores mostraron cmo autenticar a los usuarios en base a una lista en Web.config. El mtodo Autentcate de la clase FormsAuthentication est preparado para leer automticamente de este archivo. Esto es adecuado si los nombres y contraseas los crea y mantiene un administrador de sistema, pero si permite que los usuarios creen sus propios nombres de usuario o cambien sus contraseas necesitar almacenar esta informacin fuera de Web.config. Esto se debe a que los cambios en este archivo en tiempo de ejecucin provocan el reinicio de la aplicacin, lo que reinicia todas las variables de estado de aplicacin y de sesin utilizadas. Puede almacenar los nombres de usuario y contraseas en cualquier tipo de archivo; sin embargo el uso de una base de datos tiene las siguientes ventajas. 163

MCAD/MCSD

Los nombres de usuario se pueden usar como clave primaria para almacenar informacin sobre el usuario. Las bases de datos pueden proporcionar altas prestaciones para el acceso a los nombres de usuario y contraseas. El aadido, modificacin y acceso estn estandarizados mediante SQL. Cuando almacena nombres de usuario y contraseas en una base de datos tiene la opcin de encriptarlos usando el mtodo HashPasswordForStoringInConfigFile. Este mtodo utiliza los algoritmos SHA1 o MD5, y se mostrar en el ejemplo del apartado siguiente, dentro de la funcin auxiliar AddUser. Las siguientes secciones muestran cmo aadir nuevos nombres de usuario y contraseas a una base de datos sencilla y cmo usar la base de datos para autenticar a los usuarios.

8.3.5 Aadir usuarios a una base de datos


Para aadir usuarios a una base de datos recoja su nombre y contrasea en dos TextBox y proporcione un procedimiento de suceso para aadir el usuario que muestre un mensaje indicando si ha tenido xito. El siguiente procedimiento de suceso utiliza la funcin auxiliar AddUser para aadir el nombre de usuario y contrasea a la base de datos. Visual Basic .NET
Private Sub butNewUser_Click(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles butNewUser.Click If AddUser(txtUserName.Text, txtPassword.Text) Then spnNote.InnerText = "Aadido usuario." Else spnNote.InnerText = "Nombre de usuario en uso. Elija uno diferente." End If End Sub

Visual C#
private void butNewUser_Click(object sender, System.EventArgs e){ if (AddUser(txtUserName.Text, txtPassword.Text)) spnNote.InnerText = " Aadido usuario."; else spnNote.InnerText = " Nombre de usuario en uso. Elija uno diferente."; }

La funcin auxiliar AddUser que se muestra a continuacin encripta la contrasea antes de insertarla junto con el nombre de usuario en la base de datos usando la sentencia INSERT de SQL. Si el nombre de usuario ya existe en la base de datos el bloque de control de excepciones captura el error y devuelve False para indicar que no se ha aadido al usuario. Visual Basic .NET
Private Function AddUser(ByVal UserName As String, ByVal Password As String) _ As Boolean ' Declara la variable para registrar xito o fracaso. Dim bSuccess As Boolean ' Encripta la contrasea. Password = FormsAuthentication.HashPasswordForStoringInConfigFile _ (Password, "SHA1") ' Crea el comando para insertar el nombre de usuario y la contrasea. Dim oleCommand As New OleDbCommand("INSERT INTO Users" + _ " VALUES('" + UserName + "', '" + Password + "')", oledbUsers) ' Captura los errores si existe el registro. Try oledbUsers.Open() ' Abre la conexin. ' Si se aade el registro, indica xito. If oleCommand.ExecuteNonQuery() Then bSuccess = True oledbUsers.Close() ' Cierra la conexin. Catch bSuccess = False ' Si no, indica fracaso. oledbUsers.Close() ' Cierra la conexin. End Try ' Devuelve el estado de xito/fracaso. Return bSuccess End Function

164

Developing Web Applications

Visual C#
private bool AddUser(string UserName, string Password){ // Declara la variable para registrar xito o fracaso. bool bSuccess = false; // Encripta la contrasea. Password = FormsAuthentication.HashPasswordForStoringInConfigFile (Password "SHA1"); // Crea el comando para insertar el nombre de usuario y la contrasea. OleDbCommand oleCommand = new OleDbCommand("INSERT INTO Users" + " VALUES('" + UserName + "', '" + Password + "')", oledbUsers); // Captura los errores si existe el registro. try{ oledbUsers.Open(); // Abre la conexin. if (oleCommand.ExecuteNonQuery() != 0){ // Si se aade, indica xito. bSuccess = true; oledbUsers.Close(); // Cierra la conexin. } }catch{ bSuccess = false; // Si no, indica fracaso. oledbUsers.Close(); // Cierra la conexin. } return bSuccess; // Devuelve xito/fracaso. }

8.3.6 Autenticar usuarios contra una base de datos


Cuando se autentican usuarios contra Web.config se usa el mtodo Autentcate. Cuando se autentican usuarios contra una base de datos se debe escribir el cdigo para localizar y comparar nombres de usuario y contraseas. El siguiente procedimiento de suceso utiliza la funcin auxiliar CheckPassword para validar el nombre de usuario y contrasea antes de autenticar al usuario y permitir el acceso a la aplicacin. Visual Basic .NET
Private Sub butSignOn_Click(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles butSignOn.Click ' Si encuentra el nombre y contrasea, autoriza el usuario ' y muestra la pgina de inicio. If CheckPassword(txtUserName.Text, txtPassword.Text) Then FormsAuthentication.RedirectFromLoginPage(txtUserName.Text, True) Else ' Muestra mensaje. spnNote.InnerText = _ "Nombre de usuario o contrasea incorrectos. Pruebe de nuevo." ' Permite tres intentos. ViewState("tries") = ViewState("tries") + 1 If ViewState("tries") > 3 Then Response.Redirect("Denied.htm") End If End If End Sub

Visual C#
private void butSignOn_Click(object sender, System.EventArgs e){ // Comprueba el nombre de usuario y contrasea. if (CheckPassword(txtUserName.Text, txtPassword.Text)) // Si los encuentra, muestra la pgina de inicio. FormsAuthentication.RedirectFromLoginPage(txtUserName.Text, true); else{ // Si no, limpia la contrasea. txtPassword.Text = ""; // Muestra el mensaje. spnNote.InnerText = "Nombre de usuario o contrasea incorrectos. Pruebe de nuevo."; // Si es el tercer intento muestra la pgina de denegacin de acceso. if (System.Convert.ToInt32(ViewState["Tries"]) > 1) Response.Redirect("Denied.htm");

165

MCAD/MCSD

} }

else{ // Si no, incrementa el nmero de intentos. ViewState["Tries"] = System.Convert.ToInt32(ViewState["Tries"]) + 1; if (System.Convert.ToInt32(ViewState["Tries"]) > 3) Response.Redirect("Denied.htm"); }

La funcin auxiliar CheckPassword que se muestra a continuacin encripta la contrasea, encuentra el registro correspondiente al nombre de usuario y compara la contrasea encriptada con la que hay en la base de datos. El acceso a la base de datos se realiza en un bloque de control de excepciones para impedir que conflictos de bloqueo provoquen un mensaje al usuario. Visual Basic .NET
Private Function CheckPassword(ByVal UserName As String, _ ByVal Password As String) As Boolean ' Declara la variable para indicar xito/error. Dim bSuccess As Boolean ' Encripta la contrasea. Password = _ FormsAuthentication.HashPasswordForStoringInConfigFile(Password, "SHA1") ' Crea un comando para obtener la fila de la tabla de usuarios. Dim oleCommand As New OleDbCommand("SELECT * FROM Users" + _ " WHERE UserName='" + txtUserName.Text + "'", oledbUsers) ' Comprueba errores al usar la base de datos. Try oledbUsers.Open() ' Abre la conexin. ' Lee el registro del usuario. Dim rdrUsers As OleDbDataReader = oleCommand.ExecuteReader() While rdrUsers.Read() If Password = rdrUsers.Item("Password") Then bSuccess = True End While oledbUsers.Close() ' Cierra la conexin. Catch bSuccess = False ' Si no, indica fallo. oledbUsers.Close() ' Cierra la conexin. End Try Return bSuccess End Function

Visual C#
private bool CheckPassword(string UserName, string Password){ // Declara la variable para indicar xito/error. bool bSuccess = false; // Encripta la contrasea. Password = FormsAuthentication.HashPasswordForStoringInConfigFile(Password, "SHA1"); // Crea un comando para obtener la fila de la tabla de usuarios. OleDbCommand oleCommand = new OleDbCommand("SELECT * FROM Users" + " WHERE UserName='" + txtUserName.Text + "'", oledbUsers); // Comprueba errores al usar la base de datos try{ oledbUsers.Open(); // Abre la conexin. // Lee el registro del usuario. OleDbDataReader rdrUsers = oleCommand.ExecuteReader(); while (rdrUsers.Read()) if (Password == rdrUsers["Password"].ToString()) bSuccess = true; oledbUsers.Close(); // Cierra la conexin. }catch{ bSuccess = false; // Si falla indica error. oledbUsers.Close(); // Cierra la conexin. } return bSuccess; }

8.4 Autenticacin Passport


La autenticacin Passport identifica a los usuarios mediante el servicio de conexin nica Microsoft Passport. Passport est pensado para proporcionar a los usuarios de Internet una identidad nica que puede usar para visitar una gran variedad de sitios Web que precisan autenticacin. La informacin sobre el usuario est disponible para la aplicacin mediante un perfil almacenado por Microsoft. 166

Developing Web Applications

La ventaja de la autorizacin Passport es que el usuario no tiene que recordar nombres de usuario y contraseas diferentes para varios sitios Web, y que el usuario puede mantener su perfil en un nico lugar. La autenticacin Passport proporciona acceso a otros servicios de Microsoft.

8.4.1 Activar la autenticacin Passport


La autenticacin Passport utiliza el proveedor de autenticacin centralizado de Microsoft para identificar a los usuarios. Passport proporciona una forma para que los usuarios usen una sola identidad en varias aplicaciones Web. Para usar la autenticacin Passport en su aplicacin Web debe instalar el SDK de Passport, que est disponible en el rea de descargas de MSDN en http://msdn.microsoft.com/downloads. El SDK de Passport es gratuito para desarrollo y pruebas. Para colocar un sitio para uso pblico debe obtener una licencia anual de Microsoft. Puede encontrar ms informacin sobre licencias en http://www.microsoft.com /myservices/passport. Cuando un usuario accede a una aplicacin que implementa autenticacin Passport ASP.NET comprueba si existe una cookie de autorizacin Passport en la mquina. Si no la encuentra, dirige al usuario a una pgina de registro Passport. Una vez que el usuario se registra el servicio Passport lo autentica, guarda la cookie de autenticacin en el ordenador del usuario y lo devuelve a la pgina que solicit originalmente. Para usar autenticacin Passport siga estos pasos. 1. Instale el SDK de Passport. Passport no est incluido con Visual Studio, aunque el marco de trabajo .NET incluye clases para trabajar con l una vez instalado. 2. Establezca Passport como modo de autenticacin en Web.config. Deniegue la autorizacin para usuarios no autenticados. 3. Use el suceso PassportAuthentication_OnAuthenticate para acceder al perfil Passport del usuario para identificarlo y autorizarlo. 4. Implemente un procedimiento de desconexin para borrar las cookies Passport de la mquina del usuario. Por ejemplo, el siguiente Web.config activa la autenticacin Passport y exige que todos los usuarios estn autenticados.
<authentication mode="Passport" /> <authorization> <deny users="?" /> <! -- Niega usuarios no autenticados --> </authorization>

Cuando se ejecuta la aplicacin localmente con esta configuracin automticamente se le redirige a la pgina de entrada de Passport. Si tiene instalada la versin limitada (sin licencia) del SDK Passport la pgina no es la misma que la que se muestra para un sitio desplegado. Una vez que el usuario se ha registrado Passport guarda una cookie de autorizacin en su mquina y redirige al usuario de vuelta a la pgina que pidi originalmente. Passport almacena un perfil de informacin sobre la persona. Puede acceder a este perfil desde el suceso PassportAuthentication_OnAuthenticate en el mdulo Global.asax, como se muestra a continuacin: Visual Basic .NET
' Aadir al comienzo del mdulo. Imports System.Web.Security Private Sub PassportAuthentication_OnAuthenticate(ByVal sender As Object, _ ByVal e As PassportAuthenticationEventArgs) ' Obtiene la identidad de sesin Passport si est autenticado. If e.Identity.IsAuthenticated Then Response.Write("Nombre: " & e.Identity.Item("FirstName") & _ " " & e.Identity.Item("LastName") & "<br>") Response.Write("Direccin: " & e.Identity.Item("City") & _ " " & e.Identity.Item("PostalCode") & "<br>") Response.Write("Email: " & e.Identity.Item("PreferredEmail") & "<br>") Response.Write("Passport ID: " & e.Identity.Name & "<br>") End If End Sub

Visual C#
// Aadir al comienzo del mdulo using System.Web.Security;

167

MCAD/MCSD

protected void PassportAuthentication_OnAuthenticate(Object sender, PassportAuthenticationEventArgs e){ // Obtiene la identidad de sesin Passport si est autenticado. if (e.Identity.IsAuthenticated) { Response.Write("Name: " + e.Identity["FirstName"] + " " + e.Identity["LastName"] + "<br>"); Response.Write("Address: " + e.Identity["City"] + " " + e.Identity["PostalCode"] + "<br>"); Response.Write("Email: " + e.Identity["PreferredEmail"] + "<br>"); Response.Write("Passport ID: " + e.Identity.Name + "<br>"); } }

Este cdigo muestra el nombre del usuario, su localizacin e informacin de identidad de su perfil Passport. Si ha instalado el SDK Passport limitado la informacin refleja una cuenta de pruebas en lugar de datos reales. La informacin de autorizacin y perfil de Passport se guarda en cinco cookies diferentes en la mquina del usuario. El SDK de Passport exige que se eliminen estas cookies cuando el usuario abandona la aplicacin. El siguiente procedimiento de suceso muestra cmo desconectar borrando las cookies Passport. Visual Basic .NET
Private Sub butSignOut_Click(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles butSignOut.Click ' Desconecta borrando las cookies Passport. Response.Cookies("MSPProf").Expires = Now Response.Cookies("MSPAuth").Expires = Now Response.Cookies("MSPSecAuth").Expires = Now Response.Cookies("MSPProfC").Expires = Now Response.Cookies("MSPConsent").Expires = Now ' Vuelve a mostrar la pgina (vuelve a registro). Response.Redirect("UserInfo.aspx") End Sub

Visual C#
private void butSignOut_Click(object sender, System.EventArgs e){ // Desconecta borrando las cookies Passport. Response.Cookies["MSPProf"].Expires = DateTime.Now; Response.Cookies["MSPAuth"].Expires = DateTime.Now; Response.Cookies["MSPSecAuth"].Expires = DateTime.Now; Response.Cookies["MSPProfC"].Expires = DateTime.Now; Response.Cookies["MSPConsent"].Expires = DateTime.Now; // Vuelve a mostrar la pgina (vuelve a registro). Response.Redirect("UserInfo.aspx"); }

La autenticacin Passport tambin proporciona caractersticas comerciales y de proteccin de menores adicionales que se explican en el SDK.

8.5 Proporcionar comunicaciones seguras


Hasta ahora hemos tratado la seguridad como un asunto de identificar usuarios e impedir que usuarios no autorizados accedan a las aplicaciones Web, pero igualmente importante es asegurar que los datos sensibles enviados a travs de la red no son ledos por otros. Para proporcionar comunicaciones seguras en Internet IIS soporta un medio estandarizado de encriptado y desencriptado de peticiones y respuestas Web. Esta criptografa precisa de una clave de encriptado denominada certificado de servidor de un tercero independiente llamado Autoridad de Certificacin.

8.5.1 Activar la comunicacin segura


La capa de comunicaciones seguras (Secure Socket Layer, SSL) es el medio estndar para asegurar que los datos enviados sobre Internet no pueden ser ledos por otros. Cuando un usuario solicita una pgina Web segura el servidor genera una clave de encriptado para la sesin de usuario y encripta los datos de la pgina antes de enviar una respuesta. En el lado cliente, el navegador usa la misma clave para desencriptar la respuesta y para encriptar nuevas peticiones enviadas a la pgina. El uso de SSL en su aplicacin precisa una autorizacin especial de una Autoridad de Certificacin reconocida. Esta autorizacin tiene la forma de un certificado de servidor que se instala en IIS para identificar el servidor. La Autoridad de Certificacin licencia certificados de servidor (por una tarifa) y acta como punto en el que verificar la identidad de su servidor en Internet. Cuando uniusuario inicia una comunicacin segura solicita el certificado de servidor y lo comprueba contra una lista de sitios de confianza que proporciona la Autoridad de Certificacin. Si el certificado de servidor no co168

Developing Web Applications

rresponde con alguno de los sitios ya autorizados por el usuario, o si no corresponde a la direccin Web para la que se registr, o si hay algn otro problema con l, el navegador muestra un aviso. De esta forma la Autoridad de Certificacin no solo proporciona encriptado para transmisin de datos segura, sino que tambin proporciona a los usuarios la seguridad de que el sitio Web es autntico. La mayor Autoridad de Certificacin es VeriSign Inc. En el momento de escribir el libro, adems de sus servicios de pago ofreca certificados de prueba gratuitos para evaluacin en http://www.verisign.com. Para usar SSL en su aplicacin Web siga estos pasos: 1. 2. 3. 4. 5. Genere una peticin de certificado desde IIS Solicite un certificado a una Autoridad de Certificacin Instale el certificado en el servidor usando IIS Instale el certificado en navegadores si est usando un certificado de prueba Use el protocolo seguro (https:) cuando acceda a las pginas seguras de la aplicacin. Las siguientes secciones describen estos pasos con mayor detalle.

8.5.2 Generar una peticin de certificado


Antes de poder solicitar un certificado a una Autoridad de Certificacin debe generar una peticin de certificado desde IIS. La peticin de certificado contiene informacin encriptada sobre el servidor que la Autoridad de Certificacin utiliza para identificar el servidor en Internet. 1. Seleccione Sitio Web predeterminado en la lista de carpetas en el lado izquierdo de la ventana de IIS y seleccione Propiedades en el men Accin. IIS muestra el dilogo de Propiedades de Sitio Web predeterminado. 2. Pulse la lengeta Seguridad de directorios, y el botn Certificado de servidor. IIS inicia el asistente de certificado de servidor Web. 3. Siga los pasos del servidor pulsando Siguiente en cada pantalla. Las instrucciones del servidor son directas. 4. Cuando termine, el asistente crea un archivo de texto encriptado con la extensin .cer. Este archivo es la peticin de certificado que se enva a la Autoridad de Certificacin. IIS exige que se cree el certificado a nivel raz del servidor antes de que se puedan crear o configurar comunicaciones seguras para sitios subordinados del servidor. Por este motivo se selecciona el sitio Web predeterminado (o el sitio Web raz si lo ha renombrado) en el paso 1. Despus de instalar un certificado de servidor en la raz puede repetir el proceso para sitios subordinados si quiere certificados separados para ellos.

8.5.3 Solicitar un certificado


El proceso de solicitar un certificado de servidor a una Autoridad de Certificacin vara dependiendo de la Autoridad de Certificacin que se seleccione. Como se mencion anteriormente VeriSign proporciona certificados de prueba gratuitos, lo que cuadra muy bien con los objetivos de este libro. Para solicitar un certificado de servidor siga estos pasos. 1. Visite el sitio Web de la Autoridad de Certificacin y solicite un certificado de servidor para SSL. Los diferentes niveles de seguridad y soporte normalmente se basan en una tarifa anual. 2. Seleccione el tipo de certificado de servidor que quiere solicitar y complete la informacin de registro de la peticin. 3. Copie o enve por correo electrnico la peticin de certificado creada en la seccin anterior a la Autoridad de Certificacin. Una vez aprobada la peticin, la autoridad de certificacin le enviar el certificado de servidor como parte de un mensaje de correo electrnico. Guarde el certificado como archivo de texto con la extensin .cer cortando y pegando en el Block de Notas u otro editor.

8.5.4 Instalar el certificado


Despus de grabar el certificado de servidor puede instalarlo en IIS para activar SSL para sus aplicaciones Web. Siga estos pasos: 1. Seleccione el sitio Web predeterminado en la lista de carpetas a la izquierda de la ventana de IIS y seleccione Propiedades en el men Accin. IIS muestra el dilogo de propiedades del sitio Web predeterminado. 2. Pulse en la lengeta Seguridad de Directorios y en el botn Certificado de Servidor. IIS inicia el Asistente de certificados de servidor. 3. Pulse Siguiente y seleccione Procesar la peticin pendiente e instalar el certificado. 4. Pulse Siguiente y escriba el nombre del archivo de certificado creado en la seccin anterior. 5. Pulse Siguiente y despus Finalizar para completar la instalacin.

169

MCAD/MCSD

8.5.5 Usar comunicaciones seguras


Despus de instalar el certificado de servidor las comunicaciones seguras estn activadas para cualquier pgina solicitada mediante el protocolo seguro de transferencia de hipertexto (https). El protocolo https: es el que inicia la comunicacin segura. Cuando se ha comenzado una comunicacin segura, esta contina hasta que se especifica un sitio no seguro. Para terminar una comunicacin segura hay que indicar el protocolo http, no basta con utilizar una direccin relativa. IIS permite que se exija comunicacin segura para carpetas o archivos especficos en la aplicacin Web. Esto impide que los usuarios vean accidentalmente (o intencionadamente) una pgina segura usando el protocolo http: no seguro. Para exigir comunicacin segura para una pgina Web usando IIS siga estos pasos: 1. Seleccione la carpeta o archivo que exige comunicacin segura y Propiedades en el men Accin. IIS muestra el dilogo de Propiedades del archivo o carpeta. 2. Pulse la lengeta Seguridad de archivo o Seguridad de directorio y el botn Modificar en el grupo Comunicaciones seguras. IIS muestra el dilogo Comunicaciones seguras. 3. Seleccione Exigir canal seguro (IIS) y pulse Aceptar. Cuando se exige comunicacin segura para una pgina Web la pgina no se puede ver mediante el protocolo http:. El usuario debe escribir el protocolo https: o pulsar en un enlace que lo incluya; en caso contrario se deniega el acceso. Como la diferencia entre http y https est poco clara para que la recuerden los usuarios es importante proporcionar un punto de entrada http para la aplicacin que dirija a las pginas seguras https. El punto de entrada http puede ser simplemente una pgina predeterminada que automticamente redirija al usuario al sitio seguro. La exigencia de comunicacin segura para un sitio web completo es una forma rpida de reducir el trfico a cero.

8.6 Resumen
La autenticacin es el proceso de identificar a los usuarios. La autorizacin es el proceso de autorizar el acceso a estos usuarios. El mtodo predeterminado de acceso a la aplicacin Web es el acceso annimo. Los usuarios annimos obtienen acceso mediante la cuenta de usuario Windows IUSR_nombremaquina. ASP.NET proporciona tres modos de autenticacin diferentes mediante el espacio de nombres System.Web.Security: Windows, Forms y Passport Las pginas HTML no se incluyen automticamente en la autenticacin ASP.NET. Para asegurar que los usuarios se autentican antes de poder ver este tipo de archivos use IIS para hacer corresponder las extensiones de archivo .htm y .html con el ejecutable ASP.NET. Para exigir la autenticacin aada el elemento <deny users=?> en la seccin de autorizacin de Web.config. Esto se aplica a los tres modos de autenticacin. Use el elemento <authorization> para permitir o denegar el acceso a los usuarios bajo autenticacin Windows. Use el elemento <credentials> o una base de datos externa para permite a los usuarios bajo autenticacin de formularios. Al cambiar el archivo Web.config se reinicia la aplicacin Web, por lo que no es buena idea aadir usuarios al elemento <credentials> en tiempo de ejecucin. Utilice en su lugar un archivo o base de datos externos para almacenar los nombres de usuario y las contraseas. Instale el SDK de Passport para activar las clases Passport en el espacio de nombres System.Web.Security. Para activar comunicaciones seguras, encriptadas, en Internet instale un certificado de servidor y utilice el protocolo https.

8.7 Prctica: Crear una aplicacin segura


En esta prctica va a crear una aplicacin sencilla que usa autenticacin por formularios para identificar y autorizar usuarios. La aplicacin permite que los nuevos usuarios aadan su nombre de usuario y contrasea y que los existentes se conecten, y muestra la identidad del usuario una vez que se ha conectado.

8.7.1 Activar la autenticacin por formularios


Para activar la autenticacin por formularios cree una nueva aplicacin ASP.NET y abra el archivo Web.config generado para el proyecto. Haga al elemento <authentication> los cambios siguientes:
<authentication mode="Forms"> <forms loginUrl="LogIn.aspx"> <credentials passwordFormat="SHA1"></credentials> </forms> </authentication>

170

Developing Web Applications

La autenticacin anterior activa la autenticacin por formularios, dirige a los usuarios no autenticados a la pgina LogIn.aspx y activa el encriptado de contraseas mediante el algoritmo SHA1. Para exigir la autenticacin usando esta configuracin aada al archivo Web.config el siguiente elemento <authorization>:
<authorization> <deny users="?" /> <!-- Niega usuarios no autorizados --> </authorization>

La anterior configuracin de autorizacin deniega el acceso a los usuarios no autenticados, forzando la autenticacin. Cuando haya hecho los cambios en Web.config puede crear el formulario Web LogIn.aspx para aadir nuevas cuentas y conectar los usuarios existentes.

8.7.2 Crear el formulario Web LogIn


En este ejercicio crear un formulario Web llamado LogIn.aspx y un archivo de datos llamado Users.xml que se usan para autenticar a los usuarios. Como este es un ejemplo simplificado, LogIn.aspx permite que los usuarios creen una nueva cuenta si no se encuentra su nombre. En el mundo real se dirigira a los usuarios a una formularios Web diferente para crear nuevas cuentas o las creara un administrador que despus enviara la contrasea por correo al usuario. En ambos casos los conceptos son los mismos. Para crear el archivo de datos Users.xml use Visual Studio o un editor de texto para crear un archivo de texto que contenga la lnea:
<users name="" password="" />

El ejemplo usar este archivo como plantilla para guardar los nombres de usuario y contraseas. Como las contraseas estarn encriptadas el primer nombre y contrasea estarn en blanco se puede borrar esta lnea ms adelante, cuando se hayan aadido otros nombres de usuario y contraseas. A continuacin cree el formulario Web LogIn.aspx. Este formulario contiene cajas de texto, validaciones y otros controles, como muestra la siguiente tabla: Tipo de control TextBox RequiredFieldValidator Propiedad ID ID ControlToValidate ErrorMessage ID TextMode ID ControlToValidate ErrorMessage ID Text ID Text Visible ID Valor txtUserName vldUserName txtUserName El nombre es imprescindible txtPassword Password vldPassword txtPassword La contrasea es imprescindible butSignOn Entrar butAddUser Agregar Usuario False lblStatus

TextBox RequiredFieldValidator

Button Button

Label Visual Basic .NET


Imports System.Web.Security

Comience a escribir el cdigo para LogIn.aspx aadiendo la siguiente lnea al inicio del mdulo de cdigo.

Visual C#
using System.Web.Security;

Aada el siguiente cdigo al suceso Click del control butSignOn para comprobar el nombre y contrasea del usuario e indicar al usuario si no se encuentra el nombre. El procedimiento de suceso usa dos funciones auxiliares: UserExists para comprobar si existe el nombre de usuario en Users.xml y PasswordValid para comprobar si la contrasea es vlida.

171

MCAD/MCSD

Visual Basic .NET


Private Sub butSignOn_Click(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles butSignOn.Click ' Comprueba el nombre de usuario. If UserExists(txtUserName.Text) Then ' Comprueba la contrasea (encriptada). If PasswordValid(txtUserName.Text, txtPassword.Text) Then ' Conecta al usuario. FormsAuthentication.RedirectFromLoginPage(txtUserName.Text, True) Else ' Muestra un mensaje de contrasea no vlida. lblStatus.Text = "Contrasea no corresponde. Prueba de nuevo." End If Else ' Si no encuentra el nombre de usuario ofrece aadirlo. lblStatus.Text = "Nombre de usuario no existe. Pulse Agregar para aadirlo ahora." ' Hace visible el botn Aadir. butAddUser.Visible = True End If ' Control de intentos. Session("Tries") = CInt(Session("Tries")) + 1 If Session("Tries") > 2 Then ' Tras el tercer intento niega el acceso. Response.Redirect("Denied.htm") End If End Sub

Visual C#
private void butSignOn_Click(object sender, System.EventArgs e){ // Comprueba el nombre de usuario. if (UserExists(txtUserName.Text)) // Comprueba la contrasea (encriptada). if (PasswordValid(txtUserName.Text, txtPassword.Text)) // Conecta al usuario. FormsAuthentication.RedirectFromLoginPage(txtUserName.Text, true); else // Muestra un mensaje de contrasea no vlida. lblStatus.Text = " Contrasea no corresponde. Prueba de nuevo."; else{ // Si no encuentra el nombre de usuario ofrece aadirlo. lblStatus.Text = " Nombre de usuario no existe. Pulse Agregar para aadirlo ahora."; // Hace visible el botn Aadir. butAddUser.Visible = true; } // Control de intentos. ViewState["Tries"] = System.Convert.ToInt32(ViewState["Tries"]) + 1; if (System.Convert.ToInt32(ViewState["Tries"]) > 3) Response.Redirect("Denied.htm"); }

Las funciones UserExists y PasswordValid cargan el archivo Users.xml en un conjunto de datos y buscan en l un nombre de usuario y contrasea. Si encuentran una correspondencia las funciones devuelven true y en caso contrario false. Visual Basic .NET
Private Function UserExists(ByVal UserName As String) As Boolean ' Crea un conjunto de datos para leer el archivo XML. Dim dsUsers As New DataSet() ' Control de errores por si falta el archivo. Try ' Construye la ruta del archivo Users.xml. Dim strXMLFile As String = Server.MapPath(Request.ApplicationPath) &_ "\Users.xml" ' Lee el archivo. dsUsers.ReadXml(strXMLFile, XmlReadMode.InferSchema)

172

Developing Web Applications

' Para cada fila de la tabla Users. Dim rowUser As DataRow For Each rowUser In dsUsers.Tables("Users").Rows ' Comprueba si el nombre corresponde. If rowUser("name") = UserName Then Return True Exit For End If Next Catch ' En caso de error devuelve False. Return False End Try End Function Private Function PasswordValid(ByVal UserName As String, _ ByVal Password As String) ' Crea un conjunto de datos para leer el archivo XML. Dim dsUsers As New DataSet() ' Usa control de errores por si falta el archivo. Try ' Construye la ruta del archivo Users.xml. Dim strXMLFile As String = Server.MapPath(Request.ApplicationPath) &_ "\Users.xml" ' Lee el archivo. dsUsers.ReadXml(strXMLFile, XmlReadMode.InferSchema) ' Para cada fila de la tabla Users. Dim rowUser As DataRow For Each rowUser In dsUsers.Tables("Users").Rows ' Comprueba si el nombre corresponde. If rowUser("name") = UserName Then If rowUser("password") = FormsAuthentication. _ HashPasswordForStoringInConfigFile (Password, "SHA1") Then Return True Exit For End If End If Next Catch ' En caso de error devuelve false. Return False End Try End Function

Visual C#
private bool UserExists(string UserName){ // Crea un conjunto de datos para leer el archivo XML. DataSet dsUsers = new DataSet(); // Usa control de errores por si falta el archivo. try{ // Construye la ruta del archivo Users.xml. string strXMLFile = Server.MapPath(Request.ApplicationPath) + "\\Users.xml"; // Lee el archivo. dsUsers.ReadXml(strXMLFile, XmlReadMode.InferSchema); // Para cada fila de la tabla Users. foreach (DataRow rowUser in dsUsers.Tables["Users"].Rows) // Comprueba si el nombre corresponde. if (rowUser["name"].ToString() == UserName) return true; }catch // En caso de error devuelve false. return false; // Si ha terminado sin encontrar el nombre, devuelve false return false; } private bool PasswordValid(string UserName, string Password){ // Crea un conjunto de datos para leer el archivo XML. DataSet dsUsers = new DataSet();

173

MCAD/MCSD

// Usa control de errores por si falta el archivo. try{ // Construye la ruta del archivo Users.xml. string strXMLFile = Server.MapPath(Request.ApplicationPath) + "\\Users.xml"; // Lee el archivo. dsUsers.ReadXml(strXMLFile, XmlReadMode.InferSchema); // Para cada fila de la tabla Users. foreach (DataRow rowUser in dsUsers.Tables["Users"].Rows) // Comprueba si el nombre corresponde. if (rowUser["name"].ToString() == UserName) if (rowUser["password"].ToString() == FormsAuthentication. HashPasswordForStoringInConfigFile(Password, "SHA1")) return true; }catch // En caso de error devuelve false. return false; // Si termina sin encontrar correspondencia devuelve false. return false; }

La funcin PasswordValid del cdigo anterior usa el mtodo HashPasswordForStoringInConfigFile porque las contraseas estn guardadas usando encriptado. AddUser tambin usa la misma funcin cuando guarda la contrasea en Users.xml como se muestra a continuacin. Visual Basic .NET
Private Sub butAddUser_Click(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles butAddUser.Click If AddUser(txtUserName.Text, txtPassword.Text) Then ' Muestra xito. lblStatus.Text = "Aadido usuario. Pulse Entrar para continuar." ' Oculta el botn. butAddUser.Visible = False Else ' Muestra fracaso. lblStatus.Text = "No se pudo aadir el usuario. Elija otro nombre." End If End Sub Private Function AddUser(ByVal UserName As String, ByVal Password As String) ' Si el usuario existe, devuelve False y termina. If UserExists(UserName) Then Return False Exit Function End If ' Si no, lo aade al archivo XML. Dim dsUsers As New DataSet() ' Usa control de errores por si no existe el archivo. Try ' Construye la ruta del archivo Users.xml. Dim strXMLFile As String = Server.MapPath(Request.ApplicationPath) & _ "\Users.xml" ' Lee el archivo. dsUsers.ReadXml(strXMLFile, XmlReadMode.InferSchema) ' Crea una nueva fila. Dim rowUser As DataRow = dsUsers.Tables("users").NewRow() ' Establece el nombre de usuario. rowUser("name") = UserName ' Establece la contrasea (encriptada). rowUser("password") = FormsAuthentication. _ HashPasswordForStoringInConfigFile(Password, "SHA1") ' Aade la fila. dsUsers.Tables("users").Rows.Add(rowUser) ' Escribe el conjunto de datos. dsUsers.WriteXml(strXMLFile) Return True Catch ' En caso de error devuelve False. Return False End Try End Function

174

Developing Web Applications

Visual C#
private void butAddUser_Click(object sender, System.EventArgs e){ if (AddUser(txtUserName.Text, txtPassword.Text)) { // Muestra xito. lblStatus.Text = "Usuario aadido. Pulse Entrar para continuar."; // Oculta el botn. butAddUser.Visible = false; }else // Muestra fracaso. lblStatus.Text = "No se pudo aadir el usuario. Elija otro nombre."; } private bool AddUser(string UserName, string Password){ // Si el usuario ya existe, devuelve False y sale. if (UserExists(UserName)) return false; // Si no, aade el usuario al archivo XML. DataSet dsUsers = new DataSet(); // Usa control de errores por si falta el archivo. try{ // Construye la ruta del archivo Users.xml. string strXMLFile = Server.MapPath(Request.ApplicationPath) + "\\Users.xml"; // Lee el archivo. dsUsers.ReadXml(strXMLFile, XmlReadMode.InferSchema); // Crea una nueva fila. DataRow rowUser = dsUsers.Tables["users"].NewRow(); // Establece el nombre de usuario. rowUser["name"] = UserName; // Establece la contrasea (encriptada). rowUser["password"] = FormsAuthentication.HashPasswordForStoringInConfigFile (Password, "SHA1"); // Aade la fila. dsUsers.Tables["users"].Rows.Add(rowUser); // Escribe el conjunto de datos. dsUsers.WriteXml(strXMLFile); return true; }catch // En caso de error devuelve false. return false; }

8.7.3 Mostrar informacin de usuario


En este ejercicio va a crear el formulario Web UserInfo.aspx para mostrar el nombre e informacin de autenticacin del usuario usando el objeto Identity de la clase User. Tambin crear una pgina HTML para mostrar si se deniega el acceso. Como la pginas HTML no se incluyen automticamente en el esquema de autenticacin de una aplicacin Web los usuarios podrn acceder a esta pgina incluso aunque no se autentiquen. Cree el formulario Web UserInfo.aspx y haga que sea la pgina de inicio de la aplicacin. Los usuarios no autenticados sern dirigidos primero a la pgina LogIn.aspx, porque esta es la pgina de conexin indicada en Web.config. Despus de ser autenticados se les dirige a la pgina de inicio de la aplicacin usando el mtodo RedirectFromLoginPage. La pgina UserInfo.aspx contiene una tabla en la que muestra el nombre e informacin de autenticacin del usuario y un botn para permitir que el usuario desconecte de la aplicacin. La tabla contiene elementos <span> como espacios para los datos de usuario, como muestra el siguiente HTML:
<H2>Autenticacin por Formularios</H2> <TABLE id="tblUser" borderColor="black" cellSpacing="1" cellPadding="1" width="500" bgColor="aliceblue" border="1"> <TR> <TD>Autenticado</TD> <TD><SPAN id="spnAuthenticated" runat="server"></SPAN></TD> </TR> <TR> <TD>Nombre de Usuario</TD> <TD><SPAN id="spnUserName" runat="server"></SPAN></TD> </TR> <TR> <TD>Tipo de Autenticacin</TD> <TD><SPAN id="spnAuthenticationType" runat="server"></SPAN></TD> </TR>

175

MCAD/MCSD

</TABLE> <P><asp:Button id="butSignOut" runat="server" Text="Salir"></asp:Button></P>

El suceso Page_Load del formulario Web obtiene la informacin de usuario para mostrar, como se ve aqu. Visual Basic .NET
Private Sub Page_Load(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles MyBase.Load ' Muestra informacin de autenticacin del usuario. spnAuthenticated.InnerText = User.Identity.IsAuthenticated() spnUserName.InnerText = User.Identity.Name() spnAuthenticationType.InnerText = User.Identity.AuthenticationType() End Sub

Visual C#
private void Page_Load(object sender, System.EventArgs e){ // Muestra informacin de autenticacin del usuario. spnAuthenticated.InnerText = User.Identity.IsAuthenticated.ToString(); spnUserName.InnerText = User.Identity.Name; spnAuthenticationType.InnerText = User.Identity.AuthenticationType; }

Despus de crear el formulario Web UserInfo.aspx agregue a la aplicacin una pgina HTML llamada Denied.html. Esta es la pgina que muestra el formulario Web LogIn.aspx si el usuario no introduce un nombre de usuario y contrasea correctos despus de tres intentos. Denied.htm incluye un mensaje para el usuario, como muestra el siguiente HTML:
<H2>Acceso denegado</H2> <p>Para usar esta aplicacin debe introducir un nombre de usuario y contrasea vlidos</p>

8.7.4 Temas avanzados


Los ejercicios anteriores muestran cmo implementar la autenticacin por formularios paso a paso . Para obtener una comprensin completa de otros tipos de autenticacin puede experimentar cambiando el modo de autenticacin en el archivo Web.config de la aplicacin. Para cambiar a autenticacin Windows comente el elemento <authentication> actual en Web.config y aada el que se muestra aqu: <authentication mode="Windows" /> Para cambiar a autenticacin Passport instale el SDK de Passport y modifique el elemento <authentication> como se muestra a continuacin: <authentication mode="Passport" /> Finalmente, como extra, obtenga un certificado de servidor de una Autoridad de Certificacin, como VeriSign e implemente comunicaciones seguras en la aplicacin. Use el protocolos https para activar comunicaciones seguras, como se indica en la leccin 8.5.

8.8 Repaso
Las siguientes preguntas estn pensadas para reforzar informacin clave mostrada en este captulo. Si no es capaz de contestar a una pregunta repase la leccin correspondiente e intente de nuevo. Las respuestas se pueden encontrar en el captulo 16. 1. Qu modo de autenticacin de ASP.NET est mejor adaptado a identificar y autorizar usuarios pertenecientes a una red corporativa? 2. Cul es la diferencia entre las listas de usuarios para autenticacin Windows o de formularios en Web.config? 3. Cmo se exige la autenticacin usando el archivo Web.config?(La respuesta es la misma para todos los modos de autenticacin ASP.NET) 4. Cmo proporciona SSL seguridad en una aplicacin Web? 5. Cmo se comienza y se termina una comunicacin segura mediante SSL?

176

Developing Web Applications

9 Generar y desplegar aplicaciones


En este captulo aprender cmo publicar su aplicacin Web terminada en un servidor Web para uso general. Tambin aprender cmo controlar y mantener la aplicacin cuando est en uso, de modo que siga comportndose bien al cambiar las demandas de los usuarios. Para completar este captulo debe: Tener acceso a un servidor Web, ya sea mediante un servicio de alojamiento Web o en su red de rea local. Haber completado con xito una o ms de las aplicaciones Web de este libro. Estar familiarizado con Internet Information Services (IIS) y la consola de administracin de Microsoft (Microsoft Management Console, MMC). Tener instalado Microsoft Visual Studio .NET Profesional, Enterprise Developer o Enterprise Architect. Este requisito solo se aplica a la ltima leccin del captulo.

9.1 Generar una aplicacin Web


En su forma ms sencilla, generar una aplicacin Web en Visual Studio .NE no precisa casi ningn esfuerzo. De hecho, la aplicacin se genera automticamente cada vez que se pulsa Iniciar durante el desarrollo y depurado de la aplicacin. Sin embargo, cuando la aplicacin est lista para su despliegue hay que ejecutar tres pasos adicionales antes de generarla: 1. Configurar las opciones de generacin 2. Identificar la aplicacin 3. Configurar la aplicacin En esta aplicacin aprender cmo llevar a cabo estas tareas para preparar su aplicacin antes del despliegue.

9.1.1 Configurar las opciones de generacin


Las aplicaciones Web tienen dos opciones de generacin: depurado (debug) y distribucin (release). Para cambiarla, siga estos pasos: 1. En el men Generar seleccione Administrador de configuracin. Visual Studio .NET muestra el dilogo Administrador de configuracin. 2. Seleccione la opcin y pulse Cerrar. 3. Abra el archivo Web.config del proyecto y modifique el elemento compilation para que coincida con la opcin seleccionada en el paso 2. Por ejemplo, para una generacin de distribucin:
<compilation defaultLanguage=vb debug=false />

Al seleccionar la opcin de depurado se genera un archivo de base de datos de programa (.pdb) que contiene informacin sobre los smbolos que se usan dentro de la aplicacin cuando se compila el proyecto. Visual Studio .NET usa la base de datos de programa para controlar los valores de variables, establecer puntos de interrupcin y evaluar los miembros de la clase Debug. Si se selecciona la opcin de distribucin no se genera este archivo, desactivando los miembros de la clase Debug y haciendo que se ignoren los puntos de interrupcin. Como las generaciones para distribucin no tienen que controlar esta informacin extra se ejecutan ms rpido que las de depurado. La opcin de generacin de la aplicacin y el valor en Web.config deben coincidir. No hay ninguna ventaja en tener uno en depurado y otro en distribucin; Visual Studio .NET no cambia automticamente uno cuando se cambia el otro.

9.1.2 Identificar la aplicacin


Antes de desplegar una aplicacin debe incluir informacin sobre la misma, como su ttulo, autor y versin. Esta informacin se muestra cuando los usuarios ven las propiedades de versin del ensamblado (.dll) de la aplicacin en Windows. Para identificar la aplicacin abra el archivo AssemblyInfo y escriba la informacin de la aplicacin en los atributos del ensamblado. Por ejemplo, los siguientes atributos establecen el nombre de producto e informacin de versin: Visual Basic .NET
Imports System.Reflection Imports System.Runtime.InteropServices

177

MCAD/MCSD

' La informacin general de un ensamblado se controla mediante el siguiente ' conjunto de atributos. Cambie estos atributos para modificar la informacin ' asociada con un ensamblado. ' Repase los valores de los atributos del ensamblado <Assembly: <Assembly: <Assembly: <Assembly: <Assembly: <Assembly: <Assembly: AssemblyTitle("Web Flyer Storefront")> AssemblyDescription("Low-price reservation finder.")> AssemblyCompany("Contoso Ltd. ")> AssemblyProduct("Web Flyer")> AssemblyCopyright("2002")> AssemblyTrademark("Web Flyer is a trademark of Contoso Ltd.")> CLSCompliant(True)>

' El siguiente GUID es para el ID de la librera de tipos si ' este proyecto se expone a COM <Assembly: Guid("CE84F243-D7D9-4B7E-B43B-520A0D6B9B30")> ' ' ' ' ' ' ' ' ' ' ' La informacin de versin de un ensamblado consta de los siguientes cuatro valores: Versin principal Versin secundaria Versin de compilacin Revisin Puede especificar todos los valores o usar los valores predeterminados (nmero de versin de compilacin y de revisin) usando el smbolo '*' como se muestra a continuacin:

<Assembly: AssemblyVersion("2.1.*")>

Visual C#
using System.Reflection; using System.Runtime.CompilerServices; // // La informacin general de un ensamblado se controla mediante el siguiente // conjunto de atributos. Cambie estos atributos para modificar la informacin // asociada con un ensamblado. // [assembly: AssemblyTitle("Web Flyer Storefront")] [assembly: AssemblyDescription("Low-price reservation finder.")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("Contoso Ltd.")] [assembly: AssemblyProduct("Web Flyer")] [assembly: AssemblyCopyright("2002")] [assembly: AssemblyTrademark("Web Flyer is a trademark of Contoso Ltd.")] [assembly: AssemblyCulture("")] // // // // // // // // // // // // La informacin de versin de un ensamblado consta de los siguientes cuatro valores: Versin principal Versin secundaria Versin de compilacin Revisin Puede especificar todos los valores o usar los valores predeterminados (nmero de versin de compilacin y de revisin) usando el smbolo '*' como se muestra a continuacin:

[assembly: AssemblyVersion("2.1.*")]

En el archivo AssemblyInfo se generan automticamente dos elementos de informacin: El atributo Guid, para identificar el ensamblado ante componentes COM. Solo necesita cambiar este nmero si rompe la compatibilidad con versiones anteriores el ensamblado eliminando o cambiando significativamente objetos y miembros pblicos usados por componentes COM. El atributo AssemblyVersion actualiza automticamente el nmero de versin de compilacin, indicado por un asterisco (*). Puede aadir niveles de versin o eliminar el nmero de compilacin si quiere.

178

Developing Web Applications

9.1.3 Configurar la aplicacin


Las aplicaciones Web utilizan archivos de texto para configuracin (.config) que determinan la forma en que se ejecutan. El archivo de configuracin de una aplicacin Web (Web.config) reside en el directorio raz de la aplicacin, pero su funcin en realidad es reemplazar la configuracin heredada de las siguientes localizaciones: El archivo Machine.config localizado en el directorio Windows\Microsoft.NET\Famework\versin\ config. Establece la configuracin base para todos los ensamblados .NET que corren en el ordenado. El archivo Web.config localizado en el directorio raz de IIS. Establece la configuracin base para todas las aplicaciones Web y sustituye las opciones establecidas en Machine.config. Cualquier archivo Web.config encontrado en los directorios superiores de la aplicacin. Estas opciones se heredan de los archivos Web.config encontrado a lo largo de la ruta de la aplicacin. El archivo Web.config utiliza elementos XML para controlar diferentes aspectos de la aplicacin Web, como indica la tabla 9.1. Como estos elementos utilizan sintaxis XML diferencian maysculas y minsculas y se deben escribir tal cual se muestran.
Tabla 9. 1: Atributos de Web.config
Elemento Uso Indicar el tipo de generacin/compilacin: build o release Mostrar sus propias pginas de error en respuesta a cdigos de respuesta HTTP. Establecer el tipo de autenticacin usado para identificar a los usuarios. Indicar nombres o funciones de usuario autorizados para ejecutar la aplicacin. Activar el seguimiento par ayudar a diagnosticar errores o ajustar prestaciones. Determinar cmo guarda ASP.NET las variables de estado de sesin. Establecer informacin cultural para aplicaciones localizadas Para ms informacin: Apartado 9.1.1 Captulo 6 Captulo 8 Captulo 8 Captulo 6 Seccin 9.3 y Captulo 3. Captulo 15

compilation customErrors authentication authorization trace sessionState globalization

Cuando se hacen cambios en el archivo Web.config de una aplicacin IIS reinicia automticamente la aplicacin y aplica los cambios. Esto tiene el efecto colateral de reiniciar las variables de estado Application y Session, lo que puede afectar negativamente a los usuarios. Por razones de seguridad, no se puede acceder al archivo Web.config desde un navegador. Si un usuario solicita este archivo recibir un mensaje de error de acceso denegado.

9.2 Desplegar una aplicacin Web


Desplegar una aplicacin Web significa instalar la aplicacin en el servidor donde se va a ejecutar. Como las aplicaciones Web corren en servidores normalmente no necesitan un programa de instalacin. En esto las aplicaciones Web se diferencian mucho de las aplicaciones Windows, que se distribuyen a los usuarios en CD-ROM u otro medio y que usan un programa de instalacin para instalar y registrar componentes en la mquina del usuario. En esta leccin aprender cmo desplegar una aplicacin Web terminada en un servicio de alojamiento o en su propio servidor. Tambin aprender acerca de IIS y la configuracin de seguridad que necesitan las aplicaciones Web.

9.2.1 Uso de las herramientas desSubida


Si se registr en un servicio de alojamiento Web ASP.NET como se indic en el Captulo 1 puede instalar su aplicacin Web en el servidor de alojamiento directamente desde Visual Studio .NET. Para instalar su aplicacin en un servicio de alojamiento desde Visual Studio .NET siga estos pasos: 1. 2. 3. 4. Abra el proyecto que quiere instalar usando Visual Studio .NET En la pgina de inicio de Visual Studio .NET pulse Alojamiento Web. En la pgina de alojamiento Web pulse la lengeta Premier Providers o Additional Providers En la seccin de la pgina de proveedores que incluya a su proveedor pulse Subir directamente a su cuenta; Visual Studio muestra la pgina de subida de su proveedor. 5. Siga las instrucciones en la pgina del proveedor. Estas instrucciones varan ligeramente entre proveedores.

9.2.2 Alojamiento en su propio servidor


Si su aplicacin est pensada para ejecutarse como parte de una red local o si tiene acceso a su propio servidor Web pblico instale su aplicacin en el servidor siguiendo estos pasos: 1. 2. 3. 4. Use IIS para configurar un directorio virtual para la aplicacin. Copie la aplicacin Web al directorio virtual Aada los componentes .NET compartidos a la cach de ensamblados global del servidor. Configure los permisos de seguridad del servidor para permitir que la aplicacin acceda a los recursos necesarios. Las siguientes secciones describen estos pasos con mayor detalle. 179

MCAD/MCSD

9.2.3 Configurar un directorio virtual


Las aplicaciones ASP.NET corren bajo IIS, de modo que antes de que el servidor pueda alojar aplicaciones ASP.NET tienen que estar instalados tanto IIS como el marco de trabajo Microsoft .NET. ASP.NET necesita las siguientes versiones de los componentes: IIS versin 5.0 o posterior Marco de trabajo .NET de la misma versin que el utilizado para compilar el ensamblado de la aplicacin. Los discos de distribucin de Visual Studio .NET incluyen herramientas para configurar los componentes de servidor necesarios. Cuando haya confirmado que los componentes correctos estn instalados en el servidor cree un directorio virtual para la aplicacin siguiendo estos pasos: 1. Usando el explorador de Windows, cree un directorio fsico en el servidor para guardar la aplicacin 2. Usando IIS inicie el Asistente para creacin de directorio virtual para crear el nuevo directorio virtual correspondiente a la direccin fsica creada en el paso 1. En el Captulo 2 se cubre en detalle este asistente.

9.2.4 Copiar la aplicacin


Los lmites de una aplicacin Web los define su estructura de directorios. Esto significa que una aplicacin comienza en su directorio raz y se extiende a todos sus directorios subordinados. De esta forma, instalar una aplicacin Web es tan sencillo como arrastrar los archivos y subdirectorios desde su directorio de desarrollo hasta su ubicacin fsica en el servidor. En general, los archivos de contenido de una aplicacin Web se pueden organizar en subdirectorios de la forma que se quiera. Sin embargo, hay que seguir un par de convenios: El ensamblado (.dll) de la aplicacin se encuentra en el subdirectorio /bin. La pgina de inicio de la aplicacin por lo general se denomina Default.aspx o Default.htm. El que su aplicacin use o no una pgina predeterminada lo impone la configuracin de IIS. Una pgina predeterminada permite que IIS muestre una pgina si el usuario no especifica una en su peticin. Nota: No confunda la pgina predeterminada de IIS con la pgina de inicio de una aplicacin de formularios Web en Visual Studio .NET. Visual Studio .NET necesita que se designe una pgina de inicio para cada proyecto de modo que el entorno de desarrollo sepa qu pgina mostrar rimero durante el depurado. Esta configuracin no tiene efecto en la configuracin de pgina de inicio de IIS.

9.2.5 Instalar componentes compartidos.


Si su aplicacin usa componentes compartidos con otras aplicaciones en el mismo servidor, como controles de servidor personalizados, estos componentes se deben instalar en el servidor. Hay tres formas de hacerlo, dependiendo del tipo de componente. Para componentes COM. Copie el componente al servidor y regstrelo usando las herramientas de COM. Para componentes .NET con nombre dbil. Copie el componente al directorio /bin de la aplicacin. Para componentes .NET con nombre fuerte. Instale el componente el en cach de ensamblados global del servidor. Los componentes COM por lo general proporcionan un programa de configuracin para instalarlos en el sistema o eliminarlos de l. Si el componente no proporciona un programa de configuracin puede copiarlo en el servidor y registrarlo usando la utilidad RegSvr32 de MFC. Por ejemplo: RegSvr32 MiComponente.dll Los nombres de componentes .NET tienen dos formas: dbil y fuerte. Esta distincin se refiere a cmo se almacenan los nombres dentro del ensamblado. Los nombres dbiles no se garantiza que sean nicos y por tanto no se pueden compartir sin que exista la posibilidad de causar conflictos. Los nombres fuertes estn firmados digitalmente y proporcionan una clave pblica que asegura que no hay conflictos. An ms, los componentes .NET con nombre fuerte no pueden llamar a cdigo no administrado (como componentes COM), evitando conflictos potenciales con las dependencias. Los componentes .NET con nombre dbil se deben copiar individualmente al directorio /bin de las aplicaciones Web en las que se usan. Los componentes .NET con nombre fuerte se pueden copiar en el cach de ensamblados global. El cach de ensamblados global es un subdirectorio especial dentro del directorio Windows que almacena los componentes .NET compartidos. Cuando se abre el directorio Windows Explores inicia una extensin del shell de Windows llamada Visor del cach de ensamblados (ShFusion.dll). Puede instalar los componentes .NET con nombre fuerte arrastrndolos al Visor del cach o usando la herramienta del cach (GacUtil.exe) de la forma: GacUtil -1 MisControlesServidor.dll 180

Developing Web Applications

9.2.6 Asignar privilegios de seguridad.


De forma predeterminada el proceso de trabajo de ASP.NET corres usando la cuenta ASPNET, que se crea cuando se instala el marco de trabajo .NET. Esta cuenta tiene privilegios limitados, lo que puede provocar errores de denegacin de permiso si su aplicacin escribe archivos o intenta leeros fuera de los lmites de la aplicacin actual. Si su aplicacin necesita privilegios adicionales tiene tres opciones: Conceder al usuario ASPNET el acceso a los archivos necesarios. Para usar esta opcin el servidor tiene que tener NTFS como sistema de ficheros. Cambiar el grupo al que pertenece ASPNET Utilizar impersonacin para ejecutar el proceso bajo otro usuario. Para conceder al usuario ASPNET acceso a un archivo o directorio siga estos pasos: 1. En el explorador de Windows seleccione Opciones de carpeta en el men Herramientas. Windows muestra el dilogo Opciones de carpeta. 2. Pulse la lengeta Ver y quite la marca en Usar comparticin simple de archivos en la parte inferior de la lista. 3. En el Explorador de Windows pulse con el botn derecho sobre el archivo o directorio sobre el que quiere conceder acceso y seleccione Propiedades. Windows muestra el dilogo Propiedades. 4. Pulse sobre la lengeta Seguridad y pulse Agregar para aadir el usuario ASPNET a la lista de usuarios y grupos. 5. Seleccione las cajas de marca en la lista de permisos para otorgar los accesos necesarios. Pulse Aceptar para hacer los Para cambiar el grupo al que pertenece el usuario ASPNET siga estos pasos. 1. En el men Inicio seleccione Herramientas administrativas y despus Administracin de equipos. Windows muestra la consola de administracin de equipos. 2. Seleccione Usuarios locales y grupos y despus Usuarios en la lista de la izquierda. 3. Pulse con el botn derecho sobre la cuenta de usuario ASPNET y seleccione Propiedades. La consola de administracin muestra las propiedades de la cuenta. 4. Pulse sobre la lengeta Miembro de y despus Agregar para aadir el usuario ASPNET a un nuevo grupo. Pulse Aceptar para hacer los cambios y cerrar los dilogos. Si agrega el usuario ASPNET al grupo Administradores la aplicacin Web obtendr privilegios completos sobre el servidor; sin embargo esto origina un riesgo de seguridad porque usuarios externos podrn manipular la aplicacin para atacar al servidor. Para usar la impersonacin para ejecutar el proceso ASP.NET como un usuario diferente de ASPNET utilice el atributo impersonation del elemento identity en el archivo Web.config de la aplicacin. Por ejemplo, la siguiente entrada hace que la aplicacin se ejecute bajo el usuario WebFlyr:
<identity impersonate=true name=localhost\WebFlyr password=hpB14dq1 />

Si la aplicacin usa autenticacin Windows tambin puede usar impersonacin para pasar la identidad de usuarios autenticados al servidor. Por ejemplo, es siguiente fragmento de Web.config dice a la aplicacin que use los permisos del usuario que se conect:
<identity impersonate="true" /> <authorization> <deny users="?" </authorization> /> <!-- Usa impersonacin. --> <!-- Exige autenticacin. -->

Para ms informacin sobre autenticacin de usuarios vea el captulo 8.

9.3 Mantener una aplicacin


Despus de desplegar una aplicacin Web necesita controlar cmo se comporta en el servidor. En este momento pueden aparecer muchos temas, debido al nmero de usuarios que acceden a la aplicacin, la impredecible naturaleza de la interaccin de los usuraos y la posibilidad de un ataque malicioso. El mantenimiento de una aplicacin desplegada es una tarea continua que implica tres pasos principales: Controlar la aplicacin respecto a errores, prestaciones y seguridad. Reparar los problemas que se descubran. Ajustar la aplicacin para que responda al trfico de usuario. En esta leccin aprender cmo realizar estas tareas, as como algunas tcnicas de optimizacin.

181

MCAD/MCSD

9.3.1 Controlar el servidor


Despus de que la aplicacin se haya desplegado necesita controlar el servidor donde se ejecuta para detectar y corregir problemas relacionados con la seguridad, prestaciones y errores no previstos. Windows proporciona los siguientes aadidos a la MMC para controlar los sucesos de seguridad, prestaciones y error: Visor de Sucesos. Recoge los sucesos de aplicacin, sistema y seguridad que se producen en el sistema. Use esta herramienta para ver lo que sucede actualmente en el servidor y obtener informacin especfica sobre un suceso concreto. Registro de Alertas y Rendimiento. Permite crear nuevos sucesos que se mostrarn en el Visor de sucesos y hacer un seguimiento de contadores de sucesos con el tiempo para mostrarlo grficamente o como informe. Los siguientes apartados describen con ms detalle cmo usar estas herramientas. Ver Sucesos Utilice el Visor de sucesos para ver los sucesos de aplicacin, sistema y seguridad tal cual se produzcan. Para ejecutar el Visor de sucesos seleccinelo en Herramientas administrativas. Windows muestra el aadido Visor de sucesos en la consola de administracin. El Visor de sucesos muestra sucesos generales de aplicacin, sistema y seguridad a tres niveles: informacin, advertencia y error. Para ver informacin sobre un suceso concreto pulse dos veces sobre l. Puede usar el visor de sucesos para echar un vistazo de lo que est ocurriendo en el servidor u obtener detalles sobre un suceso concreto. Para crear nuevos sucesos o hacer un seguimiento a lo largo del tiempo necesitar el Registro de alertas y rendimiento. Definir nuevos sucesos En muchos casos los sucesos estndar de sistema, aplicacin y seguridad no le indican lo que realmente quiere saber. Por ejemplo, puede que quiera saber cundo el nmero de usuarios conectados a la aplicacin excede de 1.000, cundo se produce una excepcin no controlada dentro de la aplicacin. Para aadir sucesos como estos a los registros de contador y seguimiento use el aadido Registro de alertas y rendimiento de MMC. Para ejecutar este aadido pulse dos veces sobre Rendimiento en Herramientas administrativas. El Registro de alertas y rendimiento permite crear archivos de seguimiento que registran la actividad en el servidor y crear alertas que lanzan sucesos en el Visor de sucesos. Usando esta herramienta puede controlar una amplia variedad de informacin sobre el servidor, las aplicaciones que aloja y los usuarios conectados. Tal vez la mejor forma de comprenderlo sea aadir un suceso para controlar en su propio sistema, como describen los siguientes pasos: 1. En la ventana Rendimiento seleccione Alertas en Registros y alertas de rendimiento en el panel izquierdo 2. En el men Accin seleccione Nueva alerta. Ver el dilogo Nueva Alerta. 3. Escriba un nombre para identificar la alerta y pulse Aceptar. MMC muestra un dilogo para configurar la alerta. 4. Agregue un suceso para controlar pulsando Agregar. Ver el dilogo Contadores seleccionados. 5. Seleccione el elemento hardware o aplicacin a controlar en la lista desplegable Objeto de rendimiento. La lista de contadores se actualiza con los elementos aplicables al objeto seleccionado. Pulse Agregar para aadir el contador seleccionado a la alerta. Pulse Cerrar cuando termina. 6. Establezca el criterio que lanza la alerta en el dilogo de configuracin escribiendo un nmero en la caja de texto Lmite. 7. Pulse la lengeta Accin para especificar la accin que debe realizar el servidor cuando se produzca la alerta. De forma predeterminada el servidor registra la alerta como suceso que se puede ver en el Visor de sucesos. Tambin la puede enviar por correo o escribirla en un registro. 8. Cuando termine pulse Aceptar. La alerta aparece en la lista Alertas. De forma predeterminada el aadido comienza a controlar la alerta inmediatamente. Puede detener o reiniciar el control pulsando con el botn derecho sobre la alerta y eligiendo Detener o Iniciar. Windows lanza la alerta siempre que se cumple el criterio. Para algunos contadores, como los de error, esto significa que despus de que se lance la alerta por primera vez se lanza tras cada intervalo. Como la cuenta de errores no se reinicia, una vez que se alcance el lmite siempre lo supera. Para estas alertas debe ser muy cuidadoso con la accin que especifique el envo de correo en respuesta a una cuenta de errores puede provocar un montn de mensajes redundantes. Crear registros de sucesos Definir un nuevo suceso creando una alerta es una buena forma de ser notificado en el momento en que se produce un problema o se degrada el rendimiento, pero para hacer un seguimiento de errores y rendimiento debe crear un registro de sucesos. Los registros de sucesos permiten obtener informacin sobre una amplia variedad de sucesos en el tiempo y mostrar la informacin grficamente o en forma de texto. 182

Developing Web Applications

Para crear un registro de suceso siga estos pasos: 1. En el panel izquierdo de la ventana de Rendimiento seleccione Registros de contador, en Registros y alertas de rendimiento. 2. En el men Accin seleccione Nueva configuracin de registro. Se muestra el dilogo Nueva configuracin de registro. 3. Escriba el nombre del registro y pulse Aceptar. Se mostrar la caja de propiedades del registro. 4. Puse Agregar para aadir los elementos que se van a controlar en el archivo de registro. Ver el dilogo Contadores seleccionados. Estos contadores funcionan igual que para las alertas. 5. Pulse la lengeta Archivos de registro para especificar el formato del archivo que se va a crear. 6. Los archivos de registro se pueden grabar en formato binario, de texto o de base de datos. Pulse Aceptar cuando termine; el registro se aadir a la lista de Registros de contador. Como con las alertas, el aadido empieza a controlar el nuevo registro inmediatamente. Puede detener o reiniciar el control pulsando con el botn derecho sobre el registro y seleccionando Detener o Iniciar. Ver registros de sucesos De forma predeterminada el aadido de Registros y alertas de rendimiento graba los archivos de registro en el directorio raz PerfLogs. Para ver el archivo de registro desde dentro del aadido: 1. Seleccione Monitor del sistema en el panel izquierdo de la ventana Rendimiento. Ver el monitor del sistema con las estadsticas de rendimiento actuales. 2. Pulse el botn Ver datos del archivo de registro en la barra de herramientas. El aadido mostrar el dilogo Propiedades del Monitor del Sistema5. 3. Seleccione Archivos de registro y pulse Agregar para especificar un archivo para abrir. El aadido muestra el dilogo Seleccionar archivo de registro. 4. Seleccione un archivo de registro a abrir en la carpeta PerfLogs y pulse Abrir para aadirlo al monitor. 5. Puse la lengeta Datos en el dilogo Propiedades del monitor del sistema para agregar elementos del registro al grfico. 6. Pulse Aceptar para cerrar el dilogo Propiedades del monitor del sistema. El aadido mostrar el archivo de registro en forma de grfico. 7. Pulse el botn Ver informe en la barra de herramientas para ver el archivo como texto en lugar de grficamente. Ms informacin: Los aadidos Visor de sucesos y Registros y alertas de rendimientos de la MMC proporcionan una forma para controlar la salid de un servidor, detectar errores de aplicacin, identificar conflictos de recursos y predecir necesidades de hardware futuras. Para ms informacin sobre estas tareas vea la ayuda en lnea que incluye cada uno de los aadidos.

9.3.2 Reparar aplicaciones


Despus de que una aplicacin est desplegada puede repasarla y revisarla sin reiniciar el servicio o IIS. Para reparar una aplicacin Web desplegada copie el nuevo ensamblado (.dll) y/o archivos de contenido (.aspx, .ascx, etc.) al directorio de aplicacin en el servidor. ASP.NET reinicia automticamente la aplicacin cuando se reemplaza el ensamblado; no necesita instalar o registrar el ensamblado en el servidor. Las aplicaciones Web ASP.NET tambin tienen una capacidad limitada para repararse a si mismas mediante el reciclado de procesos. El reciclado de procesos es la tcnica de cerrar y reiniciar un proceso de trabajo ASP.NET (aspnet_wp.exe) que ha quedado inactivo o est consumiendo recursos excesivos. Puede controlar cmo se reciclan los procesos ASP.NET mediante atributos del elemento processModel en el archivo Machine.config, como se muestra a continuacin en negrita.
<processModel enable="true" timeout="Infinite" idleTimeout="Infinite" shutdownTimeout="0:00:05" requestLimit="Infinite" requestQueueLimit="5000" restartQueueLimit="10" memoryLimit="60" webGarden="false" cpuMask="0xffffffff" userName="machine"

Cuando hice la prueba, el sistema solo me present un dilogo para seleccionar un archivo de registro. El resto del procedimiento est traducido literalmente, sin probar. (N. del T.)

183

MCAD/MCSD

password="AutoGenerate" logLevel="Errors" clientConnectedCheck="0:00:05" comAuthenticationLevel="Connect" comImpersonationLevel="Impersonate" responseRestartDeadlockInterval="00:09:00" responseDeadlockInterval="00:03:00" maxWorkerThreads="25" maxIoThreads="25"/>

La tabla 9.2 describe los atributos de processModel que se relacionan con el reciclado de procesos.
Tabla 9. 2: Atributos de reciclado de procesos
Atributo Determina La cantidad de tiempo (hh:mm:ss) antes de que se cierre y reinicie el proceso. Use esta configuracin para reciclar un proceso automticamente tras un cierto nmero de peticiones como medida preventiva. shutDownTimeOut Tiempo que tiene cada proceso para cerrarse a s mismo. Tras este tiempo el sistema termina el proceso si sigue en ejecucin. requestLimit Nmero de peticiones acoladas que se sirven antes de que se cierre y reinicie el proceso. Use esta opcin de la misma forma que el atributo timeout. restartQueueLimit Nmero de peticiones en cola que se retienen mientras se cierra y reinicia el proceso. memoryLimit Porcentaje de memoria fsica que se permite consumir al proceso ASP.NET antes de que se cierre y se inicie uno nuevo. Esta opcin ayuda a prevenir que el exceso de uso de memoria degrade el servidor. responseRestartDeadlockInterval Tiempo que se espera antes de reiniciar un proceso que se ha cerrado por bloqueo. Esta opcin normalmente es de varios minutos para impedir que aplicaciones con problemas serios bloqueen el servidor. responseDeadlockInterval Tiempo que se espera antes de reiniciar un proceso bloqueado. El proceso se reinicia si tiene peticiones en cola y no responde dentro de este lmite de tiempo.

timeout

9.3.3 Afinar aplicaciones desplegadas


Las aplicaciones Web ASP.NET tienen una serie de configuraciones que se pueden controlar para afinar el rendimiento cuando estn desplegadas. Use las Extensiones de servidor de FrontPage para controlar cmo se almacenan las pginas en cach en la memoria del servidor. Use la configuracin de aplicacin en IIS para controlar el nivel de proteccin de la aplicacin. Use los atributos del elemento processModel en el archivo Machine.config del servidor para controlar el nmero de hebras y el comportamiento de agotamiento de tiempo que proporciona el servidor a las aplicaciones Web. Use los atributos del elemento sessionState en el archivo Web.config de la aplicacin para controlar cmo se guarda la informacin de estado de sesin. Las siguientes secciones discuten cada una de estas tcnicas.

9.3.4 Configurar las opciones de Cach


Las aplicaciones Web ASP.NET pueden guardar documentos que se solicitan con frecuencia en la memoria del servidor para acelerar el acceso a estos elementos. El almacenamiento de elementos de esta forma se denomina cach. Para configurar el uso de cach para una aplicacin Web: 1. Configure las Extensiones de servidor de FrontPage para la aplicacin: Seleccione la aplicacin Web. En el men Accin seleccione Todas las tareas y despus Configurar Extensiones de servidor. IIS muestra el asistente para nueva subweb. Recorra el asistente pulsando Siguiente y siguiendo las instrucciones, bastante sencillas. 2. En IIS, pulse con el botn derecho sobre la aplicacin Web y pulse Propiedades. IIS muestra el dilogo de propiedades de la aplicacin 3. Pulse la lengeta Extensiones de servidor y seleccione el nmero de pginas que contiene su aplicacin en la lista desplegable Rendimiento. 4. Las extensiones de servidor de FrontPage proporcionan opciones de cach predeterminadas para aplicaciones Web en base al nmero de documentos (archivos .aspx o .htm) que contienen. Como alternativa puede establecer su propia configuracin de cach seleccionando Usar configuracin predeterminada en la lista desplegable Rendimiento. IIS muestra el dilogo Rendimiento. Haga sus cambios y pulse Aceptar. El cambio en la configuracin de cach es un acto de equilibrio. Si se guarda demasiada informacin en cach se reduce la cantidad total de memoria disponible para ejecutar la aplicacin. Si se guarda demasiado poca son necesarios ms accesos a disco para recuperar los documentos pedidos. 184

Developing Web Applications

9.3.5 Cambiar el nivel de proteccin


Como se mencion en el Captulo 2, IIS puede ejecutar una aplicacin Web como un proceso dentro del propio IIS, como proceso separado agrupado con otras aplicaciones Web o como proceso aislado. A mayor nivel de aislamiento, ms fiable es la ejecucin de la aplicacin, porque est ms protegida contra otros procesos que pueden contener errores o mostrar otros fallos. Sin embargo, un mayor aislamiento tambin ralentiza la ejecucin de una aplicacin Web, porque las llamadas a procedimientos deben cruzar lmites de proceso. Como con el cach, es un asunto de equilibrio: fiabilidad frente a velocidad. Para cambiar el nivel de proteccin de una aplicacin siga estos pasos: 1. Pulse con el botn derecho sobre la aplicacin en IIS y seleccione Propiedades. IIS muestra el dilogo Propiedades de la aplicacin. 2. En la lista desplegable Proteccin de aplicacin seleccione Bajo, Medio o Alto para especificar el nivel de proteccin. Pulse Aceptar.

9.3.6 Ajustar los atributos de processModel


Los atributos del elemento processModel en el archivo Machine.config proporcionan control sobre ciertos aspectos del rendimiento, como el nmero mximo de aplicaciones que se ponen en cola, cunto se espera antes de comprobar si un cliente est conectado y cuantas hebras se permiten por procesador. Al final de la pgina 189 hay un ejemplo de este elemento, y la tabla 9-3 describe los atributos relativos al rendimiento:
Tabla 9. 3: Atributos de rendimiento
Atributo Determina Nmero de solicitudes que se permite poner en cola antes de que ASP.NET devuelva un cdigo de respuesta 503 (Servidor ocupado) a las nuevas peticiones. Tiempo (hh:mm:ss) que se espera antes de comprobar si un cliente sigue conectado. Nmero mximo de hebras por procesador Nmero mximo de hebras de entrada/salida por procesador.

requestQueueLimit clientConnectedCheck maxWorkerThreads maxIOThreads

En general, reducir estos nmeros permite que el servidor maneje menos clientes ms rpidamente. Incrementando estos valores se permiten ms clientes y ms peticiones en cola, pero ralentiza la respuesta.

9.3.7 Ajustar los atributos de sessionState


El almacenamiento de informacin de estado para cada sesin de cliente toma tiempo. Si su aplicacin Web no usa variables de estado de sesin, debe desactivar el seguimiento de este estado. Para desactivar el estado de sesin de el valor Off al atributo mode del elemento sessionState en el archivo Web.config.

9.3.8 Consejos de optimizacin


Piense en el afinado como en hacer ajustes en una aplicacin desplegada que no afectan al cdigo. La optimizacin por lo general hace referencia a escribir cdigo de forma que se ejecute ms rpidamente o consuma menos recursos. En general, la optimizacin simplemente refleja buenas prcticas e programacin que se han aprendido hasta ahora en este libro. Algunos de los puntos ms importantes son: Desactive el depurado para las aplicaciones en explotacin. El cdigo compilado con opcin Release se ejecuta ms rpido que el compilado con la opcin Debug. Evite viajes de ida y vuelta entre el cliente y el servidor. ASP.NET utiliza el envo al servidor para procesar los sucesos de servidor en una pgina. Intente disear los formularios Web de forma que los datos estn completos antes de que el usuario los enve al servidor. Puede usar controles de validacin para asegurarse de que los datos estn completos en el lado cliente antes de enviar la pgina. Desactive el estado de sesin si no es necesario. En algunos casos puede disear su cdigo para usar otras tcnicas, como cookies, para almacenar datos de cliente. Desactive ViewState para los controles de servidor que no necesitan retener sus valores. Use procedimientos almacenados en la base de datos. Los procedimientos almacenados se ejecutan ms deprisa que las consultas desde la aplicacin. Use SqlDataReader en lugar de conjuntos de datos para recuperacin de datos de solo avance. Este componente es ms rpido y consume menos memoria que crear un conjunto de datos. Cuando se aplican estos consejos de optimizacin hay que dejarse guiar por el sentido comn. Por ejemplo, si necesita retener datos sobre una sesin de cliente, utilice el estado de sesin en lugar de implementar su propia solucin para hacer lo mismo.

185

MCAD/MCSD

9.4 Desplegar entre varios servidores


Las aplicaciones Web que sirven a un gran nmero de usuario o que manejan gran cantidad de datos necesitan tener la capacidad de crecer segn aumenten las demandas de los usuarios. La capacidad de crecer de una aplicacin se llama escalabilidad. Las aplicaciones Web soportan este concepto mediante su capacidad para correr en varios procesadores y tener sus procesos distribuidos entre varias CPU y/o varios servidores. Una aplicacin Web que corre en un nico servidor con varias CPU se denomina jardn Web (Web garden) en la documentacin de ASP.NET. Una aplicacin que corre en varios servidores se denomina granja Web (Web farm). En esta leccin aprender cmo activar su aplicacin Web para que utilice estas configuraciones de servidor.

9.4.1 Crecer con varios procesadores


Si su servidor tiene varios procesadores puede especificar que ASP.NET corra sobre todas o algunas de las CPU mediante el atributo webGarden del elemento processModel en el archivo Machine.config del servidor. La tabla 9.4 describe los atributos de processModel que se relacionan con jardines Web.
Tabla 9. 4: Atributos de jardn Web
Atributo Determina Dle el valor true para ejecutar las aplicaciones Web ASP.NET en ms de un procesador de este servidor. Especifica qu CPU,s deben utilizar la aplicaciones Web ASP.NET. El valor 0xffffffff ejecuta las aplicaciones en todas las CPU,s.

webGarden cpuMask

El atributo cpuMask es una mscara de bits que ASP.Net usa para activar (1) o desactivar (0) cada CPU del servidor. Por ejemplo, el nmero binario 1101 activa ASP.NET sobre los procesadores 0, 2 y 3 en una mquina con cuatro procesadores, dejando el 1 libre. El nmero binario 1101 corresponde con el valor hexadecimal 0x0000000d. La ejecucin de ASP.NET sobre varios procesadores hace necesario tomar ciertas medidas para poder manejar la informacin de Application y Session. Vea Compartir Informacin de Estado, ms adelante en esta leccin.

9.4.2 Crecer con varios servidores


Para que varios servidores manejen las peticiones para una sola direccin HTTP deber instalar balance de cargas en su red. Los servicios de balance de cargas se pueden proporcionar mediante hardware o software. Tanto Windows 2000 Advanced Server como Windows 2000 Datacenter incluyen software de balance de cargas (NLB6) para distribuir las peticiones entre varios servidores. Vea el tema Proveedor de balance de cargas en la red en la ayuda de Visual Studio .NET para ver cmo instalar y usar esta herramienta. Cuando est activado el balance de cargas en la red, puede instalar su aplicacin Web en varios servidores y las peticiones de los clientes se dirigirn automticamente al servidor menos ocupado en un momento dado. La ejecucin de una aplicacin Web en varios servidores hace necesario tomar ciertas medidas para poder manejar la informacin de Application y Session. Vea la siguiente seccin.

9.4.3 Compartir informacin de estado


Tanto en un jardn Web como en una granja Web las peticiones de los clientes se dirigen al proceso ASP.NET que est actualmente menos ocupado. Esto significa que un nico cliente puede interactuar con diferentes CPU,s o servidores a lo largo de su sesin. Esto tiene las siguientes implicaciones para las variables de estado de aplicacin y de sesin: Las variables de estado de aplicacin son nicas para cada instancia separada de la aplicacin Web. Los clientes pueden compartir informacin mediante Application si la afliccin Web se ejecuta en un jardn Web o granja Web. Las variables de estado de forma predeterminada se almacenan en proceso. Para activar el estado de sesin en una granja Web o jardn Web tiene que especificar un proveedor de estado de sesin. Las siguientes secciones exploran estos temas con mayor detalle. Compartir estado de aplicacin Para compartir datos entre varias sesiones en un jardn o granja Web debe guardar y recuperar la informacin usando un recurso disponible para todos los procesos. Esto se puede hacer mediante un archivo XML, una base de datos o algn otro recurso usando mtodos estndar de acceso a archivo o base de datos. Compartir estado de sesin ASP.NET proporciona dos formas integradas para compartir la informacin de estado de sesin dentro de un jardn o granja Web. Puede compartir el estado de sesin usando:

Network Load Balancing

186

Developing Web Applications

Un servidor de estado, especificado por una direccin de red. Esta tcnica es sencilla de implementar y no hace necesario instalar SQL Server. Una base de datos SQL, especificada por una conexin SQL. Esta tcnica proporciona el mejor rendimiento para almacenar y recuperar la informacin de estado. Para compartir estado de sesin usando un servidor de estado siga estos pasos: 1. En el archivo Web.config de la aplicacin configure los atributos mode y stateConnectionString del elemento sessionState. Por ejemplo, la siguiente configuracin usa el servidor de estado con la direccin IP 192.168.1.102, en el puerto 42:
<sessionState mode="StateServer" stateConnectionString="tcpip=192.168.1.102:42" sqlConnectionString="data source=192.168.1.102;user id=sa;password=" cookieless="false" timeout="20" />

2. Ejecute la utilidad aspnet_state.exe en el servidor de estado de sesin. Esta utilidad se instala en el directorio \Windows\Microsoft.NET\Framework\versin cuando se instala la edicin Professional o Enterprise Architect de Visual Studio .NET. Para compartir estado de sesin usando una base de datos SQL Server siga estos pasos: 1. En el archivo Web.config de la aplicacin configure los atributos mode y sqlConnectionString del elemento sessionState. Por ejemplo, la siguiente configuracin usa el servidor SQL Server con la direccin IP 192.168.1.102:
<sessionState mode="SQLServer" stateConnectionString="tcpip=192.168.1.102:42" sqlConnectionString="data source=192.168.1.102;user id=sa;password=" cookieless="false" timeout="20" />

2. Ejecute la utilidad InstallSqlState.sql en el servidor de estado de sesin. Esta utilidad instalada la base de datos SQL que comparte la informacin de estado de sesin entre procesos. La utilidad se instala en el directorio \Windows\Microsoft.NET\Framework\versin cuando se instala la edicin Professional, Enterprise Developer o Enterprise Architect de Visual Studio .NET

9.5 Resumen
Antes de generar una aplicacin para distribucin configure la opcin generar como Release y el atributo debug en Web.config como False. Utilice el archivo AssemblyInfo.vb o AssemblyInfo.cs para identificar el ensamblado de la aplicacin y proporcionar informacin de versin. Para desplegar una aplicacin use las herramientas de subida de Visual Studio .NET o sencillamente copie el ensamblado y los archivos de contenido de la aplicacin al servidor. Configure los privilegios de seguridad de la cuenta de usuario ASPNET para permitir que su aplicacin Web escriba archivos o acceda a otros recursos con restricciones de seguridad en el servidor. Despus del despliegue controle la aplicacin Web usando los aadidos Visor de sucesos y Registros de alertas y rendimiento de MMC. Puede reparar aplicaciones Web subiendo nuevas versiones del ensamblado o archivos de contenido de la aplicacin al servidor. Las aplicaciones Web con problemas de memoria u otros pueden repararse a si mismas mediante el reciclado de procesos de ASP.NET. Utilice las extensiones de servidor de FrontPage para mejorar el rendimiento de una aplicacin Web guardando en cach las pginas de uso frecuente. Para activar un jardn Web use los atributos del elemento processModel en el archivo Machine.config del servidor. Para activar una granja Web use un balanceador de carga para distribuir las peticiones entre varios servidores. Tanto en los jardines como en las granjas Web comparta la informacin de estado de sesin configurando el elemento sessionState en el archivo Web.config de la aplicacin.

9.6 Prctica: Generar y distribuir una aplicacin Web


En esta prctica va a preparar una aplicacin Web para su distribucin, la va a desplegar en un servidor y controlar y afinar su rendimiento. Antes de comenzar seleccione una de las aplicaciones que ha completado a lo largo del libro o alguna que haya terminado por si mismo para usarla en los ejercicios siguientes. 187

MCAD/MCSD

Esta prctica trata materia que se aplica a todos los tipos de aplicaciones Web, por lo que ser ms interesante si elige una que quiera compartir con otros o est interesado en usar Vd. mismo en Internet.

9.6.1 Preparar la aplicacin


En este ejercicio va a generar una versin de distribucin de la aplicacin Web. Use lo que aprendi en la leccin 1 para completar las siguientes tareas: 1. Identifique la aplicacin y establezca su nmero de versin en el archivo AssemblyInfo.vb o AssemblyInfo.cs. 2. Cambie el valor del atributo debug del elemento de compilacin a False en el archivo Web.config de la aplicacin. 3. Configure la opcin de generacin de la aplicacin como Release 4. Genere la aplicacin.

9.6.2 Despliegue la aplicacin


La forma de desplegar la aplicacin depende del tipo de servidor del que disponga. Si est alojando su aplicacin mediante un servicio de alojamiento Web como se trat en el captulo 1, use las herramientas de subida de Visual Studio .NET para enviar la aplicacin al servicio de alojamiento. Si est alojando las aplicaciones en su propio servidor use lo que aprendi en la leccin 2 de este captulo para realizar estas tareas: 1. Cree un directorio virtual para la aplicacin usando IIS en el servidor. 2. Copie la aplicacin al directorio virtual. 3. Vea las opciones de seguridad en el servidor para comprobar que la cuenta de usuario ASPNET tiene permisos para realizar las tareas que precise la aplicacin. 4. Si es necesario, conceda los permisos sobre los recursos utilizados por la aplicacin. 5. Ejecute la aplicacin desde el servidor para verificar que su configuracin de seguridad permite que la aplicacin se ejecute correctamente.

9.6.3 Comprobar el rendimiento de la aplicacin


En este ejercicio va a usar el agregado de alertas y rendimiento de MMC para mantener un registro del nmero de peticiones procesadas por ASP.NET y trazar un grfico que compare estas peticiones con la actividad del procesador en el servidor. Utilice lo que aprendi en la leccin 3 para llevar a cabo estas tareas: 1. Ejecute el agregado de alertas y rendimiento de MMC y conecte con el servidor sobre el que corre la aplicacin Web. Si aloj la aplicacin en un servicio de alojamiento Web no podr conectar con el servidor, en su lugar, ejecute la aplicacin en local en su mquina de desarrollo y conecte con esta mquina. 2. Cree un nuevo registro de contador llamado Ejercicio 3. 3. Aada al registro los contadores de la siguiente tabla:
Objeto Contador Procesador %Tiempo de procesador Aplicaciones ASP.NET Peticiones annimas ASP.NET Aplicaciones en ejecucin ASP.NET Procesos de trabajo en ejecucin

4. Inicie el registro y detngalo tras unos minutos para recoger datos sobre el servidor. 5. Seleccione el monitor del sistema en el agregado y cambie las propiedades del monitor para ver los archivos de registro: Pulse con el botn derecho en el monitor del sistema y seleccione Propiedades en el men emergente. Pulse la lengeta Origen y seleccione Archivos de registro. Pulse Agregar para aadir los archivos de registro al monitor. Pulse sobre la lengeta Datos y pulse Agregar para aadir los contadores ASP.NET al monitor En la lengeta Datos establezca la escala de cada contador ASP.NET a 10 Pulse Aceptar para ver el registro como grfico. 6. En el monitor del sistema seleccione Informe para ver el registro en forma de texto. 7. Experimente con otros contadores, como errores de aplicaciones ASP.NET, aciertos de cach, etc.

9.6.4 Afinar la aplicacin


En este ejercicio va a instalar las extensiones de servidor de FrontPage y configurar las opciones de cach para la aplicacin Web. De forma predeterminada Visual Studio .NET instala las extensiones cuando se instalan los componentes .NET. Si ha alojado su aplicacin en un servicio de alojamiento Web no podr realizar estas tareas sobre la aplicacin desplegada porque no tendr acceso fsico al servidor. En su lugar, use la versin local de la aplicacin, como en el ejercicio anterior. 188

Developing Web Applications

Use lo que aprendi en la leccin 3 para realizar las siguientes tareas: 1. Ejecute IIS e instale las extensiones de servidor de FrontPage en el directorio virtual que contiene la aplicacin. 2. En IIS, vea las propiedades del directorio virtual y pulse la lengeta Extensiones del servidor. 3. En la lista desplegable Rendimiento seleccin para menos de 100 pginas y pulse Aceptar. 4. Vuelva a ejecutar el registro de contador creado en 9.6.3 para ver si puede detectar cambios en el servidor.

9.7 Repaso
Las siguientes preguntas estn pensadas para reforzar informacin clave mostrada en este captulo. Si no es capaz de contestar a una pregunta repase la leccin correspondiente e intente de nuevo. Las respuestas se pueden encontrar en el captulo 16. 1. Bajo qu permisos se ejecutan de forma predeterminada las aplicaciones Web? 2. Por qu es importante el archivo Machine.config para las aplicaciones Web desplegadas? 3. Cmo se configuran las opciones de cach para una aplicacin Web? 4. Cmo afecta al estado de sesin de una aplicacin Web el despliegue en una granja Web o jardn Web?

189

MCAD/MCSD

190

Developing Web Applications

10 Probar aplicaciones Web


El objetivo de las pruebas de software es asegurar que el producto cubre los requisitos deseados. De esta sentencia se deducen dos precondiciones: Sin requisitos no se pueden iniciar las pruebas Sin objetivos cuantificables no se sabe cuando detener las pruebas. Por lo general tanto los requisitos de producto como los objetivos se determinan fuera del proceso de desarrollo normalmente por clientes o administracin. En este captulo aprender cmo aplicar requisitos de producto para planificar, crear, ejecutar y corregir problemas encontrados en pruebas. Para completar este captulo debe: Tener acceso a un servidor Web ya sea mediante un servicio de alojamiento o por medio de su red de rea local que pueda usar para probar y depurar aplicaciones Web. Haber completado y desplegado con xito una o ms de las aplicaciones Web de ejemplo de este libro. Estar familiarizado con un lenguaje de secuencias de comandos de Windows, como VBScript o JScript. Tener instalado el centro de pruebas de aplicaciones (Application Center Test, ACT) que se incluye con Visual Studio .NET Enterprise Architect. Este requisito solo se aplica al material del captulo que trata las pruebas de carga de aplicaciones Web.

10.1 Crear pruebas


Todo el software pensado para consumo pblico debe sufrir algn nivel de pruebas. Mientras ms ampliamente se distribuya o ms complejo sea el software, ms necesarias son las pruebas. Sin pruebas no tiene la seguridad de que el software se comportar como se espera. Para software, pruebas casi siempre significa pruebas automatizadas. Las pruebas automatizadas usan un lenguaje de programacin para repetir acciones de usuario grabadas o simular el uso interno de un componente. Las pruebas automatizadas son reproducibles (se puede ejecutar de nuevo la misma prueba) y cuantificables (la prueba tiene xito o fracasa). Estas dos ventajas son clave para asegurar que el software cumple los requisitos. En este captulo aprender cmo escribir un plan de pruebas, cmo asegurar que el producto est perfectamente probado y cmo crear diferentes tipos de pruebas usando Visual Studio .NET.

10.1.1 Desarrollar un plan de pruebas


El primer paso en las pruebas es desarrollar un plan de prueba basado en los requisitos del producto. Normalmente, el plan de pruebas es un documento formal que asegura que el producto cubre los siguientes estndares: Est completamente probado: El cdigo no probado aade un elemento desconocido al producto e incrementa el riesgo de fallo. Cumple los requisitos del producto: Para cumplir las necesidades del cliente el producto debe proporcionar las caractersticas y comportamiento descritos en la especificacin del producto. Por este modito, las especificaciones de producto deben estar claramente escritas y ser bien comprendidas. No contiene defectos: Las caractersticas deben trabajar dentro de estndares de calidad establecidos, y estos estndares deben indicarse claramente dentro del plan. Tener un plan de pruebas ayuda a evitar las pruebas ad hoc el tipo de pruebas que confa en los esfuerzos descoordinados de los desarrolladores o probadores para asegurar que el cdigo funciona. El resultado de las pruebas as hoc normalmente es desigual y siempre es impredecible. Un buen plan de pruebas responde las siguientes preguntas: Cmo estn escritas las pruebas?. Describe las herramientas y lenguajes utilizados para pruebas. Quin es responsable de las pruebas?. Indica los equipos o individuos que escriben y ejecutan las pruebas. Cundo se ejecutan las pruebas?. El plan de pruebas debe basarse en el plan de desarrollo. Dnde estn las pruebas y cmo se comparten los resultados?. Las pruebas se deberan organizar de modo que se puedan volver a ejecutar de forma regular. Qu se est probando?. Objetivos cuantificables con fines concretos le permiten saber cundo ha conseguido el xito.

Algunas de estas preguntas pueden tener ms de una respuesta, dependiendo del tipo de prueba. Por ejemplo, a menudo desarrolladores individuales son responsables de escribir el primer nivel de pruebas para su propio cdigo, mientras que un equipo de pruebas separado ser responsable de asegurar que todo el cdigo funciona junto. Las siguientes secciones describen los diferentes tipos de pruebas y las tcnicas usadas con Visual Studio .NET para ejecutar estas pruebas.

191

MCAD/MCSD

10.1.2 Tipos de pruebas


El plan de prueba especifica los diferentes tipos de pruebas que se realizarn para asegurar que el producto cubre los requisitos del cliente y no contiene defectos. La tabla 10.1 describe los tipos de pruebas ms habituales.
Tabla 10. 1: Tipos de pruebas
Tipo de prueba De Unidad Integracin Regresin Carga (stress) Plataforma Asegura que Cada fragmento de cdigo independiente funciona correctamente. Todas las unidades funcionan juntas sin errores Las caractersticas nuevas aadidas no introducen errores en otras caractersticas que estn funcionando El producto sigue funcionando en condiciones extremas de uso El producto funciona en todo el hardware y plataformas hardware de destino

Estos tipos de pruebas se apoyan unos en otros y por lo general se ejecutan en el orden que muestra la tabla. El proceso de pruebas sigue el proceso que muestra el diagrama 10.1. El proceso que muestra la figura 10.1 se basa en un diseo de producto modular en el que el producto se desarrollar como un conjunto de componentes que se pueden programar, probar, integrar y distribuir individualmente. Esta es la aproximacin moderna, y debe mirar con recelo cualquier proyecto que proponga un diseo monoltico en el que la integracin y pruebas se ejecuten solo al final del ciclo de desarrollo.

10.1.3 Pruebas de unidad


Una unidad de producto es el menor fragmento de cdigo que se puede probar de forma independiente. Desde un punto de vista de programacin orientada a objetos, las clases, propiedades, mtodos y sucesos son unidades individuales. Una unidad debe pasar su prueba de unidad entes de que se integre en el proyecto. Las pruebas de unidad normalmente las escribe el desarrollador que program la unidad, y estn escritas en el mismo lenguaje de programacin que la unidad que se est probando o en un lenguaje de secuencia de comandos similar, como VBScript. La prueba de unidad puede ser tan sencilla como obtener y escribir un valor de propiedad, o ms complicada. Por ejemplo, una prueba de unidad puede tomar datos sencillos, calcular un resultado y compararlo con el resultado esperado para comprobar la precisin.

Fig.10. 1: Ciclo de pruebas

Agrupe lgicamente las pruebas de unidad. Las pruebas que comprueban cada propiedad y mtodo de una clase se pueden incluir en un nico procedimiento, que se llama desde una aplicacin de pruebas separada. Por ejemplo, el siguiente procedimiento de prueba crea una instancia de la clase FlashCardClass creada anteriormente en este libro y prueba cada uno de sus propiedades y mtodos. Visual Basic .NET
Function TestFlashCard() As Boolean 'Crea la clase Dim FlashCard As New vbFlashCards.FlashCardClass() 'Prueba si existe la clase. If IsNothing(FlashCard) Then Console.WriteLine("FlashCardClass fallida") 'Devuelve false y termina. Return False End If 'Prueba el mtodo de barajado usando valores mximo y mnimo. FlashCard.Shuffle(Integer.MinValue, Integer.MaxValue) 'Prueba propiedades. Dim bResult As Boolean = True Dim intFirst As Integer = FlashCard.FirstNumber Dim intSecond As Integer = FlashCard.SecondNumber Dim dblAnswer As Double = intFirst + intSecond If dblAnswer <> FlashCard.Answer Then Console.WriteLine("Error: los nmeros no se suman") bResult = False End If

192

Developing Web Applications

'Baraja de nuevo. FlashCard.Shuffle(Integer.MinValue, Integer.MaxValue) 'Se asegura de que los nuevos valores son nicos. If intFirst = FlashCard.FirstNumber Then Console.WriteLine("Aviso: FirstNumber no es nico despus de barajar") End If If intSecond = FlashCard.SecondNumber Then Console.WriteLine("Aviso: SecondNumber no es nico despus de barajar ") End If 'Comprueba diferentes operadores. FlashCard.Operation = "-" If FlashCard.FirstNumber - FlashCard.SecondNumber <> FlashCard.Answer Then Console.WriteLine("Error: operador no resta.") bResult = False End If FlashCard.Operation = "x" If FlashCard.FirstNumber * FlashCard.SecondNumber <> FlashCard.Answer Then Console.WriteLine("Error: operador x no multiplica.") bResult = False End If FlashCard.Operation = "+" If FlashCard.FirstNumber + FlashCard.SecondNumber <> FlashCard.Answer Then Console.WriteLine("Error: operador + no suma.") bResult = False End If 'Devuelve xito/error. Return bResult End Function

Visual C#
static bool TestFlashCardClass(){ //Crea la clase csFlashCards.FlashCardClass FlashCard = new csFlashCards.FlashCardClass(); //Comprueba si existe la clase. if (FlashCard == null){ Console.WriteLine("FlashCardClass fall"); //Devuelve false y termina. return false; } //Comprueba el mtodo de barajado usando valores mnimo y mximo. FlashCard.Shuffle(int.MinValue, int.MaxValue); //Prueba propiedades. bool bResult = true; int intFirst = FlashCard.FirstNumber; int intSecond = FlashCard.SecondNumber; double dblAnswer = intFirst + intSecond; if (dblAnswer != (double)FlashCard.Answer()){ Console.WriteLine("Error: los nmeros no se suman"); bResult = false; } //Baraja de nuevo. FlashCard.Shuffle(int.MinValue, int.MaxValue); //Se asegura de que los nuevos valores son nicos. if (intFirst == FlashCard.FirstNumber) Console.WriteLine("Aviso: FirstNumber no es nico despus de barajar"); if (intSecond == FlashCard.SecondNumber) Console.WriteLine("Aviso: SecondNumber no es nico despus de barajar"); //Comprueba diferentes operadores. FlashCard.Operation = "-"; if (FlashCard.FirstNumber - FlashCard.SecondNumber != FlashCard.Answer()){ Console.WriteLine("Error: operador no resta."); bResult = false; } FlashCard.Operation = "x"; if (FlashCard.FirstNumber * FlashCard.SecondNumber != FlashCard.Answer()){ Console.WriteLine("Error: operador x no multiplica."); bResult = false; }

193

MCAD/MCSD

FlashCard.Operation = "+"; if (FlashCard.FirstNumber + FlashCard.SecondNumber != FlashCard.Answer()){ Console.WriteLine("Error: operador + no suma."); bResult = false; } //Devuelve xito/error. return bResult; }

El factor ms importante en una prueba de unidad es que sea completa. Las pruebas de unidad deben comprobar cada fragmento de cdigo de la aplicacin y usar un rango de valores posibles. El ejemplo anterior muestra el uso de un amplio rango pasando MinValue y MaxValue al mtodo Shuffle. Las pruebas tambin deben informar de los errores a nivel de unidad de forma que la localizacin y correccin de los problemas sea directa. El ejemplo anterior lo hace mostrando un mensaje en la ventana de salida mediante Console.WriteLine. Como alternativa puede escribir los errores en un registro de prueba mediante Debug.WriteLine o lanzar alertas usando Debug.Assert.

10.1.4 Pruebas de integracin


La primera prueba de integracin responde a la pregunta se compila la aplicacin?. En este punto un error de compilacin en cualquiera de los componentes puede impedir la continuacin de las pruebas de integracin. Algunos proyectos utilizan compilaciones nocturnas para asegurarse de que el producto siempre se compila. El problema de compilacin ms habitual se produce cuando un componente intenta utilizar otro que an no se ha escrito. Esto sucede con el diseo modular porque los componentes a menudo se crean fuera de secuencia. Este problema se crea mediante la creacin de muones7. Los muones son componentes no funcionales que proporcionan la definicin de clase, propiedad o mtodo que utiliza otro componente. Son una especie de esquema del cdigo que se crear ms adelante. Cuando se han resuelto todos los problemas de compilacin, las pruebas de integracin se convierten en una aplicacin de las pruebas de unidad, solo que ahora el foco se centra en ver si las unidades trabajan juntas. En este punto es posible encontrarse con dos componentes que necesitan trabajar en conjunto mediante un tercero que no se ha escrito an. Para probar estos dos componentes se crea un controlador8. Un controlador es sencillamente un componente de prueba que asegura que dos componentes funcionan juntos. Ms adelante en el proyecto, las pruebas realizadas con el controlador se pueden ejecutar con el componente real. Adems de muones y controladores puede que necesite un interface de prueba que le ayude a automatizar las pruebas de integracin de algunos componentes. Un interface de prueba es un conjunto de propiedades y mtodos pblicos que se usan para controlar un componente desde un programa de prueba externo. Por ejemplo, el siguiente interface de prueba permite la prueba automatizada del formulario Web de la aplicacin FlashCard. Visual Basic .NET
#If DEBUG Then 'Interface de pruebas de integracin pblico. Public FirstNumber As String Public SecondNumber As String Public Function TestUI(ByVal Answer As String) As Boolean FirstNumber = lblFirst.Text SecondNumber = lblSecond.Text 'Pone la respuesta en txtAnswer. txtAnswer.Text = Answer 'Ejecuta el suceso Changed. txtAnswer_TextChanged(Me, EventArgs.Empty) 'Comprueba si es correcto. If lblFeedback.Text = "Correcto" Then Return True Else Return False End If End Function #End If

7 8

stubs en el original. driver en el original

194

Developing Web Applications

Visual C#
#if DEBUG //Interface de pruebas de integracin pblico. public string FirstNumber; public string SecondNumber; public bool TestUI(string Answer){ FirstNumber = lblFirst.Text; SecondNumber = lblSecond.Text; txtAnswer.Text = Answer; //Ejecuta el suceso Changed. txtAnswer_TextChanged(this, EventArgs.Empty); //Comprueba si es correcto. if (lblFeedback.Text == "Correcto") return true; else return false; } #endif

El cdigo anterior utiliza directivas de procesador #If ... #End If o #if ... #endif para evitar que el interface de prueba se compile en la versin de distribucin del producto. Esto es importante porque un interface de prueba expone el funcionamiento interno de la aplicacin, que normalmente se quiere mantener privado en la versin final.

10.1.5 Pruebas de regresin


Las pruebas de unidad y de integracin forman la base de las pruebas de regresin. Segn se escribe y pasa cada prueba se registra en la biblioteca de pruebas para ejecucin de pruebas planificada de forma regular. Si un nuevo componente o un cambio en un componente existente rompe una de las pruebas de unidad o de integracin existentes el error se denomina regresin. Si las pruebas estn correctamente diseadas las pruebas de unidad y de integracin informan de sus errores de forma que es fcil localizar la causa de la regresin. Si la prueba no proporciona una forma sencilla de localizar la causa puede que necesite mejorar estas pruebas so que necesite escribir nuevas pruebas para capturar la regresin. La clave del xito tanto en las pruebas de integracin como en las de regresin es ejecutar con frecuencia el conjunto de pruebas completo si es posible como parte de una compilacin nocturna. La deteccin temprana de los errores y su resolucin en cuanto se producen impide que un error oculte otros.

10.1.6 Pruebas de carga


Cuando se despliega una aplicacin Web puede ser utilizada por uno o dos clientes a la vez, o puede que reciba miles de peticiones. Para averiguar cmo funcionar esta aplicacin en estas condiciones variables necesita realizar pruebas de carga. Use el centro de pruebas de aplicaciones (ACT) para crear y ejecutar pruebas de carga en una aplicacin Web. Para usar ACT siga estos pasos: 1. Cree una prueba grabando una sesin de usuario con la aplicacin Web usando ACT. 2. Establezca las propiedades de nivel de carga y duracin de la prueba. 3. Ejecute la prueba. En general, las pruebas de carga no se crean tan temprano ni se ejecutan con tanta frecuencia como las de unidad, integracin o regresin. Las siguientes secciones describen con ms detalle el procedimiento anterior. Grabar una prueba de carga Para grabar una prueba de carga en ACT siga estos pasos. 1. 2. 3. 4. 5. 6. En el men Accin de ACT seleccione Nueva Prueba. ACT muestra el asistente de nueva prueba. Pulse Siguiente. El asistente muestra la pgina Origen de prueba. Seleccione Grabar una nueva prueba y pulse siguiente. El asistente muestra la pgina Tipo de prueba. Pulse siguiente. El asistente muestra la pgina Explorar Registro. Pulse Iniciar grabacin. El asistente muestra una ventana de exploracin. Ejecute las acciones que quiere grabar. Por ejemplo, puede recorrer todas las pginas de la aplicacin Web, ejecutando tareas en todas las pginas. 7. En la pgina de Explorar registro pulse Detener grabacin cuando termine de grabar acciones, y pulse Siguiente. El asistente muestra la pgina Propiedades de prueba. 8. Escriba un nombre para la prueba y pulse Siguiente. El asistente muestra la pgina Completar nueva prueba. Pulse Finalizar para cerrar el asistente.

195

MCAD/MCSD

Establecer propiedades de prueba. Despus de grabar una prueba se muestra en la lista de pruebas de ACT. Las pruebas ACT se pueden escribir en VBScript o JScript, pero ACT las graba usando solo VBScript. Despus de grabar una prueba establezca la carga y duracin de la prueba siguiendo estos pasos. 1. En el men Accin seleccione Propiedades. ACT muestra las propiedades de carga y duracin de la prueba. 2. Establezca el nivel de carga para incrementar el nmero de usuario que acceden a la aplicacin Web simultneamente. Establezca la duracin para ejecutar la prueba durante un cierto tiempo o para una serie de peticiones. Pulse Aceptar cuando termine. Ejecutar pruebas de carga Para ejecutar una prueba de carga en ACT seleccione Iniciar prueba en el men Accin. ACT muestra el dilogo Estado de prueba. La ejecucin de pruebas con ACT y el anlisis de sus resultados se trata en ms detalle en la leccin 2.

10.1.7 Pruebas de plataforma


Para aplicaciones Web las pruebas de plataforma normalmente significan verificar cuatro puntos principales. Los formularios Web se muestran correctamente en todos los navegadores soportados y en todas las versiones de estos navegadores. La aplicacin Web gestiona correctamente todas las versiones de navegador no soportadas, por ejemplo mostrando instrucciones para la descarga de la versin correcta. Se pide al cliente que instale los componentes necesarios, como objetos ActiveX o plugins, si no estn ya instalados en su ordenador. La aplicacin Web tiene un rendimiento aceptable con las formas de conexin ms lentas, como mdems. Para ejecutar pruebas de plataforma necesita configurar un laboratorio de plataformas que contenga ordenadores representativos de las diferentes configuraciones hardware y software que soporte su aplicacin. La verificacin de que todos los formularios Web se muestran correctamente precisa de intervencin humana. ASP.NET disea los controles de forma diferente en diferentes navegadores, de modo que hay que inspeccionar visualmente la aplicacin Web como parte del ciclo de pruebas final.

10.2 Ejecutar pruebas


En la leccin anterior aprendi cmo planificar pruebas y cmo crear diferentes tipos de pruebas usando Visual Studio .NET. En esta leccin aprender cmo usar estas pruebas y capturar sus resultados.

10.2.1 Ejecutar pruebas con ACT


La leccin anterior le mostr brevemente cmo crear una prueba de carga y ejecutarla en ACT. Esta seccin describe cmo configurar y ejecutar pruebas ACT con ms detalle describiendo cmo realizar las siguientes tareas. Registrar resultados de pruebas Configurar las pruebas para usar varias conexiones simultneas Ejecutar pruebas con diferentes combinaciones de nombre de usuario y contrasea Aadir contadores de rendimiento a las pruebas Imitar diferentes navegadores y diferentes tipos de conexin.

Registrar resultados de pruebas De forma predeterminada, ACT crea un archivo de registro para cada proyecto de prueba en la carpeta /Perflogs de la unidad donde est instalado ACT. Para cambiar la ubicacin donde ACT guarda el archivo de registro siga estos pasos. 1. Pulse con el botn derecho en el elemento de proyecto en el panel izquierdo de la ventana de ACT y seleccione propiedades en el men emergente. ACT muestra las propiedades del proyecto de prueba. 2. Pulse la lengeta Depuracin y escriba una ubicacin en la caja Carpeta para guardar el registro. Pulse aceptar cuando termine. Los archivos de registro ACT guardan diferentes cantidades de informacin dependiendo de la configuracin de TraceLevel. Para cambiar la cantidad de informacin registrada configure la propiedad TraceLevel del objeto Test dentro de una secuencia de comandos de prueba. Por ejemplo, la siguiente lnea le dice a ACT que registre todos los mensajes: VBScript
Test.TraceLevel = -1

JScript
Test.TraceLevel = -1;

196

Developing Web Applications

Tabla 10. 2: Opciones de TraceLevel


Opcin Registra -1 Toda la informacin, incluyendo peticiones enviadas a la aplicacin, respuestas desde la aplicacin y mensajes escritos por mtodos Trace de la secuencia de comandos. 0 Ninguna informacin desactiva el registro. 1 Peticiones enviadas a la aplicacin y respuestas desde la misma. 2 Mensajes escritos por los mtodos Trace de la secuencia de comandos. Es la opcin predeterminada.

Utilice el mtodo Trace del objeto Test para escribir mensajes en el registro desde la secuencia de comandos. Por ejemplo, la siguiente secuencia de comandos escribe un mensaje en el registro si ACT no es capaz de conectar con el servidor. VBScript
Dim g_oConnection ConectaConServidor Sub ConectaConServidor() Set g_oConnection = Test.CreateConnection("http://www.contoso.com, 80, false) If (g_oConnection is Nothing) Then Test.Trace "Error: Imposible crear conexin con contoso" End If End Sub

JScript
var g_oConnection ConectaConServidor(); function ConectaConServidor(){ g_oConnection = Test.CreateConnection("http://www.contoso.com", 80, false); if (g_oConnection == null) Test.Trace("Error: Imposible crear conexin con contoso"); }

Usar varias conexiones ACT puede simular diferentes niveles de carga del servidor aadiendo varias conexiones para usar durante la prueba. De forma predeterminada ACT usa conexin para enviar peticiones a la aplicacin Web. Conexiones adicionales son equivalentes a usuarios simultneos adicionales. Para aumentar el nmero de conexiones utilizadas en una prueba: 1. Pulse con el botn derecho sobre el panel derecho de la ventana de ACT y seleccione Propiedades. ACT muestra las propiedades de la prueba. 2. Cambie el nmero en el apartado Nivel de carga de la prueba y pulse Aceptar. Aadir usuarios y contraseas ACT puede proporcionar a una aplicacin Web nombres de usuario y contraseas mediante los grupos de usuarios guardados con el proyecto de prueba. Esto permite probar cmo autentica una aplicacin Web a los usuarios y probar cookies. Para aadir nombres de usuario y contraseas a un grupo de usuarios: 1. Seleccione Usuarios en el panel izquierdo de la ventana ACT para expandir la lista de grupos de usuarios. 2. Seleccione un grupo de usuarios y escriba nombres de usuario y contraseas en la tabla del panel derecho de la ventana. 3. Pulse con el botn derecho sobre el nombre de la prueba y seleccione Propiedades. 4. Pulse la lengeta Usuarios y marque Especificar usuarios. Pulse Aceptar. ACT cambia de usuario automticamente para cada repeticin de la prueba y para cada conexin que crea. Tambin puede cambiar de usuario durante una prueba manualmente usando el mtodo GetNextUser del objeto Test: VBScript
Sub ChangeUser() Test.GetNextUser Test.Trace("Next user name: " & Test.GetCurrentUser.Name) End Sub

JScript
function ChangeUser(){ Test.GetNextUser(); Test.Trace("Next user name: " + Test.GetCurrentUser.Name); }

197

MCAD/MCSD

Aadir contadores de rendimiento Puede seguir el rendimiento de una aplicacin Web durante una prueba de carga aadiendo contadores de rendimiento a las propiedades de la prueba. Estos contadores de rendimiento son los mismos que se usaron para controlar el rendimiento del servidor en el Captulo 9, Generar y Desplegar Aplicaciones Web usando el aadido Alertas y contadores de rendimiento de la MMC. Para aadir contadores de rendimiento a una prueba de carga: 1. Pulse con el botn derecho sobre el elemento prueba en el panel izquierdo de la ventana de ACT y seleccione Propiedades. 2. Pulse la lengeta Contadores y Agregar. ACT muestra el dilogo Examinar contadores de rendimiento. 3. Seleccione los contadores que quiere controlar y pulse Agregar. Cierre cuando termine. 4. Pulse Aceptar. Cuando se ejecuta una prueba ACT guarda las estadsticas de rendimiento en un archivo XML que se muestra en el panel de resultados de la ventana de ACT. Imitar tipos de navegador ACT puede imitar varios tipos de navegados modificando la informacin de agente de usuario que incluye en la cabecera que enva con cada peticin. La prueba Browser Type del proyecto ACTSamples que se instala con ACT muestra cmo hacerlo. Puede copiar la prueba Browser Type a sus propios proyectos de prueba para comprobar la compatibilidad con navegadores y probar si su aplicacin responde correctamente a tipos de navegadores no soportados. Sin embargo, como ACT no muestra las respuestas no puede confiar en esta prueba para comprobar visualmente que su aplicacin Web se ve correctamente en diferentes navegadores. Obtener el contenido de las respuestas ACT devuelve la respuesta del servidor en la propiedad Body del objeto Response. Puede usar la funcin Instr de VBScript para comprobar si una respuesta contiene el resultado esperado: VBScript
Set oResponse = oConnection.Send(oRequest) If Instr(oResponse.Body, "Correcto") Then Test.Trace("Respuesta correcta.") Else Test.Trace("Respuesta incorrecta.") End If

JScript
oResponse = oConnection.Send(oRequest); if (oResponse.Body.search"Correcto")) Test.Trace("Respuesta correcta."); else Test.Trace("Respuesta incorrecta.");

La bsqueda en Body del proyecto ACTSamples muestra el uso de Instr para localizar elementos en una respuesta. Ms informacin: La ayuda en lnea de ACT proporciona una referencia completa del modelo de objetos de prueba e incluye informacin de concepto sobre el uso de ACT para pruebas de carga en aplicaciones Web.

10.2.2 Ejecutar pruebas con ensamblados .NET


ACT se escribi principalmente para interactuar con aplicaciones Web mediante peticiones y respuestas. Esto es adecuado para probar los aspectos de Interface de usuario de una aplicacin Web, pero es una limitacin cuando se intenta realizar pruebas sobre las clases subyacentes usadas por la aplicacin. Por ejemplo suponga que quiere usar ACT para probar la clase FlashCardClass como se muestra en la leccin 1. Probablemente intentara algo como: VBScript
Test.TraceLevel = -1 Dim FlashCard Set FlashCard = CreateObject("vbFlashCards.FlashCardClass") If (FlashCard Is Nothing) Then Test.Trace("Error: FlashCard no creado.") Test.StopTest End If

JScript
Test.TraceLevel = -1;

198

Developing Web Applications

var FlashCard; FlashCard = CreateObject("csFlashCards.FlashCardClass"); if (FlashCard == null) { Test.Trace("Error: FlashCard no creado."); Test.StopTest(); }

Lo malo es que esto no funciona. Como las aplicaciones Web estn basadas en el marco de trabajo .NET no puede usar sus espacios de nombres como argumento del mtodo CreateObject. Este mtodo espera el ID de programa (progID) de un objeto COM, no un espacio de nombres. Para usar una secuencia de comandos para probar un ensamblado .NET siga estos pasos: 1. Registre el ensamblado .NET para uso con COM. 2. Asegrese de que la aplicacin COM puede usar el ensamblado 3. Cree el objeto .NET usando el progID registrado para el ensamblado .NET. Las siguientes secciones describen estos pasos con ms detalle. Registrar ensamblados .NET Para registrar un ensamblado .NET en la base de datos de registro del sistema use RegAsm.exe. Esta utilidad se instala con el marco de trabajo .NET. Para utilizarla: 1. Inicie una ventana de consola de Visual Studio .NET. 2. En esta ventana vaya al directorio que contiene el ensamblado a registrar y ejecute el comando RegAsm.exe ensamblado.dll, donde ensamblado es el ensamblado que se quiere registrar. RegAsm.exe registra las clases pblicas del ensamblado .NET usando su espacio de nombres y nombres de clase como progID. Localizar el ensamblado .NET Despus de registrar un ensamblado .NET los componentes COM necesitan una forma de encontrarlo. Hay varias formas de hacerlo, pero estas son las tres ms sencillas: Instalar el ensamblado en el cach de ensamblados global (GAC) Copiar el ensamblado en el mismo directorio que el componente COM que lo va a usar Copiar el componente COM en el directorio donde reside el ensamblado. Los ensamblados instalados en el GAC estn disponibles para todas las aplicaciones en el ordenador. Antes de poder ser instalados en el cach, los ensamblados deben estar configurados con nombre seguro. Puede ver las instrucciones para configurar ensamblados e instalarlos en el GAC en la ayuda de Visual Studio. Para ensamblados que no estn pensados para compartir con otras aplicaciones la solucin ms sencilla puede copiar el ensamblado o el componente COM a la carpeta del otro. Esto es particularmente cierto para pruebas, en las que no se quiere que el ensamblado sea de acceso general. Crear el objeto .NET Despus de registrar un ensamblado .NET y asegurarse de que los componentes COM pueden encontrarlo puede crear una instancia del objeto .NET usando los mtodos de creacin del objeto COM, como la funcin CreateObject de VBScript. Para ver cmo funciona esto con una herramienta de pruebas como Windows Scripting Host siga estos pasos: 1. Registre un ensamblado de aplicacin Web tal como se indica en la seccin anterior. 2. Copie CScript.exe del directorio System32 de Windows al directorio \bin de la aplicacin Web. Esta es la copia de CScript que usaremos para las pruebas; debe estar en el mismo directorio que el ensamblado .NET para que los objetos COM y .NET puedan interactuar. 3. Cree un archivo VBScript o JScript y ejectelo usando la copia de CScript.exe que cre en el paso 1. El siguiente cdigo muestra cmo probar FlashCardClass usando Windows Scripting Host: VBScript
' TestFlash.vbs ' Pruebas de unidad de FlashCardClass Option Explicit Dim FlashClass

199

MCAD/MCSD

Set FlashClass = CreateObject("vbFlashCards.FlashCardClass") ' Comprueba si se ha creado la clase. If (FlashClass is Nothing) Then WScript.Echo "Error: no se ha creado FlashCardClass." WScript.Quit End If ' Prueba barajado FlashClass.Shuffle 1, 1000 Dim X, Y x = FlashClass.FirstNumber y = FlashClass.SecondNumber ' Baraja de nuevo FlashClass.Shuffle 1, 1000 If (x = FlashClass.FirstNumber) or (y = FlashClass.SecondNumber) Then WScript.Echo "Advertencia: nmero no nico." End If ' Prueba la respuesta If (FlashClass.FirstNumber + FlashClass.SecondNumber = FlashClass.Answer) Then WScript.Echo "Correcto: la respuesta suma" Else WScript.Echo "Error: Respuesta incorrecta." End If

JScript
// TestFlash.js // Pruebas de unidad de FlashCardClass var FlashClass; FlashClass = new ActiveXObject("vbFlashCards.FlashCardClass"); // Comprueba si se ha creado la clase. if (FlashClass == null){ WScript.Echo("Error: No se ha creado FlashCardClass."); WScript.Quit(); } // Prueba barajado FlashClass.Shuffle(1, 1000); var X, Y; x = FlashClass.FirstNumber; y = FlashClass.SecondNumber; // Baraja de nuevo FlashClass.Shuffle(1, 1000); if ((x == FlashClass.FirstNumber) (y == FlashClass.SecondNumber)) WScript.Echo("Advertencia: nmero no nico."); // Prueba la respuesta if (FlashClass.FirstNumber + FlashClass.SecondNumber == FlashClass.Answer()) WScript.Echo("Correcto: Respuesta suma"); else WScript.Echo("Error: Respuesta incorrecta.");

Para ejecutar la anterior secuencia de comandos use una lnea similar a la siguiente:
@rem VBScript bin\cscript TestFlash.vbs > logs\FlashErr.log @rem JScript bin\cscript TestFlash.js > logs\FlashErr.log

10.2.3 Compilaciones y pruebas desatendidas


La ejecucin de pruebas de unidad, integracin y carga de forma regular proporciona un aseguramiento de calidad constante y comprueba regresiones. La mayora de los desarrolladores ejecutan la compilacin y una serie de pruebas cada noche. La ejecucin de pruebas nocturnas previene conflictos con conexiones y no disturba el flujo de trabajo mientras que una mquina est dedicada a una compilacin. Al ejecutarse de noche estas compilaciones por lo general son desatendidas, lo que significa que no debe haber nadie presente para iniciarlas o controlar su progreso. Para ejecutar compilaciones y pruebas desatendidas siga estos pasos: 1. Cree un archivo de secuencia de comandos con las rdenes para establecer variables de entorno, compilar y probar que quiera ejecutar. 2. Use el administrador de tareas programadas de Windows para planificar la ejecucin de la . 3. Controle los archivos de registro para asegurarse de que la compilacin y pruebas tienen xito.

200

Developing Web Applications

Crear un archivo de comandos. Puede crear un archivo de comandos (.bat) para ejecutar cualquier conjunto de rdenes que quiera. En general un archivo de comandos tiene tres secciones: Configuracin de variables de entorno, como PATH y LIB, necesarias para localizar los componentes utilizados en la compilacin. Ejecutar el entorno de desarrollo de Visual Studio .NET para compilar el ensamblado. Ejecutar las herramientas de prueba utilizadas para probar el ensamblado. Las variables de entorno que utiliza Visual Studio .NET se pueden encontrar en el archivo de comandos VsVars.bat que se instala en el directorio Command\Tools del producto. Puede cortar y pegar desde este archivo a su archivo de comandos. Para ejecutar Visual Studio .NET desde lnea de comandos use el comando DevEnv.exe con el archivo de solucin del proyecto (.sln). Por ejemplo, la siguiente lnea compila la aplicacin FlashCards usando la configuracin Debug y registra todos los errores en el directorio Logs:
DevEnv vbFlashCards.sln /build Debug > Logs\builders.log

Puede reunir todos estos pasos en un nico archivo de comando. Por ejemplo, el siguiente archivo configura las variables de entorno, compila una aplicacin Web y ejecuta una secuencia de comandos de prueba sobre el ensamblado.
@rem Build.bat @rem ======================================================================== @rem Configuracin de entorno tomada de vsvars32.bat @rem ======================================================================== @SET VSINSTALLDIR=E:\Program Files\Microsoft Visual Studio .NET\Common7\IDE @SET VCINSTALLDIR=E:\Program Files\Microsoft Visual Studio .NET @SET FrameworkDir=C:\WINDOWS\Microsoft.NET\Framework @SET FrameworkVersion=v1.0.3705 @SET FrameworkSDKDir=C:\Program Files\Microsoft Visual Studio .NET\FrameworkSDK @rem Raz de los archivos comunes de Visual Studio. @rem Raz de los archivos instalados del ide de Visual Studio. @rem @set DevEnvDir=%VSINSTALLDIR% @rem Raz de los archivos instalados de Visual C++. @rem @set MSVCDir=%VCINSTALLDIR%\VC7 @set PATH=%DevEnvDir%;%MSVCDir%\BIN;%VCINSTALLDIR%\Common7\Tools; %VCINSTALLDIR%\Common7\Tools\bin\prerelease;%VCINSTALLDIR%\Common7\Tools\bin;%Fra meworkSDKDir%\bin;%FrameworkDir%\%FrameworkVersion%;%PATH%; @set INCLUDE=%MSVCDir%\ATLMFC\INCLUDE;%MSVCDir%\INCLUDE; %MSVCDir%\PlatformSDK\include\prerelease;%MSVCDir%\PlatformSDK \include;%FrameworkSDKDir%\include;%INCLUDE% @set LIB=%MSVCDir%\ATLMFC\LIB;%MSVCDir%\LIB; %MSVCDir%\PlatformSDK\lib\prerelease; %MSVCDir%\PlatformSDK\lib;%FrameworkSDKDir%\lib;%LIB% @rem ======================================================================== @rem Fin de configuracin del entorno @rem ======================================================================== @rem ======================================================================== @rem Comandos de compilacin del entorno de desarrollo @rem ======================================================================== devenv vbBuildSnippet.sln /build debug > logs\builderrs.log @rem ======================================================================== @rem Fin de comandos de compilacin @rem ======================================================================== @rem ======================================================================== @rem Comandos de prueba @rem ======================================================================== bin\cscript RunTests.vbs > logs\testerrs.log @rem ======================================================================== @rem Fin de comandos de prueba @rem ========================================================================

201

MCAD/MCSD

Planificacin de tareas. Para planificar la ejecucin nocturna de un archivo de comandos use el planificador de tareas de Windows. Siga estos pasos: 1. En el panel de control, tareas programadas, pulse Agregar tarea programada. Se abrir el asistente para taras programadas. 2. Pulse Siguiente y Examinar para seleccionar el archivo de comandos. Cuando haya seleccionado el archivo el asistente muestra la pgina de planificacin. 3. Seleccione una opcin para indicar cundo ejecutar la tarea y pulse Siguiente. El asistente muestra la pgina de hora. 4. Escriba la hora para ejecutar la tarea y pulse Siguiente. El asistente muestra la pgina de contrasea. 5. Escriba el nombre de usuario y contrasea bajo los que se debe ejecutar el comando, pulse Siguiente y despus Finalizar para completar el asistente. Ver archivos de registro Como las compilaciones y pruebas planificadas con el planificador de tareas corren desatendidas es importante controlar los archivos de registro creados por los comandos en el proceso de compilacin. Los comandos de compilacin y prueba que se mostraron anteriormente usan el operador de redireccin (>) para escribir la salida de los comandos en archivos de registro que se pueden ver en el Block de notas.

10.3 Depurado
Las pruebas son probablemente una de las pocas tareas en las que el fracaso es un tipo de xito. En esta leccin aprender cmo usar estos xitos para corregir problemas en su aplicacin. Los temas que cubre esta leccin se apoyan en la discusin de las herramientas de depurado de Visual Studio que se trat en el Captulo 1, Introduccin a la programacin Web. Incluye correccin de problemas concretos que no cubren las pruebas, aadir cdigo de diagnstico a una aplicacin y depurar una aplicacin Web que corre en un servidor remoto.

10.3.1 Poner a trabajar los resultados de las pruebas


Si ha ejecutado las pruebas de unidad de la aplicacin FlashCards en la leccin 1 habr observado que no pasa las pruebas. Esto se debe a que FlashCards es un programa de demostracin simplificado, no una aplicacin robusta pensada para uso comercial. Sin embargo, los resultados son instructivos. El primer conjunto de errores que se encuentra en las pruebas de unidad de FlashCardClass son desbordamientos al utilizar MinValue y MaxValue enteros para inicializar los nmeros aleatorios. La suma de dos valores cercanos al valor mximo de entero tiene como resultado un nmero mayor que un entero. A continuacin se muestra el cdigo relacionado Visual Basic .NET
' Cdigo de prueba Function TestFlashCard() As Boolean 'Crea la clase Dim FlashCard As New vbFlashCards.FlashCardClass() 'Prueba si la clase existe. If IsNothing(FlashCard) Then Console.WriteLine("FlashCardClass fallida") 'Devuelve false y termina. Return False End If 'Prueba mtodo de barajado. FlashCard.Shuffle(Integer.MinValue, Integer.MaxValue) 'Prueba propiedades. If (FlashCard.Answer <> FlashCard.FirstNumber + FlashCard.SecondNumber) Then Console.Write("Error: Respuestas no corresponden") End If End Function ' Cdigo de FlashCardClass con error. ' Calcula la respuesta en base a la operacin actual. Public Function Answer() As Integer Select Case mstrOp Case "+" Return mintFirstNumber + mintSecondNumber Case "x", "*" Return mintFirstNumber * mintSecondNumber Case "-" Return mintFirstNumber mintSecondNumber

' Desbordamiento!!!!

202

Developing Web Applications

Case Else Return 0 End Select End Function

Visual C#
// Cdigo de prueba. static bool TestFlashCardClass(){ //Crea la clase csFlashCards.FlashCardClass FlashCard = new csFlashCards.FlashCardClass(); //Comprueba si existe la clase. if (FlashCard == null){ Console.WriteLine("FlashCardClass fallida"); //Devuelve false y termina. return false; } //Prueba mtodo de barajado con valores mnimo y mximo. FlashCard.Shuffle(int.MinValue, int.MaxValue); //Prueba propiedades. int intFirst = FlashCard.FirstNumber; int intSecond = FlashCard.SecondNumber; double dblAnswer = intFirst + intSecond; if (dblAnswer != (double)FlashCard.Answer()) Console.WriteLine("Error: los nmeros no suman"); } // Cdigo de FlashCardClass con error. // Calcula la respuesta en base a la operacin actual. public int Answer(){ switch(mstrOp){ case "+": return mintFirstNumber + mintSecondNumber; case "x": return mintFirstNumber * mintSecondNumber; case "*": return mintFirstNumber * mintSecondNumber; case "-": return mintFirstNumber - mintSecondNumber; default : return 0; } }

break; break; break; break;

Tiene dos formas de tratar este problema: restringir el rango de valores posibles de las propiedades FirstNumber y SecondNumber o cambiar el tipo devuelto por el mtodo Answer. La segunda posibilidad es ms obvia desde el punto de vista del usuario porque los enteros son un tipo de entrada habitual y sera difcil explicar porqu se usa un tipo menor para estas propiedades. El siguiente cdigo muestra los cambios en el mtodo Answer que permiten pasar las pruebas de unidad. Visual Basic .NET
Public Function Answer() As Double Select Case mstrOp Case "+" Return CDbl(mintFirstNumber) Case "x", "*" Return CDbl(mintFirstNumber) Case "-" Return CDbl(mintFirstNumber) Case "/" Return CDbl(mintFirstNumber) Case Else Return 0 End Select End Function

+ CDbl(mintSecondNumber) * CDbl(mintSecondNumber) - CDbl(mintSecondNumber) / CDbl(mintSecondNumber)

Visual C#
public double Answer(){ switch(mstrOp){ case "+": return mintFirstNumber case "x": return mintFirstNumber case "*": return mintFirstNumber case "-": return mintFirstNumber default : return 0; } } + * * mintSecondNumber; mintSecondNumber; mintSecondNumber; mintSecondNumber; break; break; break; break;

203

MCAD/MCSD

Si especifica una operacin diferente a +. -, * o x surge otro problema con la clase FlashCardClass. La propiedad Operation se limita a devolver 0, lo que resulta un poco tonto. Los siguientes cambios aseguran que solo se usan operaciones vlidas: Visual Basic .NET
Public Property Operation() As String Get Operation = mstrOp End Get Set(ByVal Value As String) If InStr("+-/x*", Value) Then mstrOp = Value Else Throw New Exception("Operador no reconocido") End If End Set End Property

Visual C#
public string Operation{ get{return mstrOp;} set{ if (" +-/x*".IndexOf(value, 1) != 0) mstrOp = value; else throw(new Exception("Operador no reconocido")); } }

Estas correcciones muestran lo importante que es realizar pruebas de unidad antes de comprobar las nuevas clases en el conjunto del proyecto. Cuando una clase es parte de un proyecto mayor es mucho ms difcil localizar la causa de un error.

10.3.2 Clases Debug y Trace


El marco de trabajo .NET incluye las clases Debug y Trace en el espacio de nombres System.Diagnostics como herramientas para ayudarle a capturar errores y comportamientos inesperados de su aplicacin. Estas clases permiten mostrar alertas o escribir mensajes basados en los resultados de su aplicacin. La diferencia entre las dos clases es cmo la gestionan las compilaciones definitivas (release). De forma predeterminada, los mtodos y propiedades de Debug se eliminan automticamente del cdigo en la compilacin definitiva, mientras que los de Trace se mantienen. Esto le da dos niveles de diagnstico: uno para errores de depurado anteriores a la distribucin y otro para diagnsticos de rendimiento y problemas sobre el terreno. Como Trace y Debug son parte de un espacio de nombres .NET necesita aadirlo o importarlo antes de utilizar estas clases.

10.3.3 Mostrar alertas y mensajes


El mtodo Assert de las clases Debug y Trace comprueban un valor y muestran una alerta si es False. Use este mtodo para detener una aplicacin cuando hay un resultado inesperado. Por ejemplo, el siguiente cdigo muestra una alerta si el nmero mostrado en el formulario FlashCards no se suma tal como se espera: Visual Basic .NET
Private Sub txtAnswer_TextChanged(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles txtAnswer.TextChanged If txtAnswer.Text = FlashCard.Answer Then lblFeedback.Text = "Correcto" Debug.Assert(CInt(txtAnswer.Text) = CInt(lblFirst.Text) + _ CInt(lblSecond.Text), "los valores del formulario no se suman") 'Obtiene otro conjunto de nmeros. FlashCard.Shuffle() 'Renueva la presentacin para mostrar los nuevos nmeros. RefreshDisplay() 'Limpia la respuesta txtAnswer.Text = "" Else lblFeedback.Text = "Error; pruebe de nuevo." End If End Sub

204

Developing Web Applications

Visual C#
private void txtAnswer_TextChanged(object sender, System.EventArgs e){ if(txtAnswer.Text == FlashCard.Answer().ToString()){ lblFeedback.Text = "Correcto"; Debug.Assert(Convert.ToInt32(txtAnswer.Text) == Convert.ToInt32(lblFirst.Text) + Convert.ToInt32(lblSecond.Text), "Los valores del formulario no se suman"); //Obtiene otro conjunto de nmeros. FlashCard.Shuffle(); //Renueva la presentacin para mostrar los nuevos nmeros. RefreshDisplay(); //Limpia la respuesta txtAnswer.Text = ""; }else lblFeedback.Text = "Error; pruebe de nuevo."; }

En una aplicacin Web la alerta se muestra en el servidor. Si est ejecutando el servidor en su mquina local esta alerta se ve tal cmo se espera. Si corre en un servidor remoto solo ver la alerta si est asociado al proceso de aplicacin que corre en el servidor para depurado remoto, como se indica ms adelante. Para escribir un mensaje sin detener la aplicacin use los mtodos Write o WriteLine. De forma predeterminada estos mensajes se muestran en la ventana de resultados de Visual Studio durante el depurado.

10.3.4 Registrar mensajes de Debug y Trace


Para registra los mensajes de Debug y Trace en una aplicacin desplegada cree una clase TextWriterTraceListener y adala a la coleccin Listeners de las clases Debug y Trace. Por ejemplo, el siguiente cdigo dirige los resultados de Debug a la consola del servidor. Visual Basic .NET
Debug.Listeners.Add(New TextWriterTraceListener(Console.Out)) Debug.WriteLine("Iniciando pruebas.")

Visual C#
Debug.Listeners.Add(new TextWriterTraceListener(Console.Out)); Debug.WriteLine("Iniciando pruebas.");

Para escribir mensajes en un archivo en lugar de en la consola especifique un nombre de archivo y use el mtodo Flush para escribir la salida. Por ejemplo, el siguiente cdigo escribe un mensaje en el archivo Results.log. Visual Basic .NET
Debug.Listeners.Add(New TextWriterTraceListener("Results.log")) Debug.WriteLine("Iniciando pruebas.") Debug.Flush()

Visual C#
Debug.Listeners.Add(new TextWriterTraceListener("Results.log")); Debug.WriteLine("Iniciando pruebas."); Debug.Flush();

10.3.5 Depurado remoto


El asistente de instalacin de Visual Studio .NET incluye una opcin para instalar componentes remotos. Ejecute la instalacin de Visual Studio en el servidor y seleccione la opcin Depurado remoto completo. Se instalarn los componentes necesarios y se configurar el servidor para permitir depurado remoto. Establecer permisos en el servidor Para poder depurar procesos que corren en el servidor debe tener una cuanta de usuario en l, y esta cuenta debe pertenece al grupo Usuario del depurador. El asistente de instalacin de Visual Studio .NET crea este grupo cuando se instalan los componentes de depurado remoto. Debe asegurarse de que los usuarios que necesitan privilegios de depurado en el servidor pertenecen a este grupo. Asociar a un proceso remoto Visual Studio .NET se puede asociar a procesos que corren en un servidor remoto. Mientras est asociado al proceso Visual Studio puede recibir mensajes en la ventana de resultados, mostrar alertas del mtodo Assert, establecer puntos de interrupcin, ver variables y recorrer el cdigo que corre en el servidor remoto. Para asociarse a un proceso remoto: 1. En el men Herramientas pulse Procesos de depuracin. Visual Studio muestra el dilogo Procesos. 2. De forma predeterminada las aplicaciones Web corren en un proceso llamado aspnet_wp.exe. Seleccione el proceso remoto que quiere depurar, pulse Asociar y Cerrar. 205

MCAD/MCSD

Cuando est asociado a un proceso remoto Visual Studio .NET puede recorrer el cdigo estableciendo puntos de interrupcin. La forma ms fcil de hacer esto con una aplicacin Web es establecer un punto de interrupcin en la funcin Page_Load para detener la aplicacin al inicio de un formulario Web y entonces establecer puntos de interrupcin o inspecciones en el cdigo remoto como se desee. Para establecer un punto de interrupcin en un proceso remoto: 1. Pulse la lengeta Puntos de interrupcin en Visual Studio. 2. Pulse el botn Nuevo en la barra de herramientas de puntos de interrupcin. Visual Studio muestra el dilogo Nuevo punto de interrupcin. 3. Escriba un nombre de procedimiento en la caja Funcin y pulse Aceptar. Para aplicaciones Web lo ms fcil es detener la aplicacin en el procedimiento Page_Load y despus agregar los puntos de interrupcin requeridos. Cuando se detiene un proceso remoto en un punto de interrupcin se pueden usar las herramientas de depurado de Visual Studio .NET para ver variables, recorrer el cdigo o ejecutar comandos tal como se hara con un proceso local

10.4 Resumen
Las pruebas miden la adaptacin a los requisitos de producto. Las pruebas de unidad comprueban que cada fragmento de cdigo funciona correctamente. Las pruebas de integracin comprueban que todos los componentes funcionan en conjunto. Las pruebas de regresin aseguran que el nuevo cdigo no introduce errores en el existente. Las pruebas de carga comprueban que el producto funciona bajo uso extremo. Las pruebas de plataforma aseguran que una aplicacin Web se muestra correctamente y tiene un rendimiento aceptable usando diferentes configuraciones de navegador y conexin de red. Utilice ACT para grabar interaccin del usuario con una aplicacin Web en VBScript y despus reproduzca esta secuencia de comandos para simular varios usuarios y registrar errores de aplicacin y rendimiento del servidor. Para probar un ensamblado .NET con Windows Scripting Host registre el ensamblado para uso con COM y copie CScript.exe al directorio del ensamblado. Para ejecutar compilaciones y pruebas desatendidas cree un archivo de comando que contenga los comandos de compilacin y las secuencias de comandos de pruebas y planifique el archivo de comandos con el planificador de tareas de Windows. Use las clases de diagnstico Debug y Trace para mostrar condiciones de alerta y de error durante el proceso de desarrollo. De forma predeterminada el cdigo escrito con la clase Debug se elimina en las compilaciones finales, mientras que el de la clase Trace se mantiene. Visual Studio .NET puede asociarse al proceso de una aplicacin Web que corra en un servidor remoto para depurar la aplicacin con una configuracin real.

10.5 Prctica: Pruebas y depurado


En esta prctica aplicar las lecciones de este captulo para repasar un plan de pruebas real, escribir unidades de prueba para una aplicacin de ejemplo, hacer una prueba de carga a una aplicacin desplegada y recorrer una aplicacin Web que corre en un servidor remoto usando las herramientas de depurado de Visual Studio .NET.

10.5.1 Repasar un plan de pruebas


Las estrategias y terminologa de pruebas cambian de una compaa a otra. En este ejercicio usar un plan de pruebas de su propia compaa para identificar los conceptos tratados en la leccin 1. Si no trabaja para una compaa que use planes de prueba busque en Internet usando la frase plan de pruebas software (software test plan) y elija un plan de pruebas en los resultados. Usando un plan de pruebas real, destaque cualquier mencin a los siguientes elementos: Pruebas de unidad Pruebas de integracin Pruebas Ad hoc. Vea si puede encontrar las respuestas a las preguntas hechas en la leccin 1 206 Cmo estn escritas las pruebas? Quin es responsable de las pruebas? Cundo se realizan las pruebas? Dnde se guardan las pruebas y sus resultados? Qu se est probando?

Developing Web Applications

Segn este informacin le da el plan de prueba una idea clara de cmo demostrarn las pruebas que se cumplen los requisitos?

10.5.2 Escribir pruebas de unidad


En este ejercicio usar VBScript o JScript para crear pruebas de unidad para las clases Sphere y Circle que se derivaron de la clase abstracta Shapes en el captulo 3, Trabajar con objetos Web. Las pruebas deben verificar que se cumplen las siguientes condiciones: Se pueden crear las clases Circle y Sphere. Se pueden pasar las clases a procedimientos que acepten el interface IFigure. Todas las propiedades funcionan con valores mnimos y mximos. Todos los mtodos devuelven los resultados esperados para dos o ms casos de prueba. Para crea las pruebas de unidad: 1. 2. 3. 4. libro. Registre el ensamblado para uso con COM mediante la utilidad RegAsm.exe. Copie CScript.exe al directorio que contiene el ensamblado que va a probar Cree las pruebas en VBScript o JScript usando el Block de notas o cualquier otro editor Ejecute las pruebas usando la copia de CScript.exe. Cuando termine compare sus resultados con los de los archivos de ejemplo del CD-ROM que acompaa al

10.5.3 Crear una prueba de carga


Si tiene Visual Studio .NET Enterprise Architect use ACT para crear una prueba de carga para una aplicacin Web que haya desplegado en un servidor de prueba. Elija la aplicacin Web que prefiera, pero siga estos parmetros de prueba: 1. Registre al menos cinco peticiones diferentes al servidor. 2. Agregue contadores de rendimiento para el porcentaje de tiempo de procesador, pginas de memoria por segundo y promedio de longitud de la cola de lectura de disco. 3. Registre los resultados en un directorio dentro de la estructura de la aplicacin Web. 4. Configure las propiedades de la prueba para que se ejecute durante 30 segundos usando 4 conexiones simultneas. 5. Ejecute la prueba. 6. Vea los contadores de rendimiento del servidor en forma grfica dentro de ACT.

10.5.4 Recorrer un proceso remoto


En este ejercicio usar Visual Studio .NET para detener y recorrer una aplicacin Web en ejecucin en un servidor remoto. Para completar este ejercicio debe pertenecer al grupo Usuarios del depurador del servidor, y este debe tener instalados los componentes remotos de Visual Studio .NET. 1. Desde su puesto de trabajo acceda a la aplicacin Web usando el explorador de Internet. Esto asegura que la aplicacin est en ejecucin en el servidor cuando se intente asociar con su proceso. 2. En el men Herramientas de Visual Studio seleccione Procesos de depuracin. Seleccione el servidor donde corre la aplicacin, seleccione el proceso de la aplicacin (llamado aspnet_wp.exe) y pulse Asociar. 3. Establezca un punto de interrupcin en la funcin Page_Load. 4. Cambie al explorador de Internet y pulse Recargar. 5. Vuelva a Visual Studio. La aplicacin se debe haber detenido en Page_Load. 6. Establezca puntos de interrupcin en otros lugares de la aplicacin. 7. En Visual Studio pulse Continuar para ejecutar hasta el siguiente punto de interrupcin.

10.6 Repaso
Las siguientes preguntas estn pensadas para reforzar informacin clave mostrada en este captulo. Si no es capaz de contestar a una pregunta repase la leccin correspondiente e intente de nuevo. Las respuestas se pueden encontrar en el captulo 16. 1. Cmo se relacionan entre s las pruebas de unidad, integracin y regresin?. 2. Por qu tiene ms importancia la prueba de carga en una aplicacin Web que en una aplicacin Windows independiente? 3. Cul es la diferencia entre las clases Debug y Trace? 4. Cules son los dos pasos especiales necesarios para asegurar que un componente COM puede usar un componente de un ensamblado .NET?

207

MCAD/MCSD

208

Developing Web Applications

11 Crear controles Web


Los controles personalizados extienden las herramientas disponibles para los desarrolladores Web. Usando controles personalizados puede encapsular aspectos clave del interface visual y lgica de programa que quiere reutilizar a lo largo de su aplicacin o de su organizacin. Visual Studio .NET proporciona tres tipos de controles personalizados para uso en aplicaciones Web. En este captulo aprender cmo desarrollar y usar estos tipos de controles: Controles de usuario Web: Combinan controles de servidor y HTML existentes usando el diseador de Visual Studio para crear unidades funcionales que encapsulan algn aspecto del interface de usuario. Los controles de usuario residen en archivos de contenido que se deben incluir en el proyecto en el que se usen. Controles personalizados compuestos: Crean nuevos controles a partir de controles de servidor y HTML existentes. Aunque son similares a los controles de usuario, los controles compuestos se crean en cdigo en lugar de visualmente y por tanto se pueden compilar en un ensamblado (.dll) que se puede compartir entre varias aplicaciones y usar desde la caja de herramientas de Visual Studio. Controles de usuario trazados: Crean controles completamente nuevos mediante HTML directo en lugar de usar composicin. Estos controles se compilan y se pueden usar desde la caja de herramientas, igual que los compuestos, pero hay que escribir cdigo extra para tareas que en los compuestos son automticas. Para completar este captulo debe: Estar familiarizado con el ciclo de vida de una aplicacin Web. Comprender las tcnicas de programacin orientada a objetos, espacios de nombres e informacin de estado, como se indica en el Captulo 3, Trabajar con objetos Web. Tener experiencia en el desarrollo de aplicaciones Web con controles de servidor y HTML estndar.

11.1 Crear controles de usuario Web


Los controles Web de usuario combinan uno o ms controles de servidor o HTML en una pgina de control de usuario Web, que a su vez se puede usar en un formulario Web como un control nico. Los controles de usuario hacen posible crear un nico componente visual que usa varios controles para realizar una tarea concreta. Una vez creados, los controles de usuario se pueden usar en los formularios Web de un proyecto. Sin embargo, como no se compilan en ensamblados tienen las siguientes limitaciones que no se encuentran en los dems tipos de controles: Debe haber una copia del control en cada proyecto de aplicacin Web que lo utilice. No se pueden cargar en la caja de herramientas de Visual Studio. Se crean arrastrndolos desde el explorador de soluciones. El cdigo del control de usuario se inicializa despus de que se cargue la pgina web, lo que significa que los valores de las propiedades del control de usuario no se actualizan hasta despus del suceso Page_Load del formulario Web.

11.1.1 Crear y usar controles de usuario


La creacin y uso de un control de usuario en una aplicacin Web tiene cinco pasos: 1. 2. 3. 4. 5. Agregar una pgina de control Web de usuario (.ascx) al proyecto Dibujar el interface de usuario del control en el diseador Escribir cdigo para crear las propiedades, mtodos y sucesos del control Usar el control en un formulario Web arrastrndolo desde el explorador de soluciones Usar el control en el cdigo del formulario Web declarando el control a nivel de mdulo y usando sus mtodos, propiedades y sucesos.

11.1.2 Crear un control de usuario y dibujar su interface


Los controles de usuario se crean a partir de otros controles de servidor y HTML de la caja de herramientas de Visual Studio. Esto se hace arrastrando los controles a una pgina de control de usuario, que es sencillamente otro tipo de archivo en un proyecto de aplicacin Web, como un formulario Web o una pgina HTML. Los controles de usuario se identifican por la extensin .ascx en su nombre de archivo. Para crear un control de usuario y agregarlo a su aplicacin Web: 1. En el men Proyecto seleccione Agregar control de usuario Web. Visual Studio muestra el dilogo Agregar nuevo elemento. 2. Escriba el nombre del control de usuario en la caja de texto Nombre. Visual Studio crea una nueva pgina de control de usuario en blanco y la agrega al proyecto. Despus de aadir una pgina de control de usuario al proyecto cree el interface visual del control aadiendo controles de servidor o HTML. Los controles de usuario solo permite diseo de flujo, de modo que si quiere colocar 209

MCAD/MCSD

los controles en la pgina usando rejilla deber colocar un control HTML Grid Layout Panel para usarlo como contenedor para los controles que quiere colocar. En los siguientes apartados se utilizar un control de usuario llamado Spin con dos botones, cuyo HTML es el siguiente:
<DIV id="pnlGrid" runat="server" style="WIDTH: 20px; POSITION: relative; HEIGHT: 48px" ms_positioning="GridLayout"> <asp:Button id="butUp" Text="^" runat="server" /> <asp:Button id="butDown" Text="v" runat="server" /> </DIV>

11.1.3 Escribir las propiedades, mtodos y sucesos del control


Los controles que se aaden al control de usuario se manipulan desde el mdulo de cdigo del control de usuario. Esto permite ocultar el funcionamiento interno del control y exponer las tareas que ejecuta como propiedades, mtodos y sucesos. Para editar el mdulo de cdigo del control de usuario pulse dos veces sobre el control. La plantilla que genera Visual Studio para un nuevo control es similar a la de un formulario Web, con las siguientes notables diferencias: La clase del control de usuario se declara como MustInherit en Visual Basic o abstract en C#. La clase de control de usuario solo se puede usar como base para una clase derivada. En este caso la clase derivada es el control de usuario creado en el formulario Web. La clase del control de usuario se basa en System.Web.UI.UserControl. Esta clase base proporciona el conjunto bsico de propiedades y mtodos que se usan para crear el control y obtener su configuracin de tiempo de diseo de sus atributos HTML en el formulario Web. El suceso Page_Load del control de usuario se produce cuando lo carga la pgina que lo contiene. El Page_Load del control se produce despus del Page_Load del formulario Web. Para crear propiedades y mtodos para el control de usuario que pueda usar desde un formulario Web: 1. Cree la propiedad o mtodo pblico que quiere que est disponible para el formulario Web contenedor. 2. Escriba cdigo para responder a los sucesos que se produzcan para los controles contenidos por el control de usuario. Estos procedimientos de suceso hacen el grueso del trabajo del control de usuario. 3. Si la propiedad o mtodo necesita retener un valor entre presentaciones de la pgina escriba el cdigo para guardar y recuperar los valores en ViewState del control. Por ejemplo, el siguiente cdigo muestra una propiedad Value que devuelve el valor del control Spin creado en la seccin anterior. Visual Basic .NET
Public Property Value() As Integer Get Return ViewState("Value") End Get Set(ByVal Value As Integer) ViewState("Value") = Value End Set End Property

Visual C#
public int Value{ get{return Convert.ToInt32(ViewState["Value"]);} set{ViewState["Value"] = value; } }

El usuario cambia el valor del control Spin pulsando en sus botones, de modo que el siguiente cdigo incrementa o decrementa el valor dependiendo del botn pulsado: Visual Basic .NET
Private Sub butDown_Click(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles butDown.Click Me.Value -= 1 End Sub Private Sub butUp_Click(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles butUp.Click Me.Value += 1 End Sub

Visual C#
private void butDown_Click(object sender, System.EventArgs e){this.Value -= 1;}

210

Developing Web Applications

private void butUp_Click(object sender, System.EventArgs e){this.Value += 1;}

11.1.4 Agregar el control a un formulario Web


Los controles de usuario se pueden arrastrar directamente desde el explorador de soluciones a un formulario Web. Cuando se agrega un control de usuario a un formulario Web de esta forma Visual Studio genera una directiva Register y etiquetas HTML para crear el control en el formulario Web. Por ejemplo, el siguiente cdigo muestra el HTML generado cuando se arrastra el control de usuario Spin a un formulario Web:
<%@ Page Language="vb" AutoEventWireup="false" Codebehind="WebForm1.aspx.vb" Inherits="vbUserSnippet.WebForm1"%> <%@ Register TagPrefix="uc1" TagName="Spin" Src="Spin.ascx" %> <HTML> <body> <form id="Form1" method="post" runat="server"> <uc1:Spin id="Spin1" runat="server"></uc1:Spin> </form> </body> </HTML>

Los controles de usuario pueden existir junto a y coexistir con otros controles en un formulario Web. Por ejemplo, el siguiente HTML muestra el control de usuario Spin junto a un control TextBox:
<%@ Page Language="vb" AutoEventWireup="false" Codebehind="WebForm1.aspx.vb" Inherits="vbUserSnippet.WebForm1"%> <%@ Register TagPrefix="uc1" TagName="Spin" Src="Spin.ascx" %> <HTML> <body> <form id="Form1" method="post" runat="server"> <asp:TextBox id="TextBox1" runat="server"></asp:TextBox> <uc1:Spin id="Spin1" runat="server" Value="5"></uc1:Spin> </form> </body> </HTML>

Observe que el control de usuario incluye un atributo para la propiedad Value. Cuando se carga el control Spin en tiempo de ejecucin ASP.NET configura las propiedades del control segn los atributos en HTML. Los atributos del control proporcionan una forma de configurar las propiedades desde HTML. Al colocar el control en un formulario Web observar que el diseador de formularios Web de Visual Studio no lo muestra como se ver en tiempo de ejecucin; en su lugar muestra un control genrico. Es una limitacin de Visual Studio no puede mostrar controles de usuario en modo diseo. Otra cosa que observar es que el control Spin solo soporta diseo de flujo en el formulario Web. Es una limitacin del propio control. Para soportar diseo de rejilla y posicionamiento absoluto tiene que aadir cdigo para soportar el atributo de estilo. Esto ser ver ms adelante.

11.1.5 Usar el control en el cdigo


Cuando ha creado un control de usuario y lo ha agregado a un formulario Web puede usarlo desde el mdulo de cdigo del formulario Web siguiendo estos pasos: 1. Declare el control de usuario a nivel de mdulo. Por ejemplo, la siguiente lnea declara el control de usuario Spin que se agreg al formulario Web en la seccin anterior: Visual Basic .NET
Protected WithEvents Spin1 As Spin

Visual C#
protected Spin Spin1;

2. Utilice las propiedades, mtodos y sucesos del control como hara con cualquier otro. Por ejemplo, el siguiente procedimiento de suceso muestra el valor del control Spin en una caja de texto: Visual Basic .NET
Private Sub Page_PreRender(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles MyBase.PreRender TextBox1.Text = Spin1.Value End Sub

Visual C#
private void Page_PreRender(object sender, System.EventArgs e){ TextBox1.Text = Spin1.Value.ToString(); }

211

MCAD/MCSD

Algo muy importante que hay que observar es que el cdigo anterior usa el procedimiento Page_PreRender del formulario Web, no su procedimiento Page_Load. Si usa Page_Load slo ver el valor establecido en el atributo HTML Value del control de usuario la primera vez que pulse sobre el control (intntelo). Esto se debe a que el cdigo del control de usuario no corre hasta que no ha terminado el suceso Page_Load del formulario Web. Los cambios que se grabaron en el ViewState del control no se cargan hasta que no se ejecuta Page_Load del control.

11.1.6 Aadir sucesos al control de usuario


Adems de propiedades y mtodos los controles de usuario pueden proporcionar sucesos que pueden responder a acciones del usuario en el formulario web. Para aadir un suceso a un control de usuario siga estos pasos: 1. Declare un suceso dentro del mdulo de cdigo del control. Por ejemplo, el siguiente cdigo declara un suceso Click para el control de usuario Spin. Visual Basic .NET
Public Event Click(ByVal sender As System.Object, ByVal e As System.EventArgs)

Visual C#
public event EventHandler Click;

2. Cree un mtodo para lanzar el suceso. Este paso facilita que otras clases deriven de esta, ya que pueden sustituir este mtodo. Visual Basic .NET
Protected Overridable Sub OnClick(ByVal e As EventArgs) RaiseEvent Click(Me, e) End Sub

Visual C#
protected virtual void OnClick(EventArgs e){ if (Click != null) Click(this, e); }

3. Lance el suceso desde el cdigo del control de usuario. Por ejemplo, el siguiente cdigo lanza el suceso Click siempre que un usuario pulsa uno de los botones del control Spin: Visual Basic .NET
Private Sub butDown_Click(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles butDown.Click Me.Value -= 1 'Decrementa el valor. OnClick(e) 'Llama al mtodo OnClick. End Sub Private Sub butUp_Click(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles butUp.Click Me.Value += 1 'Incrementa el valor. OnClick(e) 'Llama al mtodo OnClick. End Sub

Visual C#
private void butDown_Click(object sender, System.EventArgs e){ this.Value -= 1; // Decrementa el valor OnClick(e); // Llama al mtodo OnClick. } private void butUp_Click(object sender, System.EventArgs e){ this.Value += 1; // Incrementa el valor OnClick(e); // Llama al mtodo OnClick. }

Para utilizar el suceso del control de usuario desde un formulario Web incluya el control de usuario en un formulario Web, como se mostr en las secciones anteriores, y escriba un procedimiento de suceso que responda al suceso. Por ejemplo, el siguiente cdigo actualiza una caja de texto cuando el usuario pulsa sobre el control Spin: Visual Basic .NET
Private Sub Spin1_Click(ByVal sender As Object, ByVal e As System.EventArgs) _ Handles Spin1.Click TextBox1.Text = Spin1.Value End Sub

Visual C#
private void Spin1_Click(object sender, System.EventArgs e){ TextBox1.Text = Spin1.Value.ToString(); }

212

Developing Web Applications

11.1.7 Activar el diseo en rejilla


Como ya se ha mencionado los controles de usuario no incorporan soporte para el posicionamiento absoluto utilizado por el diseo en rejilla de los formularios Web. En ASP.NET los controles soportan posicionamiento absoluto por medio del atributo style. Para obtener soporte para posicionamiento absoluto en tiempo de diseo sencillamente aada un atributo style al HTML del control de usuario en el formulario Web. Por ejemplo, el siguiente HTML crea un control de usuario Spin que puede arrastrar a diferentes ubicaciones en un formulario Web en modo diseo.
<UserControl:Spin id="Spin1" runat="server" Value="5" style="Z-INDEX: 101; LEFT: 248px; POSITION: absolute; TOP: 88px"></UserControl:Spin>

Cuando ejecute la aplicacin ver el problema que trae esta solucin: en tiempo de ejecucin ASP.NET ignora el atributo style y coloca el control de usuario Spin usando diseo de flujo. Para que el atributo style funcione tendr que agregar una propiedad Style al control de usuario, para establecer la posicin y tamao del control segn los valores del atributo. Si su control usa un contenedor, como el Grid Layout Panel que usa el control de usuario Spin, sencillamente puede pasar el atributo style del control al control Panel, como muestra el siguiente cdigo. Visual Basic .NET
Public Property Style() As String Get 'Devuelve el atributo style del panel contenedor del control. Return pnlGrid.Attributes("style") End Get Set(ByVal Value As String) 'Establece el atributo style del panel contenedor del control. pnlGrid.Attributes("style") = Value End Set End Property

Visual C#
public string Style{ get{ // Devuelve el atributo style del panel contenedor del control. return pnlGrid.Attributes["style"]; } set{ // Establece el atributo style del panel contenedor del control. pnlGrid.Attributes["style"] = value; } }

Puede usar esta misma tcnica llamada a veces delegacin para implementar otros atributos estndar de control como Visible, Enabled o BackColor. Sencillamente aada al control de usuario una propiedad que pase el valor del atributo a un control contenedor usando la propiedad Attributes, como muestra el cdigo anterior.

11.2 Crear controles compuestos


Los controles compuestos combinan uno o ms controles de servidor o HTML en una nica clase control, que se puede compilar junto con otras clases control para crear un ensamblado (.dll) que contiene una librera de controles personalizados. Una vez creada la librera de controles se puede cargar en Visual Studio .NET y se puede utilizar de la misma forma que los controles de servidor y HTML estndar. Los controles compuestos son funcionalmente similares a los de usuario, pero residen en sus propios ensamblados, de modo que se pueden compartir entre proyectos sin tener que copiarlo en cada uno de ellos. Sin embargo, los controles compuestos son algo ms difciles de crear que los de usuario porque no se pueden dibujar visualmente en el diseador de Visual Studio. Tiene muchas ms opciones para definir su comportamiento, por tanto los controles compuestos son ms complejos que los de usuario.

11.2.1 Crear y usar controles compuestos


Para crear y usar un control compuesto siga estos seis pasos: 1. Cree una solucin que contenga un proyecto de control personalizado. 2. Agregue a la solucin un proyecto de aplicacin Web y establzcalo como proyecto de inicio. Usar el proyecto Web para probar el control personalizado durante el desarrollo. 3. Agregue una referencia de proyecto desde la aplicacin Web al proyecto de control personalizado y aada una directiva Register de HTML y un elemento de control para usar el control en el formulario Web. 4. Cree el interface visual del control compuesto aadiendo controles existentes por medio del mtodo CreateChildControls del control. 213

MCAD/MCSD

5. Agregue las propiedades, mtodos y sucesos que proporcione el control personalizado 6. Compile y pruebe el control. Este ltimo paso en realidad es parte de cada uno de los anteriores.

11.2.2 Crear el proyecto de control personalizado


Los controles personalizados son sencillamente clases creadas dentro de un ensamblado. Estas clases control personalizadas heredan mucho de su comportamiento de la clase WebControl e implementan varios interfaces, dependiendo del tipo de control que se est creando. La forma ms sencilla de empezar es usar la plantilla de proyecto Biblioteca de controles Web que proporciona Visual Studio .NET. 1. En el men Archivo seale Nuevo y seleccione Proyecto. Visual Studio muestra el dilogo Nuevo Proyecto. 2. Seleccione Biblioteca de controles Web en la lista Plantillas, escriba el nombre del proyecto en la caja de texto Nombre y pulse Aceptar. Visual Studio crea un proyecto que contiene el cdigo para un nico control personalizado llamado WebControl1. El cdigo creado sirve como plantilla para crear un nuevo control personalizado. La plantilla incluye una clase llamada WebControl1 que contiene una propiedad llamada Text. Visual Basic .NET
Imports System.ComponentModel Imports System.Web.UI <DefaultProperty("Text", ToolboxData("{0}:WebCustomControl1 runat=server> _ </{0}:WebCustomControl1>")> Public Class WebCustomControl1 Inherits System.Web.UI.WebControls.WebControl Dim _text As String <Bindable(True), Category("Appearance"), DefaultValue("")> _ Property[Text]() As String Get Return _text End Get Set(ByVal Value As String) _text = Value End Set End Property Protected Overrides Sub Render(ByVal output As System.Web.UI.HtmlTextWriter) output.Write([Text]) End Sub End Class

Visual C#
using using using using System; System.Web.UI; System.Web.UI.WebControls; System.ComponentModel;

namepace csCompositeSnippet{ ///<summary> ///Descripcin breve de WebCustomControl1 ///</summary> [DefaultProperty("Text"), ToolboxData("<{0}:WebCustomControl1 runat=server> </{0}:WebCustomControl1>")] public class WebCustomControl1 : System.Web.UI.WebControls.WebControl{ private string text; [Bindable(true), Category("Appearance"), DefaultValue("")] public string Text{ get{return text;} set{text = value;} } ///<summary> ///Procesar este control en el parmetro de salida especificado ///</summary> ///<param name="output">Programa de escritura HTML para escribir</param>

214

Developing Web Applications

protected override void Render(HtmlTextWriter output){ output.Write(Text); } } }

El cdigo precedente contiene algunos elementos que puede que no haya visto hasta ahora, La tabla 11.1 describe estos elementos (se muestra la versin Visual Basic, ver en el listado anterior el equivalente C#):
Tabla 11. 1: Plantilla de control personalizado
Fragmento Nombre Atributos de clase Descripcin Los atributos de clase determinan las opciones de tiempo de diseo del control. Estos valores ayudan a determinar lo que aparece en la ventana de propiedades de Visual Studio .NET cuando se selecciona el control en un formulario Web. Los controles personalizados derivan de una de las clases base de control Como los atributos de clase, los atributos de propiedad determinan la configuracin en tiempo de diseo de una propiedad. La definicin de propiedad determina lo que hace la propiedad en tiempo de ejecucin. Los corchetes ([]) indican que el nombre de la propiedad puede ser una palabra clave (aunque en este caso no lo es). El mtodo Render muestra el control personalizado. Sustituye al del mismo nombre en la clase base.

<DefaultProperty("Text", ToolboxData("{0}: WebCustomControl1 runat=server> </{0}:WebCustomControl1>")> System.Web.UI.WebControls. WebControl <Bindable(True), Category("Appearance"), DefaultValue("")> Property[Text]() As String

Clase base Atributos de propiedad Definicin de propiedad Mtodo

Protected Overrides Sub Render(ByVal output As System.Web.UI.HtmlTextWriter)

Render

Las secciones siguiente describe cmo agregar y modificar estas partes para crear un control personalizado compuesto, pero para una descripcin ms completa de los atributos vea la ayuda de Visual Studio.

11.2.3 Crear el proyecto de prueba


El proyecto de control personalizado de la seccin anterior tiene como tipo de salida Biblioteca de clases. Esto significa que solo se puede utilizar desde otra aplicacin no puede correr como aplicacin independiente. Para ejecutar y depurar un control personalizado en Visual Studio .NET debe agregar un segundo proyecto a la solucin actual. 1. Con el proyecto del control personalizado abierto, en el men Archivo seale Agregar proyecto y pulse Nuevo proyecto. Visual Studio muestra el dilogo Nuevo proyecto 2. En la lista de plantillas seleccione Aplicacin Web ASP.NET, escriba el nombre del proyecto en la caja Ubicacin y pulse Aceptar. Visual Studio crea un nuevo proyecto de aplicacin Web y lo agrega a la solucin. 3. En el explorador de soluciones, pulse con el botn derecho sobre el proyecto de aplicacin Web y seleccione Establecer como proyecto de inicio. Visual Studio muestra el proyecto de inicio en negrita. 4. En el explorador de soluciones, pulse con el botn derecho en elemento References del proyecto de aplicacin Web y seleccione Agregar referencia. Visual Studio muestra el dilogo Agregar referencia. 5. Pulse la lengeta Proyectos para agregar una referencia desde el proyecto de aplicacin Web al proyecto del control personalizado y pulse Aceptar. Visual Studio agrega la referencia, como muestra el explorador de soluciones. Al establecer una referencia a proyecto tal como se ha descrito se copia el ensamblado del control personalizado (.dll) al directorio /bin de la aplicacin Web. Esto hace que el control est disponible para la aplicacin Web. Cualquier cambio en el ensamblado del control se copia automticamente al directorio /bin de la aplicacin. Durante el desarrollo del control recuerde que los cambios no se actualizan en la aplicacin Web hasta que no se genera el control. Esto se produce automticamente cuando se ejecuta la aplicacin, pero no cuando se cambia desde el control a la aplicacin de prueba en modo diseo. Para ver los cambios al control en modo diseo debe generarlo antes de cambiar a la aplicacin de prueba.

11.2.4 Agregar el control personalizado al proyecto de prueba


Para probar y depurar el control personalizado durante el desarrollo debe agregar una instancia del control a un formulario Web de la aplicacin de prueba creada en el paso anterior. 1. En la aplicacin Web de prueba muestre un formulario Web y cambie al modo HTML. 2. Aada en la parte superior del formulario una directiva Register. Por ejemplo, la siguiente directiva registra el ensamblado de control personalizado llamado CompositeControls:
<%@ Register TagPrefix="Custom" Namespace="vbCompositeSnippet" Assembly="vbCompositeSnippet" %>

3. Cree una instancia del control personalizado en el formulario Web usando sintaxis HTML. Por ejemplo, el siguiente HTML crea una instancia de WebCustomControl1 creado en la seccin anterior:
<Custom:WebCustomControl1 id="custTest" runat="server" />

215

MCAD/MCSD

La tabla 11-2 muestra el significado de los tres atributos de la directiva Register cuando se aplican a controles personalizados.
Tabla 11. 2: Atributos de la directiva Register
Atributo Significado Este nombre indica el grupo al que pertenece el control. Por ejemplo, el prefijo de etiqueta para los controles de servidor ASP.NET es asp. Este prefijo se usa para crear un convenio de nombres para organizar sus controles personalizados. Nombre de proyecto y espacio de nombres dentro del ensamblado del control personalizado que contiene los controles a registrar. Visual Basic .NET usa el nombre de proyecto como espacio de nombres implcito, por lo que para controles escritos en Visual Basic .NET use el nombre de proyecto. Nombre del ensamblado (.dll) que contiene los controles personalizados. La aplicacin Web debe hacer referencia al ensamblado del control. Como se dijo anteriormente, la referencia al ensamblado mantiene una copia del mismo en el directorio /bin de la aplicacin Web.

TagPrefix Namespace Assembly

El atributo TagPrefix de la directiva Register compone la primera parte del nombre que se usa en el elemento HTML del control personalizado. La segunda parte es el nombre del proyecto y nombre de clase del control dentro del ensamblad. TagPrefix="Custom" y el nombre de clase WebCustomControl1 significan que el control personalizado se crea usando un elemento HTML <Custom:WebCustomControl1 />. Los controles personalizados pueden existir junto con otros controles e interactuar con ellos en una pgina Web. Por ejemplo, el siguiente HTML muestra el control personalizado WebControl1 junto con un control Button:
<%@ Page Language="vb" AutoEventWireup="false" Codebehind="Default.aspx.vb" Inherits="vbCompositeSnippet.WebForm1"%> <%@ Register TagPrefix="Custom" NameSpace="vbCompositeSnippet " Assembly="CompositeSnippet" %> <HTML> <body> <form id="Form1" method="post" runat="server"> <asp:button id="butCount" runat="server" /> <Custom:WebCustomControl1 id="custTest" runat="server" Text="Esto es un control personalizado" /> </form> </body> </HTML>

Observe que el control personalizado incluye un atributo para la propiedad Text. Los atributos HTML del control proporcionan una forma de establecer las propiedades del control desde HTML. A diferencia de los controles e usuario los controles personalizados se muestran correctamente en el diseador de Visual Studio. Otra cosa que debe observar sobre los controles personalizados es que cuando se seleccionan en el diseador de Visual Studio sus propiedades aparecen en la ventana de propiedades. Para usar el control personalizado en el cdigo basta hacer referencia a l como hara con cualquier otro control. Por ejemplo, el siguiente procedimiento de suceso Click de botn incrementa el valor que muestra el control personalizado WebCustomControl1 Visual Basic .NET
Private Sub butAdd_Click(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles butAdd.Click custTest.Text = Val(custTest.Text) + 1 End Sub

Visual C#
private void butAdd_Click(object sender, System.EventArgs e){ int intText = 0; try intText = int.Parse(custTest.Text); catch intText = 0; intText ++; custTest.Text = intText.ToString(); }

Si se ejecuta la aplicacin y se pulsa el botn ms de una vez el valor nunca sube de 1. Por qu?. La plantilla de control que crea Visual Studio no toma ninguna medida para guardar sus propiedades entre presentaciones de la pgina. Para esto es necesario aadir cdigo, como se describe en las secciones posteriores.

216

Developing Web Applications

11.2.5 Crear el aspecto del control compuesto


El interface visual de un control compuesto se crea aadiendo controles de servidor o HTML existentes a la coleccin Controls en el mtodo CreateChildControls. El mtodo CreateChildControls personalizado sustituye al de la clase base. El siguiente cdigo muestra cmo crear la apariencia de un control personalizado compuesto. El cdigo crea un control personalizado compuesto llamado MathBox. El control MathBox contiene controles TextBox, Button y Label que se declaran a nivel de clase, por lo que estn disponibles para todos los procedimientos de la misma. El procedimiento CreateChildControls aade estos controles y algunos controles Literal a la coleccin Controls para crear el aspecto del control personalizado. Visual Basic .NET
Public Class MathBox Inherits System.Web.UI.WebControls.WebControl Dim txtMath As New TextBox() Dim butSum As New Button() Dim lblResult As New Label() Protected Overrides Sub CreateChildControls() txtMath.TextMode = TextBoxMode.MultiLine Controls.Add(txtMath) Controls.Add(New LiteralControl("<br>")) 'Salto de lnea butSum.Text = "Suma" Controls.Add(butSum) Controls.Add(New LiteralControl("&nbsp&nbspResultado:&nbsp<b>")) Controls.Add(lblResult) Controls.Add(New LiteralControl("</b>")) End Sub End Class

Visual C#
public class MathBox : System.Web.UI.WebControls.WebControl{ TextBox txtMath = new TextBox(); Button butSum = new Button(); Label lblResult = new Label(); private string text; protected override void CreateChildControls(){ txtMath.TextMode = TextBoxMode.MultiLine; Controls.Add(txtMath); Controls.Add(new LiteralControl("<br>")); //Salto de lnea butSum.Text = "Suma"; Controls.Add(butSum); Controls.Add(new LiteralControl("&nbsp&nbspResultado:&nbsp<b>")); Controls.Add(lblResult); Controls.Add(new LiteralControl("</b>")); } }

La clase MathBox del ejemplo anterior se usa como base para el resto de la leccin. Si la aade al proyecto de control compuesto creado en las secciones anteriores puede aadirla a la aplicacin Web de prueba usando la misma directiva Register utilizada para WebCustomControl1, y se crea una instancia del control con el HTML:
<Custom:MathBox id="mathTest" runat="server" />

Si aade el control MathBox a un formulario Web en este momento ver que en diseador aparece solo como una pequea caja verde, pero sin embargo en tiempo de ejecucin se muestra correctamente. En este punto el control MathBox no tiene apariencia en tiempo de diseo porque an no expone propiedades de tiempo de diseo. Lo solucionaremos en la siguiente seccin. Cuando crea un control personalizado compuesto no necesita sustituir el mtodo Render. La plantilla de cdigo que genera Visual Studio lo sustituye, por lo que si est usando esta plantilla debe borrar el mtodo Render generado o cambiarlo para que delegue de vuelta a la clase base (haciendo que sea una operacin nula) como se muestra a continuacin: Visual Basic .NET
Protected Overrides Sub Render(ByVal writer As HtmlTextWriter) MyBase.Render(writer) End Sub

217

MCAD/MCSD

Visual C#
protected override void Render(HtmlTextWriter output){ base.Render(output); }

11.2.6 Crear propiedades y mtodos


El control personalizado MathBox toma una lista de nmeros escritos en una caja de texto, los suma y devuelve el resultado. Desde un punto de vista de diseo esto precisa dos propiedades: Values, que contiene un array de nmeros, y Result, que contiene la suma de estos nmeros. Tambin implica un mtodo Sum para realizar el clculo. El siguiente cdigo muestra las propiedades Values y Result y el mtodo Sum de MathBox. Tambin incluye una propiedad Text por coherencia con los controles de servidor ASP.NET y para simplificar la configuracin de un texto predeterminado desde HTML. Visual Basic .NET
'Propiedades y mtodos de MathBox. <DefaultValue("")> Property Text() As String Get EnsureChildControls() 'Se asegura de que existen los controles hijo. Return txtMath.Text 'Devuelve el texto del control TextBox. End Get Set(ByVal Value As String) EnsureChildControls() 'Se asegura de que existen los controles hijo. txtMath.Text = Value 'Establece el texto del control TextBox. End Set End Property Property Values() As String() Get EnsureChildControls() Return txtMath.Text.Split(Chr(13)) End Get Set(ByVal Value() As String) EnsureChildControls() txtMath.Text = String.Join(Chr(13), Value) End Set End Property

' devuelve un array de cadenas

'Configura el TextBox desde array

ReadOnly Property Result() As String Get EnsureChildControls () Return lblResult.Text 'Devuelve el resultado desde la etiqueta. End Get End Property Sub Sum() EnsureChildControls() If txtMath.Text.Length Then ' Si hay texto en el TextBox. Dim arrNums As String() ' Divide el texto en una array lnea a lnea. arrNums = txtMath.Text.Split(Chr(13)) Dim strCount As String, dblSum As Double For Each strCount In arrNums ' Suma los elementos del array. Try ' Ignora entrada no numricas dblSum += Convert.ToDouble(strCount) Catch End Try Next lblResult.Text = dblSum.ToString ' Muestra el resultado en la etiqueta. Else lblResult.Text = "0" End If End Sub

218

Developing Web Applications

Visual C#
//Propiedades y mtodos de MathBox. [DefaultValue("0")]public string Text{ get{ EnsureChildControls(); //Se asegura de que existen los controles hijo return txtMath.Text; //Devuelve el texto del TextBox. } set{ EnsureChildControls(); //Se asegura de que existen los controles hijo txtMath.Text = value; //Establece el texto en el TextBox } } char[] strSep = {'\r'}; public string[] Values{ get{ EnsureChildControls(); return txtMath.Text.Split(strSep); } set{ EnsureChildControls(); txtMath.Text = String.Join(" ", value); } }

//Devuelve un array de cadenas.

//Establece contenido del TextBox

public string Result{ get{ EnsureChildControls(); return lblResult.Text; // Devuelve el resultado desde la etiqueta. } } public void Sum(){ EnsureChildControls(); if (txtMath.Text.Length != 0){ //Si hay texto en el TextBox. string[] arrNums; //Divide el texto en un array lnea a lnea. arrNums = txtMath.Text.Split(strSep); double dblSum = 0; foreach (string strCount in arrNums){ //Suma los elementos el array. try{dblSum += Convert.ToDouble(strCount);} //Ignora no numricos catch{} } lblResult.Text = dblSum.ToString(); //Muestra el resultado en la etiqueta. }else lblResult.Text = "0"; }

La sentencia EnsureChildControls en el cdigo asegura que se han instanciado los controles hijo. Se usa en un control compuesto antes de hacer referencia a los controles que contiene. Despus de aadir propiedades y mtodos al control compuesto vuelva a generar el control para actualizar su ensamblado. En este punto el control compuesto debe aparecer en modo diseo. Si el control no aparece en modo diseo normalmente puede hacerlo aparecer dando un valor a una de sus propiedades modificadas, por ejemplo:
<Custom:MathBox id="mthTest" runat="Server" Text="0" />

Como los controles compuestos usan el mtodo Render de su clase base soportan de forma automtica el posicionamiento absoluto con disposicin en rejilla. En otras palabras, puede arrastrar controles compuestos a diferentes posiciones de un formulario Web y se vern all en tiempo de ejecucin.

11.2.7 Control de sucesos


Hasta ahora, MathBox puede aceptar valores, realizar clculos y mostrar y resultado. Pero si se pulsa el botn no hace nada. Para activar el botn siga estos pasos: 1. Aada un controlador de suceso para el suceso Click del botn al procedimiento CreateChildControls usando el mtodo AddHandler. 2. Cree un procedimiento para controlar el suceso. Este procedimiento debe tener los mismos argumentos y tipos de retorno que el suceso Click del botn.

219

MCAD/MCSD

El siguiente cdigo muestra los aadidos al control MathBox en negrita. Observe que el procedimiento de suceso simplemente llama al mtodo Sum creado anteriormente para ejecutar el clculo y mostrar el resultado. Visual Basic .NET
Protected Overrides Sub CreateChildControls() ' Aade los controles subordinados al control compuesto. ' Configura la propiedad TextMode y aade la caja de texto. txtMath.TextMode = TextBoxMode.MultiLine Controls.Add(txtMath) Controls.Add(New LiteralControl("<br>")) ' Configura la propiedad Text y aade el botn. butSum.Text = "Suma" Controls.Add(butSum) ' Aade etiquetas y literales para mostrar el resultado. Controls.Add(New LiteralControl("&nbsp&nbspResult:&nbsp<b>")) Controls.Add(lblResult) Controls.Add(New LiteralControl("</b>")) ' Aade un control para el suceso de pulsacin del botn. AddHandler butSum.Click, AddressOf Me.butSumClicked End Sub ' Procedimiento de suceso para el botn. Sub butSumClicked(ByVal source As Object, ByVal e As EventArgs) SUM() 'Llama al mtodo Sum End Sub

Visual C#
protected override void CreateChildControls(){ // Aade los controles subordinados al control compuesto. // Configura la propiedad TextMode y aade la caja de texto. txtMath.TextMode = TextBoxMode.MultiLine; Controls.Add(txtMath); Controls.Add(new LiteralControl("<br>")); // Configura la propiedad Text y aade el botn. butSum.Text = "Suma"; Controls.Add(butSum); // Aade etiquetas y literales para mostrar el resultado. Controls.Add(new LiteralControl("&nbsp&nbspResult:&nbsp<b>")); Controls.Add(lblResult); Controls.Add(new LiteralControl("</b>")); // Aade el controlador de suceso. butSum.Click += new EventHandler(butSumClicked); } void butSumClicked(object sender, EventArgs e){ Sum(); // Llama al mtodo Sum. }

11.2.8 Lanzar sucesos


Adems de controlar el suceso Click del botn es posible lanzar un suceso que se pueda controlar desde el formulario Web que contiene el control personalizado. Para lanzar un suceso desde un control personalizado siga estos pasos: 1. Aada una declaracin de suceso pblico a la clase de control personalizado. 2. Lance el suceso desde el cdigo dentro del control personalizado usando el mtodo de suceso del control. El siguiente cdigo muestra cmo declarar y lanzar un suceso desde el interior de la clase del control MathBox: Visual Basic .NET
Event Click(ByVal sender As Object, ByVal e As EventArgs) ' Declara un suceso ' Procedimiento de suceso para pulsacin del botn Sub butSumClicked(ByVal source As Object, ByVal e As EventArgs) Sum() ' Llama al mtodo Sum. OnClick(EventArgs.Empty) ' Llama al mtodo para lanzar el suceso. End Sub Protected Overridable Sub OnClick(ByVal e As EventArgs) RaiseEvent Click(Me, e) ' Lanza el suceso. End Sub

220

Developing Web Applications

Visual C#
public event EventHandler Click; // Declara el suceso. void butSumClicked(object sender, EventArgs e){ Sum(); // Llama al mtodo Sum. OnClick(EventArgs.Empty); // Llama al mtodo de suceso. } protected virtual void OnClick(EventArgs e) { Click(this, e); // Lanza el suceso. }

Para que el suceso Click sea el predeterminado del control aada un atributo DefaultEvent a la declaracin de la clase. Un suceso predeterminado es aquel que crea automticamente Visual Studio cuando se pulsa dos veces sobre el control en el formulario Web. El siguiente cdigo muestra el aadido en negrita: Visual Basic .NET
<DefaultEvent("Click")> Public Class MathBox

Visual C#
[DefaultEvent("Click")] public class MathBox : System.Web.UI.WebControls.WebControl

Para usar el suceso de MathBox desde un formulario Web pulse dos veces sobre el control en el formulario Web de prueba y utilice el siguiente procedimiento de suceso: Visual Basic .NET
Private Sub mathTest_Click(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles mathTest.Click Response.Write(mathTest.Result) End Sub

Visual C#
private void mathTest_Click(object sender, System.EventArgs e){ Response.Write(mthTest.Result.ToString()); }

11.2.9 Cambio de tamao del control


Los controles compuestos manejan automticamente muchas caractersticas de presentacin en tiempo de diseo y en tiempo de ejecucin por medio del mtodo Render de su clase base. Sin embargo, no pueden cambiar automticamente el tamao de sus controles hijos porque no hay una forma razonable de decir qu tipo de comportamiento de cambio de tamao es el adecuado. Para manejar el cambio de tamao de controles compuestos siga estos pasos: 1. Sustituya el mtodo Render de la clase base 2. Aada cdigo para cambiar el tamao de los controles hijos como corresponda 3. Llame al mtodo Render de la clase base para presentar el control. El siguiente cdigo cambia el tamao del control TextBox hijo segn el ancho y alto del control MathBox. Visual Basic .NET
Protected Overrides Sub Render(ByVal writer As System.Web.UI.HtmlTextWriter) EnsureChildControls() ' Cambia el ancho de la caja de texto al del control. txtMath.Width = Me.Width ' Cambia la altura de la caja de texto segn la del control. txtMath.Height = Unit.Parse(Me.Height.Value butSum.Height.Value) ' Dibuja el control. MyBase.Render(writer) End Sub

Visual C#
protected override void Render(HtmlTextWriter output){ EnsureChildControls(); // Cambia el ancho de la caja de texto al del control. txtMath.Width = this.Width; // Cambia la altura de la caja de texto segn la del control. double dHeight = this.Height.Value - butSum.Height.Value; txtMath.Height = Unit.Parse(dHeight.ToString()); // Dibuja el control. base.Render(output); }

221

MCAD/MCSD

11.2.10 Superclasificar controles de servidor


La seccin anterior mostr cmo crear un control compuesto a partir de varios controles existentes. Puede usar las misma tcnicas para crear nuevos controles a partir de un nico control existente aadiendo propiedades, mtodos o sucesos para este control, o cambiando su comportamiento. Como este tipo de control personalizado se basa solo en un control, puede derivar directamente de la clase del control en lugar de usar la clase ms general WebControl. Los controles personalizados de este tipo en realidad no son controles compuestos en ocasiones se denominan controles superclasificados. Por ejemplo, la siguiente clase SuperText crea un control personalizado basado en el control de servidor TextBox y aade un mtodo para ordenar el contenido: Visual Basic .NET
Public Class SuperText Inherits System.Web.UI.WebControls.TextBox Public Sub Sort() ' Dim arrText As String() ' arrText = Me.Text.Split(" ") ' Array.Sort(arrText) ' Me.Text = String.Join(" ", arrText) ' End Sub End Class Nuevo mtodo para la caja de texto. Crea un array. Pone las palabras de la caja en el array. Ordena el array. Une la cadena y la pone en la caja.

Visual C#
public class SuperText : System.Web.UI.WebControls.TextBox{ public void Sort(){ string[] arrText; // Crea un array. char[] strSep = {' '}; arrText = this.Text.Split(strSep); // Pone las palabras de la caja en array Array.Sort(arrText); // Ordena el array. this.Text = String.Join(" ", arrText); // Une la cadena y la pone en la caja. } }

Para usar el control en un formulario Web registre el ensamblado del control como muestran los ejemplos anteriores, e incluya el siguiente HTML en el formulario Web:
<Custom:SuperText id="superTest" runat="server" /> <asp:Button ID="butSort" Runat="server" Text="Sort" />

Para probar el mtodo Sort aada el siguiente cdigo al mdulo de cdigo del formulario Web: Visual Basic .NET
Private Sub butSort_Click(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles butSort.Click superTest.Sort() End Sub

Visual C#
private void butSort_Click(object sender, System.EventArgs e){superTest.Sort();}

Tanto en tiempo de diseo como de ejecucin el control SuperText se comporta igual que una caja de texto normal.

11.3 Crear controles personalizados trazados


Los controles personalizados trazados se crean prcticamente desde cero, lo que significa que se tiene control completo sobre su aspecto y comportamiento. Sin embargo, puesto que no se componen de controles hijos hay que escribir cdigo para realizar las tareas que de otra forma se delegaran a estos. Los controles compuestos y los trazados estn muy relacionados, y esta leccin ampla las habilidades aprendidas en la leccin 2. Algunos de los temas se aplican por igual a ambos tipos de controles debe considerar esta leccin como temas avanzados del desarrollo de controles Web personalizados. Dicho esto, an hay mucho ms que aprender sobre el tema. Para una gua completa del desarrollo de controles Web personalizados vea ASP.NET Server Controls and Components, por Nikhil Kothari y Vandana Datye, Microsoft Press, 2002.

11.3.1 Crear y usar controles trazados


Si ha recorrido los procedimientos de la leccin 2 ya ha creado un control personalizado trazado. La plantilla de cdigo que genera Visual Studio .NET cuando se crea un proyecto de biblioteca de controles Web es, de hecho, un control trazado. Sin embargo, es un control sencillo que no hace mucho. Puede crear controles ms interesantes 222

Developing Web Applications

ms rpidamente usando composicin, que es por lo que se ensea a crear controles compuestos antes que controles trazados. Como los controles trazados son muy similares a los compuestos, las tcnicas aprendidas en la leccin 2 tambin se aplican a esta, con una excepcin. En lugar de crear el interface visual del control a partir de otros controles los controles trazados crean sus interfaces visuales exclusivamente a partir de elementos HTML. Esto significa que no tendr propiedades, mtodos o sucesos incorporados que pueda usar para obtener o mostrar datos; deber crearlos. Cuando se crean controles personalizados trazados, los tres primeros pasos son los mismos que se describieron en la leccin 2 para un control personalizado. Para crear controles personalizados trazados complete estos pasos: 1. Cree una solucin que contenga un proyecto de control personalizado 2. Aada a la solucin un proyecto de aplicacin Web y establzcalo como proyecto de inicio. Usar este proyecto para probar el control personalizado durante su desarrollo. 3. Aada una referencia de proyecto desde la aplicacin Web al proyecto de control personalizado y aada una directiva Register y un elemento control de HTML para usar el control personalizado en un formulario Web. 4. Cree el interface visual del control personalizado sustituyendo el mtodo Render de la clase base. 5. Escriba cdigo para guardar valores de propiedades, responder a acciones de usuario y obtener datos del usuario. Las siguientes secciones describen los dos ltimos pasos con mayor detalle. Las dos ltimas secciones de la leccin muestran cmo aadir controles personalizados terminados a la caja de herramientas y cmo establecer iconos y etiquetas generadas utilizadas por Visual Studio .NET para los controles. Estas dos ltimas secciones se aplican tambin a controles compuestos.

11.3.2 Crear la apariencia del control


La apariencia de un control personalizado trazado se crea sustituyendo el mtodo Render de la clase base y escribiendo en el argumento de salida del mtodo por medio de los mtodos de utilidad de HtmlTextWriter. Estos mtodos, resumidos en la tabla 11.3, permiten aadir HTML en el argumento de salida:
Tabla 11. 3: Mtodos de utilidad de HtmlTextWriter
Mtodo Descripcin Aade un atributo HTML al siguiente elemento HTML a trazar. Coloca la etiqueta de inicio de un elemento HTML que se escribir ms adelante con WriteLine Coloca la etiqueta de fin de un elemento HTML y escribe el elemento y los atributos que estn pendientes. Todos los atributos se eliminan despus de ejecutar este mtodo. Write Escribe inmediatamente una cadena WriteAttribute Escribe inmediatamente un atributo HTML. WriteBeginTag Escribe inmediatamente la etiqueta de inicio de un elemento HTML. WriteEndTag Escribe inmediatamente la etiqueta de fin de un elemento HTML. WriteFullBeginTag Escribe inmediatamente la etiqueta de inicio junto con el ngulo de cierre (>) para el elemento HTML. WriteLine Escribe inmediatamente una lnea de contenido. Es equivalente al mtodo Write, pero aade un salto de lnea.

AddAttribute RenderBeginTag RenderEndTag

Como puede ver probablemente en la tabla 11.3 hay dos aproximaciones para escribir elementos HTML en el argumento de salida. La aproximacin ms directa es usar los mtodos Write para aadir directamente HTML al HtmlTextWriter. Por ejemplo el siguiente cdigo crea un botn que muestra una caja de mensaje cuando el usuario la pulsa. Visual Basic .NET
Imports System.ComponentModel Imports System.Web.UI Public Class AlertButton Inherits System.Web.UI.WebControls.WebControl Protected Overrides Sub Render(ByVal output As System.Web.UI.HtmlTextWriter) ' Escribe un ttulo output.Write("<h3>Control trazado</h3>") ' Abre una etiqueta input de HTML. output.WriteBeginTag("INPUT") ' Escribe algunos atributos. output.WriteAttribute("value", "Botn personalizado") output.WriteAttribute("type", "button") output.WriteAttribute("onclick", "javascript:alert(Yeppaa!')") ' Cierra la etiqueta input de HTML (inserta ">"). output.WriteEndTag("INPUT") End Sub End Class

223

MCAD/MCSD

Visual C#
using using using using System; System.Web.UI; System.Web.UI.WebControls; System.ComponentModel;

namespace csRenderedSnippet{ public class AlertButton : System.Web.UI.WebControls.WebControl{ protected override void Render(HtmlTextWriter output){ // Escribe un ttulo output.Write("<h3>Control trazado</h3>"); // Abre una etiqueta input de HTML. output.WriteBeginTag("INPUT"); // Escribe algunos atributos. output.WriteAttribute("value", "Botn personalizado"); output.WriteAttribute("type", "button"); output.WriteAttribute("onclick", "javascript:alert('Howdy!')"); // Cierra la etiqueta input de HTML (inserta ">"). output.WriteEndTag("INPUT"); } } }

Como alternativa, puede disear etiquetas y atributos y escribirlos como una sola unidad usando el mtodo RenderEndTag. El siguiente cdigo muestra el mtodo Render del control personalizado AlertButton escrito usando esta tcnica: Visual Basic .NET
Protected Overrides Sub Render(ByVal output As System.Web.UI.HtmlTextWriter) output.Write("<h3>Control trazado</h3>") ' Escribe un ttulo output.AddAttribute("value", "Botn modificado") ' Aade atributos output.AddAttribute("type", "button") output.AddAttribute("onclick", "javascript:alert('Howdy!')") output.RenderBeginTag("INPUT") ' Abre un input de HTML ("<INPUT"). output.RenderEndTag() ' Cierra el input de HTML (">"). End Sub

Visual C#
protected override void Render(HtmlTextWriter output){ output.Write("<h3>Control trazado</h3>"); // Escribe un ttulo output.AddAttribute("value", "Botn modificado"); // Aade atributos output.AddAttribute("type", "button"); output.AddAttribute("onclick", "javascript:alert('Howdy!')"); output.RenderBeginTag("INPUT"); // Abre un input de HTML ("<INPUT") output.RenderEndTag(); // Cierra el input de HTML (">") }

La ventaja de trazar elementos HTML de esta forma es que puede crear los atributos HTML en cualquier sentencia.

11.3.3 Guardar configuracin de propiedad


Los controles compuestos mostrados en la leccin 2 guardaban valores de propiedades usando las propiedades de los controles contenidos. Como los controles trazados no contienen otros controles, debe usar el ViewState del control trazado para guardar cualquier valor de propiedad que quiera mantener entre presentaciones de la pgina. El siguiente cdigo muestra una propiedad Text que retiene su valor entre presentaciones de la pgina. Visual Basic .NET
Property Text() As String Get If Not IsNothing(ViewState("Text")) Then Return ViewState("Text") Else Return "" End If End Get Set(ByVal Value As String) ViewState("Text") = Value End Set End Property ' Si se ha establecido ' Devuelve su valor ' Si no, devuelve "".

' Guarda el valor de la propiedad.

224

Developing Web Applications

Visual C#
public string Text{ get{ if (ViewState["Text"] != null) return ViewState["Text"].ToString(); else return null; } set{ViewState["Text"] = value; } } // Si se ha establecido // Devuelve el valor // Si no, devuelve "". // Guarda el valor

Al dar valores a ViewState se serializan los datos y se guardan en un campo oculto del formulario Web. Cuando se devuelve la pgina al servidor, la recuperacin de un valor de ViewState recupera y de-serializa los datos del campo oculto. ViewState est optimizado para los tipos de datos String, ArrayList y HashTable, pero puede grabar cualquier tipo de datos que pueda ser serializado o que proporcione un TypeConverter. Para otros tipos de datos puede crear su propio cdigo para grabar y recuperar ViewState sustituyendo los mtodos SaveViewState y LoadViewState.

11.3.4 Recuperar texto contenido


Los elementos HTML a menudo contiene texto literal que modifican de alguna forma, como muestran las etiquetas HTML para poner un texto en negrita: <b>En negrita</b>. Para obtener el texto que contiene un control personalizado siga estos pasos: 1. Aada un atributo ParseChildren a la definicin de la clase del control. 2. Implemente el interface INamingContainer 3. Recupere el texto contenido usando la coleccin Controls. La siguiente clase de control personalizado muestra cmo recuperar texto entre las etiquetas de comienzo y final de un control personalizado para mostrar el texto que contiene en rojo: Visual Basic .NET
' El atributo ParseChildren activa los controles contenidos. <ParseChildren(False)> Public Class Red Inherits WebControls.WebControl ' Este interface hace posible obtener el array Controls. Implements INamingContainer Protected Overrides Sub Render(ByVal output As System.Web.UI.HtmlTextWriter) ' El texto contenido se devuelve como control Literal. Dim litText As LiteralControl ' Obtiene el texto contenido de la coleccin Controls. litText = Controls(0) ' Lo pone en rojo usando el elemento <font>. output.Write("<font color='red'>" & litText.Text & "</font>") End Sub End Class

Visual C#
[ParseChildren(false)] public class Red : System.Web.UI.WebControls.WebControl, INamingContainer{ // El interface INamingContainer hace posible obtener el array Controls. protected override void Render(HtmlTextWriter output){ // El texto contenido se devuelve como control Literal. LiteralControl litText ; // Obtiene el texto contenido de la coleccin Controls. litText = (LiteralControl)Controls[0]; // Lo pone en rojo usando el elemento <font>. output.Write("<font color='red'>" + litText.Text + "</font>"); } }

En un formulario Web, el control personalizado anterior se usara mediante el siguiente HTML:


<custom:red id="Red1" runat="server">Un texto en rojo</custom:red>

Puede usar la coleccin Controls para obtener los elementos que existen entre las etiquetas de apertura y cierre del control personalizado, incluyendo otros controles. Por ejemplo, la siguiente clase control agrupa los controles contenidos en un panel, los centra en la pgina y los muestra en un fondo rojo:

225

MCAD/MCSD

Visual Basic .NET


'El atributo ParseChildren activa los controles contenidos. <ParseChildren(False)> Public Class Center Inherits WebControls.WebControl ' Este interface hace posible obtener el array Controls. Implements INamingContainer Protected Overrides Sub Render(ByVal output As System.Web.UI.HtmlTextWriter) output.AddAttribute("align", "center") ' Aade atributos al panel. output.AddStyleAttribute("BACKGROUND-COLOR", "red") output.RenderBeginTag("div") ' Inicia el panel Dim ctrItem As Control ' Variable para controles contenidos. For Each ctrItem In Controls ' Para cada control contenido. ctrItem.RenderControl(output) ' Traza el control Next output.RenderEndTag() End Sub End Class

Visual C#
[ParseChildren(false)] public class Center : System.Web.UI.WebControls.WebControl, INamingContainer{ // El interface INamingContainer hace posible obtener el array Controls. protected override void Render(HtmlTextWriter output) { output.AddAttribute("align", "center"); //Aade atributos al panel output.AddStyleAttribute("BACKGROUND-COLOR", "red"); output.RenderBeginTag("div"); //Inicia el panel foreach (Control ctrItem in Controls) //Para cada control contenido ctrItem.RenderControl(output); //Traza el control output.RenderEndTag(); } }

11.3.5 Responder a acciones de usuario


Los controles personalizados compuestos puede usar los sucesos de sus controles contenidos para responde a las acciones de usuario, como se mostr en la leccin 2. Los controles trazados, en cambio, necesitan dar pasos especiales para responder a las acciones de usuario. La forma de tratar las acciones de usuario depende del tipo de suceso: Los sucesos en cach se pueden lanzar desde el cdigo del control personalizado Los sucesos con envo se deben lanzar desde el lado cliente usando una secuencia de comandos escrita por el control personalizado. Las siguientes secciones muestran cmo lanzar cada uno de estos tipos de sucesos. Lanzar sucesos en cach Los sucesos en cach se controlan en el cdigo de servidor del formulario Web cuando se enva el formulario de vuelta al servidor y despus de que se hayan controlado los sucesos Page_Load y de envo. Lanzar un suceso en cach implica dos pasos: 1. Declarar un suceso a lanzar 2. Lanzar el suceso desde algn lugar dentro del cdigo de control personalizado Por ejemplo, la siguiente clase de control personalizado define un suceso OnChange que se lanza siempre que cambia la propiedad Text: Visual Basic .NET
<DefaultEvent("OnChange")>Public Class RenderText Inherits WebControls.WebControl Event Change(ByVal sender As Object, ByVal e As EventArgs) Property Text() As String Get If Not IsNothing(ViewState("Text")) Then Return ViewState("Text") Else Return "" End If End Get

226

Developing Web Applications

Set(ByVal Value As String) ViewState("Text") = Value OnChange(EventArgs.Empty) End Set End Property ' Mtodo de suceso Protected Overridable Sub OnChange(ByVal e As EventArgs) RaiseEvent Change(Me, EventArgs.Empty) End Sub

' Lanza el suceso.

Protected Overrides Sub Render(ByVal output As System.Web.UI.HtmlTextWriter) ' Configura los atributos del control input. output.AddAttribute("value", Me.Text) ' Crea un elemento control input usando anterior. output.RenderBeginTag("Input") ' Cierra el elemento de control input (inserta />). output.RenderEndTag() End Sub End Class

Visual C#
[DefaultEvent("Change")] public class RenderText : System.Web.UI.WebControls.WebControl{ public event EventHandler Change; // Declara un suceso. public string Text{ get{ if (ViewState["Text"] != null) return ViewState["Text"].ToString(); else return null; } set{ ViewState["Text"] = value; OnChange(EventArgs.Empty); } } protected virtual void OnChange(EventArgs e){ if (Change != null) Change(this, e); } protected override void Render(HtmlTextWriter output){ // Configura los atributos del control input. output.AddAttribute("value", this.Text); // Crea un elemento control input usando anterior. output.RenderBeginTag("Input"); // cierra el control de elemento input (inserta />). output.RenderEndTag(); } }

Lanzar sucesos de envo Los sucesos de envo hacen que el formulario Web se enve de vuelta al servidor para procesamiento inmediato. Se controlan inmediatamente despus del suceso Page_Load del formulario Web. Para lanzar un suceso de envo desde un control personalizado siga estos pasos: 1. 2. 3. 4. Implemente el interface IPostBackEventHandler en el control personalizado Declare un suceso para lanzar Trace un elemento HTML que pueda responder a sucesos de lado cliente, como onclick. Agregue un atributo al elemento HTML que contenga una secuencia de comandos para enviar la pgina de vuelta al servidor 5. Lance el suceso desde el mtodo RaisePostBackEvent, que es parte del interface IPostBackEventHandler. El siguiente cdigo muestra cmo usar estos pasos para lanzar el suceso de envo Click desde un control personalizado.

227

MCAD/MCSD

Visual Basic .NET


' Lanza suceso de envo. <DefaultEvent("Click")> Public Class AlertButton Inherits System.Web.UI.WebControls.WebControl ' (1) Interface que permite procesamiento de suceso PostBack. Implements IPostBackEventHandler ' (2) Declara el suceso Event Click(ByVal sender As Object, ByVal e As EventArgs) ' (3) Traza un elemento HTML que puede detectar sucesos de usuario. Protected Overrides Sub Render(ByVal output As System.Web.UI.HtmlTextWriter) ' Aade atributos. output.AddAttribute("value", "Botn de envo") output.AddAttribute("type", "button") ' (4) Aade atributo para lanzar el suceso en el cliente. output.AddAttribute("onclick", "javascript:alert('Howdy!');" & _ Page.GetPostBackEventReference(Me)) ' Abre una etiqueta input de HTML (inserta "<INPUT"). output.RenderBeginTag("INPUT") ' Cierra la etiqueta input de HTML(inserta ">" y escribe atributos). output.RenderEndTag() End Sub ' Parte del interface IPostBackEventHandler: debe crear este mtodo. Public Sub RaisePostBackEvent(ByVal eventArgument As String) _ Implements System.Web.UI.IPostBackEventHandler.RaisePostBackEvent OnClick(EventArgs.Empty) ' (5) lanza el suceso. End Sub Protected Overridable Sub OnClick(ByVal e As EventArgs) RaiseEvent Click(Me, EventArgs.Empty) ' Lanza el suceso. End Sub End Class

Visual C#
// (1) Interface IPostBackEventHandler permite procesar sucesos PostBack. [DefaultEvent("Click")] public class AlertButtonThree : System.Web.UI.WebControls.WebControl, IPostBackEventHandler{ // (2) Declara el suceso de envo public event EventHandler Click; // (3) Traza un elemento HTML que puede detectar sucesos de usuario. protected override void Render(HtmlTextWriter output) { output.Write("<h3>Control trazado</h3>"); // Escribe un ttulo // Aade atributos. output.AddAttribute("value", "Botn personalizado"); output.AddAttribute("type", "button"); // (4) Aade atributo para lanzar el suceso en el cliente. output.AddAttribute("onclick", "javascript:alert('Howdy!');" + Page.GetPostBackEventReference(this)); // Abre una etiqueta input de HTML (inserta"<INPUT"). output.RenderBeginTag("INPUT"); // Cierra la etiqueta input de HTML (inserta ">"). output.RenderEndTag(); } // Parte del interface IPostBackEventHandler: debe crear este mtodo. public void RaisePostBackEvent(string eventArgument){ OnClick(EventArgs.Empty); // (5) Llama al mtodo que lanza el suceso. } protected virtual void OnClick(EventArgs e) { if (Click != null) Click(this, e); } } // Lanza el suceso.

Cuando el usuario pulsa sobre el control personalizado anterior en tiempo de ejecucin, el suceso onclick del botn ejecuta la siguiente secuencia de comandos:
alert('Howdy!'); //Muestra una caja de mensaje. __doPostBack('winTest',''); //Generado por Page.GetPostBackEventReference(Me);

El mtodo _doPostBack() enva la pgina de vuelta al servidor, donde la intercepta el mtodo RaisePostBackEvent del interface IPostBackEventHandler, que a su vez lanza el suceso Click dentro del control. 228

Developing Web Applications

Use el siguiente cdigo para controlar el suceso Click desde el formulario Web: Visual Basic .NET
Private Sub altTest_Click(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles altTest.Click Response.Write("Botn pulsado") End Sub

Visual C#
private void altTest(object sender, System.EventArgs e){ Response.Write("Botn pulsado"); }

11.3.6 Obtener datos desde el usuario


Los controles trazados no retienen automticamente los datos introducidos por el usuario. Lo puede ver si crea un control TextBox personalizado trazando un elemento Input de html. Puede escribir en el elemento Input, pero en cuando se enve la pgina al servidor todo lo escrito se pierde. Para obtener datos del usuario siga estos pasos: 1. Implemente el interface IPostBackDataHandler. 2. Aada un atributo name que identifique de forma nica al elemento HTML del que se van a obtener los datos. 3. Sustituya el mtodo LoadPostBackData del interface IPostBackDataHandler. Use este mtodo para obtener los datos del usuario. 4. Sustituya el mtodo RaisePostDataChangedEvent del interface IPostBackDataHandler. No tiene que escribir cdigo para este mtodo, pero debe sustituirlo porque es parte del interface. 5. Lance un suceso para indicar que los datos han cambiado. Este paso es opcional si no quiere proporcionar un suceso de cambio para un control no tiene por qu hacerlo. El siguiente control personalizado muestra cmo usar estos pasos para retener datos introducidos por un usuario en un control TextBox trazado a partir de un elemento Inputde HTML: Visual Basic .NET
<DefaultEvent("Change")> Public Class RenderText Inherits WebControls.WebControl ' (1) Interface que permite obtener los datos enviados. Implements IPostBackDataHandler Event Change(ByVal sender As Object, ByVal e As EventArgs) Property Text() As String Get If Not IsNothing(ViewState("Text")) Then Return ViewState("Text") Else Return "" End If End Get Set(ByVal Value As String) ViewState("Text") = Value OnChange(EventArgs.Empty) End Set End Property Protected Overrides Sub Render(ByVal output As System.Web.UI.HtmlTextWriter) ' Configura los atributos del control Input. output.AddAttribute("value", Me.Text) ' (2) Debe definir este atributo para activar los datos enviados. output.AddAttribute("name", Me.UniqueID) ' Crea un elemento control Input usando el anterior. output.RenderBeginTag("Input") ' Cierra el elemento de control Input. output.RenderEndTag() ' Escribe el elemento en el HtmlTextWriter. output.WriteLine() End Sub ' (3)Obtiene datos desde el usuario. Debe crear este mtodo Public Function LoadPostData(ByVal postDataKey As String, _ ByVal postCollection As _ System.Collections.Specialized.NameValueCollection) As Boolean Implements System.Web.UI.IPostBackDataHandler.LoadPostData

229

MCAD/MCSD

' Si el usuario cambia el valor del input actualiza la propiedad text. If Me.Text <> postCollection(postDataKey) Then Me.Text = postCollection(postDataKey) ' Devolver True llama a RaisePostDataChangedEvent siguiente. Return True Else ' Devolver False no llama a RaisePostDataChangedEvent. Return False End If End Function ' (4) Sustituye al mtodo RaisePostDataChangedEvent. Debe crear este mtodo Public Sub RaisePostDataChangedEvent() Implements _ System.Web.UI.IPostBackDataHandler.RaisePostDataChangedEvent ' (5) Llama al mtodo de suceso. Opcional. OnChange(EventArgs.Empty) End Sub ' Mtodo de suceso. Protected Overridable Sub OnChange(ByVal e As EventArgs) ' Lanza el suceso RaiseEvent Change(Me, EventArgs.Empty) End Sub End Class

Visual C#
// (1) Interface IPostBackDataHandler permite obtener los datos enviados. [DefaultProperty("Text"), DefaultEvent("Change")] public class RenderText : System.Web.UI.WebControls.WebControl, IPostBackDataHandler{ public event EventHandler Change; [DefaultValue("")]public string Text{ get{ if (ViewState["Text"] != null) return ViewState["Text"].ToString(); else return null; } set{ ViewState["Text"] = value; OnChange(EventArgs.Empty); } } protected override void Render(HtmlTextWriter output) { // Configura los atributos del control Input. output.AddAttribute("value", this.Text); // (2) Debe definir este atributo para activar los datos de envo. output.AddAttribute("name", this.UniqueID); // Crea un elemento de control Input usando el anterior. output.RenderBeginTag("Input"); // Cierra el elemento de control Input (inserta />). output.RenderEndTag(); } // (3) Obtiene los datos del usuario. Debe crear este mtodo. public bool LoadPostData(string postDataKey, System.Collections.Specialized.NameValueCollection postCollection) { // Si el usuario cambia el valor del input actualiza la propiedad text. if (this.Text != postCollection[postDataKey]){ this.Text = postCollection[postDataKey]; // Devolver true llama a RaisePostDataChangedEvent. return true; }else // Devolver false no llama a RaisePostDataChangedEvent. return false; } // (4) Sustituye el mtodo RaisePostDataChangedEvent. Debe crear este mtodo. public void RaisePostDataChangedEvent(){ // (5) Llama al mtodo de suceso. Opcional. OnChange(EventArgs.Empty); }

230

Developing Web Applications

protected virtual void OnChange(EventArgs e) { if (Change != null) Change(this, e); // lanza el suceso. } } }

11.3.7 Aadir controles personalizados a la caja de herramientas


Tras crear y depurar un conjunto de controles personalizados puede agregarlo a la caja de herramientas de Visual Studio .NET siguiendo estos pasos: 1. En el men Herramientas seleccione Agregar o quitar elementos del cuadro de herramientas. 2. Pulse la lengeta Componentes de .NET Framework y Examinar. Visual Studio muestra el dilogo Abrir. 3. Use el dilogo Abrir para localizar y seleccionar el ensamblado (.dll) que contiene el control personalizado que se quiere agregar y pulse Abrir. Visual Studio abre el ensamblado y agrega el control que contiene a la lista de controles de la caja de dilogo Personalizar cuadro de herramientas. 4. Pulse Aceptar para cerrar el dilogo. Cuando agregue controles a la caja de herramientas aparecen en la categora General cuando Visual Studio est en modo Diseo. Para agregar un control personalizado a un formulario Web sencillamente pulse dos veces sobre el control o arrstrelo desde la caja de herramientas al formulario Web. Cuando agregue un control personalizado desde la caja de herramientas Visual Studio automticamente aadir la directiva Register para el control al formulario Web e insertar el HTML para el control personalizado, como se muestra a continuacin en negrita:
<%@ Page Language="vb" AutoEventWireup="false" Codebehind="WebForm1.aspx.vb" Inherits="vbRenderedTest.WebForm1"%> <%@ Register TagPrefix="cc1" Namespace="vbRenderedSnippet" Assembly="vbRenderedSnippet" %> <HTML> <body> <form id="Form1" method="post" runat="server"> <cc1:Chart id="Chart1" runat="server"></cc1:Chart> </form> </body> </HTML>

11.3.8 Establecer el icono y TagPrefix para controles personalizados


Puede hacer que sus controles muestren un icono propio en la caja de herramientas y usen su propio atributo TagPrefix en HTML. Si ya ha aadido el control a la caja de herramientas debe descargarlo y volver a agregarlo de nuevo en la caja antes de que el cambio surta efecto. Para agregar un icono propio a la caja de herramientas siga estos pasos: 1. Cree un archivo de mapa de bits de 16x16 que contenga el icono. Gurdelo en el directorio /bin del proyecto del control. 2. Al inicio del mdulo de la clase del control use o importe (using o Imports) el espacio de nombres System.Drawing. 3. Agregue el atributo ToolboxBitmap a la definicin de clase del control. Por ejemplo, la siguiente lnea especifica un archivo de icono llamado Red para el control personalizado Red. Visual Basic .NET
<ParseChildren(False), ToolboxBitmap("Red")> Public Class Red

Visual C#
[ParseChildren(false), ToolboxBitmap("Red")]

4. Vuelva a generar el control. Para cambiar el TagPrefix utilizado por el control en HTML siga estos pasos 1. Agregue las siguientes lneas al archivo AssemblyInfo del proyecto de control personalizado: Visual Basic .NET
Imports System.Web.UI <Assembly: TagPrefix("proyecto.espacionombres", "prefijo")>

Visual C#
using System.Web.UI [assembly: TagPrefix("espacionombres", "prefijo")]

231

MCAD/MCSD

2. Vuelva a generar la pgina. En el procedimiento anterior proyecto.espacionombres es el nombre y espacio de nombres del proyecto del control personalizado, y prefijo es el prefijo que se utilizar para los controles contenidos en este espacio de nombres.

11.4 Resumen
Cree controles de usuario dibujando controles de servidor y HTML en una pgina de control de usuario (.ascx). Aada un control de usuario a un formulario Web arrastrndolo desde el explorador de soluciones en lugar de la caja de herramientas. Los controles de usuario deben ser parte del proyecto donde se usan y se inicializan despus del suceso Page_Load del formulario Web que los contiene. Cree controles compuestos definiendo una clase derivada de la clase base WebControl. Los controles compuestos estn formados a partir de controles HTML y de servidor aadidos por medio del mtodo CreateChildControls. Para aadir caractersticas a un control de servidor existente superclasifique el control derivando un nuevo control personalizado a partir de la clase del existente. Los controles trazados proporcionan ms controles sobre el aspecto y comportamiento del control, pero necesitan ms programacin para manejar las tareas que los controles compuestos normalmente manejan por medio de sus controles hijos. Use el mtodo Render y los mtodos de utilidad de HtmlTextWriter para crear la apariencia de un control personalizado trazado. Use el interface IPostBackEventHandler para permitir que un control lance sucesos de envo. Use el interface IPostBackDataHandler para permitir que un control trazado para obtener datos introducidos por el usuario en un control en tiempo de ejecucin.

11.5 Prctica: Crear controles personalizados


En esta prctica crear un proyecto de aplicacin Web para contener los tres controles diferentes creados en cada uno de los ejercicios. Encontrar este ejemplo con el nombre vbUserControlSample o csUserControlSamplo en el CD-ROM.

11.5.1 Ejercicio 1: Crear un control de usuario AddressBox


En este ejercicio crear una aplicacin Web que contiene un control de usuario que obtiene informacin de nombre de usuario y contrasea. Use las capacidades aprendidas en la leccin 1 para crear y probar un control de usuario completando las siguientes tareas principales: 1. Cree un proyecto de aplicacin Web. 2. Agregue un control de usuario (.ascx) que contenga texto y controles para recoger el nombre, direccin, ciudad, estado y cdigo postal. 3. Use controles de validacin dentro del control de usuario para asegurar que se rellenan los campos requeridos. 4. Use un control HTML Grid Layout Panel para dar formato y colocar el texto y los controles dentro del control de usuario. 5. Proporcione un suceso Click que se lance desde el control de usuario una vez una vez validadas las entradas de datos. 6. Proporcione propiedades pblicas de solo lectura para devolver la informacin de direccin desde el control de usuario. 7. Proporcione una propiedad pblica Style de lectura y escritura para dar soporte al posicionamiento absoluto en la rejilla. 8. Pruebe el control de usuario aadindolo a un formulario Web y accediendo a sus sucesos y propiedades desde el cdigo. Cuando termine (o cuando se atasque) compare sus resultados con el control de usuario AddressBox incluido en el CD-ROM.

11.5.2 Ejercicio 2: Crear el control personalizado compuesto DigitPad


En este ejercicio va a crear una librera de controles Web que contendr un control personalizado que permitir al usuario introducir nmeros pulsando botones. Use las capacidades aprendidas en la leccin 2 para crear y probar el control personalizado completando las siguientes tareas principales: 1. Agregue un proyecto de librera de controles Web a la solucin creada en el ejercicio anterior. 2. Agregue una referencia desde el proyecto de control de usuario al proyecto de librera de controles Web de forma que pueda probar el control personalizado desde formularios Web del proyecto. 232

Developing Web Applications

3. Cree un control personalizado compuesto que use controles InputButton de HTML para aceptar entradas numricas. 4. Proporcione un suceso de envo que se lance desde el control personalizado una vez completos los datos numricos. 5. Proporcione una propiedad pblica de solo lectura que devuelva el nmero introducido en el control. 6. Pruebe el control aadindolo a un formulario Web y accediendo a su suceso y propiedades desde el cdigo. Cuando termine, compare sus resultados con el control personalizado DigitPad incluido en el CD-ROM.

11.5.3 Ejercicio 3: Cree el control personalizado trazado BartChar


En este ejercicio aadir un control trazado personalizado al la librera de controles Web que cre en el ejercicio 2. El control personalizado crear un grfico de barras sencillo a partir de los nmeros introducidos entre las etiquetas HTML de inicio y fin del control personalizado. Use las capacidades aprendidas en la leccin 3 para completar las siguientes tareas principales. 1. Aada una nueva clase de control personalizado Web al proyecto de librera de controles Web creado en el ejercicio anterior. 2. Cree una propiedad Values que recibe un array de datos del texto introducido entre las etiquetas de inicio y fin del control personalizado. 3. Cree una propiedad ChartTitle que configura o devuelve un encabezado mostrado en la parte superior del grfico. 4. Sustituya el mtodo Render del control para crear un grfico de barras a partir de los datos de la propiedad Values. Para simplificar la elaboracin del diagrama use controles regla horizontal de HTML (<HR>) para crear el grfico. 5. Pruebe el control de usuario agregndolo a un formulario Web y accediendo a sus sucesos y propiedades desde el cdigo. Compare sus resultados con el control personalizado BartChar incluido en el CD-ROM

11.6 Repaso
Las siguientes preguntas estn pensadas para reforzar informacin clave mostrada en este captulo. Si no es capaz de contestar a una pregunta repase la leccin correspondiente e intente de nuevo. Las respuestas se pueden encontrar en el captulo 16. 1. Describa brevemente los mejores usos para cada uno de los tres tipos de controles Web completando las siguientes frases: Cree un control de usuario si quiere ... Cree un control personalizado compuesto si quiere ... Cree un control trazado si quiere ... 2. Qu importancia tiene la derivacin para crear controles Web personalizados? 3. Cul es el mtodo ms importante que hay que sustituir cuando se crea un control personalizado compuesto? 4. Cul es el mtodo ms importante que hay que sustituir cuando se crea un control trazado? 5. En que se diferencia lanzar un suceso de vuelta en un control compuesto a hacerlo en un control trazado?

233

MCAD/MCSD

234

Developing Web Applications

12 Trabajar con multimedia


Una cosa que hace interesante Internet es la cantidad de tipos de medios que puede presentar un sitio Web. Texto e imgenes pueden coexistir con msica, video y animacin. En este captulo aprender como aadir estos elementos a aplicaciones Web ASP.NET y cmo controlar su presentacin y reproduccin en cdigo. Para completar este captulo debe: Comprender el ciclo de vida de un formulario Web ASP.NET Saber cmo editar formularios Web en HTML Estar familiarizado con la creacin de secuencias de comandos de cliente en un formulario Web usando JScript o VBScript.

12.1 Interpretar audio


Cuando se vuelve a mostrar una pgina Web que contiene un sonido de fondo el navegador detiene y vuelve a iniciar la interpretacin del sonido. Por este motivo, la tcnica de ASP.NET de utilizar el envo de vuelta de la pgina para interceptar sucesos de cliente en el servidor provoca que el sonido de la pgina se detenga y reinicie cuando el servidor enva una respuesta. Por tanto por lo general es mejor controlas audio y otro multimedia usando secuencias de comandos de cliente en lugar de cdigo de servidor. En el captulo 7, Programacin avanzada de formularios web, aprendi cmo aadir secuencias de comandos a un formulario Web para responder a sucesos de cliente y controlar el navegador. En esta leccin aprender cmo usar elementos HTML para incluir audio en un formulario Web o una pgina HTML y cmo controlar reproduccin de audio usando secuencia de comandos de cliente.

12.1.1 Formas de interpretar audio


Hay tres formas bsicas para interpretar audio en un formulario web ASP.NET: Como sonido de fondo usando el elemento HTML bgsound. Como sonido incrustado usando el elemento HTML embed para insertar el intrprete de medios del usuario en la pgina. Como objeto ActiveX usando el elemento HTML object para insertar un intrprete de medios concreto en una pgina. La primera tcnica la soporta la mayor variedad de navegadores y plataformas, pero no permite controlar la reproduccin como se puede con el resto. Las siguientes secciones exploran estas tcnicas con mayor detalle.

12.1.2 Interpretar sonidos de fondo


El elemento bgsound interpreta un sonido cuando se muestra una pgina Web. Este elemento no se proporciona como controle HTML, de modo que no aparece en la caja de herramientas de Visual Studio .NET. Para aadir un sonido de fondo a un formulario web siga estos pasos: 1. En Visual Studio, muestre el formulario Web y cambie a modo HTML 2. Inserte un elemento HTML bgsound, por ejemplo, <bgsound src="prueba.wav" id="bgPrueba"
loop="infinite">

Una de las primeras cosas que se observan sobre los sonidos de fondo es que se reinician cada vez que se vuelve a mostrar la pgina. Esto no es muy preocupante con pginas HTML normales, pero los formularios Web ASP.NET se vuelven a mostrar cada vez que se produce un suceso de envo, como al pulsar un botn de servidor. Si quiere que se interprete un sonido una sola vez la primera vez que se muestre un formulario Web use la propiedad IsPostBack de la pgina para determinar si se inserta el sonido. Por ejemplo, el siguiente cdigo interpreta el sonido solo una vez la primera vez que se muestra la pgina. Visual Basic .NET
Private Sub Page_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) _ Handles MyBase.Load If Not(IsPostBack) Then Response.Write("<bgsound src='prueba.wav' id='bgPrueba' loop='1'>") End If End Sub

Visual C#
private void Page_Load(object sender, System.EventArgs e){ if(!IsPostBack) Response.Write("<bgsound src='prueba.wav' id='bgPrueba' loop='1'>"); }

235

MCAD/MCSD

Puede usar una tcnica similar para interpretar sonidos en respuesta a otros sucesos de pgina, como pulsaciones de botn. Los sonidos de fondo son aditivos si interpreta ms de un sonido a la vez se oirn todos simultneamente.

12.1.3 Incrustar sonidos


Una de las limitaciones de los sonidos de fondo es que no puede controlarlos una vez que empiezan a sonar. Los sonidos de fondo comienzan cuando se muestra la pgina y se detienen cuando terminan o cuando se muestra una nueva pgina. Para que el usuario pueda detener, iniciar o cambiar el volumen de sonido, necesita usar el elemento embed de HTML. Por ejemplo, el siguiente HTML incrusta un sonido y muestra el intrprete de medios predeterminado del usuario en el formulario Web:
<embed src="test.wav" id="wavTest" hidden="false" height="20" width="150" autostart="false" type="audio/wav" loop="true"></embed>

El plug in que muestra el anterior HTML puede cambiar dependiendo puede variar dependiendo de qu intrprete de audio tenga instalado el usuario. La incrustacin de un sonido permite que el usuario controle la reproduccin, pero el desarrollador tiene muy poco control desde el cdigo cliente. Puede ocultar o mostrar el plug in, indicar que repita, cambiar su tamao y posicin, pero esto es todo. Por ejemplo, los siguientes botones HTML ocultan y muestran el plug in:
<input type="button" value="Oculta" id="butHide" onclick="wavTest.hidden='true'"> <input type="button" value="Muestra" id="butShow" onclick="wavTest.hidden='false'">

Para iniciar, detener, pausar o enmudecer el sonido desde secuencias de comandos de cliente necesita incluir el sonido como objeto en el formulario Web. La siguiente seccin describe cmo hacerlo.

12.1.4 Sonido como objetos ActiveX


Puede incluir sonidos en un formulario como objetos ActiveX mediante el elemento object de HTML con la informacin de ID de clase adecuada para el intrprete concreto que quiere usar. La insercin de sonidos como objetos le da control sobre la reproduccin desde secuencias de comandos de cliente usando el elemento como un objeto. Para incluir un sonido como objeto siga estos pasos: 1. Aada un objeto ActiveX de intrprete de medios en el formulario Web 2. Configure las propiedades del objeto ActiveX para que interprete el sonido 3. Aada el cdigo para determinar si el sistema del usuario tiene instalado el objeto ActiveX y tomar las acciones adecuadas en caso contrario Las siguientes secciones describen estos pasos con mayor detalle Aadir un objeto ActiveX a un formulario Web Varios objetos ActiveX pueden interpretar medios, como sonido, desde el interior de un navegador. Dos de los ms extendidos son Windows Media Player y RealPlayer. Puede aadir cualquiera d estos intrpretes a un formulario web siguiendo estos pasos: 1. Con un formulario Web en modo diseo pulse la lengeta HTML de la caja de herramientas de Visual Studio, pulse sobre ella con el botn derecho y seleccione Agregar o quitar elementos. 2. Pulse la lengeta Componentes COM y recorra la lista de componentes instalados. Localice el componente que quiere agregar a la caja de herramientas y seleccinelos. Por ejemplo, el objeto RealPlayer se llama RealPlayer G2 Control; el intrprete de Microsoft se llama Windows Media Player. 3. Pulse Aceptar para cerrar el dilogo. Visual Studio carga los controles en la caja de herramientas. 4. Arrastre el objeto intrprete de medios desde la caja de herramientas al formulario Web. Visual Studio inserta un elemento object de HTML con id de clase del intrprete y valores de parmetro predeterminados, como muestra el siguiente HTML:
<p>Sonido como objeto Windows Media Player:</p> <OBJECT id="objWMPlay" classid="clsid:22D6F312-B0F6-11D0-94AB-0080C74C7E95" VIEWASTEXT> <PARAM NAME="AudioStream" VALUE="-1"> <PARAM NAME="AutoSize" VALUE="-1"> <PARAM NAME="AutoStart" VALUE="0"> <PARAM NAME="AnimationAtStart" VALUE="-1"> <PARAM NAME="AllowScan" VALUE="-1"> <PARAM NAME="AllowChangeDisplaySize" VALUE="-1"> <PARAM NAME="AutoRewind" VALUE="0"> <PARAM NAME="Balance" VALUE="0"> <PARAM NAME="BaseURL" VALUE=""> <PARAM NAME="BufferingTime" VALUE="5"> <PARAM NAME="CaptioningID" VALUE=""> <PARAM NAME="ClickToPlay" VALUE="-1">

236

Developing Web Applications

<PARAM <PARAM <PARAM <PARAM <PARAM <PARAM <PARAM <PARAM <PARAM <PARAM <PARAM <PARAM <PARAM <PARAM <PARAM <PARAM <PARAM <PARAM <PARAM <PARAM <PARAM <PARAM <PARAM <PARAM <PARAM <PARAM <PARAM <PARAM <PARAM <PARAM <PARAM <PARAM <PARAM <PARAM <PARAM <PARAM <PARAM <PARAM <PARAM <PARAM <PARAM <PARAM <PARAM <PARAM <PARAM <PARAM </OBJECT>

NAME="CursorType" VALUE="0"> NAME="CurrentPosition" VALUE="-1"> NAME="CurrentMarker" VALUE="0"> NAME="DefaultFrame" VALUE=""> NAME="DisplayBackColor" VALUE="0"> NAME="DisplayForeColor" VALUE="16777215"> NAME="DisplayMode" VALUE="0"> NAME="DisplaySize" VALUE="0"> NAME="Enabled" VALUE="-1"> NAME="EnableContextMenu" VALUE="-1"> NAME="EnablePositionControls" VALUE="-1"> NAME="EnableFullScreenControls" VALUE="0"> NAME="EnableTracker" VALUE="-1"> NAME="Filename" VALUE="test.wav"> NAME="InvokeURLs" VALUE="-1"> NAME="Language" VALUE="-1"> NAME="Mute" VALUE="0"> NAME="PlayCount" VALUE="1"> NAME="PreviewMode" VALUE="0"> NAME="Rate" VALUE="1"> NAME="SAMILang" VALUE=""> NAME="SAMIStyle" VALUE=""> NAME="SAMIFileName" VALUE=""> NAME="SelectionStart" VALUE="-1"> NAME="SelectionEnd" VALUE="-1"> NAME="SendOpenStateChangeEvents" VALUE="-1"> NAME="SendWarningEvents" VALUE="-1"> NAME="SendErrorEvents" VALUE="-1"> NAME="SendKeyboardEvents" VALUE="0"> NAME="SendMouseClickEvents" VALUE="0"> NAME="SendMouseMoveEvents" VALUE="0"> NAME="SendPlayStateChangeEvents" VALUE="-1"> NAME="ShowCaptioning" VALUE="0"> NAME="ShowControls" VALUE="-1"> NAME="ShowAudioControls" VALUE="-1"> NAME="ShowDisplay" VALUE="0"> NAME="ShowGotoBar" VALUE="0"> NAME="ShowPositionControls" VALUE="-1"> NAME="ShowStatusBar" VALUE="0"> NAME="ShowTracker" VALUE="-1"> NAME="TransparentAtStart" VALUE="0"> NAME="VideoBorderWidth" VALUE="0"> NAME="VideoBorderColor" VALUE="0"> NAME="VideoBorder3D" VALUE="0"> NAME="Volume" VALUE="0"> NAME="WindowlessVideo" VALUE="0">

<p>Este es el sonido como objeto RealPlayer:</p> <OBJECT id="objRPlay" classid="clsid:CFCDAA03-8BE4-11CF-B84B-0020AFBBCCFA" VIEWASTEXT> <PARAM NAME="_ExtentX" VALUE="7938"> <PARAM NAME="_ExtentY" VALUE="2646"> <PARAM NAME="AUTOSTART" VALUE="0"> <PARAM NAME="SHUFFLE" VALUE="0"> <PARAM NAME="PREFETCH" VALUE="0"> <PARAM NAME="NOLABELS" VALUE="0"> <PARAM NAME="LOOP" VALUE="0"> <PARAM NAME="NUMLOOP" VALUE="0"> <PARAM NAME="CENTER" VALUE="0"> <PARAM NAME="MAINTAINASPECT" VALUE="0"> <PARAM NAME="BACKGROUNDCOLOR" VALUE="#000000"> </OBJECT>

Como puede ver en el HTML anterior, diferentes intrpretes tienen conjuntos de parmetros diferentes que los controlan. Desde una perspectiva de programacin, es mucho ms sencillo seleccionar un intrprete concreto y pedir al usuario que lo instales que dar soporte a mltiples intrpretes. Muchos usuarios tienen ms de un intrprete instalado, de modo que elegir uno u otro no debe ser un gran problema de compatibilidad.

237

MCAD/MCSD

Configurar las propiedades y mtodos del intrprete Los elementos param incluidos en el HTML de un objeto ActiveX representan las propiedades del objeto. Estas propiedades se usan junto con los mtodos y sucesos del objeto para controlar el intrprete desde secuencias de comandos de cliente. Puede ser muy difcil tener buena informacin de referencia sobre un objeto ActiveX. Una de las formas ms sencillas de aprender sobre las propiedades, mtodos y sucesos es aadir una referencia desde al proyecto actual al objeto y usar el inspector de objetos para ver sus miembros. Para usar las propiedades de un objeto ActiveX desde una secuencia de comandos use los mtodos del elemento HTML. Por ejemplo, las siguientes secuencias de comandos para la pulsacin de un botn inician y detienen la reproduccin en Windows Media Player:
<input type="button" value="Start" id="butStart" onclick="objWMPlay.play()"> <input type="button" value="Stop" id="butStop" onclick="objWMPlay.stop()">

El objeto RealPlayer utiliza nombres de mtodo ligeramente diferentes:


<input type="button" value="Start" id="butStartPlay" onclick="objRPlay.object.source='test.wav';objRPlay.doplay()"> <input type="button" value="Stop" id="butStopPlay" onclick="objRPlay.dostop()">

Para responder a sucesos de objeto en el cliente cree un controlador de suceso de secuencia de comandos. El siguiente ejemplo muestra un mensaje cuando termina la ejecucin del sonido en Windows Media Player: JScript
<SCRIPT FOR="objWMPlay" EVENT="EndOfStream(lResult)" LANGUAGE="Jscript"> alert("Fin de la pieza"); </SCRIPT>

VBScript
<script language="vbscript"> Sub objWMPlay_EndOfStream(lResult) alert("Fin de la pieza.") End Sub </script>

De nuevo, el objeto RealPlayer tiene nombres ligeramente diferentes para el mismo suceso: JScript
<SCRIPT FOR="objRPlay" EVENT="OnClipClosed()" LANGUAGE="Jscript"> alert("Fin de la pieza."); </SCRIPT>

VBScript
<script language="vbscript"> Sub objRPlay_OnClipClosed() alert("Fin de la pieza.") End Sub </script>

Puede usar las propiedades, mtodos y sucesos del cdigo de servidor. Si embargo, al hacerlo recarga la pgina Web y por tanto reinicia el sonido, que normalmente no es lo que se quiere. Instalar objetos ActiveX en el cliente Utilice al atributo codebase del elemento object para especificar una ubicacin desde la que el usuario puede instalar el objeto ActiveX si no existe actualmente en su sistema. El atributo codebase recibe dos argumento: el primero es la ubicacin desde la que se descargar el control, y el segundo el nmero de versin del control. Por ejemplo, el siguiente elemento de objeto ActiveX descarga Windows Media Player si el usuario no tiene instalada la versin 6.4:
<OBJECT ID="objWMPlayer" classid="CLSID:22D6F312-B0F6-11D0-94AB-0080C74C7E95" CODEBASE="http://activex.microsoft.com/activex/controls/mplayer/en/ nsmp2inf.cab#Version=6,4,5,715" VIEWASTEXT> <PARAM NAME="AutoStart" VALUE="True"> <PARAM NAME="FileName" VALUE="test.avi"> </OBJECT>

Cuando el usuario muestra una pgina con el elemento object anterior el navegador comprueba si en la mquina del usuario existe la versin indicada; si no, el navegador muestra un dilogo antes de descargar e instalar el objeto. Cuando se instala el objeto se muestra la pgina y se interpreta el sonido.

238

Developing Web Applications

Control de objetos ActiveX desde Netscape Navigator. Netscape Navigator no soporta objetos ActiveX o el elemento object de HTML. Para incluir sonidos como objetos dentro de Navigator debe incluirlos como plug incrustado. Navigator ignora el elemento object, de modo que puede incluir el elemento embed dentro del elemento object para dar soporte tanto a Microsoft Internet Explorer como a Netscape Navigator en la misma pgina. El siguiente HTML muestra Windows Media Player en ambos navegadores:
<OBJECT ID="objWMPlayer" classid="CLSID:22D6F312-B0F6-11D0-94AB-0080C74C7E95" CODEBASE="http://activex.microsoft.com/activex/controls/mplayer/en/nsmp2inf .cab#Version=6,4,5,715" type="application/x-oleobject" VIEWASTEXT> <PARAM NAME="AutoStart" VALUE="False"> <PARAM NAME="FileName" VALUE="test.wav"> <EMBED type="application/x-mplayer2" pluginspage="http://www.microsoft.com/Windows/MediaPlayer/" SRC="test.wav" name="objWMPlayer" autostart="0" showcontrols="1" </EMBED> </OBJECT>

Si no est instalado Media Player en Netscape Navigator el cdigo anterior redirige al usuario a la pgina de descarga desde la que pueden instalarlo. Para asegurarse de que los usuarios no tienen que reiniciar sus navegadores despus de instalar el plug in incluya la siguiente secuencia de comandos tras el objeto en la pgina:
<!Debe escribirse en JavaScript, ya que Navigator no soporta VBScript --> <script language="JavaScript"> // Si el navegador es Netscape Navigator. if ( navigator.appName == "Netscape" ){ // Refresca los plugins recin instalados. navigator.plugins.refresh(); } </script>

Los plug in de Netscape permiten algn control mediante comandos, pero no es coherente con el de ActiveX. En concreto: Se accede a las propiedades mediante mtodos Set y Get en lugar de mediante asignacin Los sucesos de plug in se interceptan mediante un proxy applet de Java. Estos temas de programacin, junto con los relativos a la estabilidad del navegador y la dificultad de depurar cdigo diferente para diferentes plataformas limitan la practicabilidad de usar secuencias de comandos con objetos ActiveX como plug in dentro de Navigator. Si su aplicacin utiliza objetos ActiveX y necesita dar soporte a Netscape Navigator es ms prctico incrustar el objeto como plug in, como se muestra en esta seccin, y desactivar los intentos de controlar el objeto en secuencias de comandos. Por ejemplo, el siguiente HTML comprueba si el navegador del usuario es Netscape. Si lo es, el cdigo desactiva los botones que controlan Windows Media Player y muestran en su lugar el interface completo del intrprete.
<html> <head> <title>Objetos ActiveX para varios navegadores</title> </head> <body> <h2>Uso de objetos ActiveX en varios navegadores</h2> <OBJECT ID="objWMPlayer" classid="CLSID:22D6F312-B0F6-11D0-94AB-0080C74C7E95" CODEBASE="http://activex.microsoft.com/activex/controls/mplayer/en/ns mp2inf.cab#Version=6,4,5,715" type="application/x-oleobject" VIEWASTEXT> <PARAM NAME="AutoStart" VALUE="False"> <PARAM NAME="FileName" VALUE="test.wav"> <!-- Oculta controles de Media Player si es IE --> <param name="ShowControls" value="False"> <EMBED type="application/x-mplayer2" pluginspage="http://www.microsoft.com/Windows/MediaPlayer/" SRC="test.wav" name="objWMPlayer" autostart="0" showcontrols="1"> <!-- Muestra controles si es Navigator --> </EMBED> </OBJECT>

239

MCAD/MCSD

<!-- botones para interface personalizado en IE --> <div id="pnlControls"> <!-- Debe estar Java porque Navigator no soporta VBScript --> <script language="JavaScript"> // Si el navegador es Netscape Navigator. if ( navigator.appName == "Netscape" ){ // Refresca plugins recin instalados. navigator.plugins.refresh(); // La pgina termina aqu (sin botones HTML). alert("Est usando Netscape Navigator. Algunas caractersticas de objetos ActiveX se han desactivado."); document.all["pnlControls"].setAttribute("disabled","1"); } </script><br> <p>Use estos botones para controlar el objeto Media Player.</p> <input type="button" value="Iniciar" id="butStart" onclick="objWMPlayer.Play();" > <input type="button" value="Parar" id="butStop" onclick="objWMPlayer.stop()" > <input type="button" value="Repetir" id="butRepeat" onclick="objWMPlayer.PlayCount='2'" > <input type="button" value="Mudo" id="butMute" onclick="objWMPlayer.Mute=!(objWMPlayer.Mute)" > </div> </body> </html>

12.2 Mostrar video


Muchas de las tcnicas usadas para controlar video son las mismas o similares que las que se vieron en la leccin anterior para controlar audio. Como con el audio, al volver a mostrar una pgina Web se reinicia el video. Por tanto, por lo general es mejor controlar video y responder a los sucesos de video usando secuencias de comandos de cliente en lugar de cdigo de servidor. En esta leccin aprender cmo incluir video en un formulario Web o pgina HTML usando elementos HTML y objetos ActiveX. Tambin aprender cmo controlar reproduccin de video usando secuencias de comandos de cliente en JScript y VBScript.

12.2.1 Formas de mostrar video


Hay tres formas bsicas de mostrar video en un formulario Web: Como elemento img de HTML usando el atributo dynsrc. Como video incrustado usando el elemento embed de HTML para insertar el intrprete de medios predeterminado del usuario en la pgina. Como objeto ActiveX usando el elemento object de HTML para insertar un intrprete de medios concreto en la pgina. Como con audio, cada una de estas posibilidades tiene ventajas e inconvenientes. Las siguientes secciones exploran estas tcnicas en detalle.

12.2.2 Elemento img


La forma ms sencilla de mostrar video en una pgina es incluir el video como elemento img de HTML. El atributo dynsrc del elemento img permite especificar una archivo de video para mostrar en el elemento:
<img dynsrc="clock.avi">

Los controles de servidor Image e ImageButton y los controles HTML Image e Image Button soportan el atributo dynsrc. Por ejemplo, el siguiente HTML muestra un video en un control ImageButton:
<asp:ImageButton id="ImageButton1" dynsrc="clock.avi" runat="server" />

Sin embargo este atributo tiene las siguientes limitaciones: Netscape Navigator no lo soporta Solo acepta AVI No se puede controlar desde secuencias de comandos de cliente.

12.2.3 Incrustar videos


Use el elemento embed de HTML para mostrar un video en un formulario Web con el intrprete de medios predeterminado del usuario. Por ejemplo, el siguiente HTML incrusta un video en una pgina: 240

Developing Web Applications

<embed src="clock.avi" id="aviTest" hidden="false" height="200" width="200" autostart="false" type="video/avi" loop="true"></embed>

Los videos incrustados se muestran usando el plugin que est registrado para este tipo de medio. Usar el elemento embed para mostrar video tiene las siguientes ventajas: Lo soporta la mayora de los navegadores, incluyendo Internet Explorer y Netscape Navigator El usuario puede controlar la reproduccin usando los controles del intrprete de medios incrustados. Se pueden mostrar diferentes formatos de video. La desventaja de usar el elemento HTML embed es que no proporciona el nivel de soporte para secuencia de comandos que se obtiene con un objeto ActiveX.

12.2.4 Videos como objetos ActiveX


Como con sonidos, puede incluir videos como objetos ActiveX en un formulario Web insertando un elemento object de HTML con el ID de clase adecuado. Insertar videos como objetos le da el control de la reproduccin desde secuencias de comandos de cliente usando el elemento como objeto. Para mostrar un video como ActiveX se usan los mismos procedimientos que con un sonido. La diferencia es que el parmetro FileName indica un video y no un sonido. Por ejemplo, el siguiente HTML muestra un video como objeto AciveX de Windows Media Player9.
<OBJECT id="objWMPlay" classid="clsid:22D6F312-B0F6-11D0-94AB-0080C74C7E95" CODEBASE="http://activex.microsoft.com/activex/controls/mplayer/en/ns mp2inf.cab#Version=6,4,5,715" type="application/x-oleobject" VIEWASTEXT> <PARAM NAME="AutoStart" VALUE="0"> <PARAM NAME="EnableTracker" VALUE="-1"> <PARAM NAME="Filename" VALUE="clock.avi"> <PARAM NAME="Mute" VALUE="0"> <PARAM NAME="ShowControls" VALUE="-1"> <PARAM NAME="ShowAudioControls" VALUE="-1"> <PARAM NAME="ShowDisplay" VALUE="0"> <PARAM NAME="ShowGotoBar" VALUE="0"> <PARAM NAME="ShowPositionControls" VALUE="-1"> <PARAM NAME="ShowStatusBar" VALUE="0"> <PARAM NAME="ShowTracker" VALUE="-1"> <PARAM NAME="VideoBorderWidth" VALUE="0"> <PARAM NAME="VideoBorderColor" VALUE="0"> <PARAM NAME="VideoBorder3D" VALUE="0"> <PARAM NAME="Volume" VALUE="0"> <PARAM NAME="WindowlessVideo" VALUE="0"> </OBJECT>

Puede controlar la reproduccin de video del objeto ActiveX Windows Media Player usando las mismas propiedades y mtodos que usaba para controlar la reproduccin de audio en las lecciones anteriores. Por ejemplo, los siguientes botones permiten iniciar, detener, pausar y enmudecer el video:
<input onclick="objWMPlay.object.play()" type="button" value="Start"> <input onclick="objWMPlay.stop()" type="button" value="Stop"> <input onclick="objWMPlay.PlayCount='2'" type="button" value="Repeat"> <input onclick="objWMPlay.mute=!objWMPlay.mute" type="button" value="Mute"> <input onclick="objWMPlay.showcontrols='false'" type="button" value="Hide Controls">

Para responder a los sucesos de Media Player cree secuencias de comandos como hizo para audio. Por ejemplo, la siguiente secuencia de comandos de cliente muestra una caja de mensaje cuando el usuario detiene el video. JScript
<SCRIPT language="Jscript" event="PlayStateChange(iState)" for="objWMPlay"> if (iState==2) alert("Video Detenido."); </SCRIPT>

VBScript
<script language="vbscript"> Sub objWMPlay_PlayStateChange(iState) if iState=2 then alert("Video detenido.") End Sub </script>

Estos parmetros corresponden a la versin 6.4. Vea la pgina siguiente para versiones posteriores.

241

MCAD/MCSD

12.2.5 Objetos ActiveX en Netscape Navigator


Como se mencion en la leccin anterior Netscape Navigator no soporta objetos ActiveX o el elemento object de HTML. Para incluir videos en Netscape Navigator deber hacerlo como plugins incrustados. Para ello siga el mismo procedimiento que se mostr en la leccin anterior para controlar sonidos ActiveX dentro de Netscape Navigator.

12.2.6 Versiones de Windows Media Player


Hasta ahora, en los ejemplos de audio y video para Windows Media Player hemos usado la versin 6.4, aunque ya se distribuye la 8.010. Hay un par de razones para esto: La versin 6.4 tienen un plugin equivalente para soporte de Netscape Navigator La versin 7.0 y posteriores no se pueden instalar en sistemas operativos anteriores de Microsoft, como Windows 95 o NT 4. Si la compatibilidad con sistemas operativos anteriores no es una preocupacin probablemente querr usar la versin actual. Para incluir el Windows Media Player actual en un formulario Web use el siguiente elemento object:
<OBJECT id="Player" height="240" width="320" classid="CLSID:6BF52A52-394A-11d3-B153-00C04F79FAA6" VIEWASTEXT> <PARAM NAME="URL" VALUE="clouds.avi"> <PARAM NAME="rate" VALUE="1"> <PARAM NAME="balance" VALUE="0"> <PARAM NAME="currentPosition" VALUE="0"> <PARAM NAME="defaultFrame" VALUE=""> <PARAM NAME="playCount" VALUE="1"> <PARAM NAME="autoStart" VALUE="-1"> <PARAM NAME="currentMarker" VALUE="0"> <PARAM NAME="invokeURLs" VALUE="-1"> <PARAM NAME="baseURL" VALUE=""> <PARAM NAME="volume" VALUE="50"> <PARAM NAME="mute" VALUE="0"> <PARAM NAME="uiMode" VALUE="full"> <PARAM NAME="stretchToFit" VALUE="0"> <PARAM NAME="windowlessVideo" VALUE="0"> <PARAM NAME="enabled" VALUE="-1"> <PARAM NAME="enableContextMenu" VALUE="-1"> <PARAM NAME="fullScreen" VALUE="0"> <PARAM NAME="SAMIStyle" VALUE=""> <PARAM NAME="SAMILang" VALUE=""> <PARAM NAME="SAMIFilename" VALUE=""> <PARAM NAME="captioningID" VALUE=""> </OBJECT>

Media Player versin 7 tiene un ID de clase y un modelo de objeto diferentes a los de la versin 6.4. Por ejemplo, en lugar de usar la propiedad Filename para especificar un video usa la propiedad URL. La ltima versin (en el momento de escribir el original la 8.0) no tiene un archivo .cab que se pueda instalar usando el atributo codebase. En su lugar es necesario comprobar si el Media Player est instalado y si no lo est dirigir a los usuarios a la situacin desde pueden instalarlo. Por ejemplo, el siguiente cdigo comprueba si est instalado Media Player versin 7.0 o posterior y dirige al usuario al sitio de descarga de Microsoft si no es as. JScript
<script language="JavaScript"> // Usa control de excepciones para vers si se pudo crear el intrprete. try{ if(document.objWMPlayer.object.enabled); // Si funciona, no hace nada. }catch(ex){ // Si hay error, pide al usuario que lo instale. document.writeln("<p>No tiene la versin actual de Media Player."); document.writeln("<a href='http://www.microsoft.com/windows/windowsmedia/download /'>Pulse aqu</a> para instalarlo.</p>"); } </script>

10

Y la 9.0

242

Developing Web Applications

VBScript
<script language="vbscript"> ' Usa control de excepciones para probar si se puede crear el intrprete. On Error Resume Next ' Si funciona, no hace nada. If Document.objWMPlayer.enabled then x=0 If Err Then ' Si hay error pide al usuario que lo instale. document.writeln("<p>No tiene la versin actual de Media Player.") document.writeln("<a href='http://www.microsoft.com/windows/windowsmedia/" & _ "download/'>Pulse aqu</a> para instalarlo.</p>") End If On Error Goto 0 </script>

La versin 7 de Windows Media Player tiene una amplia informacin de referencia en la ayuda en lnea de Visual Studio.

12.3 Animar pginas Web


Las pginas Web a menudo usan texto en movimiento para atraer la vista del usuario hacia anuncios, aclarar algo o sencillamente divertir. Puede usar una amplia variedad de tcnicas para crear contenido animado para la Web. Esta leccin le presenta las tcnicas principales, compara sus ventajas y desventajas y muestra cmo usarlas.

12.3.1 Formas de mostrar animaciones


Hay varias formas de mostrar animaciones. La tabla 12.1 compara las ventajas y desventajas de las ms comunes.
Tabla 12. 1: Tcnicas de animacin
Tcnica Elemento marquee de HTML Archivos GIF animados Ventajas Usa etiquetas y atributos HTML sencillos No precisa cdigo de secuencia de comandos Se puede usar en cualquier elemento HTML que admita un grfico No precisa cdigo. Desventajas Disponible solo en Internet Explorer Nmero de efectos limitado Los archivos crecen al aumentar la complejidad y el tamao Se debe descargar el archivo entero antes de mostrarse No se puede controlar la reproduccin Puede crear presentaciones animadas complejas Precisa que los usuarios tengan instalado el objeto ActiveX o el plugin Puede comenzar antes de que termine la Es posible que el creador de contenido necesite descarga (soporte de streaming) adquirir una licencia y aprender el uso de la Herramientas de tercero para creacin y herramienta. presentacin ampliamente disponibles Puede interactuar con el usuario Pueden ser controlados por secuencias de comandos de cliente. Los efectos que puede crear solo con cdigo son Puede controlar cualquier elemento de la limitados. pgina. Si escribe JScript, el cdigo es soportado por la El cdigo se puede volver muy complejo y difcil de mantener. mayora de navegadores. La sincronizacin de efectos es difcil y compleja. Usa un lenguaje estndar basado en XML. Netscape Navigator no lo soporta Puede controlar cualquier elemento de la pgina No puede ver los efectos en la vista de diseo usando animacin basada en tiempo. de Visual Studio debe editar en HTML Se puede combinar con secuencias de comandos de cliente para aadir interactividad

Objetos ActiveX o plugins incrustados en una pgina Secuencias de comandos de cliente HTML + TIME

12.3.2 Animar Texto


El elemento marquee de HTML anima cualquier elemento que contenga desplazndolo hacia arriba, abajo, izquierda o derecha. Se usa normalmente para mostrar avisos que deben captar la atencin. Por ejemplo, el siguiente HTML muestra el texto Mrame en colores contrastados botando de izquierda a derecha en pantalla.
<marquee bgcolor="red" scrollamount="10" behavior="alternate" direction="right" loop="true"> <h1 style="COLOR:Yellow">Mrame</h1> </marquee>

Tambin puede usar el elemento marquee para revelar texto desplazndolo a travs de una ventana de vista. El siguiente HTML desplaza una lista de crditos; los crditos empiezan en la parte inferior de la marquesina, suben y desaparecen por arriba:
<marquee scrollamount="1" behavior="scroll" direction="up" loop="false"> <h2>Crditos</h2> <p>Gracias a los siguientes participantes(me niego a traducir esta chorrada):</p> <p>Denise Smith - trusted friend and advisor.</p> <p>Alan Steiner - original party animal.</p>

243

MCAD/MCSD

<p>Will Shakespeare - lead grammarian.</p> <p>Gary Yukish - thanks for the spell check. </p> <p>Karin Zimprich - who invented the four-point seat belt.</p> </marquee>

Los desarrolladores pueden anidar elementos marquee para crear diferentes efectos visuales. Por ejemplo, el siguiente HTML muestra una pelota que bota en un marco.
<marquee scrollamount="10" behavior="alternate" direction="up" loop="true"> <marquee scrollamount="5" behavior="alternate" direction="right" loop="true"> <img src="circles.gif"> </marquee> </marquee>

El elemento marquee incluye un suceso onbounce que se puede usar para crear ms efectos. Por ejemplo, el siguiente marquee muestra una pelota que bota cada vez menos hasta que rueda y se detiene:
<marquee id="mrqVert" scrollamount="10" behavior="alternate" direction="down" loop="true" height="400" onbounce="OnBounce()"> <marquee id="mrqHoriz" scrollamount="5" behavior="alternate" direction="right" loop="true"> <img src="circles.gif"> </marquee> </marquee>

VBScript
<script language=vbscript> bOdd=0 Sub OnBounce() x = document.all("mrqVert").height bOdd = Not bOdd if x > 100 then if bOdd then document.all("mrqVert").height = x 20 end if else document.all("mrqVert").scrollamount=0 document.all("mrqHoriz").scrollamount=0 end if End Sub </script>

' Obtiene la altura ' Cambia el indicador de bote ' Si abajo es impar bota. ' Reduce altura en cada bote. ' Detiene el movimiento

JScript
<script language=JavaScript> var bOdd=0; function OnBounce(){ x = document.all["mrqVert"].height; bOdd = !bOdd; if (x > 100) if (bOdd) document.all["mrqVert"].height = x - 20; else{ document.all["mrqVert"].scrollamount=0; document.all["mrqHoriz"].scrollamount=0; } } </script>

// Obtiene la altura // Cambia el indicador de bote. // Si abajo es impar bota. // Reduce altura en cada bote. // Detiene el movimiento.

12.3.3 Animar grficos sencillos


La forma ms sencilla de animacin para la Web es el GIF animado. Los archivos GIF pueden contener varias imgenes que puede combinar usando una herramienta como Microsoft PhotoDraw para crear una nica imagen en movimiento. Usando Microsoft PhotoDraw u otra herramienta puede agregar imagines como fotogramas a la animacin, establecer cuanto tiempo se muestra cada fotograma y configurar otros atributos de la animacin. Despus de haber creado el archivo GIF puede usarlo dentro de cualquier elemento HTML que acepte un grfico. Los GIF animados tambin se pueden combinar con otras tcnicas de animacin, como el elemento marquee. Por ejemplo, el siguiente HTML muestra un avin animado que vuela alrededor de la pantalla del navegador.

244

Developing Web Applications

<marquee behavior="scroll" direction="down" height="800" width="800"> <marquee behavior="alternate" direction="right"> <img src="airplane.gif"> </marquee> </marquee>

12.3.4 Mostrar animaciones como objetos o plugins


Hay varios objetos ActiveX o plugins de navegador que puede usar para crear presentaciones animadas sobre la Web. Dos de las ms ampliamente usadas son Macromedia ShockWave y Windows Media Player. Estros objetos ActiveX y plugins usan diferentes tcnicas para presentar animaciones, y todos tienen documentacin que discute cmo usarlos y crear presentaciones. Vea en la leccin 1 informacin sobre cmo agregar objetos ActiveX y plugins a la pgina Web.

12.3.5 Animar con secuencias de comandos de cliente


Como las secuencias de comandos de cliente pueden controlar cualquier elemento de un formulario Web, puede usarlos para animar estos elementos ocultndolos y mostrndolos o movindolos. Por ejemplo, el siguiente HTML y secuencia de comandos de cliente crea una imagen animada que sigue al cursor por la ventana del navegador.
<html> <body MS_POSITIONING="GridLayout" onmousemove="OnMove()"> <img id="imgPlane" src="circles.gif" height="20" width="20" style="Z-INDEX: 101; LEFT: 1px; POSITION: absolute; TOP: 1px">

VBScript
<script language="vbscript"> iCount = 0 ' Variables globales. x = 0 y = 0 xImg = 0 yImg = 0 Sub OnMove() if iCount > 0 then exit sub ' Obtiene las coordenadas del ratn. xMouse = window.event.clientx yMouse = window.event.clienty ' Obtiene las coordenadas de la imagen. xImg = document.all("imgPlane").style.getAttribute("LEFT",0) yImg = document.all("imgPlane").style.getAttribute("TOP",0) ' Convierte las coordenadas de cadena a nmero. xImg = cint(left(xImg,len(xImg) -2)) yImg = cint(left(yImg,len(yImg) -2)) ' Cierra la distancia entre los dos conjuntos de coordenadas. x = (xMouse - xImg) / 4 y = (yMouse - yImg) / 4 ' Lanza cada .1 secgundos. window.setInterval "MoveImg", 100, "VBScript" window.setInterval "MoveImg", 200, "VBScript" window.setInterval "MoveImg", 300, "VBScript" window.setInterval "MoveImg", 400, "VBScript" window.setInterval "MoveImg", 500, "VBScript" End Sub Sub MoveImg() if iCount < 5 then iCount = iCount + 1 else iCount = 0 ' Mueve el elemento IMG para seguir al ratn. document.all("imgPlane").style.setAttribute "LEFT", xImg + x, 0 document.all("imgPlane").style.setAttribute "TOP", yImg + y, 0 End Sub </script>

JScript
<script language="JScript"> // Variables globales. var iCount = 0; var x = 0; var y = 0; var xImg = 0; var yImg = 0;

245

MCAD/MCSD

function OnMove(){ if (iCount > 0 ) return; // Obtiene las coordenadas del ratn. xMouse = parseInt(window.event.clientX); yMouse = parseInt(window.event.clientY); // Obtiene las coordenadas de la imagen. xImg = document.all["imgPlane"].style.getAttribute("LEFT",0); yImg = document.all["imgPlane"].style.getAttribute("TOP",0); // Convierte las coordenadas de cadena a nmero. xImg = parseInt(xImg); yImg = parseInt(yImg); // Cierra la distancia entre dos conjuntos de coordenadas. x = (xMouse - xImg) / 4; y = (yMouse - yImg) / 4; // Lanza cada .1 segundos. window.setInterval ("MoveImg()", 100, "JavaScript") ; window.setInterval ("MoveImg()", 200, "JavaScript") ; window.setInterval ("MoveImg()", 300, "JavaScript") ; window.setInterval ("MoveImg()", 400, "JavaScript") ; window.setInterval ("MoveImg()", 500, "JavaScript") ; } function MoveImg(){ if (iCount < 4) iCount ++; else iCount = 0; // Mueve el elemento IMG para seguir al ratn. document.all["imgPlane"].style.setAttribute ("LEFT", xImg + x, 0); document.all["imgPlane"].style.setAttribute ("TOP", yImg + y, 0); } </script>

El cdigo anterior muestra tanto la potencia como la dificultad de usar secuencias de comandos de cliente para animar elementos HTML: puede controlar cualquier elemento de cualquier forma. Pero es muy difcil sincronizar las animaciones. El ejemplo anterior usa el mtodo setInterval para coordinar la animacin, haciendo que la imagen se mueva un cuarto de la distancia cada dcima de segundo. En la prctica el efecto es muy interesante, pero no resulta suave. Para resolver realmente este problema necesita poder coordinar sucesos usando el propio HTML. La siguiente seccin explica como hacerlo usando una extensin del HTML estndar.

12.3.6 Animar con HTML+TIME


Hasta ahora, nuestra discusin sobre audio, video y animacin ha carecido de un elemento importante: tiempo. Los estndares originales de HTML no prevean la necesidad de sincronizar sucesos en la pgina, pero la sincronizacin es la clave para crear y presentar medios basados en tiempo, como audio, video y animacin. Para resolver este problema el consorcio WWW (W3C) ha generado el estndar SMIL, lenguaje de integracin de multimedia sincronizado11. Internet Explorer implementa este estndar bajo el nombre HTML+TIME. HTML+TIME permite coordinar sucesos temporizados en una pgina para crear presentaciones multimedia. Los sucesos se pueden producir en lneas de tiempo secuenciales, paralelas o exclusivas. HTML+TIME precisa Internet Explorer 5.5 o posterior para su ejecucin. Las siguientes secciones describe cmo usar HTML+TIME en un formulario Web o pgina HTML.

12.3.7 Uso de HTML+TIME


Para usar HTML+TIME en un formulario Web o pgina HTML siga estos pasos: 1. Aada al elemento HTML de la pgina un atributo espacio de nombres XML (XMLNS). El siguiente HTML declara el espacio de nombres HTML+TIME para una pgina:
<HTML XMLNS:t ="urn:schemas-microsoft-com:time">

2. Aada un estilo para definir el comportamiento de tiempo para elementos HTML en la pgina. La siguiente definicin de estilo establece el comportamiento predeterminad (mostar/ocultar) para la clase time:
<style> .time {behavior: url(#default#time2);} </style>

3. Aada una directiva IMPORT para importar el espacio de nombres XML declarado previamente en la pgina. El siguiente HTML importa el espacio de nombres HTML+TIME:

11

Synchronizer Multimedia Integration Languaje

246

Developing Web Applications

<?IMPORT namespace="t" implementation="#default#time2">

4. Cree una lnea de tiempo para los elementos que quiere controlar usando elementos HTML+TIME. Por ejemplo, el siguiente HTML establece una lnea de tiempo secuencial para el elemento que le sigue:
<t:SEQ>

5. Establezca los atributos de tiempo para los elementos HTML que quiere controlar. Por ejemplo, el siguiente HTML muestra una lnea de texto durante dos segundos.
<DIV CLASS="time" DUR="2">Este texto desaparece en dos segundos</DIV>

El siguiente HTML rene todos los pasos anteriores para mostrar una lnea de texto que cambia cada dos segundos hasta que se muestra la ltima lnea. Los elementos HTML+TIME se muestran en negrita para destacar los cambios que hay que hacer en un formulario Web o pgina HTML normal.
<html XMLNS:t ="urn:schemas-microsoft-com:time"> <head> <title>HTMLTIME</title> <meta name="GENERATOR" content="Microsoft Visual Studio.NET 7.0"> <meta name="CODE_LANGUAGE" content="Visual Basic 7.0"> <meta name="vs_defaultClientScript" content="JavaScript"> <meta name="vs_targetSchema" content="http://schemas.microsoft.com/intellisense/ie5"> <style> .time {behavior: url(#default#time2);} </style> </head> <body MS_POSITIONING="GridLayout"> <form id="Form1" method="post" runat="server"> <?IMPORT namespace="t" implementation="#default#time2"> <t:SEQ> <DIV CLASS="time" DUR="2">Estas palabras se muestran</DIV> <DIV CLASS="time" DUR="2">secuencialmente, una lnea cada vez</DIV> <DIV CLASS="time" DUR="2">para que todo quede ms claro.</DIV> <DIV CLASS="time">Te acuerdas de lo que he dicho?</DIV> </t:SEQ> </form> </body> </html>

La ventana de diseo de Visual Studio no soporta la directiva IMPORT. Solo puede ver los elementos HTML+TIME desde Visual Studio ejecutando la aplicacin. Si quiere crear o ajustar elementos en la pgina usando la ventana de diseo de Visual Studio comente temporalmente la directiva IMPORT antes de cambiar a diseo. Con la directiva IMPORT comentada los elementos HTML+TIME no aparecern y los elementos HTML ordinarios no mostrarn sus atributos de tiempo; sin embargo, podr aadir y modificar otros elementos de la pgina.

12.3.8 Crear lneas de tiempo


En la seccin anterior el elemento t:SEQ de HTML+TIME crea una lnea de tiempo secuencial. Como sugiere el nombre, los sucesos en una lnea de tiempo secuencial se producen uno tras otro tal como determina el atributo de duracin (DUR). Adems de lneas de tiempo secuenciales puede crear lneas de tiempo exclusivas (t:EXCL) y paralelas (t:PAR). Las lneas de tiempo exclusivas muestran un elemento cada vez tal como determina el atributo BEGIN del elemento. Si un segundo elemento empieza antes de que termine la duracin del primero, el segundo sustituye al primero. Por ejemplo, el siguiente fragmento HTML muestra cada lnea por turno durante dos segundos. El atributo DUR esencialmente se ignora hasta la ltima lnea, que se muestra durante tres segundos.
<t:EXCL> <DIV CLASS="time" <DIV CLASS="time" <DIV CLASS="time" <DIV CLASS="time" </t:EXCL> BEGIN="0" BEGIN="2" BEGIN="4" BEGIN="6" DUR="3">Estas palabras se muestran</DIV> DUR="3">usando una lnea de tiempo exclusiva.</DIV> DUR="3">Cada lnea tiene su momento de inicio.</DIV> DUR="3">Te acuerdas de lo que he dicho?</DIV>

Las lneas de tiempo paralelas pueden mostrar ms de un elemento a la vez. Cada elemento usa tanto el atributo BEGIN como el atributo DUR para determinar cundo comienza y durante cuanto tiempo se muestra. Por ejemplo, el siguiente HTML muestra cada lnea por turno durante tres segundos. En algunos momentos se muestran dos lneas a la vez:

247

MCAD/MCSD

<t:PAR> <DIV CLASS="time" <DIV CLASS="time" <DIV CLASS="time" <DIV CLASS="time" </t:PAR>

BEGIN="0" BEGIN="2" BEGIN="4" BEGIN="6"

DUR="3">Estas palabras se muestran</DIV> DUR="3">usando una lnea de tiempo paralela.</DIV> DUR="3">Se muestra ms de una lnea.</DIV> DUR="3">a la vez.</DIV>

Otra diferencia entre las lneas de tiempo secuenciales y los otros dos tipos es que los elementos de una lnea de tiempo secuencial se reemplazan uno al anterior. En el primero de los dos ejemplos anteriores cada elemento se muestra en la misma lnea de la pgina. En los ejemplos de lnea de tiempo paralela y exclusiva cada elemento aparece en su propia lnea. Las lneas de tiempo se pueden anidar de modo que una lnea de tiempo maestra controle varias subordinadas. Por ejemplo, el siguiente HTML muestra cada una de las tres lneas de tiempo secuencialmente:
<h1>Demo lneas de tiempo</h1> <t:SEQ> <h2 CLASS="time" DUR="2">Lnea de tiempo secuencial</h2> <t:SEQ> <DIV CLASS="time" DUR="2">Estas palabras se muestran</DIV> <DIV CLASS="time" DUR="2">secuencialmente, lnea a lnea</DIV> <DIV CLASS="time" DUR="2">para dejar este punto claro.</DIV> <DIV CLASS="time" DUR="2">Puedes recordar lo que he dicho?</DIV> </t:SEQ> <h2 CLASS="time" DUR="2">Lnea de tiempo exclusiva</h2> <t:EXCL> <DIV CLASS="time" BEGIN="0" DUR="3">Estas palabras se muestran usando</DIV> <DIV CLASS="time" BEGIN="2" DUR="3">una lnea de tiempo exclusiva.</DIV> <DIV CLASS="time" BEGIN="4" DUR="3">Cada lnea tiene su tiempo de inicio</DIV> <DIV CLASS="time" BEGIN="6" DUR="3">Puedes recordar lo que he dicho?</DIV> </t:EXCL> <h2 CLASS="time" DUR="2">Lnea de tiempo paralela</h2> <t:PAR> <DIV CLASS="time" BEGIN="0" DUR="3">Estas palabras se muestran usando</DIV> <DIV CLASS="time" BEGIN="2" DUR="3">una lnea de tiempo paralela.</DIV> <DIV CLASS="time" BEGIN="4" DUR="3">Se muestra ms de una lnea</DIV> <DIV CLASS="time" BEGIN="6" DUR="3">a la vez.</DIV> </t:PAR> <h2 CLASS="time" DUR="4">Esto es todo</h2> </t:SEQ>

12.3.9 Contenedores de tiempo


Los elementos t:SEQ, t:EXCL y t:PAR mostrados anteriormente crean una lnea de tiempo para los elementos que se encuentran entre sus etiquetas de comienzo y fin. Tambin puede crear lneas de tiempo dentro de elementos HTML individuales usando el atributo TIMECONTAINER. Por ejemplo, el siguiente HTML es equivalente al ejemplo de lnea de tiempo secuencial en la seccin precedente.
<DIV class="time" timeContainer="seq"> <DIV CLASS="time" DUR="2">Estas palabras se presentan</DIV> <DIV CLASS="time" DUR="2">secuencialmente, una lnea cada vez</DIV> <DIV CLASS="time" DUR="2">para dejar cada punto ms claro.</DIV> <DIV CLASS="time" DUR="2">Puedes recordar lo que he dicho?</DIV> </DIV>

El atributo TIMECONTAINER facilita la creacin de lneas de tiempo porque se puede aadir a contenedores HTML existentes, como elementos div, form o body. Tambin facilitan la creacin de lneas de tiempo separadas para elementos individuales de una pgina. Por ejemplo, el siguiente HTML usa una lnea de tiempo separada para la ltima lnea mostrada en la marquesina.
<marquee CLASS="time" TIMECONTAINER="seq" REPEATCOUNT="indefinite" behavior=alternate> <h2 CLASS="time" DUR="2">Estas palabras se presentan</h2> <h2 CLASS="time" DUR="2">secuencialmente, una lnea cada vez</h2> <h2 CLASS="time" DUR="2">para dejar cada punto ms claro.</h2> <h2 TIMECONTAINER="seq" CLASS="time" DUR="2"> <div class="time" dur="1">Puedes recordar lo que he dicho?</div> <div class="time" dur="1">Porque yo ya lo he olvidado.</div> </h2> </marquee>

248

Developing Web Applications

12.3.10 Animar atributos


El comportamiento predeterminado de una lnea de tiempo es mostrar u ocultar elementos. Puede crear otros efectos usando el elemento t:ANIMATE para cambiar los atributos de un elemento en un momento especificado. Por ejemplo, el siguiente HTML cambia el texto del elemento span de fin a principio cada cuarto de segundo.
<t:ANIMATE targetelement="sEnd" attributename="innerHTML" from="fin" to="principio" dur=".25" repeatcount="indefinite" /> <h2>Este es el <span id="sEnd">fin</span>.</h2>

Puede usar transiciones de color usando el elemento t:ANIMATECOLOR. Por ejemplo, el siguiente HTML funde el texto de encabezado de amarillo a rojo en un periodo de 5 segundos:
<t:ANIMATECOLOR targetElement="hEnd" attributeName="color" from="yellow" to="red" start="2" dur="5" fill="hold"> <h2 id="hEnd" style="color:black">Este es el <span id="sEnd">fin</span>.</h2>

El elemento t:ANIMATEMOTION se usa para mover elementos en una pgina. Por ejemplo, el siguiente HTML mueve un encabezado desde las coordenadas de rejilla (400, 400) a (1, 1):
<t:ANIMATEMOTION targetElement="hEnd" from="400,400" to="1,1" start="2" dur="5" fill="hold"> <h2 id="hEnd" style="position:absolute;color:black">Este es el <span id="sEnd"> fin </span>.</h2>

Puede mover elementos respecto a sus posiciones iniciales usando el atributo BY del elemento t:ANIMATEMOTION en lugar del atributo TO. Como alternativa puede crear una ruta para el elemento usando los atributos VALUES o PATH. El atributo VALUES acepta una cadena de pares de coordenadas. Por ejemplo, el siguiente HTML mueve un encabezado alrededor de un cuadrado de 200 por 200.
<t:ANIMATEMOTION targetElement="hEnd" values="1,200;200,200;200,1;1,1;1,200" start="2" dur="5" fill="hold"> <h2 id="hEnd" style="position:absolute;color:black">Este es el <span id="sEnd">fin</span>.</h2>

El atributo PATH recibe como argumento una cadena que contiene comandos de grficos de vectores escalables (SVG12) que permiten mover elementos usando coordenadas absolutas o relativas. Por ejemplo, el siguiente HTML mueve un encabezado en una ruta triangular.
<t:ANIMATEMOTION targetElement="hEnd" path="M 0 200 h 200 v -200 z" start="2" dur="10" repeatcount="indefinite"> <h2 id="hEnd"style="position:absolute;color:black">Este es el <span id="sEnd">fin</span>.</h2>

12.3.11 Controlar audio, video y otros medios


HTML+TIME proporciona elementos para audio, video, imagen fija y medios genricos temporizados. Sin embargo, todos estos elementos actualmente son equivalentes al elemento t:ANIMATION. Puede usar etiquetas propias de cada medio si cree que esto documenta mejor su cdigo o espera algn beneficio de versiones futuras de HTML+TIME. Los elementos t:AUDIO, t:VIDEO, t:MEDIA, t:IMG y t:REF se usan exactamente igual que el elemento t:ANIMATION. Por ejemplo, el siguiente HTML hacer sonar un pitido cada dos segundos:
<t:AUDIO src="beep.wav" hasaudio="True" dur="2" repeatcount="indefinite" />

Igualmente, el siguiente HTML cambia entre dos imgenes cada cinco segundos:
<t:par REPEATCOUNT="indefinite" > <t:IMG src="gondola.jpg" style="position:absolute;" begin="0" end="5" > <t:IMG SRC="bridge.jpg" style="postion:absolute;" begin="5" end="10" > </t:par>

No es realment necesario usar t:IMG o el equivalente t:ANIMATE en el ejemplo anterior porque una etiqueta <img class=time > hara lo mismo. Sin embargo, los elementos HTML+TIME permiten aadir transiciones que no estn disponibles con el elemento img. El siguiente HTML aade transiciones a los cambios de imagen:
<t:seq REPEATCOUNT="indefinite" > <t:IMG src="gondola.jpg" style="position:absolute;" DUR="5" FILL="transition" timecontainer="par" > <t:TRANSITIONFILTER TYPE="fade" mode="in" begin="0" end="1"/> <t:TRANSITIONFILTER TYPE="fade" mode="out" begin="4" end="5" /> </t:IMG>
12

Scalable Vector Graphics

249

MCAD/MCSD

<t:IMG SRC="bridge.jpg" style="postion:absolute;" DUR="5" FILL="transition" timecontainer="par" > <t:TRANSITIONFILTER TYPE="clockwipe" mode="in" begin="0" end="1" /> <t:TRANSITIONFILTER TYPE="clockwipe" mode="out" begin="4" end="5" /> </t:IMG> </t:seq>

Ms informacin: HTML+TIME permite controlar el ritmo de la animacin, las transiciones entre imgenes y muchos otros aspectos de la animacin que no se tratan en esta leccin. Para ms informacin vea el tema de ayuda HTML+TIME en la ayuda en lnea de Visual Studio.

12.4 Resumen
Use sucesos y secuencias de comandos de cliente para controlar multimedia, puesto que el cdigo de servidor precisa que se vuelva a mostrar la pgina, haciendo que el medio se reinicie. El elemento bgsound de HTML interpreta audio como sonido de fondo. Use el atributo dynsrc del elemento img de HTML para mostrar vdeo sin tener la capacidad de controlar la reproduccin. El elemento embed de HTML reproduce audio o video usando el intrprete de medios predeterminado del usuario. Incluya audio o video como objeto ActiveX usando el elemento object de HTML. Puede controlar la reproduccin de un objeto ActiveX usando secuencias de comandos de cliente. Aada objetos ActiveX a la caja de herramientas de Visual Studio .NET y arrstrelos al formulario Web para obtener el id de clase correcto y los atributos predeterminados para el objeto. Use el atributo codebase del elemento object de HTML para comprobar automticamente si el cliente tiene la versin adecuada de un objeto ActiveX instalada e instalarla automticamente si no. Los archivos gif animados y el elemento marquee de HTML ofrecen formas sencillas para crear animacin. Las secuencias de comandos de cliente pueden animar cualquier elemento de un formulario Web y pueden responder a suceso de usuario, pero presentan problemas cuando se intenta sincronizar sucesos. Sincronice sucesos multimedia en Internet Explorer usando HTML+TIME, que es la implementacin por Microsoft del estndar SMIL. HTML+TIME le permite: Crear diferente tipos de lneas de tiempo en una pgina Web Especificar el orden, temporizacin y duracin de sucesos dentro de una lnea de tiempo Controlar los atributos, color y posicin de los elementos en respuesta a estos sucesos con tiempo.

12.5 Prctica: Crear una aplicacin multimedia


En esta aplicacin va a crear una prctica que contiene dos formularios Web o pginas HTML. La primera muestra el uso de sonido y movimiento, y la segunda demuestra el uso de HTML+TIME para crear una presentacin de diapositivas de texto. Estos ejemplos son intencionadamente sencillo para mostrar lo que se puede hacer aplicando correctamente la tcnica multimedia adecuada.

12.5.1 Ejercicio 1: Usar sonido y movimiento


En este ejercicio va a crear un formulario Web o pgina HTML que muestre un GIF animado que bota en torno a la pantalla e interpreta un sonido cuando bota. Utilice lo que ha aprendido en las lecciones 1, 2 y 3 para crear un formulario Web o pgina HTML que realice las siguientes tareas principales: 1. 2. 3. 4. Muestre un archivo .gif animado como elemento img de HTML Mueva el .gif animado alrededor de la pantalla usando elementos marquee de HTML anidados. Incluya botones que permitan al usuario controlar la velocidad del movimiento. Use un objeto ActiveX de Windows Media Player para interpretar un sonido en respuesta a un suceso de bote. 5. Compruebe si el navegador del usuario es Internet Explorer, y si no lo es indique al usuario que algunas caractersticas de la pgina no estn disponibles. Cuando termine compare sus resultados con el ejemplo multimedia incluido en el CD-ROM del libro.

12.5.2 Ejercicio 2: Mostrar una presentacin de diapositivas


En este ejercicio va a crear un formulario Web o pgina HTML que usa HTML+TIME para mostrar una presentacin animada. Use lo que ha aprendido en las lecciones 1, 2 y 3 para crear un formulario Web o pgina HTML que realice las siguientes tareas principales: 1. Prepare la pgina para HTML+TIME aadiendo las directivas correspondientes de espacio de nombres, estilo e IMPORT. 250

Developing Web Applications

2. 3. 4. 5.

Cree una lnea de tiempo que muestre tres textos secuencialmente. Cree lneas de tiempo paralelas entre los dos primeros textos para mostrar tres elementos de lista Cree una lnea de tiempo secuencial con el ltimo texto para contar hacia atrs de 5 a 1. Navegue a otra pgina cuando termine la lnea de tiempo. Cuando termine compare su resultado con el ejemplo incluido en el CD-ROM.

12.6 Repaso
Las siguientes preguntas estn pensadas para reforzar informacin clave mostrada en este captulo. Si no es capaz de contestar a una pregunta repase la leccin correspondiente e intente de nuevo. Las respuestas se pueden encontrar en el captulo 16. 1. Por qu normalmente se controla el multimedia desde secuencias de comandos de cliente en lugar de cdigo de servidor? 2. Qu elementos HTML de sonido y video soportan la mayora de los navegadores? 3. Cmo se da soporte a los usuarios de Netscape Navigator desde dentro de un elemento de objeto ActiveX? 4. Qu caracterstica principal proporciona HTML+TIME que no est disponible con otras tcnicas de animacin? 5. Indique dos formas de crear una nueva lnea de tiempo usando HTML+TIME

251

MCAD/MCSD

252

Developing Web Applications

13 Dar formato a salida de aplicacin Web


ASP.NET proporciona dos formas complementarias para dar formato a la salida de una aplicacin Web: Usar hojas de estilo en cascada (CSS13) para controlar el aspecto de los elementos en un formulario Web. Estos estilos pueden establecer el color, tamao, fuente y comportamiento de los elementos HTML en una pgina Web. Usar transformaciones de lenguaje de marcas extensible (XSLT14) para convertir informacin de un archivo XML en salida HTML y colocar esta informacin en una pgina Web. XSLT pone datos del archivo XML en elementos HTML y aplica estilos a estos elementos. En este captulo aprender cundo y cmo usar cada una de estas tcnicas en una aplicacin web. Para completar este captulo debe: Saber cmo crear formularios Web usando el modo HTML en Visual Studio.NET Estar familiarizado con los elementos HTML usados para crear formularios Web y pginas HTML.

13.1 Hojas de estilo en cascada


Las hojas de estilo en cascada renen y organizan toda la informacin de formato aplicada a elementos HTML en un formulario Web. Como mantiene esta informacin en un nico sitio facilitan ajustar la apariencia de las aplicaciones Web. Visual Studio .NET incluye herramientas de edicin de estilos, junto con una hoja de estilos predeterminada que se crea como parte de cada nuevo proyecto de aplicacin Web. En esta leccin aprender cmo usar las herramientas de Visual Studio .NET para modificar la hoja de estilos predeterminada, anexar la hoja de estilos a formularios Web y cambiar de hoja de estilos en tiempo de ejecucin.

13.1.1 Cmo funcionan los estilos


Como se mencion al inicio de esta leccin las hojas de estilo almacenan el formato en un nico lugar: el archivo CSS. Sin embargo, el formato se puede aplicar a tres niveles dentro de una aplicacin. Antes de comenzar a trabajar con hojas de estilo debe comprender cmo afectan al formato los estilos definidos a diferentes niveles. La tabla 13.1 describe estos niveles y dicen cmo se aplican a los elementos en un formulario Web.
Tabla 13. 1: Niveles de estilo
Nivel Global Pgina En lnea Definido en Archivo de hoja de estilos Elemento head de la pgina El propio elemento HTML Se aplica a Todas las pginas que hacen referencia a la hoja de estilos Todos los elementos de la pgina Solo al elemento actual

Estos tres niveles siguen reglas de precedencia similares a los niveles de alcance con los que ya est familiarizado como programador. El formato en lnea tiene preferencia sobre el formato de pgina, que a su vez tiene preferencia sobre el global. Estas reglas de precedencia son el motivo de que la hojas de estilo se denominen en cascada. El siguiente HTML muestra la aplicacin de los tres niveles de estilo:
<HTML> <HEAD> <title>WebForm1</title> <!-- (1) Referencia a la hoja de estilo. --> <LINK REL="stylesheet" TYPE="text/css" HREF="Styles.css"> <!-- (2) Definicin de estilo a nivel de pgina. --> <style> p { font-family: 'Comic Sans MS', Lucida Sans, sans-serif; font-size: medium; } </style> </HEAD> <body> <p>El alineamiento es de la hoja de estilo.</p> <p>La fuente es del estilo en el elemento head de la pgina.</p>

13 14

Cascading Style Sheets Extensible Stylesheet Language Transformation

253

MCAD/MCSD

<!-- (3) Definicin de estilo en lnea --> <p style="FONT-SIZE: large; FONT-STYLE: italic">La cursiva es del estilo en lnea.</p> </body> </HTML> <!-- (1) Fragmento de la hoja de estilos Styles.css . --> p{ font-size: small; text-align: center; }

El ejemplo anterior muestra cmo se pueden aplicar atributos de estilo a un mismo elemento a diferentes niveles. El atributo font-size se aplica a los tres niveles, pero solo se ven los efectos de las configuraciones a nivel pgina y en lnea porque la configuracin de pgina tiene prioridad sobre la configuracin a nivel hoja de estilo. Los atributos text-align, font-family y font-style se definen una sola vez cada uno, de modo que sus efectos se suman. Almacenar las definiciones de estilo en un archivo de hoja de estilo en lugar de localmente en cada formulario Web o en lnea en cada elemento HTML tiene un par de ventajas: El formato se mantiene en un solo lugar, de modo que los cambios se hacen una sola vez para toda la aplicacin. Se pueden mantener varios conjuntos de reglas de estilo paralelas en hojas de estilo separadas para dar formato a salida en diferentes dispositivos o con diferentes necesidades de usuario. Por ejemplo, una aplicacin puede tener hojas de estilo estndar, con tipos grandes y para impresin que los usuarios pueden seleccionar en tiempo de ejecucin. Consejo: Por lo general, debe usar los estilos en pgina y en lnea solo cuando tenga una razn verdaderamente buena para sustituir los estilos globales. Confiar mucho en los estilos en pgina y en lnea puede hacer difcil mantener el formato en una aplicacin Web.

13.1.2 Usar hojas de estilo con formularios Web


Cuando se crea una nueva aplicacin Web Visual Basic .NET Visual Studio .NET crea automticamente una hoja de estilo llamada Styles.css. Sin embargo, Visual Studio .NET no usa esta hoja de forma automtica en los formularios Web o pginas HTML que se creen. Para usar la hoja de estilo debe aadir un elemento de enlace en la seccin head de la pgina:
<LINK REL="stylesheet" TYPE="text/css" HREF="Styles.css" />

Importante: Slo los proyectos Visual Basic se crean con una hoja de estilo. Para proyectos C# deber crear la hoja de estilo desde cedo o cortar y pegar el contenido de la hoja predeterminada creada en un proyecto Visual Basic.

13.1.3 Modificar estilos


Para cambiar la apariencia de los estilos en una hoja de estilos use el generador de estilos. Los cambios en la hoja de estilos cambian la apariencia de todos los formularios Web que hacen referencia a la misma. Para modificar un estilo: 1. Abra la hoja de estilos en Visual Studio. Ver las definiciones de estilos en la ventana de documento y un esquema de la hoja de estilos en la ventana de herramientas. 2. Seleccione el estilo a modificar en la ventana de herramientas. Ver la definicin del estilo en la ventana de documento. 3. Pulse con el botn derecho sobre la definicin de estilo o sobre el estilo en la ventana de herramientas y seleccione Generar estilo. Se abrir el asistente Generador de estilo. 4. Use el generador de estilo para componer el formato que quiere aadir o modifique el estilo existente. Cuando termine pulse aceptar. Cuando cierre el generador de estilo ver que se han aadido los atributos nuevos o modificados en la definicin de estilo.

13.1.4 Aadir estilos


Hasta ahora hemos cread estilos aplicados usando nombres de elemento HTML. CSS usa el nombre de elemento para localizar el formato predeterminado que se aplica a cada elemento. Sin embargo, tambin puede aplicar estilos usando nombres de clase o ID de elemento. Los nombres de clase le permiten aplicar un mismo estilo a diferentes elementos o diferentes estilos a un mismo elemento, dependiendo de cmo se use el elemento. Los ID de elemento le permite aplicar un estilo a un nico elemento en uno o ms formularios Web. 254

Developing Web Applications

Para aadir un estilo: 1. Abra la hoja de estilo, pulse con el botn derecho en la ventana de documento o la de herramientas y seleccione Agregar regla de estilo. Se abre el asistente Agregar regla de estilo. 2. Seleccione el tipo de estilo que quiere crear. Puede crear estilos que se aplican a elementos HTML, class o ID,s de elemento especficos. Seleccione el elemento o escriba el nombre de clase o ID y pulse el botn agregar (>) para aadir el elemento a la regla de estilo. 3. Repita el paso 2 para cada elemento al que quiere aplicar el estilo.

13.1.5 Usar clases de estilo


Las clases de estilo le permiten aplicar el mismo formato a diferentes elementos HTML en un formulario Web. Cuando crea una regla de estilo para una clase Visual Studio .NET aade una definicin en la hoja de estilos usando un identificador .nombreclase:
.emphasis { font-style: italic; }

El estilo anterior pone en cursiva todos los elementos que usan la clase .emphasis. La clase de estilo se aplica a elementos HTML usando el atributo class y a los controles de servidor usando el atributo CssClass. El siguiente HTML muestra la diferencia en negrita:
<p>Este es un prrafo que contiene <span class="emphasis">nfasis</span>.</p> <asp:TextBox ID="Text1" Runat="server" CssClass="emphasis">Texto</asp:TextBox>

13.1.6 Crear estilos para elementos concretos


Tambin puede crear estilos para elementos concretos en un formulario web en base al ID del elemento. Los ID de elemento deben ser nicos para cada elemento de una pgina, de modo que el formato establecido por un ID de elemento solo se puede aplicar a un elemento de cada pgina. Cuando se crea una regla de estilo para un ID de elemento Visual Studio .NET aade a la hoja de estilo una definicin de estilo usando un identificador #idElemento:
#inserted { text-decoration: underline; } #deleted { text-decoration: line-through; }

Las definiciones de estilo anteriores dan formato subrayado a los elementos con el ID inserted y tachado a los elementos con el ID deleted. Los estilos aplicados en Visual Studio .NET no siempre se muestran correctamente en el diseador de formularios. Si no ve el formato aplicado a un estilo concreto intente lo siguiente: Asegrese de que ha grabado la hoja de estilo Cambie entre vista HTML y vista Diseo en el formulario Web. Pulse con el botn derecho sobre el formulario Web y seleccione Ver en explorador.

13.1.7 Crear estilos anidados


Si examina las definiciones de estilos en la hoja de estilos predeterminada Styles.css observar que algunas definiciones de estilo recogen varios nombres de elemento. Estas definiciones establecen qu formato usar para elementos anidados. Por ejemplo, los siguientes estilos especifican diferentes tipos de vietas para listas anidadas no numeradas:
UL LI{ list-style-type: } UL LI LI { list-style-type: } UL LI LI LI{ list-style-type: } square ;

disc;

circle;

Para crear sus propios estilos anidados aada varios elementos en la jerarqua de la regla de estilo en el dilogo Agregar regla de estilo. 255

MCAD/MCSD

13.1.8 Cambiar la hoja de estilo en ejecucin


Como se mencion anteriormente, puede crear varias hojas de estilo y permitir que el usuario seleccione qu estilo utilizar en tiempo de ejecucin para dar formato al formulario Web para imprimir o para proporcionar caractersticas como versiones con tipos grandes de formularios Web. Para cambiar de hoja de estilo automticamente cuando se imprima un formulario Web use el atributo media del elemento de enlace de la hoja de estilo para especificar la hoja de estilo que se utilizar para imprimir y para pantalla. Por ejemplo, los siguientes elementos de enlace aplican formato de la hoja de estilo predeterminada cuando se muestra el formulario en pantalla, pero usan le estilo Print.css cuando el usuario imprime el formulario:
<LINK REL="stylesheet" TYPE="text/css" HREF="Styles.css" media="screen"> <LINK REL="stylesheet" TYPE="text/css" HREF="Print.css" media="print">

Para cambiar entre hojas de estilo en tiempo de ejecucin cree una secuencia de comandos de cliente para cambiar el elemento href del elemento de enlace de la hoja de estilo. Por ejemplo, el siguiente HTML crea un formulario Web que cambia entre las hojas de estilo Styles.css y BigType.css cuando el usuario pulsa un enlace: VBScript
<HTML> <HEAD id="myhead"> <title>ChangeSheets</title> <LINK ID="ScreenStyle" REL="stylesheet" TYPE="text/css" HREF="Styles.css"> <script language="vbscript"> Sub SwitchSheets() If document.all("ScreenStyle").GetAttribute("HREF") = "Styles.css" then document.all("ScreenStyle").SetAttribute "HREF", "BigType.css", 0 else document.all("ScreenStyle").SetAttribute "HREF", "Styles.css", 0 end if End Sub </script> </HEAD> <body> <form id="Form1" method="post" runat="server"> <h2>Cambio de hoja de estilo en tiempo de ejecucin </h2> <p>Esta pgina aparece usando la hoja de estilo predeterminada.</p> <p><a onclick="SwitchSheets" href="#">Pulse aqu </a> para cambiar entre la versin normal y la de tipos grandes.</p> </form> </body> </HTML>

JScript
<HTML> <HEAD> <title>ChangeSheets</title> <LINK ID="ScreenStyle" REL="stylesheet" TYPE="text/css" HREF="Styles.css" media="screen"> <LINK ID="PrintStyle" REL="stylesheet" TYPE="text/css" HREF="Print.css" media="print"> <script id=clientEventHandlersJS language=jscript> function SwitchSheets(){ if (document.all["ScreenStyle"].getAttribute("HREF") == "Styles.css") document.all["ScreenStyle"].setAttribute ("HREF", "BigType.css", 0); else document.all["ScreenStyle"].setAttribute ("HREF", "Styles.css", 0); } </script> </HEAD> <body MS_POSITIONING="FlowLayout"> <FORM id="Form1" method="post" runat="server"> <h2>Cambio de hoja de estilo en tiempo de ejecucin </h2> <p>Esta pgina aparece usando la hoja de estilo predeterminada.</p> <p><a onclick="SwitchSheets" href="#">Pulse aqu </a> para cambiar entre la versin normal y la de tipos grandes.</p> <A href="Behave.aspx">Siguiente&gt;&gt;</A> </FORM> </body> </HTML>

256

Developing Web Applications

13.1.9 Comportamientos
Adems de dar formato los estilos tambin pueden definir comportamientos que los elementos HTML muestran en tiempo de ejecucin. Los comportamientos son un tipo de formato dinmico: como el contenido Web no siempre es esttico las hojas de estilo usan comportamientos para definir cambios dinmicos. Si ha leido el Captulo 12, Trabajar con multimedia estar familiarizado con los comportamientos. Las animaciones HTML+TIME usan la clase time para aplicar animaciones a elementos HTML en una pgina, como se ve aqu:
<style> .time </style> {behavior: url(#default#time2);}

La propiedad behavior importa archivos de comportamiento que contienen cdigo JScript o VBScript que controla lo que hace el comportamiento. EL tema Librera de Comportamientos en la ayuda de Visual Studio .NET proporciona una serie de comportamientos de ejemplo que puede descargar y usar en su propio cdigo. Por ejemplo, el siguiente HTML importa el archivo de comportamiento de ejemplo Movible.htc y lo usa para crear un prrafo que el usuario puede arrastrar a una nueva ubicacin en el formulario Web en tiempo de ejecucin.
<HEAD> <title>Comportamiento</title> <style> .movable {behavior: url(behaviors/movable.htc); CURSOR: move; mv--boundary: 0 800 600 0} </style> </HEAD> <body> <form id="Form1" method="post" runat="server"> <p class="movable">Puede arrastrar este texto por la pantalla.</p> </form> </body> </HTML>

En el HTML anterior la definicin de estilo para la clase movable incluye el URL del archivo de comportamiento, el estilo de cursor que debe utilizar y los lmites a que se confinan los elementos. El estilo se aplica por el atributo class del elemento p. En tiempo de ejecucin el usuario puede arrastrar el prrafo por la pantalla. El comportamiento movable se puede aplicar a cualquier elemento de un formulario Web, incluyendo controles de servidor. Algunos comportamientos, sin embargo, solo se pueden aplicar a ciertos tipos de controles. Por ejemplo, el comportamiento ColorPick del siguiente cdigo se puede aplicar solo a los controles HTML campo de texto (elementos input de tipo text).
<HTML xmlns:control> <HEAD> <title>Comportamiento</title> <style>.color { BEHAVIOR: url(behaviors/ColorPick.htc) } </style> </HEAD> <body> <form id="Form1" method="post" runat="server"> <p>Use el selector de color para cambiar el fondo:</p> <input ID="ColorPic" type="text" class="color" value="#fFFf00" onchange="document.bgColor=ColorPic.value;" style="cp--grid-size:2"> </form> </body> </HTML>

El anterior HTML muestra una paleta de colores sobre la que puede pulsar el usuario para cambiar el color de fondo en tiempo de ejecucin. Finalmente, algunos comportamientos crean sus propios tipos de elementos que se pueden usar en un formulario Web. Por ejemplo, el comportamiento de ejemplo Slider crea un elemento deslizante que puede usar para obtener entrada del usuario. Para usar el control Slider primero debe aadir un atributo xmlns al elemento html del formulario Web para declarar el nombre del control:
<HTML xmlns:control> <HEAD> <title>Comportamiento</title> <style>control\:slider { BEHAVIOR: url(behaviors/slider.htc) } </style> </HEAD>

257

MCAD/MCSD

<body> <form id="Form1" method="post" runat="server"> <control:slider ID="Slider" onchange="alert(Slider.value)" STYLE="sl--orientation:horizontal"></control:slider> </form> </body> </HTML>

El HTML anterior crea un control deslizador que muestra el valor del control cuando el usuario lo arrastra. Importante: Aunque puede usar comportamientos que crean controles en formularios web, normalmente es mejor idea crear controles personalizados para tareas que no realizan los controles de servidor estndar o controles HTML. Los controles creados por comportamientos no se muestran correctamente en la ventana del diseador de Visual Studio .NET y no proporcionan propiedades y mtodos que estn disponibles con facilidad en el cdigo de servidor. Los controles personalizados si proporcionan estas ventajas.

13.2 Transformaciones XSL


En esta leccin aprender sobre el uso de XSL para transformar archivos XML usando expresiones escritas en el lenguaje de rutas de XML (XML Path Language, XPath).

13.2.1 Cmo funcionan las transformaciones XSL


Las transformaciones XSL usan el control de servidor XML para generar salida con formato a partir de un archivo de entrada XML usando un conjunto de reglas almacenado en un archivo de descripcin XSL. El archivo XSL es similar al archivo CSS sobre el que aprendi en la leccin anterior proporciona las reglas de formato que se aplican a la salida que se muestra en el formulario web. A diferencia de los archivos CSS, sin embargo, XSL puede colocar elementos en cualquier parte del formulario Web y ejecutar operaciones lgicas, como repeticin y operacin condicional. Puede pensar en los archivos XSL como en una capa de formato inteligente que complementa no reemplaza a CSS. Use XSL para colocar datos estructurados en un formulario Web, y CSS para establecer la apariencia de los elementos dentro de esta capa. Para realizar una transformacin XSL sobre un formulario Web siga estos pasos: 1. Aada un control de servidor XML a un formulario Web. 2. Indique en la propiedad DocumentSource del control el archivo XML al que se va a dar formato 3. Indique en la propiedad TransformSource el archivo XSL que se usar para dar formato a la salida. En tiempo de ejecucin el control de servidor XML procesa la entrada XML usando la descripcin XSL para proporcionar salida con formato.

13.2.2 Crear un archivo XML


Los archivos XML son una forma de describir datos estructurados en formato de texto. XML identifica los elementos de datos usando etiquetas <elemento> </elemento> muy similares a las de HTML. Pero a diferencia de HTML las reglas de XML son estrictas: Cada elemento debe tener una etiqueta de apertura y una de cierre. En HTML hay etiquetas que pueden usarse sin cerrar. Esto no se permite en XML. Los nombres de etiquetas de elemento diferencian maysculas y minsculas. En HTML <P> y <p> son equivalentes, en XML constituyen etiquetas diferentes. Los valores de atributos siempre deben ir entre comillas dobles. En HTML se pueden omitir las comillas para atributos numricos, en XML deben usarse siempre. Los elementos anidados deben cerrarse antes que el elemento contenedor. Estas estrictas reglas permiten que XML tenga una importante capacidad que HTML no tiene: en XML puede definir sus propias etiquetas y puede asignar a estas etiquetas el significado que prefiera. Cuando cree un nuevo archivo XML es una buena idea escribir primero las etiquetas y estructura que usar a lo largo del documento. Esto le ahorra el problema de intentar reetiquetar elementos si descubre que ha olvidado algo. Por ejemplo, el siguiente XML describe datos de un libro de cocina que usaremos como ejemplo durante esta leccin:
<cookbook> <title></title> <subtitle></subtitle> <description></description>

258

Developing Web Applications

<recipe> <title></title> <subtitle></subtitle> <description></description> <servings></servings> <ingredients> <ingredient> <name></name> <quantity></quantity> </ingredient> <ingredient> <name></name> <quantity></quantity> </ingredient> </ingredients> <instructions> <introduction></introduction> <step></step> <step></step> <step></step> <summary></summary> </instructions> </recipe> </cookbook>

Los datos para cada uno de estos elementos irn entre cada una de las etiquetas de comienzo y de fin. Los que es importante observar en este punto es la estructura del archivo y que los nombres de elemento describen el contenido del elemento y no su formato. Etiquetando el contenido puede aplicar formato basado en contenido usando XSL. La estructura XML es estrictamente jerrquica. XML se refiere a los elementos en esta jerarqua como nodos. Los nodos tienen relaciones padre-hijo que se identifican usando el lenguaje de rutas XML (XPath), como muestra la figura 13.1.

Fig.13. 1: Nodos XML

XML est bien adaptado para datos estructurados como datos de bolsa, informacin de empleados, inventario de productos, estado de pedidos y otros datos que estamos acostumbrados a tratar de forma ordenada. XML no est bien adaptado para informacin que usa organizacin creativa o a la medida.

13.2.3 Crear un archivo XSL


El archivo XSL proporciona el diseo y la lgica que transforma los datos almacenados en un archivo XML en la salida que se ve en un formulario Web. Para crear un archivo XSL en Visual Studio seleccione Agregar nuevo elemento en el men Proyecto, elija Archivo XSLT en la lista de plantillas y pulse Abrir. El archivo XSL contiene sentencias de plantilla que seleccionan los elementos a importar del archivo XML. Cada plantilla incluye elementos HTML estndar para aplicar formato a los elementos importados del archivo XML. Por ejemplo, la siguiente plantilla XSL convierte los elementos title, subtitle e introduction del libro de cocina de un archivo XML a elementos h1, h2 y p de HTML.
<?xml version="1.0" encoding="UTF-8" ?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:template match="/cookbook"> <xsl:apply-templates select="cookbook" /> <h1><xsl:value-of select="title" /></h1> <h3><xsl:value-of select="subtitle" /></h3> <hr /> <p><xsl:value-of select="introduction" /></p> <hr /> <h2><xsl:text>Recipes</xsl:text></h2> <xsl:apply-templates select="recipe" /> </xsl:template> </xsl:stylesheet>

El ejemplo anterior usa los elementos y atributos XML que se resumen en la tabla 13.2. 259

MCAD/MCSD

Tabla 13. 2: Elementos XSL bsicos


Elemento Atributos Se usa para Identificar la versin de XSL que se est usando. La versin en uso en el momento de escribir el texto original era la 1.0 xmlns:xsl Especificar los prefijos para elementos en el archivo XSL xsl:template match Definir una plantilla para un nodo XML xsl:apply-templates select Aplicar una plantilla al nodo seleccionado xsl:value-of select Recuperar el valor de un nodo XML o evaluar una expresin XPath xsl:text Incluir texto o caracteres de espacio en blanco literalmente en la salida.

xsl:stylesheet

version

Los elementos XSL mostrados realizan las tareas mnimas para mostrar datos con XSL: definen una plantilla, importan datos a la plantilla, muestran valores desde XML e insertan texto literal. Todas estas son tareas que se realizan ms fcilmente usando HTML ordinario y hojas de estilo, pero el uso de XSL tiene dos ventajas: Puede cambiar la posicin del elemento (diseo de pgina) en el archivo XSL sin tener que cambiar los datos. Puede realizar tareas lgicas sobre los datos, como bucles y procesamiento condicional. Las siguientes secciones discuten estas ventajas.

13.2.4 Cambiar el diseo


El diseo de pgina se cambia en XSL moviendo elementos en el archivo XSL. Por ejemplo, el siguiente XSL muestra el XML del libro de cocina en un formato de dos columnas y muestra el subttulo antes del ttulo:
<?xml version="1.0" encoding="UTF-8" ?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:template match="/cookbook"> <xsl:apply-templates select="cookbook" /> <table> <tr> <td width="300"> <h3><xsl:value-of select="subtitle" /> <xsl:text>...</xsl:text></h3> <h1><xsl:value-of select="title" /></h1> </td> <td width="500"> <xsl:text>recipe text goes here..</xsl:text> </td> </tr> <tr> <td width="300"> <hr /> <xsl:value-of select="introduction" /> <hr /> </td> <td width="500"> </td> </tr> </table> </xsl:template> </xsl:stylesheet>

13.2.5 Incluir otras plantillas


Un archivo XSL puede contener muchas plantillas. Se define una plantilla XSL para cada nodo XML que tiene un formato nico. Por ejemplo, el libro de cocina XML mostrado anteriormente en esta leccin se podra organizar en cuatro plantillas: La plantilla principal da formato al ttulo y descripcin del libro y proporciona un punto de inicio. La ejecucin de XSL comienza con esta plantilla porque selecciona el nodo raz (match=/cookbook) La plantilla de receta (recipe) da formato a las recetas incluidas en el libro. La plantilla de ingredientes (ingredients) da formato a la lista de ingredientes La plantilla de instrucciones (instructions) da formato a los pasos que sigue a la lista de ingredientes Use el elemento xsl:apply-templates para aplicar una plantilla a un nodo. Por ejemplo, el siguiente XSL aplica las plantillas de ingredientes e instrucciones a partir de la plantilla de recetas, que a su vez se aplica desde la plantilla principal. Los enlaces entre plantillas se muestran en negrita:
<?xml version="1.0" encoding="UTF-8" ?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

260

Developing Web Applications

<xsl:template match="/cookbook"> <xsl:apply-templates select="cookbook" /> <h1><xsl:value-of select="title" /></h1> <h3><xsl:text>...</xsl:text><xsl:value-of select="subtitle" /></h3> <hr /> <p><xsl:value-of select="introduction" /></p> <hr /> <xsl:apply-templates select="recipe" /> </xsl:template> <xsl:template match="recipe"> <h3><xsl:value-of select="title" /></h3> <p><xsl:value-of select="description" /></p> <p><b><xsl:text>Serves: </xsl:text></b> <i><xsl:value-of select="servings" /></i></p> <xsl:apply-templates select="ingredients" /> <xsl:apply-templates select="instructions" /> </xsl:template> <xsl:template match="ingredients"> <ul> <li><xsl:value-of select="ingredient/name" /> <xsl:text> </xsl:text> <b><xsl:value-of select="ingredient/quantity" /></b></li> </ul> </xsl:template> <xsl:template match="instructions"> <p><xsl:value-of select="introduction" /></p> <ol> <li><xsl:value-of select="step" /></li> </ol> <p><xsl:value-of select="summary" /></p> </xsl:template> </xsl:stylesheet>

Pero de esta forma solo se muestra un ingrediente y una instruccin. Tal como estn escritas las plantillas procesan un solo nodo cada una. Para repetir tareas necesita usar los elementos de bucle de XML, tal como indica la siguiente seccin.

13.2.6 Repetir tareas


Para dar formato a elemento repetitivos en un archivo XML, como elementos de lista o de tabla, use el elemento XSL xsl:for-each. Este elemento selecciona el nodo repetido y aplica el XSL que contiene a cada una de sus apariciones, como se muestra a continuacin:
<xsl:for-each select="ingredient"> <xsl:value-of select="name" /><br /> </xsl:for-each>

El XSL anterior incluye en la salida el nombre de cada nodo de ingrediente repetido. Para hacer referencia al propio nodo repetido use el identificador <;&QD>.<;&QD > de XPath. Por ejemplo, el siguiente XSL incluye en la salida el texto de todos los nodos de paso repetidos en el XML:
<xsl:for-each select="step"> <xsl:value-of select="." /><br /> </xsl:for-each>

El siguiente XSL usa el elemento xsl:for-each (en negrita) para mostrar todas las recetas, ingredientes y pasos en el libro de cocina:
<?xml version="1.0" encoding="UTF-8" ?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:template match="/cookbook"> <xsl:apply-templates select="cookbook" /> <h1><xsl:value-of select="title" /></h1> <h3><xsl:text>...</xsl:text><xsl:value-of select="subtitle" /></h3> <hr /> <p><xsl:value-of select="introduction" /></p> <hr />

261

MCAD/MCSD

<xsl:for-each select="recipe"> <xsl:apply-templates select="." /> </xsl:for-each> </xsl:template> <xsl:template match="recipe"> <h3><xsl:value-of select="title" /></h3> <p><xsl:value-of select="description" /></p> <p><b><xsl:text>Serves: </xsl:text></b> <i><xsl:value-of select="servings" /></i></p> <xsl:apply-templates select="ingredients" /> <xsl:apply-templates select="instructions" /> </xsl:template> <xsl:template match="ingredients"> <ul> <xsl:for-each select="ingredient"> <li><xsl:value-of select="name" /> <xsl:text> </xsl:text> <b><xsl:value-of select="quantity" /></b></li> </xsl:for-each> </ul> </xsl:template> <xsl:template match="instructions"> <p><xsl:value-of select="introduction" /></p> <ol> <xsl:for-each select="step"> <li><xsl:value-of select="." /></li> </xsl:for-each> </ol> <p><xsl:value-of select="summary" /></p> </xsl:template> </xsl:stylesheet>

13.2.7 Insertar enlaces y otros elementos HTML


Use el elemento xsl:element para componer elementos HTML que contienen atributos, como enlaces, controles de servidor u otros controles HTML. Por ejemplo, el siguiente XSL crea un enlace que devuelve al usuario a la parte superior de la pgina:
<xsl:element name="a"> <xsl:attribute name="name"> <xsl:text>#top</xsl:text> </xsl:attribute> <xsl:text>Volver al inicio.</xsl:text> </xsl:element>

En tiempo de ejecucin el XSL anterior genera la siguiente salida:


<a href="#top">Volver al inicio.</a>

Puede acoplar este XSL con una funcin generate-id de XPath para crear automticamente una tabla de contenidos para su documento que vincule con ubicaciones dentro del documento, como muestra en negrita el siguiente XSL:
<xsl:template match="/cookbook"> <h1><xsl:value-of select="title" /></h1> <h3><xsl:text>...</xsl:text><xsl:value-of select="subtitle" /></h3> <hr /> <p><xsl:value-of select="introduction" /></p> <hr /> <!-- Muestra la tabla de contenidos --> <h4>Contents</h4> <xsl:apply-templates mode="contents" select="recipe" /> <xsl:for-each select="recipe"> <xsl:apply-templates select="." /> </xsl:for-each> </xsl:template>

262

Developing Web Applications

<xsl:template match="recipe"> <!-- Crea los enlaces de ubicacin --> <xsl:element name="a"> <xsl:attribute name="name"> <xsl:value-of select="generate-id(title)" /> </xsl:attribute> <h3><xsl:value-of select="title" /></h3> </xsl:element> <p><xsl:value-of select="description" /></p> <p><b><xsl:text>Serves: </xsl:text></b> <i><xsl:value-of select="servings" /></i></p> <xsl:apply-templates select="ingredients" /> <xsl:apply-templates select="instructions" /> </xsl:template> <xsl:template mode="contents" match="recipe"> <!-- Crea la tabla de enlaces de contenido --> <xsl:element name="a"> <xsl:attribute name="href"> <xsl:text>#</xsl:text> <xsl:value-of select="generate-id(title)" /> </xsl:attribute> <xsl:value-of select="title" /> </xsl:element> <br /> </xsl:template>

La funcin generate-id de XPath genera un identificador nico para el nodo XML que se la pasa como argumento. El ID tiene la forma XSLTnombrenodo#, donde # es un entero de 12 dgitos.

13.2.8 Ordenar elementos


Use el elemento xsl:sort para ordenar elementos dentro de otro elemento XSL. Por ejemplo, el siguiente XSL ordena la tabla de contenidos creada en la seccin anterior.
<h4>Contenido</h4> <xsl:apply-templates mode="contents" select="recipe"> <xsl:sort select="title" order="ascending" /> </xsl:apply-templates>

El elemento xsl:sort se puede incluir en elementos xsl:apply-templates como muestra el ejemplo anterior, o en elementos xsl:for-each.

13.2.9 Tareas condicionales


XSL incluye dos conjuntos de elementos para realizar tareas condicionales. Use xsl:if para evaluar una sola condicin, y xsl:choose conteniendo elementos xsl:when y xsl:otherwise para evaluar varias condiciones. La tabla 13.3 resume los elementos condicionales:
Tabla 13. 3: Elementos XSL condicionales
Atributos Se usa para test Probar una expresin lgica y procesar los elementos contenidos si el resultado es cierto. Prueba varias condiciones usando elementos xsl:when y xsl:otherwise. Es el equivalente a un Select Case en VB.NET o switch en C# xsl:when test Prueba una expresin lgica dentro de un elemento xsl:choose, y si el resultado es cierto procesa el resultado y sale del elemento xsl:choose. Es el equivalente de las sentencias Case. xsl:otherwise Procesa el elemento contenido si no es cierto ninguno de los xsl:when del xsl:choose. Es equivalente a Case Else en VB.NET o default en C# Elemento

xsl:if xsl:choose

El atributo test de los elementos condicionales evala una expresin XPath para determinar si el XSL contenido en el elemento condicional se debe procesar. Por ejemplo, el siguiente XSL crea una tabla de contenido si hay ms de cuatro recetas en el libro de cocina.
<xsl:if test="count(recipe) > 4"> <h4>Contenido</h4> <xsl:apply-templates mode="contents" select="recipe" /> </xsl:if>

El XSL anterior utiliza la funcin Count para devolver el nmero de nodos receta en el libro de cocina. Si la cuenta es mayor de cuatro se enva a la salida el encabezado Contenido y se procesa la plantilla contents. En caso contrario se omiten los contenidos. De forma similar puede usar funciones XPath dentro de elementos xsl:choose para cambiar la salida en base a diferentes condiciones. Por ejemplo, el siguiente XSL inserta un salto de lnea tras cada cuatro elementos de contenido, en caso contrario los separa por un espacio en blanco: 263

MCAD/MCSD

<xsl:template mode="contents" match="recipe"> <xsl:element name="a"> <xsl:attribute name="href"> <xsl:text>#</xsl:text> <xsl:value-of select="generate-id(title)" /> </xsl:attribute> <xsl:value-of select="title" /> </xsl:element> <xsl:choose> <xsl:when test="position() mod 4 = 0"> <br /> </xsl:when> <xsl:otherwise> <xsl:text> </xsl:text> </xsl:otherwise> </xsl:choose> </xsl:template>

El XSL anterior usa la funcin position de XPath para devolver la posicin del nodo actual dentro de la coleccin de nodos. Tambin usa el operador mod de XPath para decir si la posicin actual es divisible por cuatro. Ms informacin: Si siente que solo hemos araado la superficie de lo que se puede hacer con XSL, tiene razn. XSL y XPath son lenguajes de pleno derecho. La leccin anterior da informacin suficiente para empezar, pero para una informacin completa vea la documentacin del SDK de XML de Microsoft incluida en la ayuda en lnea de Visual Studio .NET. Entre los libros de Microsoft Press que tratan este tema se incluyen XML Step by Step Second Edition, por Michael J. Young y XML Programming (Core Reference) por R. Allen Wyke, Sultan Rehman y Brad Leuden.

13.3 Resumen
Los estilos siguen un orden de precedencia en base a dnde se aplican: local (aplicado en un elemento), pgina (aplicado dentro del elemento head de una pgina) y global (aplicado mediante una hoja de estilo). Use el elemento link dentro del elemento head de un formulario Web para anexar una hoja de estilo. Use el asistente de generacin de estilos de Visual Studio .NET para modificar estilos existentes. Use el asistente Agregar regla de estilo de Visual Studio .NET para crear un nuevo estilo. Cree una clase estilo para aplicar el mismo formato a diferentes tipos de elementos. Use el atributo CssStyle para aplicar una clase de estilo a un control de servidor. Use el atributo class para aplicar una clase de estilo a un elemento HTML. Las transformaciones XSL convierten archivos de entrada XML en HTML por medio del control de servidor XML. XML organiza los datos en un conjunto de nodos jerrquico. Las plantillas XSL aplican formato a nodos dentro de un archivo XML. Use el elemento xsl:value-of para recuperar datos desde un nodo XML. Use el elemento xsl:text para incluir texto literal y caracteres de espacio en blanco en la salida XSL. Use el elemento xsl:for-each para repetir tareas para listas, tablas y otros nodos repetidos dentro de un archivo XML. Use los elementos xsl:if, xsl:choose, xsl:when y xsl:otherwise para realizar procesamiento condicional dentro de XSL.

13.4 Lab: Crear el libro de recetas


En este laboratorio va a crear un nico formulario Web que usa una hoja de estilos modificada, proporciona una hoja de estilo con tipos ampliados para usuarios con problemas visuales y usa XML con transformaciones XSL para dar formato a la informacin. Tambin se le sugerir que aplique sus conocimientos de XML a datos del mundo real con los que ya est familiarizado.

13.4.1 Ejercicio 1: Crear y anexar una hoja de estilo


Use los conocimientos adquiridos en la leccin 1 para crear su propia hoja de estilo basada en la predeterminada que crea Visual Studio .NET. Como el estilo (y el gusto) son temas personales, puede hacer los cambios sugeridos en los siguientes pasos o desarrollar su propio aspecto nico. 1. Haga los siguientes cambios, o lo que prefiera, en la hoja de estilo predeterminada (Styles.css): Cambie la fuente predeterminada en todos los encabezados a Comic Sans MS. Cambie la fuente predeterminada para el texto a Lucida Sans-Serif. Aada una imagen de fondo a la pgina desde la hoja de estilo. Cambie el color de los encabezados y lneas de separacin (HR) para que contrasten con el fondo. 264

Developing Web Applications

2. Cuando termine de modificar la hoja de estilo anxela a un formulario Web aadiendo el correspondiente elemento link en el elemento head. 3. Aada texto y encabezados al formulario para probar la apariencia del formulario Web. 4. Vea el formulario Web en el navegador y ajuste la hoja de estilo hasta que est a gusto con el aspecto del formulario web.

13.4.2 Ejercicio 2: Proporcionar hojas de estilo alternativas


En este ejercicio va a crear una hoja de estilo alternativa que muestra los encabezados y texto con una fuente alternativa de mayor tamao para que el formulario Web sea legible para usuarios con problemas visuales. Tambin agregar un control de cliente que permita al usuario cambiar a esta hoja de estilo en tiempo de ejecucin. 1. Aada una nueva hoja de estilo vaca al proyecto. Llmela BigType.css. 2. Corte y pegue los contenidos de la hoja de estilos predeterminada (Styles.css) a BigType.css. Si est usando Visual C#, tendr que coger la hoja de estilo desde un proyecto Visual Basic .NET y aadirla a su proyecto Visual C#. 3. En BigType.css, cambie el tamao de fuente del elemento body a large. 4. En el formulario Web creado en el ejercicio 1 aada un atributo ID y un atributo media al elemento link que enlaza la hoja de estilos predeterminadas, con los valores ScreenStyle y screen respectivamente. 5. Aada otro elemento link para usar la hoja de estilo predeterminada para impresin, con ID=PrintStyle y media=print. 6. En el formulario Web creado en el ejercicio 1 aada un enlace con un suceso onclick para cambiar entre la hoja de estilo predeterminada y BigType.css:
<a onclick="SwitchSheets()" href="#">Pulse aqu </a> para cambiar entre la versin estndar y con tipos grandes.

7. Aada la siguiente secuencia de comandos de cliente para cambiar entre hojas de estilo. VBScript
<script language="vbscript"> ' Cambia entre hojas de estilo. Sub SwitchSheets() If document.all("ScreenStyle").GetAttribute("HREF", 0) = "Styles.css" then document.all("ScreenStyle").SetAttribute "HREF", "BigType.css", 0 else document.all("ScreenStyle").SetAttribute "HREF", "Styles.css", 0 end if End Sub </script>

JScript
<script id="clientEventHandlersJS" language="jscript"> function SwitchSheets(){ // Cambia entre hojas de estilo. if (document.all["ScreenStyle"].getAttribute("HREF") == "Styles.css") document.all["ScreenStyle"].setAttribute ("HREF", "BigType.css", 0); else document.all["ScreenStyle"].setAttribute ("HREF", "Styles.css", 0); } </script>

8. Muestre el formulario Web en el navegador y pruebe el cambio entre hojas de estilo. Ajuste BigType.css para lograr el mejor aspecto.

13.4.3 Ejercicio 3: Transformacin XSL


En este ejercicio va a aadir al formulario Web creado en el ejercicio 1 un control XML de servidor. Configurar las propiedades DocumentSource y TransformSource del documento con los archivos XML y XSL utilizados en la leccin 2, que se incluyen en los ejemplos que acompaan al libro. 1. En el formulario de los ejercicios anteriores, borre el texto de ejemplo usado para probar las hojas de estilo. Mantenga el enlace y la secuencia de comandos aadidos en el ejercicio 2. 2. Aada un control de servidor tras el enlace:
<asp:Xml id="XmlTransform" runat="server" DocumentSource="" TransformSource="" />

3. Copie los archivos de ejemplo cook.xml y cook.xsl al directorio del proyecto. 4. Configure la propiedad DocumentSource del control XML como cook.xml y la propiedad TransformSource como cook.xsl. 5. Muestre el formulario Web en el navegador para confirmar que las transformaciones XML funcionan correctamente.

265

MCAD/MCSD

13.4.4 Ejercicio 4: Por si mismo


Piense formas de aplicar XML con transformaciones XSL a los datos que presenta actualmente en la Web con HTML. Usar XML para etiquetar contiendo es una tarea mucho ms conceptual que usar HTML directamente para dar formato al contenido, y cuesta acostumbrarse. Tal vez la mejor forma de aprender es intentarlo por si mismo, usando datos del mundo real con los que est familiarizado, tal como se describe en los siguientes pasos. 1. Elija un proyecto sencillo, como un formulario de pedido o una lista de direcciones y cree un archivo XML sencillo basado en los datos. 2. Cree un archivo XSL que contenga plantillas para transformar el archivo XML en HTML. 3. Cree un formulario Web que use un control XML para realizar la transformacin. 4. Durante este trabajo, piense sobre las siguientes cuestiones: Cmo se determina la jerarqua de nodos? Cules son las ventajas de crear colecciones dentro de la jerarqua? Por ejemplo:
<elementos> <elemento>Elemento 1</elemento> <elemento>Elemento 2</elemento> </elementos>

Cmo se aprovechan sus capacidades de programacin de base de datos y orientada a objetos al escribir XML?

13.5 Repaso
Las siguientes preguntas estn pensadas para reforzar informacin clave mostrada en este captulo. Si no es capaz de contestar a una pregunta repase la leccin correspondiente e intente de nuevo. Las respuestas se pueden encontrar en el captulo 16. 1. Cul es la ventaja de usar CSS en lugar de estilos en lnea para dar formato a una aplicacin Web? 2. Por qu creara un estilo para una clase en lugar de para un elemento HTML? 3. Cmo se relacionan entre s CSS y XSL cuando se trata de dar a una aplicacin Web? 4. Cules son las diferencias entre HTML y XML?

266

Developing Web Applications

14 Proporcionar ayuda
En este captulo aprender sobre las diferentes formas en que puede mostrar ayuda al usuario en una aplicacin Web. Aprender cmo usar HTML Help Workshop para crear archivos de ayuda compilados, y cmo mostrar estos archivos desde una aplicacin Web de forma interactiva. Antes de comenzar este captulo debe estar familiarizado con HTML y la creacin de formularios web en modo HTML.

14.1 Aadir ayuda a aplicaciones Web


Las aplicaciones Web pueden mostrar ayuda de varias formas: como etiquetas de controles, como formularios Web o pginas HTML o como archivos de ayuda HTML compilados. En esta leccin aprender a usar estas diferentes tcnicas en sus formularios Web.

14.1.1 Etiquetas de ayuda (ToolTip)


Un ToolTip es un mensaje breve y descriptivo que se muestra cuando un usuario coloca el puntero del ratn sobre un control y lo deja all un par de segundos. Estos mensajes se usan en aplicaciones Windows para proporcionar informacin til sobre botones de barra de herramientas y otros controles grficos cuyo significado de otra forma puede no ser evidente. En cierto sentido, las etiquetas de ayuda son subttulos para quienes no entienden los iconos. La mayor parte de los controles de servidor tienen una propiedad ToolTip en la que se puede establecer el mensaje que quiere que se muestre. En tiempo de ejecucin ASP.NET genera la propiedad ToolTip como atributo de ttulo del control, que Internet Explorer muestra como etiqueta de ayuda. Solo Internet Explorer muestra los atributos de ttulo como etiqueta de ayuda. Los controles HTML no incluyen una propiedad ToolTip. En su lugar puede usar directamente el atributo title. El siguiente HTML muestra la diferencia entre configurar la etiqueta de ayuda para un control de servidor y para un control HTML:
<asp:Button id="butOK" runat="server" Text="Aceptar" ToolTip="Enviar el pedido."></asp:Button> <INPUT type="reset" value="Cancelar" title="Cancelar el pedido.">

No todos los controles tienen una propiedad ToolTip o title. En concreto, los controles de servidor DropDownList y ListBox no tienen ninguno de los dos.

14.1.2 Mostrar ayuda como formulario Web o HTML


Probablemente la forma ms sencilla de mostrar contenido de ayuda sea crearlo como formulario Web o pgina HTML. Los archivos de ayuda pueden residir en la misma carpeta de proyecto que la aplicacin Web o en una carpeta subordinada. Para mostrar la ayuda en el navegador se usan enlaces u otros controles, igual que con cualquier otra pgina, con una diferencia importante: normalmente querr mostrar la ayuda en una ventana separada, o en un marco distinto al resto de la aplicacin Web. Al mostrar la ayuda en una ventana de navegador diferentes se conserva la posicin del usuario en la aplicacin Web y se permite que compare la informacin de ayuda con la tarea que est realizando. Para mostrar ayuda en una ventana diferente use el mtodo open del objeto window de cliente, como muestra el siguiente enlace:
<a href="#" onclick="window.open('topic1.aspx', 'helpwin').focus()"> Pulse aqu para ayuda.</a>

El HTML anterior usa el suceso onclick para mostrar un tema de ayuda en una nueva ventana de navegador sobre la ventana de la aplicacin Web. Al dar al atributo href el valor # sencillamente se enlaza con la ubicacin actual en la aplicacin Web, en lugar de redirigir al usuario a una nueva. El primer argumento del mtodo open especifica el tema de ayuda que se va a mostrar; el segundo da nombre a la nueva ventana, de forma que los siguientes temas de ayuda se dirijan a esta misma. Finalmente, el mtodo focus asegura que la ventana de ayuda se muestra encima de la aplicacin Web. Otros enlaces de ayuda en la aplicacin web pueden usar la misma secuencia de comandos onclick para mostrar temas diferentes en la misma ventana. Si su aplicacin incluye ms de un enlace de ayuda por formulario Web es buena idea poner la secuencia de comandos en un procedimiento y llamarla desde es procedimiento onclick, como aqu:

267

MCAD/MCSD

VBScript
<HTML> <HEAD> <title>WebForm1</title> <script language="vbscript"> ' Muestra un formulario Web o pgina HTML en una pequea ventana de ' navegador y pasa el foco a esta ventana. Sub ShowHelp(topicName) Dim HelpWindow ' Muestra el tema en una ventana con nombre. Set HelpWindow = window.open(topicName, "helpwin", "left=600, height=300, width=200") ' Muestra la ventana encima. HelpWindow.focus End Sub </script> </HEAD> <body> <h2>Muestra ayuda en una nueva ventana </h2> <A onclick="ShowHelp('topic1.aspx')" href="#">Pulse para ayuda.</A><BR> <A onclick="ShowHelp('topic2.aspx')" href="#">Pulse para ms ayuda.</A> </body> </HTML>

JScript
<HTML> <HEAD> <script language="jscript"> // Muestra un formulario Web o pgina HTML en una pequea ventana de // navegador y pasa el foco a esta ventana. function ShowHelp(topicName){ var HelpWindow; // Muestra el tema en una ventana con nombre. HelpWindow = window.open(topicName, "helpwin", "left=600, height=300, width=200"); // Muestra la ventana encima. HelpWindow.focus(); } </script> </HEAD> <body> <h2>Muestra ayuda en una nueva ventana </h2> <A onclick="ShowHelp('topic1.aspx')" href="#">Pulse para ayuda.</A><BR> <A onclick="ShowHelp('topic2.aspx')" href="#">Pulse para ms ayuda.</A> </body> </HTML>

Dentro del tema de ayuda puede usar puede usar el mtodo close del objeto window para incluir un enlace que cierre la ventana de ayuda:
<a href="#" onclick="window.close()">Pulse para cerrar la ayuda.</a>

Hay otras formas de mostrar ayuda en una ventana con nombre, como usar el atributo target de un enlace. Sin embargo, estas tcnicas hace ms difcil asegurar que la ventana de ayuda se muestra por encima de la ventana de la aplicacin.

14.1.3 Mostrar ayuda HTML


Puede usar el mtodo showHelp del objeto window para mostrar archivos de ayuda HTML, archivos HTML ordinarios o formularios Web usando el visor de ayuda HTML (hh.exe). Un archivo de ayuda consiste en archivos de tema escritos en HTML que se han compilado en un nico archivo comprimido que proporciona caractersticas adicionales. El mtodo showHelp muestra temas de ayuda en el visor de ayuda HTML, que de forma predeterminada se muestra sobre la ventana del navegador . Para mostrar un formulario Web o pgina HTML usando showHelp especifique el nombre de archivo como primer argumento del mtodo:
<a href="#" onclick="window.showHelp('Topic1.aspx')">Ayuda</a>

El HTML anterior muestra el formulario Web Topic1.aspx cuando el usuario pulsa el enlace. Este archivo no es un archivo de ayuda compilado es sencillamente un tema de ayuda escrito usando ASP.NET. El uso de show268

Developing Web Applications

Help le da la ventaja de que la ventana siempre est por encima de la aplicacin Web incluso aunque la aplicacin tenga el foco. El mtodo showHelp tambin puede mostrar temas de archivos de ayuda compilados. Estos archivos se componen de pginas HTML que se compilan en un nico archivo (.chm) usando HTML Help Workshop. Cuando se trabaja con archivos de ayuda compilados showHelp identifica el tema usando un ID de contexto que se hace corresponder con un nombre de archivo de tema durante la compilacin. Para mostrar un tema de ayuda de un archivo de ayuda compilado especifique el nombre de archivo y el del tema como primer argumento de showHelp:
<a href="#" onclick="window.showHelp('c:\\Help\\HelpSample.chm')">Ayuda</a><br>

El HTML anterior muestra el archivo compilado llamado HelpSample.chm. Observe que el archivo de ayuda compilado se debe descargar y almacenar en la mquina del usuario. El uso de archivos de ayuda compilados tiene las siguientes ventajas sobre los formularios Web o pginas HTML en archivos separados: Tamao reducido. La compilacin comprime los temas de forma que su tamao total es mucho menor que el total de los orgenes de ayuda individuales. Contenido, ndice y bsqueda. HTML Help Workshop incluye herramientas para crear estas caractersticas y aadirlas a su sistema de ayuda. Presentacin incrustada. El control ActiveX HTML y el applet Java permiten mostrar la ayuda dentro de la ventana de navegador en lugar de en una ventana separada. Facilidad de localizacin. Como la ayuda HTML hace corresponder los nombres de archivo de tema con identificadores de contexto es posible tener varios archivos de ayuda compilados escritos en diferentes idiomas que usen los mismos identificadores de contexto. La compilacin de ayuda HTML tiene algunas limitaciones de las que debe estar avisado: Los archivos fuente deben estar en formato HTML. Los formularios Web no se pueden compilar en archivos .chm. El archivo compilado se debe descargar completo en la mquina del usuario. Si el archivo de ayuda es muy grande y los usuarios estn conectados mediante mdem puede tomar mucho tiempo cargar la ayuda la primera vez. Una vez descargado el archivo de ayuda el acceso es muy rpido. Las siguientes lecciones tratan con ms detalle la creacin de archivos de ayuda compilados y su uso desde aplicaciones Web.

14.2 HTML Help Workshop


Microsoft Visual Studio .NET incluye HTML Help Workshop, que se instala en una ubicacin separada en la mquina del desarrollador. En esta leccin aprender cmo usar HTML Help Workshop para crear un archivo de ayuda compilado que incluya una tabla de contenidos, ndice y capacidades de bsqueda de texto completas.

14.2.1 Crear ayuda HTML


Un archivo de ayuda HTML se compone de pginas HTML individuales, cada una de las cuales representa un nico tema. Cada tema de ayuda puede incluir palabras clave que se incluyen en el ndice y referencias cruzadas con otros temas. Los proyectos de ayuda HTML incluyen los tipos de archivo que describe la tabla 14.1:
Tabla 14. 1: Archivos de proyecto de ayuda HTML
Archivo Tema de ayuda Proyecto Contenido ndice Lista de detencin de bsqueda Compilado Extensin htm hhp hhc hhk stp chm Se usa para Crear contenido que se mostrar en la ayuda. Definir cmo se compila el proyecto y qu archivos de tema de ayuda, contenido e ndice incluye. Crear una tabla de contenidos para el archivo de ayuda. Crea un ndice para el archivo de ayuda Excluir palabras concretas de las bsquedas Distribuye la ayuda terminada.

HTML Help Workshop proporciona herramientas para organizar, editar y compilar estos archivos. De forma predeterminada. Visual Studio .NET instala HTML Help Workshop en Archivos de Programa\HTML Help Workshop. Para crear un nuevo proyecto de ayuda HTML siga estos pasos: 1. Desde el men File de HTML Help Workshop seleccione New. HTML Help Workshop inicia el asistente New Project. 2. El asistente permite convertir un proyecto WinHelp existente o crear un nuevo proyecto. Pulse Next para crear un nuevo proyecto. El asistente muestra la pgina Destination. 269

MCAD/MCSD

3. Escriba la ubicacin y nombre del archivo de proyecto que quiere crear y pulse Next. El asistente muestra la pgina Existing Files 4. Seleccione las cajas correspondientes a los archivos de contenido, ndice o tema que ya haya creado y pulse siguiente. Si selecciona alguno de estos archivos existentes el asistente le pide la localizacin de cada uno de los tipos de archivos seleccionado. En caso contrario crea un nuevo archivo de proyecto vaco. El uso de HTML Help Workshop es asombrosamente sencillo. Se usan las lengetas Project, Contents e Index del panel izquierdo para editar los contenidos de los archivos de proyecto, contenidos e ndice. Los botones e la parte superior del panel crean nuevos archivos, abren archivos existentes, compilan el proyecto, muestran el proyecto compilado y muestran la ayuda de HTML Workshop. Para aadir archivos de tema al proyecto de ayuda: 1. Pulse New en la parte superior de la ventana, seleccione HTML File y especifique un ttulo para el tema. El Workshop crear un nuevo archivo de tema de ayuda. 2. Guarde el archivo HTML y pulse Add/Remove Topic Files en el lado izquierdo de la lengeta Project. Se abre el dilogo Topic Files. 3. Pulse Add y seleccione los archivos para aadir al proyecto. Pulse OK. 4. Pulse OK de nuevo para cerrar el dilogo Topic Files. El Workshop aade el archivo al proyecto. HTML Help Workshop proporciona solo capacidades bsicas de edicin de texto. Por lo general se crearn los archivos de tema de ayuda en un editor HTML completo y se usar el Workshop para crear el archivo de proyecto y compilar la ayuda.

14.2.2 Opciones de proyecto


Las opciones de proyecto de ayuda se muestran en la lengeta Project de HTML Help Workshop. Estas opciones se guardan en el archivo de proyecto de ayuda (.hpp) en texto plano y se pueden modificar usando HTML Help Workshop o un editor de texto como el Block de notas. Para establecer las opciones de proyecto en HTML Help Workshop, en la lengeta Project pulse Change Project Options. El Workshop muestra el dilogo Project Options. Las opciones de proyecto permiten especificar un ttulo para el proyecto de ayuda, informacin de internacionalizacin, cmo se crean los archivos de contenido e ndice, si se soporta bsqueda y otras caractersticas. Estos elementos se encuentran en la seccin Options del archivo de proyecto. Por ejemplo, las siguientes opciones de proyecto crean automticamente archivos de ndice y de contenido cuando se compila un archivo de ayuda llamado HelpSample.chm, que muestra el ttulo HTML Help Sample:
[OPTIONS] Auto Index=Yes Auto TOC=9 Compatibility=1.1 or later Compiled file=HelpSample.chm Contents file= Contents.hhc Default topic=topic1.htm Display compile progress=No Full text search stop list file=Search.stp Index file=Index.hhk Language=0x409 English (United States) Title=HTML Help Sample

El archivo de proyecto tambin incluye una seccin FILES que indica los archivos de temas de ayuda a compilar. El orden de los archivos en esta seccin determina el orden de elementos en el archivo de contenido cuando se selecciona tabla de contenidos automtica (Auto TOC) en la seccin OPTIONS. Por ejemplo, los siguientes archivos de tema aparecen en orden secuencial en Contents:
[FILES] topic1.htm topic1a.htm topic1b.htm topic2.htm topic3.htm

14.2.3 Tablas de contenido


Cuando se genera una tabla de contenido automticamente HTML Help Workshop utiliza el nivel de encabezado del tema y su orden en la seccin FILES del archivo de proyecto para determinar cmo se organiza la tabla de contenido. Workshop pone los encabezados <H1> en el nivel superior, los <H2> bajo estos, y as hasta encontrar un nuevo <H1>. Si tiene varios niveles de encabezado en un mismo tema el Workshop crea elementos Contents subor270

Developing Web Applications

dinados para cada uno de estos encabezados incluso aunque representen un mismo tema de ayuda. Por este motivo es mejor usar un nico elemento de encabezado HTML por tema de ayuda cuando se generan los contenidos automticamente. El Workshop guarda la tabla de contenidos generada en un archivo HTML. Puede generar una tabla de contenidos automtica, desactivar Auto TOC en el archivo de proyecto y despus editar el archivo generado para personalizar la tabla de contenidos. Para editar la tabla de contenidos pulse la lengeta Contents en HTML Help Workshop. Puede que haya observado que en la tabla de contenidos automtica los iconos para los temas de nivel superior no son coherentes. Algunos muestran un libro y otros una pgina. Para cambiar el icono que muestra un tema: 1. Seleccione el tema de contenido, pulse Edit Selection y la lengeta Advanced. El Workshop muestra el dilogo Table of Contents Entry 2. Seleccione la imagen que quiere usar en la caja de lista Image Index y pulse OK. El archivo de contenido se guarda como HTML con elementos OBJECT para especificar los elementos de contenido:
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN"> <HTML> <HEAD> <meta name="GENERATOR" content="Microsoft&reg; HTML Help Workshop 4.1"> <!-- Sitemap 1.0 --> </HEAD> <BODY> <UL> <LI> <OBJECT type="text/sitemap"> <param name="Name" value="Topic1"> <param name="Local" value="topic1.htm"> </OBJECT> <UL> <LI> <OBJECT type="text/sitemap"> <param name="Name" value="Topic 1.a"> <param name="Local" value="topic1a.htm"> </OBJECT> <UL> <LI> <OBJECT type="text/sitemap"> <param name="Name" value="Topic 1.a.i"> <param name="Local" value="topic1ai.htm"> </OBJECT> <LI> <OBJECT type="text/sitemap"> <param name="Name" value="Topic 1.a.ii"> <param name="Local" value="topic1aii.htm"> </OBJECT> </UL> <LI> <OBJECT type="text/sitemap"> <param name="Name" value="Topic 1.b"> <param name="Local" value="topic1b.htm"> <param name="ImageNumber" value="1"> </OBJECT> </UL> <LI> <OBJECT type="text/sitemap"> <param name="Name" value="Topic 2"> <param name="Local" value="topic2.htm"> </OBJECT> <UL> <LI> <OBJECT type="text/sitemap"> <param name="Name" value=""> <param name="Local" value="topic2.htm"> </OBJECT>

271

MCAD/MCSD

<LI> <OBJECT type="text/sitemap"> <param name="Name" value="Topic 2.a"> <param name="Local" value="topic2a.htm"> </OBJECT> <LI> <OBJECT type="text/sitemap"> <param name="Name" value="Topic 2.b"> <param name="Local" value="topic2b.htm"> </OBJECT> </UL> <LI> <OBJECT type="text/sitemap"> <param name="Name" value="Topic 3"> <param name="Local" value="topic3.htm"> <param name="ImageNumber" value="1"> </OBJECT> </UL> </BODY> </HTML>

Los elementos de lista HTML determinan la jerarqua de los elementos en la tabla de contenidos. Los elementos objeto determinan el ttulo, icono, ubicacin y otra informacin sobre el enlace. Por ejemplo, el siguiente elemento de contenido enlaza con una pgina New Products y abre la pgina en una nueva ventana:
<OBJECT type="text/sitemap"> <param name="Name" value="New Products"> <param name="Local" value="http://www.mycompany.com/newproducts.htm"> <param name="WindowName" value="NewWindow"> <param name="Comment" value="Sample of text/sitemap params"> <param name="New" value="1"> <param name="ImageNumber" value="7"> </OBJECT>

14.2.4 ndice
HTML Help Workshop puede crear un archivo de ndice a partir de elementos objeto introducidos en los archivos de tema. Dentro de un archivo de tema se crea una entrada de ndice como objeto ActiveX con un classID concreto:
<Object type="application/x-oleobject" classid="clsid:1e2a7bd0-dab9-11d0-b93a-00c04fc99f9e"> <param name="Keyword" value="Index Item 1"> <param name="Keyword" value="Index Item 1, Subitem a"> <param name="Keyword" value="Index Item 1, Subitem b"> </OBJECT>

El HTML anterior crea tres entradas de ndice para este enlace al archivo de tema. HTML Help Workshop no guarda automticamente entradas de ndice de los archivos de tema en el archivo de ndice; pero puede aadir entradas para ayudar a organizar o complementar las entradas automticas. El archivo de ndice (.hhk) y las entradas de ndice de tema se aaden juntas para crear el ndice mostrado en el archivo de ayuda compilado. Por ejemplo, el siguiente archivo de ndice se combina con las entradas automticas para crear un ndice:
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN"> <HTML> <HEAD> <meta name="GENERATOR" content="Microsoft&reg; HTML Help Workshop 4.1"> <!-- Sitemap 1.0 --> </HEAD> <BODY> <UL> <LI> <OBJECT type="text/sitemap"> <param name="Name" value="Index Item 1"> <param name="Name" value="Topic 1.b"> <param name="Local" value="topic1b.htm"> </OBJECT>

272

Developing Web Applications

<LI> <OBJECT type="text/sitemap"> <param name="Name" value="Index Item 2"> <param name="Name" value="Topic 2.a"> <param name="Local" value="topic2a.htm"> </OBJECT> </UL> </BODY> </HTML>

14.2.5 Referencias cruzadas


Hay tres formas de hacer referencias cruzadas entre temas de ayuda: Usar enlaces HTML para crear un enlace desde un tema de ayuda a otro. Los enlaces permiten relaciones uno a uno. Usar el comando Related Topics para crear un enlace desde un tema a una lista de archivos de tema relacionados Usar enlaces asociativos (ALink) para crearn enlaces desde un tema a una lista de temas relacionados en base a las palabras clave en estos archivos de tema. Como ya sabe crear enlaces (a estas alturas mejor que sepa) las siguientes secciones tratan cmo aadir temas relacionados y cmo crear enlaces asociativos. Temas relacionados Puede aadir temas relacionados como referencia cruzada o enlace. Para aadir una referencia cruzada de temas relacionados a un tema de ayuda inserte un control ActiveX de ayuda HTML en el archivo de tema. Por ejemplo, el siguiente elemento objeto muestra un botn que lista dos temas relacionados como opciones de men emergente:
<OBJECT id=hhctrl type="application/x-oleobject" classid="clsid:adb880a6-d8ff-11cf-9377-00aa003b7a11" codebase="hhctrl.ocx#Version=4,74,9273,0" width=100 height=100> <PARAM name="Command" value="Related Topics, MENU"> <PARAM name="Button" value="Text:Related Topics"> <PARAM name="Item1" value="Topic 2;Topic2.htm"> <PARAM name="Item2" value="Topic 3;Topic3.htm"> </OBJECT>

Para mostrar temas relacionados como enlace en lugar de cmo botones especifique un parmetro Text en lugar de un parmetro Button en el elemento objeto. Por ejemplo, el siguiente HTML muestra los temas relacionados anteriores como enlace:
<OBJECT id= hhctrl type="application/x-oleobject" classid="clsid:adb880a6-d8ff-11cf-9377-00aa003b7a11" codebase="hhctrl.ocx#Version=4,74,9273,0" width=100 height=100> <PARAM name="Command" value="Related Topics, MENU"> <PARAM name="Text" value="Text:Related Topics"> <PARAM name="Item1" value="Topic 2;Topic2.htm"> <PARAM name="Item2" value="Topic 3;Topic3.htm"> </OBJECT>

Enlaces asociativos Los enlaces asociativos hacen referencia a palabras clave en lugar de a nombres de archivo concretos. Por este motivo son tiles para referencias cruzadas entre archivos de ayuda HTML no es necesario saber cmo se llaman los archivos de tema dentro de un archivo compilado, solo es necesario saber qu palabras clave se usan. Los enlaces asociativos tambin son tiles dentro de un mismo archivo de ayuda los nombres de archivo pueden cambiar durante el desarrollo, y es ms fcil mantener una lista de palabras clave que actualizar nombres de archivo en referencias cruzadas. Una referencia cruzada asociativa tiene dos partes: Las palabras clave introducidas en los archivos de tema de destino proporcionan los destinos con los que enlazan las referencias. El enlace en el archivo de tema de origen proporciona el origen desde el que enlaza la referencia cruzada.

273

MCAD/MCSD

Para crear palabras clave de enlace asociativo inserte un elemento objeto en el tema objetivo. Por ejemplo, el siguiente elemento objeto crea la palabra clave Link1:
<Object type="application/x-oleobject" classid="clsid:1e2a7bd0-dab9-11d0-b93a-00c04fc99f9e"> <param name="ALink Name" value="Link1"> </OBJECT>

Los enlaces asociativos son muy similares a las palabras claves que se usan para indexar la ayuda HTML, pero no aparecen en el ndice. El motivo es permitir que la indexacin y las referencias cruzadas se mantengan por separado. Para crear un enlace con temas que contienen una palabra clave concreta inserte un objeto ActiveX de ayuda HTML en el archivo de tema que hace la referencia. Por ejemplo, el siguiente elemento objeto muestra una lista de referencias cruzadas en un men emergente cuando el usuario pulsa el control:
<OBJECT id=hhctrl type="application/x-oleobject" classid="clsid:adb880a6-d8ff-11cf-9377-00aa003b7a11" codebase="hhctrl.ocx#Version=4,74,9273,0" width=100 height=100> <PARAM name="Command" value="ALink, menu"> <PARAM name="Button" value="Text:See Also"> <PARAM name="Flags" value=",,1"> <PARAM name="Item1" value=""> <PARAM name="Item2" value="Link1"> </OBJECT>

Para mostrar los enlaces asociativos como enlace en lugar de como botn omita el parmetro Button en el elemento objeto y llame al suceso Click del objeto desde el enlace. Por ejemplo, el siguiente HTML muestra los enlaces cuando el usuario pulsa el enlace See Also:
<OBJECT id=hhctrl type="application/x-oleobject" classid="clsid:adb880a6-d8ff-11cf-9377-00aa003b7a11" codebase="hhctrl.ocx#Version=4,74,9273,0" width=100 height=100> <PARAM name="Command" value="ALink, menu"> <PARAM name="Flags" value=",,1"> <PARAM name="Item1" value=""> <PARAM name="Item2" value="Link1"> </OBJECT> <a href="#" onclick="hhctrl.Click()">See also</a>

14.2.6 Bsqueda
Para permitir bsquedas de texto completas en un archivo de ayuda seleccione Compile Full-Text Search Information en la lengeta Compiler del dilogo Project Options. Cuando se activa la bsqueda de texto HTML Help Workshop crea una tabla de concordancia de todas las palabras de los archivos de tema e incluye esta tabla en el archivo compilado. Como esta tabla hace referencia a todas las palabras de todos los archivos puede ser muy grande. Para controlar el tamao de esta tabla puede omitir palabras que no son tiles en la bsqueda. Por ejemplo, puede omitir artculos, conjunciones, pronombres personales y nmeros. Para omitir palabras en una bsqueda de texto completa: 1. Cree un archivo de texto que contenga las palabras a omitir 2. Pulse Change Project Optionse en la lengeta Project de HTML Help Workshop 3. En la lengeta Compiles del dilogo Project Options escriba el nombre del archivo de lista de palabra a omitir en la caja de texto Full Text Search Stop List. Cuando un usuario intenta buscar una palabra que est incluida en la lista de exclusin la ayuda HTML muestra una caja de mensaje que indica que no se puede realizar la bsqueda.

14.2.7 Compilar y previsualizar


Para compilar un proyecto de ayuda HTML seleccione una de estas dos posibilidades: En la lengeta Project de HTML Help Workshop pulse Save All Files And Compile Use el compilador de ayuda HTML (hhc.exe) desde lnea de comandos. Por ejemplo, el comando hhc.exe HelpSample.hhp compila el proyecto de ayuda HelpSample.hhp. 274

Developing Web Applications

Para previsualizar un proyecto de ayuda HTML compilado seleccione una de estas dos opciones. Pulse el botn View Compiled File en la parte superior de HTML Help Workshop y seleccione el nombre del archivo compilado. Pulse dos veces sobre el archivo compilado (.chm) en Windows. Importante: No puede volver a compilar un archivo de ayuda mientras est abierto para visualizacin. Debe cerrar el archivo compilado antes de volver a compilar.

14.3 Enlazar ayuda HTML con formularios Web


En esta leccin aprender cmo mostrar ayuda HTML desde un formulario Web. Esta leccin ampla las tcnicas mostradas brevemente en la Leccin 1 mostrando las diferentes formas en que se puede mostrar ayuda HTML, describiendo las diferencias entre ayuda compilada y no compilada y explicando cmo hacer que la ayuda responda a acciones de usuario en una aplicacin Web.

14.3.1 Mostrar el visor de ayuda HTML


Como se mostr en la Leccin 1 la ayuda HTML se muestra en el visor de ayuda HTML usando el mtodo showHelp. La forma de usar showHelp depende de si la ayuda est compilada. La ayuda no compilada se puede mostrar usando la direccin del tema de ayuda en Internet: La ayuda compilada se debe copiar localmente antes de que se puedan mostrar los temas usando showHelp:
<a href="#" onclick="window.showHelp('c:\\Help\\HelpSample.chm')">Ayuda</a> <a href="#" onclick="window.showHelp('Topic1.htm')">Ayuda</a>

El visor de ayuda se muestra con un aspecto diferente segn la ayuda est no compilada. La ayuda compilada muestra contenido, ndice y bsqueda, mientras que la no compilada solo muestra el tema de ayuda solicitado. Usando ayuda compilada obtiene las caractersticas completas del sistema de ayuda HTML; sin embargo, el usuario primero debe descargar el archivo de ayuda compilada. Para descargar un archivo de ayuda compilado a la mquina del usuario cree un enlace al archivo y proporcione al usuario instrucciones sobre donde guardarlo. Por ejemplo, el siguiente HTML crea un enlace que descarga el archivo HelpSample.chm e instruye al usuario para que lo guarde en un directorio concreto:
<a href="HelpSample.chm">Pulse aqu</a> para descargar el archivo de ayuda de ejemplo y gurdelo en el directorio C:\Help de su ordenador.</p>

Cuando el usuario pulse el enlace anterior el navegador pregunta al usuario si quiere abrir o guardar el archivo de ayuda. Cuando el usuario guarda el archivo en el directorio indicado el mtodo showHelp puede mostra los temas que contiene.

14.3.2 Mostrar ayuda HTML en el navegador


El mtodo showHelp no es la nica forma de mostrar archivos de ayuda compilados. Tambin puede mostrarlos en el navegador usando URL,s desde dentro del propio archivo de ayuda. El navegador no puede mostrar las caractersticas de ndice, contenido o bsqueda, pero puede abrir temas del archivo compilado a travs de Internet, que es algo que showHelp no puede hacer. Para mostrar un archivo de ayuda compilado en el navegador cree un enlace usando el URL del archivo de tema dentro del archivo compilado. Por ejemplo, el siguiente enlace muestra Topic1.htm en una nueva ventana del navegador.
<a href="ms-its:http://www.mycompany.com/Help/HelpSample.chm::/topic1.htm" target="HelpWin">Ayuda</a>

El enlace anterior usa el protocolo incrustable ms-its: y la sintaxis de ruta de ayuda para mostrar un archivo de tema desde dentro de un archivo compilado guardado en la Web. El protocolo ms-its: lo proporciona Internet Explorer desde la versin 4.0 en adelante. La sintaxis de ruta de ayuda HTML tiene la forma archivocompilado::/archivotema, donde archivocompilado es el URL del archivo de ayuda compilado y archivotema es el nombre el archivo HTML del tema dentro del archivo compilado.

14.3.3 Ayuda sensible a contexto


Si est mostrando ayuda compilada en el visor de ayuda puede usar identificadores de contexto para identificar los temas dentro del archivo de ayuda y asociarlos con tareas de la aplicacin Web. Este tipo de ayuda se denomina sensible a contexto como porque el tema mostrado depende del contexto (o tarea) dentro de la aplicacin. Aplicar ayuda sensible a contexto dentro de una aplicacin Web presenta un par de retos: Aunque puede capturar la tecla de ayuda (F1) mediante el suceso onkeydown y la propiedad window.event.keyCode no puede cancelar la accin predeterminada para F1 dentro de Internet Explorer, que consiste en mostrar la ayuda de Internet Explorer. 275

MCAD/MCSD

El argumento contextID para el mtodo showHelp no funciona desde un formulario Web o pgina HTML. Para resolver estos problemas debe elegir un mecanismo diferente a F1 para mostrar ayuda dentro de su aplicacin Web, y debe usar la sintaxis de ruta de ayuda HTML para mostrar el tema adecuado. El siguiente HTML usa el suceso onfocus para mostrar diferentes temas de ayuda segn el usuario se mueve entre los controles de un formulario Web. VBScript
<HTML> <HEAD> <title>Context Help</title> <script language="vbscript"> Dim LastTopic Sub ShowContextHelp(Topic) If (document.all("chkHelp").checked And LastTopic <> Topic) Then ' Muestra ayuda para este contexto. window.showHelp "c:\help\HelpSample.chm::/" & Topic ' Guarda el nombre del tema LastTopic = Topic End If End Sub </script> </HEAD> <body onfocus="ShowContextHelp('Topic1.htm')> <form id="WebForm2" method="post" runat="server"> <H2>Ayuda sensible a contexto </H2> <INPUT onfocus="ShowContextHelp('Topic2.htm')" type="text"><BR> <INPUT onfocus="ShowContextHelp('Topic3.htm')" type="button" value="Button"> <BR> <INPUT id="chkHelp" type="checkbox" name="chkHelp">Mostrar ayuda al usuario. </form> </body> </HTML>

JScript
<HTML> <HEAD> <title>Context Help</title> <script language="jscript"> var LastTopic; function ShowContextHelp(Topic){ if ((document.all("chkHelp").checked) && (LastTopic != Topic)){ // Muestra ayuda para este contexto. window.showHelp("c:\\help\\HelpSample.chm::/" + Topic); // Guarda el nombre del tema. LastTopic = Topic; } } </script> </HEAD> <body onfocus="ShowContextHelp('Topic1.htm')> <form id="WebForm2" method="post" runat="server"> <H2>Ayuda sensible a contexto </H2> <INPUT onfocus="ShowContextHelp('Topic2.htm')" type="text"><BR> <INPUT onfocus="ShowContextHelp('Topic3.htm')" type="button" value="Button"> <BR> <INPUT id="chkHelp" type="checkbox" name="chkHelp">Mostrar ayuda al usuario. </form> </body> </HTML>

El control CheckBox permite que el usuario active la ayuda. En tiempo de ejecucin el procedimiento ShowContextHelp muestra el tema de ayuda para cada elemento de la pgina cuando el elemento recibe el foco.

14.4 Resumen
Puede proporcionar ayuda al usuario dentro de su aplicacin Web usando etiquetas de ayuda, formularios Web o pginas HTML o ayuda HTML. La ayuda HTML proporciona capacidades de contenido, ndice y bsqueda.

276

Developing Web Applications

Use el mtodo showHelp del objeto window en secuencias de comandos de cliente para mostrar el visor de ayuda HTML. Use el objeto ActiveX de ayuda HTML para aadir palabras clave de ndice, enlaces con temas relacionados y enlaces asociativos a los temas de ayuda. Para mostrar archivos e ayuda compilados desde una aplicacin Web primero debe descargar el archivo a la mquina del usuario.

14.5 Lab: Crear y usar un archivo de ayuda HTML


En este laboratorio va a crear un archivo de ayuda compilado que contendr varios temas, con tabla de contenido, ndice y bsqueda. Despus lo enlazar con una aplicacin Web.

14.5.1 Ejercicio 1: Crear un proyecto de ayuda


En este ejercicio va a usar las capacidades que aprendi en la leccin 2 para crear un nuevo proyecto de HTML Help Workshop, crear cinco temas de archivo de ayuda y aadir estos archivos al proyecto de ayuda. Para que el ejercicio se mantenga sencillo el contenido de los archivos de tema de ayuda es mnimo, aunque puede incluir el contenido adicional que quiera. 1. Inicie HTML Help Workshop. Seleccione New en el men File, seleccione Project en el dilogo New y siga el asistente para crear un proyecto vaco llamado HelpDemo en su ordenador. 2. Cree cinco nuevos archivos HTML llamados Topic1 a Topic5. Aada a los archivos un elemento <title> con el nombre del archivo, y un encabezado con el nivel indicado por el nmero del archivo (<h1> a <h5>) y el mismo contenido. 3. Aada todos estos archivos de tema al proyecto.

14.5.2 Ejercicio 2: Activar contenidos, ndice y bsqueda


En este ejercicio continuar usando las capacidades que aprendi en la leccin 2 para generar automticamente las caractersticas de contenido, ndice y bsqueda cuando se compile el proyecto. 1. En la dilogo de opciones del proyecto de ayuda pulse la lengeta Files y marque las opciones para crear automticamente un archivo de contenido e incluir las palabras clave en el ndice, y escriba los nombres para los archivos de contenido e ndice. 2. Pulse la lengeta Compiler en las opciones del proyecto y marque Compile Full-Text Search Information. Pulse Aceptar. 3. En la lengeta Project de HTML Help Workshop pulse Save All Files and Compile. El Workshop genera el contenido, ndice e informacin de bsqueda, compila el archivo y muestra un informe de resultado. 4. Pulse View Compiled File en la barra de herramientas de HTML Help Workshop, escriba el nombre y ubicacin del archivo HelpDemo.chm en el dilogo View Compiled File y pulse View. El Workshop muestra el archivo de ayuda compilado.

14.5.3 Ejercicio 3: Aadir palabras clave al ndice


En este ejercicio va a aadir palabras clave de ndice a los archivos de tema de ayuda y volver a compilar el archivo de ayuda para crear entradas de ndice automticas. 1. En el HTML Help Workshop abra el archivo de tema Topic2.htm e inserte una nueva lnea en el cuerpo. 2. En el men Edit seleccione Compiler Information. Workshop muestra el dilogo Compiler Information. 3. Pulse Add y escriba Item1 como nombre de la palabra clave de ndice que va a agregar al tema y pulse OK. Pulse Aceptar para cerrar el dilogo Compiler Information y aadir la entrada a Topic2.htm. El siguiente HTML muestra el texto generado que se ha aadido a Topic2.htm:
<Object type="application/x-oleobject" classid="clsid:1e2a7bd0-dab9-11d0-b93a-00c04fc99f9e"> <param name="Keyword" value="Item1"> </OBJECT>

4. Copie el fragmento anterior en cada uno de los restantes archivos de tema. Agregue o cambie los parmetros de la palabra clave para crear palabras clave diferentes. Por ejemplo, el siguiente HTML inserta tres palabras clave de ndice en un archivo de tema:
<Object type="application/x-oleobject" classid="clsid:1e2a7bd0-dab9-11d0-b93a-00c04fc99f9e"> <param name="Keyword" value="Item1"> <param name="Keyword" value="new"> <param name="Keyword" value="improved"> </OBJECT>

5. Vuelva a compilar y ver el archivo de ayuda. Compruebe la lengeta ndice.

277

MCAD/MCSD

14.5.4 Ejercicio 4: Enlazar ayuda con un formulario Web.


En este ejercicio va a usar lo que aprendi en la leccin 3 para enlazar con la ayuda compilada creada en el ejercicio anterior desde un formulario web sencillo. 1. Cree un nuevo proyecto de aplicacin web vaco llamado vbHelpDemo o csHelpDemo. 2. Aada el siguiente HTML a WebForm1 para indicar al usuario cmo descargar el archivo de ayuda y proporcionar una forma para mostrar ayuda en el formulario Web.
<p>Para usar ayuda con este formulario Web:</p> <ol> <li><a href="HelpDemo.chm">Pulse aqu</a> para descarga la ayuda.</li> <li>Guarde el archivo en el directorio c:/help de su ordenador.</li> <li>Despus use los botones siguientes para mostrar los temas de ayuda.</li> </ol> <INPUT type="button" value="Ver ayuda" onclick="window.showHelp('c:\\help\\HelpDemo.chm')"><br> <INPUT type="button" value="Show Topic3" onclick="window.showHelp('c:\\help\\HelpDemo.chm::/Topic3.htm)"><br> <INPUT type="button" value="Show Topic5" onclick="window.showHelp('c:\\help\\HelpDemo.chm::/Topic5.htm)">

3. Copie el archivo compilado creado en el ejercicio anterior al directorio del proyecto de aplicacin Web. 4. Ejecute la aplicacin Web. Despus de descargar el archivo de ayuda, al pulsar los botones se debe mostrar esta.

14.6 Repaso
Las siguientes preguntas estn pensadas para reforzar informacin clave mostrada en este captulo. Si no es capaz de contestar a una pregunta repase la leccin correspondiente e intente de nuevo. Las respuestas se pueden encontrar en el captulo 16. 1. En qu atributo del HTML mostrado por ASP.NET se convierte la propiedad ToolTip de un control de servidor? 2. En que se diferencia mostrar ayuda HTML usando el mtodo showHelp del objeto window de mostrarla en una ventana del navegador?. 3. Cmo se aaden palabras clave de ndice a un tema de ayuda?.

278

Developing Web Applications

15 Globalizar Aplicaciones Web


Globalizacin es el proceso de crear una aplicacin que cubre las necesidades de usuarios de diferentes culturas. Este proceso implica ms que la simple traduccin de elementos del interface de usuario a varios lenguajes tambin incluye utilizar formatos de moneda y de fecha y hora correctos, calendario, direccin de escritura, reglas de ordenacin y otros aspectos. La acomodacin de estas diferencias culturales en una aplicacin se denomina localizacin. Afortunadamente, el marco de trabajo .NET facilita sustancialmente las tareas de localizacin haciendo que sus clases de formato, fecha/hora, ordenacin y otras tengan en cuenta la cultura. Usando clases del espacio de nombres System.Globalization puede establecer la cultura actual de su aplicacin y gran parte del trabajo se hace automticamente. En este captulo aprender cmo detectar la cultura de un usuario y crear respuestas adecuadas, desde la redireccin del usuario a una aplicacin Web diferente localizada a manejar las diferencias culturales dentro del cdigo y mostrar un interface de usuario localizado. Antes de completar este captulo debe estar familiarizado con HTML y con la creacin de formularios Web en modo HTML.

15.1 Seleccionar un mtodo


Antes de comenzar el proceso de localizacin necesita comprender las ventajas e inconvenientes de los diferentes mtodos para globalizar aplicaciones Web. En esta leccin aprender tres formas diferentes de estructurar su aplicacin para globalizacin. Estos mtodos estn organizados de ms sencillo a ms complejo. El ltimo de ellos se trata en ms detalle en la leccin 2.

15.1.1 Formas de globalizar aplicaciones Web


Hay varios mtodos para crear aplicaciones Web que soporten varias culturas. Cada mtodo se basa en las herramientas de globalizacin que proporciona el marco de trabajo .NET. Seleccione uno de ellos o una combinacin de varios segn las necesidades de su aplicacin, como describe la tabla 15.1
Tabla 15. 1: Mtodos de globalizacin
Mtodo Detectar y redirigir Ajuste en tiempo de ejecucin Ensamblados satlite Descripcin Mejor para Cree una aplicacin Web separada para cada cultura, detecte la Aplicaciones con mucho contenido de texto cultura del usuario y redirija la peticin a la aplicacin adecuada. que necesita traduccin y pocos componentes ejecutables. Cree una sola aplicacin Web que detecte la cultura del usuario y Aplicaciones sencillas con cantidad de ajuste su salida en tiempo de ejecucin usando especificadotes contenido limitada. de formato y otras herramientas. Cree una sola aplicacin Web que guarda cadenas dependientes Aplicaciones que generan contenido en de la cultura en archivos de recursos que se compilan en tiempo de ejecucin o tienen grandes ensamblados satlite. En tiempo de ejecucin detecte la cultura componentes ejecutables. del usuario y cargue las cadenas desde el ensamblado adecuado.

Los tres mtodos anteriores dependen de la deteccin de la cultura del usuario en tiempo de ejecucin y la formacin de una respuesta en base a esta informacin. Las siguientes secciones muestran con mayor detalle cmo detectar la cultura del usuario y responder usando cada uno de estos mtodos. Estas secciones tambin proporcionan mayor detalle sobre las ventajas relativas de cada mtodo.

15.1.2 Detectar la cultura del usuario


El marco de trabajo .NET proporciona componentes para soporte de varias culturas y lenguajes en el espacio de nombres System.Globalization. Las clases CultureInfo, Calendar y de comparacin que se usan a lo largo de este captulo son parte de este espacio de nombres. Importe o use el espacio de nombres para poder usar sus clases sin necesidad de calificar las referencias. ASP.NET usa la propiedad UserLanguages del objeto Request para devolver una lista de las preferencias de idioma del usuario. El primer elemento del array devuelto por esta propiedad es el lenguaje actual del usuario. Puede usar este valor para crear una instancia de la clase CultureInfo que represente la cultura actual del usuario. Para obtener la cultura del usuario en tiempo de ejecucin siga estos pasos. 1. Obtenga la propiedad UserLanguages del objeto Request. 2. Use el valor devuelto con la clase CultureInfo para crear un objeto que represente la cultura del usuario actual. Por ejemplo, el siguiente cdigo obtiene la cultura del usuario y muestra el nombre en ingls y el nombre abreviado en una etiqueta la primera vez que se muestra la pgina.

279

MCAD/MCSD

Visual Basic .NET


Private Sub Page_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) _ Handles MyBase.Load ' Se ejecuta la primera vez que se muestra la pgina. If Not IsPostBack Then Dim sLang As String ' Obtiene el lenguaje preferido del usuario. sLang = Request.UserLanguages(0) ' Crea un objeto CultureInfo con l. Dim CurrentCulture As New CultureInfo(sLang) lblCulture.Text = CurrentCulture.EnglishName & ": " & CurrentCulture.Name End If End Sub

Visual C#
private void Page_Load(object sender, System.EventArgs e){ // Se ejecuta la primera vez que se muestra la pgina if (!IsPostBack) { // Obtiene el lenguaje preferido del usuario. string sLang = Request.UserLanguages[0]; // Crea un objeto CultureInfo con l. CultureInfo CurrentCulture = new CultureInfo(sLang); lblCulture.Text = CurrentCulture.EnglishName + ": " + CurrentCulture.Name; } }

Consejo: La propiedad Name de la clase CultureInfo y los valores del array UserLanguages usan diferentes esquemas de capitalizacin. Si compara los dos valores asegrese de convertir la propiedad Name a minsculas.

15.1.3 Redirigir a una aplicacin especfica de cultura


Conceptualmente, la redireccin es la forma ms sencilla de tratar con mltiples culturas. Cuando un usuario solicita la pgina predeterminada de la aplicacin se detecta la cultura y se redirige la respuesta a la aplicacin Web correspondiente. Este mtodo tiene algunas ventajas adems de su simplicidad conceptual: El contenido se mantiene separado, de modo que permite que diferentes aplicaciones presenten informacin muy diferente, si es necesario. Se puede dirigir a los usuarios automticamente a sitios que probablemente estn geogrficamente cercanos, de forma que se puedan cubrir mejor sus necesidades. Los archivos de contenidos (formularios Web y pginas HTML, por ejemplo) se pueden crear adecuadamente en el lenguaje natural sin la complejidad de incluir cadenas de recursos. Mantener el contenido por separado se adapta mejor a aplicaciones Web que presentan grandes cantidades de contenido que se debe traducir o cambiar de alguna otra forma. El uso de este mtodo precisa que la parte ejecutable de la aplicacin Web se compile y distribuya por separado para cada sitio Web especfico de cultura. Esto exige ms esfuerzo para mantener la coherencia y depuracin de problemas entre sitos Web. Redireccin basada en el lenguaje principal Tanto el array UserLanguages del objeto Request como la propiedad Name de la clase CultureInfo devuelven informacin de cultura en dos partes: las dos primeras letras son cdigo de lenguaje; las dos ltimas contienen un cdigo de regin. Por ejemplo tanto ingls americano (en-US) como ingls britnico (en-GB) usan ingls, pero muestran signos de moneda y orden de fecha diferentes. Para redirigir peticiones segn el lenguaje solamente: 1. Obtenga el lenguaje preferido del usuario o su CurrentCulture como se mostr anteriormente. 2. Extraiga las dos primeras letras del valor devuelto. 3. Compare estas letras con la lista de cdigos de lenguaje. Por ejemplo, el siguiente cdigo detecta el lenguaje del usuario y lo redirige a uno de los diferentes sitios especficos de lenguaje:

280

Developing Web Applications

Visual Basic .NET


Private Sub Page_Load(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles MyBase.Load Dim sLang As String ' Obtiene el idioma preferido del usuario. sLang = Request.UserLanguages(0) ' Obtiene los dos primeros caracteres del lenguaje. sLang = sLang.Substring(0, 2) ' Redirige al usuario segn su cultura. Select Case sLang Case "en" ' Sitio USA Response.Redirect("http://www.contoso.com/usa") Case "es" ' Sitio espaol Response.Redirect("http://www.contoso.com/es") Case "de" ' Sitio alemn Response.Redirect("http://www.contoso.com/de") Case "zh" ' Sitio chino Response.Redirect("http://www.contoso.com/zh") Case Else ' Sitio USA Response.Redirect("http://www.contoso.com/usa") End Select End Sub

Visual C#
private void Page_Load(object sender, System.EventArgs e){ // Obtiene el idioma preferido del usuario. string sLang = Request.UserLanguages[0]; // Obtiene los dos primeros caracteres del lenguaje. sLang = sLang.Substring(0, 2); // Redirige al usuario segn su cultura. switch (sLang){ case "en": // Sitio USA Response.Redirect("http://www.contoso.com/usa"); break; case "es": // Sitio espaol Response.Redirect("http://www.contoso.com/es"); break; case "de": // Sitio alemn. Response.Redirect("http://www.contoso.com/de"); break; case "zh": // Sitio chino. Response.Redirect("http://www.contoso.com/zh"); break; default: // Sitio USA. Response.Redirect("http://www.contoso.com/usa"); break; } }

Vea en el tema Clase CultureInfo en la ayuda de Visual Studio .NET el listado de cdigos de lenguaje y cultura. Configurar la cultura en Web.config Utilice el elemento globalization del archivo Web.config para crear una aplicacin Web especfica de una cultura. El atributo cultura de este elemento determina cmo trata la aplicacin Web los diferentes temas dependientes de la cultura, como formato de fecha, moneda y nmero. Como una aplicacin Web solo puede tener un archivo Web.config al establecer el atributo cultura se hace la aplicacin especfica de cultura. Todas las peticiones y respuestas se manejarn usando la cultura especfica indicada. Por ejemplo, la siguiente entrada en Web.config hace que todas las peticiones y respuestas de la aplicacin se controlen utilizando rabe (Arabia Saudi).
<globalization requestEncoding="utf-8" responseEncoding="utf-8" culture="ar-SA"/>

En tiempo de ejecucin la aplicacin muestra los formatos de fecha, moneda y nmero segn indica el atributo culture del elemento globalization. Sin embargo, la pgina no se muestra en formato de derecha a izquierda como ser podra esperar para el rabe. Para mostrar la pgina correctamente debe establecer el atributo dir del elemento body de la pgina: <body dir="rtl">. Puede usar este atributo individualmente en paneles, cajas de texto u otros controles.

15.1.4 Ajustar a la cultura actual en tiempo de ejecucin


De forma predeterminada, las aplicaciones Web se ejecutan en el servidor usando una cultura neutral. Cultura neutral representa lenguajes generales, como ingls o espaol, en lugar de un lenguaje y regin especficos. Cuando se establece el atributo culture para una aplicacin Web en Web.config ASP.NET asigna esta cultura a 281

MCAD/MCSD

todas la hebras que se ejecuten para esta aplicacin Web. Las hebras son la unidad bsica a la que el servidor asigna tiempo de procesador ASP.NET mantiene varias hebras para una aplicacin Web dentro del proceso de trabajo aspnet_wp.exe. Al usar Web.config para configurar la cultura se crea una asociacin esttica entre la aplicacin y una cultura concreta. Como alternativa puede establecer la cultura dinmicamente en tiempo de ejecucin usando la propiedad CurrentCulture de la clase Thread: Visual Basic .NET
Imports System.Globalization Imports System.Threading Private Sub Page_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) _ Handles MyBase.Load Dim sLang As String ' Obtiene el lenguaje preferido del usuario. sLang = Request.UserLanguages(0) ' Configura la cultura de la hebra para que corresponda con la del usuario. Thread.CurrentThread.CurrentCulture = New CultureInfo(sLang) End Sub

Visual C#
using System.Globalization; using System.Threading; private void Page_Load(object sender, System.EventArgs e){ // Obtiene el idioma preferido del usuario. sLang = Request.UserLanguages[0]; // Configura la cultura de la hebra para que corresponda con la del usuario. Thread.CurrentThread.CurrentCulture = new CultureInfo(sLang); }

El cdigo anterior detecta la cultura del usuario y configura la de la hebra actual para que corresponda. ASP.NET a partir de ahora dar formato a fechas, moneda y nmeros usando la cultura del usuario. Todas las culturas comparten el mismo cdigo de aplicacin, de modo que no es necesario volver a compilar y distribuir para cada cultura. La aplicacin reside en una nica direccin Web no necesita redirigir a los usuarios a otras aplicaciones. El usuario puede elegir de entre una serie de culturas disponibles. La configuracin dinmica de la cultura se adapta mejor a aplicaciones Web sencillas que no contienen grandes cantidades de texto que se debe traducir a lenguajes diferentes. Para proporcionar grandes cantidades de texto traducido en una nica aplicacin Web use el mtodo descrito en la seccin Ensamblados satlite ms adelante. Establecer la cultura actual El siguiente cdigo muestra las ventajas principales de configurar la cultura dinmicamente a nivel de hebra. La primera vez que se carga la pgina el cdigo crea una lista de todas las culturas disponibles y la guarda en una lista desplegable. Cuando el usuario selecciona una cultura de la lista el cdigo la asigna a la hebra actual y ASP.NET muestra el formulario Web usando la cultura seleccionada: Visual Basic .NET
Imports System.Globalization Imports System.Threading Private Sub Page_Load(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles MyBase.Load ' Aade culturas a la lista la primera vez que se muestra la pgina. If Not IsPostBack Then ' Crea un array de culturas especficas. Dim arrCultures() As CultureInfo = _ CultureInfo.GetCultures(CultureTypes.SpecificCultures) Dim item As CultureInfo ' Para cada cultura especfica For Each item In arrCultures ' Aade el nombre de la cultura como elemento en la lista. drpCulture.Items.Add(New ListItem(item.EnglishName, item.Name)) ' Si el elemento es la cultura actual de la hebra lo selecciona. If item.Name = Thread.CurrentThread.CurrentCulture.Name Then drpCulture.SelectedIndex = drpCulture.Items.Count - 1 End If Next End If End Sub

282

Developing Web Applications

Private Sub drpCulture_SelectedIndexChanged(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles drpCulture.SelectedIndexChanged ' Cambia la cultura e la hebra actual segn la seleccin. Thread.CurrentThread.CurrentCulture = New _ CultureInfo(drpCulture.SelectedItem.Value) ' Obtiene la cultura del elemento seleccionado. Dim SelectedCulture As New CultureInfo(drpCulture.SelectedItem.Value) End Sub Private Sub Page_PreRender(ByVal sender As Object, _ ByVal e As System.EventArgs) Handles MyBase.PreRender ' Muestra el nombre nativo de la cultura en el encabezado. head1.InnerHtml = Thread.CurrentThread.CurrentCulture.NativeName ' Muestra fecha, moneda y nmeros con formato de la cultura. Label1.Text = DateTime.Now.ToString("F") Label2.Text = 1234567890.ToString("C") Label3.Text = 1234567890.ToString("N") End Sub

Visual C#
using System.Globalization; using System.Threading; private void Page_Load(object sender, System.EventArgs e){ // Aade culturas a la lista la primera vez que se muestra la pgina. if (!IsPostBack){ // Crea un array de culturas especficas. CultureInfo[] arrCultures = CultureInfo.GetCultures(CultureTypes.SpecificCultures); // Para cada cultura especfica foreach (CultureInfo item in arrCultures){ // Aade el nombre e la cultura como elemento de la lista. drpCulture.Items.Add(new ListItem(item.EnglishName, item.Name)); // Si el elemento es la cultura actual de la hebra lo selecciona. if (item.Name == Thread.CurrentThread.CurrentCulture.Name) drpCulture.SelectedIndex = drpCulture.Items.Count - 1; } } } private void drpCulture_SelectedIndexChanged(object sender, System.EventArgs e){ // Cambia la cultura de la hebra actual segn la seleccin. Thread.CurrentThread.CurrentCulture = new CultureInfo(drpCulture.SelectedItem.Value); // Obtiene la cultura del elemento seleccionado. CultureInfo SelectedCulture = new CultureInfo(drpCulture.SelectedItem.Value); } private void Page_PreRender(object sender, System.EventArgs e){ // Muestra el nombre nativo de la cultura en el encabezado. head1.InnerHtml = Thread.CurrentThread.CurrentCulture.NativeName; // Muestra fecha, moneda y nmero en formato de la cultura. Label1.Text = DateTime.Now.ToString("F"); Label2.Text = 1234567890.ToString("C"); Label3.Text = 1234567890.ToString("N"); }

El cdigo anterior establece el encabezado y el texto de etiqueta en el suceso PreRender de forma que el cambio de cultura tenga lugar antes de que se guarde el texto en estos controles. El mtodo ToString utiliza especificadores de formato para cada cadena segn la cultura actual. Para ms informacin sobre especificadores de formato vea la ayuda en lnea de Visual Studio. Cuando el usuario selecciona una nueva cultura en la lista desplegable el encabezado, calendario, fecha, moneda y nmero se traducen automticamente. Responder a la cultura de la hebra Tambin puede obtener la cultura bajo la que se est ejecutando una aplicacin Web usando la propiedad CurrentCulture de la hebra. Por ejemplo, el siguiente cdigo muestra en un formulario Web un panel usando el formato de derecha a izquierda si la cultura actual es rabe o hebrea.

283

MCAD/MCSD

Visual Basic .NET


Private Sub Page_Load(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles MyBase.Load ' Obtiene la cultura de la hebra actual. Dim CurrentCulture As CultureInfo = Thread.CurrentThread.CurrentCulture ' Obtiene el lenguaje primario. Dim sLang As String = CurrentCulture.Name.Substring(0, 2) ' Si es rabe o hebreo muestra de derecha a izquierda. If sLang = "ar" or sLang = "he" Then panel1.Attributes.Add("dir", "rtl") End If End Sub

Visual C#
private void Page_Load(object sender, System.EventArgs e){ // Obtiene la cultura de la hebra actual. CultureInfo CurrentCulture = Thread.CurrentThread.CurrentCulture; // Si es rabe o hebreo muestra de derecha a izquierda. string sLang = CurrentCulture.Name.Substring(0, 2); if ((sLang == "ar") (sLang == "he")) Panel1.Attributes.Add("dir", "rtl"); }

15.1.5 Ensamblados satlite


Las secciones anteriores han mostrad cmo manejar las diferencias culturales en una nica aplicacin Web, pero se ha omitido un detalle importante: cmo se maneja el contenido traducido?. Los ensamblados satlite permiten guardar las cadenas traducidas para cada cultura en un archivo de ensamblado separado solo de recursos que se puede cargar automticamente segn la configuracin de la propiedad CurrentUICulture. El uso de ensamblados satlite proporciona las mismas ventajas que ajustar la cultura en tiempo de ejecucin, adems de simplificar la presentacin de contenido de varios orgenes traducidos. La siguiente leccin describe cmo crear y usar ensamblados satlite.

15.2 Crear y usar ensamblados satlite


Los ensamblados satlite son archivos de ensamblado (.dll) que contienen recursos localizados para una aplicacin. Cada archivo ensamblado satlite contiene los recursos para una cultura. Una aplicacin puede tener varios ensamblados satlite dependiendo de cuntas culturas soporte la aplicacin. En esta leccin aprender cmo preparar una aplicacin Web para usar ensamblados satlite, cmo guardar elementos de interface localizados dentro de un ensamblado satlite y cmo cargar y mostrar elementos desde el ensamblado satlite en tiempo de ejecucin.

15.2.1 Cmo funcionan los ensamblados satlite


Los proyectos de aplicacin Web usan ensamblados satlite para guardar cadenas traducidas, grficos y otros aspectos dependientes de cultura del interface de usuario de una aplicacin. Para crear los propios ensamblados se usa el administrador de recursos. En tiempo de ejecucin la aplicacin Web carga las cadenas traducidas en el formulario Web en base a la propiedad CurrentUICulture de la hebra actual. Para usar ensamblados satlite: 1. Configure los atributos id y runat para todos los elementos de interface de usuario de su aplicacin que necesiten traduccin. Los controles de servidor tienen estos atributos de forma predeterminada, pero tendr que aadirlos a los elementos HTML si quiere cargar en ellos cadenas traducidas. 2. Cree un archivo de recursos predeterminado que contenga las cadenas predeterminadas para mostrar en el interface de usuario si la cultura del usuario no se especifica o reconoce. De a este archivo la extensin .resx, por ejemplo cadenas.resx 3. Cree archivos de recursos que contengan las cadenas traducidas que se mostrarn para cada lenguaje general que soporta su aplicacin Web. Coloque el cdigo de lenguaje entre el nombre de archivo y la extensin, por ejemplo: cadenas.es.resx. 4. Opcionalmente, cree archivos de recursos que contengan las cadenas traducidas para cada cultura especfica que soporte su aplicacin Web. Aada el cdigo de regin a continuacin del cdigo de lenguaje, separado por un guin, por ejemplo: cadenas.es-MX.resx 5. Escriba cdigo para cargar los recursos para el formulario Web usando la clase ResourceManager. 6. Escriba cdigo para detectar la cultura del usuario y configure de forma correspondiente las propiedades CurrentCulture y CurrentUICulture de la clase Thread. La propiedad CurrentCulture determina cmo da formato ASP.NET a las fechas, moneda y nmeros; la propiedad CurrentUICulture determina qu ensamblado satlite se usa cuando se cargan cadenas traducidas. 284

Developing Web Applications

7. Escriba cdigo para obtener las cadenas de los archivos de recursos y mustrelos en elementos del formulario Web. Las siguientes secciones describen estos pasos en mayor detalle.

15.2.2 Preparar los elementos HTML para recursos


Los recursos de ensamblados satlite se cargan en los elementos de formulario web en el servidor. Por tanto, debe asegurarse de que todos los elementos de su formulario Web tienen atributos id y runat que los hacen disponibles para el cdigo de servidor. De forma predeterminada, los controles ASP.NET tienen estos atributos, pero los elementos HTML no. Por ejemplo, el siguiente HTML muestra un formulario Web sencillo con encabezado, texto y algunos controles. Para que los elementos del formulario puedan usar recursos hay que aadir las partes en negrita:
<%@ Page Language="vb" AutoEventWireup="false" Codebehind="WebForm1.aspx.vb" Inherits="vbSatelliteSnippet.WebForm1"%> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> <HTML> <HEAD><title>WebForm1</title></HEAD> <body> <form id="Form1" method="post" runat="server"> <h1 id="head1" runat="server">Encabezado de ejemplo</h1> <p id="p1" runat="server">Texto de introduccin.</p> <span id="sp1" runat="server">Escriba un nmero: </span> <asp:TextBox ID="txtCurrency" Runat="server" /><br> <span id="sp2" runat="server">Cantidad en moneda local: </span> <asp:Label ID="lblCurrency" Runat="server" /><br><br> <asp:Button ID="butOK" Text="OK" Runat="server" /> <input id="butCancel" runat="server" type="button" onclick="txtCurrencty.value=''" value="Cancelar"> </form> </body> </HTML>

Los atributos id y runat hacen que Visual Studio .NET maneje estos elementos como controles de servidor. Cuando se cambia de la vista HTML a la vista diseo Visual Studio aade las siguientes declaraciones en el archivo de cdigo del formulario: Visual Basic .NET
Protected Protected Protected Protected Protected WithEvents WithEvents WithEvents WithEvents WithEvents head1 As System.Web.UI.HtmlControls.HtmlGenericControl p1 As System.Web.UI.HtmlControls.HtmlGenericControl sp1 As System.Web.UI.HtmlControls.HtmlGenericControl sp2 As System.Web.UI.HtmlControls.HtmlGenericControl butCancel As System.Web.UI.HtmlControls.HtmlInputButton

Visual C#
protected protected protected protected protected System.Web.UI.HtmlControls.HtmlGenericControl head1; System.Web.UI.HtmlControls.HtmlGenericControl p1; System.Web.UI.HtmlControls.HtmlGenericControl sp1; System.Web.UI.HtmlControls.HtmlGenericControl sp2; System.Web.UI.HtmlControls.HtmlInputButton butCancel;

Estas declaraciones permiten establecer el valor de los atributos y de innerHTML para estos elementos en tiempo de ejecucin.

15.2.3 Crear archivos de recursos


Al utilizar ensamblados satlite para proporcionar cadenas traducidas dentro de una aplicacin Web puede crear tres tipos de archivos de recurso.
Tabla 15. 2: Tipos de archivo de recursos para ensamblados satlite
Tipo Predeterminado (Fallback) Especfico de lenguaje Especfico de cultura Extensin .resx Se compila en Ensamblado ejecutable Proporciona Cadenas de interface de usuario cuando no se especifica cultura o la aplicacin Web no la reconoce. recursos en un subdirectorio de bin Cadenas traducidas para un idioma el cdigo de idioma concreto. recursos en un subdirectorio de bin Cadenas traducidas para un dialecto el cdigo de idioma y de regin. concreto de un idioma.

.codIdioma.resx Ensamblado de identificado por .codIdiomaEnsamblado de codRegion.resx identificado por

El cdigo de cultura utilizado para identificar los archivos de recursos especficos de lenguaje y cultura se pueden ver en el tema de ayuda de la clase CultureInfo Estos cdigos tambin se usan en la propiedad Name de la clase CultureInfo y el array UserLanguages del objeto Request. 285

MCAD/MCSD

Para agregar archivos de recursos a un proyecto de aplicacin Web en Visual Studio .NET siga estos pasos. 1. En el men Proyecto seleccione Agregar nuevo elemento y en la lista de plantillas seleccione Archivo de recursos de ensamblado. 2. Escriba el nombre del archivo que quiere crear y pulse Abrir. Visual Studio crea un nuevo archivo de recursos y lo agrega al proyecto Para introducir en un archivo de recursos cadenas traducidas para el interface del formulario Web: 1. Escriba un identificador de elemento Web en el campo Name del archivo de recursos. El identificador debe ser nico dentro del alcance de la aplicacin, de modo que un convenio del tipo nombreformulario.nombreelemento funcionar bien. 2. Escriba la cadena traducida para el elemento en el campo Value del archivo de recursos. Consejo: El campo nombre dentro de un archivo de recursos diferencia maysculas y minsculas de forma predeterminada. Para evitar errores al localizar recursos en tiempo de ejecucin use un esquema de capitalizacin coherente. Por ejemplo, en esta leccin todos los nombres de recursos estn en minsculas.

15.2.4 Cargar archivos de recursos


El marco de trabajo .NET proporciona la administracin de recursos como parte del espacio de nombres System.Resources. Para usar las clases de este espacio de nombres sin necesidad de cualificar su nombre completamente use una sentencia Imports / using al comienzo del formulario Web. Para cargar recursos en un formulario Web cree una instancia de la clase ResourceManager. Por ejemplo, la siguiente lnea carga el archivo de recursos para la aplicacin Web. Visual Basic .NET
Protected gStrings As New ResourceManager("vbSatelliteSnippet.strings", _ GetType(WebForm1).Assembly)

Visual C#
protected ResourceManager gStrings = new ResourceManager("csSatelliteSnippet.strings", typeof(WebForm1).Assembly);

El ejemplo anterior carga los recursos guardados en el archivo de ensamblado Strings asociado con el ensamblado padre de Webform1 y guarda el objeto que devuelve en la variable gStrings. Los argumentos para el constructor de la clase ResourceManager se describen en la tabla 15.3.
Tabla 15. 3: Argumentos de ResourceManager
Argumento Descripcin Espacio de nombres del recurso dentro del proyecto. Para proyectos Visual Basic .NET es nombreproyecto. nombrebaserecurso Para proyectos C# es espacionombresraiz.nombrebaserecurso. La parte nombrebaserecurso

baseName assembly

omite los cdigos de cultura. Objeto que representa el ensamblado ejecutable actual. Use la propiedad Assembly de la clase Type para obtener el valor que se le pasa a este argumento.

15.2.5 Leer y configurar la cultura del interface de usuario


Como se mostr en la leccin anterior puede obtener la cultura del usuario del array UserLanguages del objeto Request, y se configura la cultura actual de la hebra asignando a la propiedad CurrentCulture de la clase Thread. Cuando trabaja con ensamblados satlite necesita dar un paso ms: configurar la propiedad CurrentUICulture. Esta propiedad determina qu ensamblado satlite se ursa cuando se cargan cadenas desde el objeto ResourceManager. Para configurar la cultura actual del interface de usuario para una hebra asigne un valor a la propiedad CurrentUICulture. Por ejemplo, el siguiente cdigo obtiene el lenguaje preferido del usuario y establece tanto la cultura como la cultura de interface de usuario de la hebra actual. Visual Basic .NET
Private Sub Page_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) _ Handles MyBase.Load If Not IsPostBack Then ' Obtiene el lenguaje preferido del usuario. Dim sLang As String = Request.UserLanguages(0) ' Establece la cultura de la hebra para formato, comparacione, etc. Thread.CurrentThread.CurrentCulture = _ CultureInfo.CreateSpecificCulture(slang) ' Establece la cultura del interface para carga de recursos ' desde el ensamblado satlite Thread.CurrentThread.CurrentUICulture = New CultureInfo(slang) End If End Sub

286

Developing Web Applications

Visual C#
private void Page_Load(object sender, System.EventArgs e){ if (!IsPostBack){ // Obtiene el lenguaje preferido del usuario. string sLang = Request.UserLanguages[0]; // Establece la cultura de la hebra para formato, comparaciones etc. Thread.CurrentThread.CurrentCulture = CultureInfo.CreateSpecificCulture(sLang); // Establece la cultura del interface para carga de recursos // desde el ensamblado satlite. Thread.CurrentThread.CurrentUICulture = new CultureInfo(sLang); } }

En el cdigo anterior, las propiedades CurrentCulture y CurrentUICulture se configuran de forma diferente. CurrentCulture utiliza el mtodo CreateSpecificCulture para asegurar que el objeto devuelto no es una cultura neutral. Las culturas neutrales representan lenguajes genricos en lugar de un lenguaje y regin concretos. La propiedad CurrentCulture no se puede establecer con una cultura neutral porque usa informacin de regin para dar formato a moneda, entre otras cosas. Cuando se ha configurado CurrentUICulture para la hebra, ASP.NET automticamente seleccionar los recursos que corresponden en el orden siguiente: 1. Si se encuentra un ensamblado satlite que corresponde exactamente a la cultura se usan los recursos de este ensamblado. 2. Si se encuentra un ensamblado satlite con una cultura neutral que corresponde al CurrentUICulture actual se usan los recursos de este ensamblado. 3. Si no se encuentra una correspondencia para el CurrentUICulture se usan los recursos del ensamblado predeterminado ejecutable.

15.2.6 Mostrar cadenas de recurso


Despus de completar las tareas anteriores, mostrar cadenas desde un archivo de recurso en un formulario web es sencillo. Utilice el mtodo GetStrings del objeto ResourceManager para recuperar cadenas y asignarlas a las propiedades Text, value o innerHTML de los elementos del formulario Web. El siguiente cdigo rene los pasos anteriores para cargar una archivo de recursos, obtener la cultura del usuario, configurar la cultura de la hebra y mostrar cadenas del archivo de recursos en los controles de servidor y elementos HTML del formulario Web: Visual Basic .NET
Imports System.Resources Imports System.Globalization Imports System.Threading ' Carga recursos. Protected gStrings As New ResourceManager("vbSatelliteSnippet.strings", _ GetType(WebForm1).Assembly) Private Sub Page_Load(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles MyBase.Load If Not IsPostBack Then ' Obtiene el idioma preferido del usuario. Dim sLang As String = Request.UserLanguages(0) ' Establece la cultura de la hebra para formato, comparaciones, etc. Thread.CurrentThread.CurrentCulture = _ CultureInfo.CreateSpecificCulture(sLang) ' Establece la cultura del interface para cargar recursos del satlite. Thread.CurrentThread.CurrentUICulture = New CultureInfo(sLang) ' Obtiene las cadenas del archivo de recurso. head1.InnerHtml = gStrings.GetString("webform1.head1") p1.InnerHtml = gStrings.GetString("webform1.p1") sp1.InnerHtml = gStrings.GetString("webform1.sp1") sp2.InnerHtml = gStrings.GetString("webform1.sp2") butOK.Text = gStrings.GetString("webform1.butOK") butCancel.Value = gStrings.GetString("webform1.butCancel") End If End Sub

Visual C#
using System.Globalization; using System.Threading; using System.Resources;

287

MCAD/MCSD

private void Page_Load(object sender, System.EventArgs e){ if (!IsPostBack) { // Obtiene el idioma preferido del usuario. string sLang = Request.UserLanguages[0]; // Establece la cultura de la hebra para formato, comparaciones, etc. Thread.CurrentThread.CurrentCulture = _ CultureInfo.CreateSpecificCulture(sLang); // Establece la cultura de interface para cargar recursos del satlite. Thread.CurrentThread.CurrentUICulture = new CultureInfo(sLang); // Obtiene las cadenas del archivo de recursos. head1.InnerHtml = gStrings.GetString("webform1.head1"); p1.InnerHtml = gStrings.GetString("webform1.p1"); sp1.InnerHtml = gStrings.GetString("webform1.sp1"); sp2.InnerHtml = gStrings.GetString("webform1.sp2"); butOK.Text = gStrings.GetString("webform1.butOK"); butCancel.Value = gStrings.GetString("webform1.butCancel"); } }

En tiempo de ejecucin el cdigo anterior muestra las cadenas traducidas desde los archivos de recursos, en base al idioma preferido del usuario.

15.3 Temas de globalizacin


El marco de trabajo .NET maneja automticamente muchos aspectos de la globalizacin, en base a la configuracin de la propiedad CurrentCulture. Sin embargo, la globalizacin tambin afecta a algunas tcnicas de programacin bsicas. En este captulo aprender algunos aspectos de programacin generales en los que necesita pensar cuando desarrolle aplicaciones globales. Tambin aprender aspectos que surgen cuando se guardan y muestran los conjuntos de caracteres extendidos usados por algunos lenguajes.

15.3.1 Temas de programacin general


El tema Prcticas recomendadas para desarrollar aplicaciones de uso internacional de la ayuda de Visual Studio proporciona una lista de tema que se deben considerar cuando se desarrollan aplicaciones que se van a traducir a varios lenguajes. Las siguientes secciones detallan puntos de este tema que son relevantes para aplicaciones Web. Ordenar y comparar cadenas La ordenacin y la comparacin de cadenas que se realiza usando las clases del marco de trabajo .NET se ejecuta correctamente en base a la cultura actual. En realidad solo necesita preocuparse de los aspectos de globalizacin cuando implemente sus propias tcnicas para estas tareas, por ejemplo sus propios procedimientos de ordenacin. En estos casos utilice la clase CompareInfo del espacio de nombres System.Globalization para realizar comparacin de cadenas teniendo en cuenta la cultura. Controles de validacin personalizada Los controles de servidor de ASP.NET adquieren propiedades especficas en base a la cultura actual. Esto incluye a los controles de validacin. Sin embargo, deber tener en cuenta los temas de globalizacin cuando cree controles de validacin personalizada. Por ejemplo, si escribe un procedimiento de validacin personalizada que comprueba que la entrada es numrica no confe en el valor numrico de los caracteres de entrada. Use en cambio una prueba que tenga en cuenta la cultura, como usar la clase Convert dentro de una estructura de control de excepciones para comprobar si el valor es numrico. Crear cadenas Como algunos lenguajes leen de derecha a izquierda, y como algunas palabras cambian su significado cuando estn prximas a otras, es difcil crear cadenas usando la concatenacin de una forma que sirva para todas las culturas. En cambio, guarde las cadenas completas en un archivo de recursos y recupere las cadenas tal como sea necesario usando el administrador de recursos. Obtener subcadenas En algunos lenguajes los smbolos de carcter (llamados glifos) se componen de dos caracteres. En estos casos es posible que necesite ajustar cmo obtiene las subcadenas. Por ejemplo, obtener el primer carcter de una respuesta de usuario puede no ser significativa en algunos casos.

15.3.2 Codificacin de caracteres


Los caracteres dentro de cadenas se pueden representar de muchas formas diferentes en un ordenador. Estas formas diferentes de representar caracteres se llama codificacin de caracteres porque codifica los caracteres en nmeros que el ordenador puede comprender. 288

Developing Web Applications

El entorno de ejecucin comn usa la codificacin de caracteres UTF-16, que hace corresponder los caracteres con nmeros de 16 bit. 16 bit proporcionan espacio suficiente para acomodar los caracteres de casi todos los lenguajes escritos. Desafortunadamente es casi el doble de tamao de lo que utilizan otros esquemas de codificacin, lo que hace que sea menos que ptimo para transmitir caracteres por Internet. Por tanto, ASP.NET utiliza codificacin de caracteres UTF-8 de forma predeterminada cuando interpreta peticiones y compone respuestas. UTF-8 est optimizado para los 127 caracteres ASCII inferiores, lo que significa que proporciona una forma eficaz de codificar lenguajes que usan el alfabeto latino. Tambin proporciona compatibilidad con la codificacin de caracteres ASCII, lo que significa que los lectores UTF-8 pueden interpretar archivos ASCII. El entorno de ejecucin comn maneja la conversin entre codificaciones usando clases del espacio de nombres System.Text. Normalmente no necesitar preocuparse de que esto, salvo: Si va a grabar un formulario Web o archivo HTML que incluye caracteres extendidos de la codificacin UTF-8 Si necesita dar soporte a codificaciones concretas diferentes a UTF-8 Guardar archivos codificados Cuando se crea un formulario Web que contiene caracteres diferentes a los 127 primeros caracteres ASCII Visual Studio pregunta si se quiere guardar utilizando codificacin. Para guardar un archivo con codificacin: 1. En el men Archivo seleccione Guardar como, pulse la flecha del botn Guardar y seleccione Guardar con codificar. Visual Studio muestra las Opciones avanzadas para guardar. 2. Seleccione la codificacin y pulse Aceptar Al guardar el archivo utilizando codificacin UTF-8 con firma ASP.NET puede detectar automticamente la codificacin del archivo. Si no elige incluir la firma, o si usa otra codificacin, debe especificar el atributo fileEncoding en el archivo Web.config:
<globalization requestEncoding="utf-8" responseEncoding="utf-8" fileEncoding="utf-8" />

Usar otras codificaciones De forma predeterminada las aplicaciones Web interpretan peticiones y componen respuestas usando la codificacin de caracteres UTF-8. Estas opciones predeterminadas se configuran en el elemento globalization del archivo Web.config, como se mostr en la seccin anterior. Si una aplicacin Web recibe una peticin para una codificacin diferente a UTF-8 ASP.NET interpreta la peticin usando la codificacin de la misma. Sin embargo, ASP.NET no genera automticamente la respuesta en esta codificacin. Para detectar cundo una peticin tiene una codificacin especfica lea la propiedad ContentEncoding del objeto Request. Por ejemplo, la siguiente lnea muestra la codificacin de una peticin en un formulario Web: Visual Basic .NET
Response.Write(Request.ContentEncoding.WebName)

Visual C#
Response.Write(Request.ContentEncoding.WebName);

Para especificar una codificacin de caracteres para una respuesta configure la propiedad ContentEncoding del objeto Response usando la clase Encoding del espacio de nombres System.Text, o use el valor devuelto por la propiedad ContentEncoding del objeto Request. Por ejemplo, el siguiente cdigo crea una respuesta usando la codificacin de caracteres shift_JIS: Visual Basic .NET
Imports System.Text Private Sub Page_Load(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles MyBase.Load Response.ContentEncoding = Encoding.GetEncoding("shift_JIS") Response.Write("Esta respuesta usa la codificacin de caracteres: ") Response.Write(Response.ContentEncoding.WebName) End Sub

289

MCAD/MCSD

Visual C#
using System.Text; private void Page_Load(object sender, System.EventArgs e){ Response.ContentEncoding = Encoding.GetEncoding("shift_JIS"); Response.Write("Esta respuesta usa la codificacin de caracteres: "); Response.Write(Response.ContentEncoding.WebName); }

Mas Informacin: Para ms informacin sobre codificacin de caracteres vea los siguientes temas de la ayuda en lnea. Unicode en .NET Framework Codificar tipos base Espacio de nombres System.Text Tambin puede encontrar informacin en los sitios Web: http://www.unicode.org http://www.w3.org/TR/REC-html40/charset.html

15.4 Resumen
Use el array UserLanguages del objeto Request para detectar la cultura del usuario. Configure los atributos culture y uiCulture del elemento globalization en Web.config para crear aplicaciones Web especficas de una cultura. El marco de trabajo .NET identifica las culturas usando los cdigos de lenguaje y de regin que se listan en el tema de ayuda en lnea de la clase CultureInfo. Configure la cultura que utiliza la aplicacin para dar formato a fechas, monedas, nmeros y determinar el la correlacin al ordenar usando la propiedad CurrentCulture de la clase Thread. Utilice la propiedad CurrentUICulture de la clase Thread para determinar qu ensamblado satlite se usar para cargar los recursos localizados. Aada los atributos id y runat a los elementos HTML para poder mostrar cadenas localizadas desde archivos de recursos en estos elementos en tiempo de ejecucin. Los elementos de un archivo de recursos diferencian maysculas y minsculas y deben tener un nombre nico en el alcance de la aplicacin, por lo que se debe usar un convenio de la forma nombreformulario.identificador. Cuando cree formularios Web que usan caracteres no ASCII gurdelos usando la codificacin UTF-8 con firma. Al incluir la firma ASP.NET puede detectar automticamente la codificacin del archivo.

15.5 Prctica: Conversor de moneda


En esta prctica va a crear una sencilla aplicacin de conversin de moneda que usa la cultura del usuario para determinar el tipo de conversin: Una cultura no reconocida convierte de euros a dlares y pesos y muestra el texto en ingls como interface predeterminado. Una cultura ingls de Estados Unidos convierte dlares a euros y pesos y muestra un interface en ingls Una cultura espaol de Mjico convierte pesos a dlares y euros y muestra un interface en espaol

15.5.1 Ejercicio 1: Crear el formulario Web del conversor de moneda


La aplicacin Web conversor de moneda contiene un nico formularios Web que recibe la entrada de una caja de texto y muestra la salida en dos etiquetas cuando el usuario pulsa Aceptar. El formulario Web tambin incluye un botn HTML Cancelar que vaca la caja de texto. Como la aplicacin va a estar localizada los elementos HTML del formulario Web deben tener atributos id y runat de forma que las cadenas de recurso localizadas se puedan cargar en estos controles en el cdigo del servidor. 1. Cree un nuevo proyecto de aplicacin Web llamado CurrencyConverter. 2. Cambie a la vista HTML y escriba el siguiente cdigo entre las etiquetas <form> y </form>:
<h1 id="head1" runat="server">Head1</h1> <span id="sp1" runat="server">Enter an amount: </span> <asp:TextBox ID="txtCurrency" Runat="server" /><br> <span id="sp2" runat="server">Amount in: </span> <asp:Label ID="lblCurrency1" Runat="server" /><br> <span id="sp3" runat="server">Amount in: </span> <asp:Label ID="lblCurrency2" Runat="server" /><br><br> <asp:Button ID="butOK" Text="OK" Runat="server" /> <input id="butCancel" runat="server" type="button" onclick="txtCurrency.Text=''" value="Cancel">

290

Developing Web Applications

3. Cuando termine, cambie de nuevo al modo diseo. Este paso es importante porque genera las declaraciones de control correctas en el archivo de cdigo.

15.5.2 Ejercicio 2: Crear los archivos de recurso del interface de usuario


El formulario Web creado en el paso anterior contiene solo entrada falsas para el texto que se mostrar realmente en el interface de usuario. Por ejemplo, el encabezado de la pgina es Head1. En este ejercicio va a crear las cadenas que se muestran en lugar de estas entradas falsas en tiempo de ejecucin. 1. En el men Proyecto seleccione Agregar nuevo elemento y en la lista de plantillas elija Archivo de recursos de ensamblado. 2. Aada las entradas de la siguiente tabla al archivo de recursos para crear los valores para el interface predeterminado:
name value

webform1.head1 Welcome webform1.sp1 Enter an amount in euros: webform1.sp2 Amount in <b>dollars</b>: webform1.sp3 Amount in <b>pesos</b>: webform1.butOK OK webform1.butCancel Cancel Deje las tres ltimas columnas con su valor predeterminado (null). 3. Cree un nuevo archivo de recursos llamado strings.en-US.resx con las entradas de la tabla siguiente para crear el interface para usuario de cultura ingls de Estados Unidos:
name value

webform1.head1 Welcome webform1.sp1 Enter an amount in dollars: webform1.sp2 Amount in <b>euros</b>: webform1.sp3 Amount in <b>pesos</b>: webform1.butOK OK webform1.butCancel Cancel 4. Cree otro nuevo archivo de recursos llamado strings.es-MX.resx con las entradas de la tabla siguiente para crear el interface para usuario de cultura espaol de Mjico:
name value

webform1.head1 Bienvenido webform1.sp1 Escriba una cantidad en pesos: webform1.sp2 Cantidad en <b>euros</b>: webform1.sp3 Cantidad en <b>dlares</b>: webform1.butOK Aceptar webform1.butCancel Cancelar 5. Cuando termine pulse Guardar todo para grabar su trabajo. Puede crear archivos de recursos adicionales para otras culturas si quiere. Incluya el cdigo de cultura en el nombre del archivo, como se ha mostrado en los pasos anteriores. Visual Studio .NET compilar automticamente los recursos como ensamblados satlite y los guardar en el sub directorio adecuado cuando se genere la aplicacin.

15.5.3 Ejercicio 3: Cargar recursos segn la cultura


En este ejercicio va a detectar la cultura del usuario, cargar los recursos y mostrarlos segn la cultura del usuario. 1. Aada las sentencias Imports o using para poder utilizar los espacios de nombres System.Resources, System.Globalization y System.Threading. 2. Aada el siguiente cdigo a nivel de clase del formulario Web para cargar los recursos en el objeto ResourceManager: Visual Basic .NET
Protected gStrings As New ResourceManager("CurrencyConverter.strings", _ GetType(WebForm1).Assembly)

Visual C#
protected ResourceManager gStrings = new ResourceManager("CurrencyConverter.strings", typeof(WebForm1).Assembly);

3. Aada el siguiente cdigo al procedimiento de suceso Page_Load para detectar la cultura del usuario, configurar la cultura de interface de usuario de la hebra y mostrar las cadenas de recurso locales en el interface de usuario:

291

MCAD/MCSD

Visual Basic .NET


Private Sub Page_Load(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles MyBase.Load If Not IsPostBack Then ' Obtiene el idioma preferido del usuario. Dim sLang As String = Request.UserLanguages(0) ' Configura el UICulture de la hebra para cargar recursos. Thread.CurrentThread.CurrentUICulture = New CultureInfo(sLang) ' Configura la cultura de la hebra para formato de fecha/cadena/moneda Thread.CurrentThread.CurrentCulture = _ CultureInfoCreateSpecificCulture(sLang) ' Obtiene las cadenas del archivo de recursos. head1.InnerHtml = gStrings.GetString("webform1.head1") sp1.InnerHtml = gStrings.GetString("webform1.sp1") sp2.InnerHtml = gStrings.GetString("webform1.sp2") sp3.InnerHtml = gStrings.GetString("webform1.sp3") butOK.Text = gStrings.GetString("webform1.butOK") butCancel.Value = gStrings.GetString("webform1.butCancel") End If End Sub

Visual C#
private void Page_Load(object sender, System.EventArgs e){ if (!IsPostBack){ // Obtiene el idioma preferido del usuario. string sLang = Request.UserLanguages[0]; // Configura el UICulture de la hebra para cargar recursos. Thread.CurrentThread.CurrentUICulture = new CultureInfo(sLang); // Configurar la cultura para formato de fecha/cadena/moneda. Thread.CurrentThread.CurrentCulture = CultureInfo.CreateSpecificCulture(sLang); // Obtiene las cadenas del archivo de recursos. head1.InnerHtml = gStrings.GetString("webform1.head1"); sp1.InnerHtml = gStrings.GetString("webform1.sp1"); sp2.InnerHtml = gStrings.GetString("webform1.sp2"); sp3.InnerHtml = gStrings.GetString("webform1.sp3"); butOK.Text = gStrings.GetString("webform1.butOK"); butCancel.Value = gStrings.GetString("webform1.butCancel"); } }

Solo tiene que cargar las cadenas de recuso localizadas la primera vez que se muestra la pgina, como muestra el cdigo anterior. ASP.NET retiene el valor de los controles entre presentaciones de pgina automticamente.

15.5.4 Ejercicio 4: Conversin dependiente de cultura


Igual que muestra un interface diferente para cada cultura, el conversor de moneda tambin realiza conversiones diferentes segn la cultura actual. En este ejercicio va a escribir el cdigo que realiza esta tarea. Aada el siguiente cdigo en el procedimiento de suceso butOK_Click para detectar la cultura actual y realizar diferentes conversiones en base a esta informacin: Visual Basic .NET
Private Sub butOK_Click(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles butOK.Click ' Obtiene la cantidad. Dim SrcAmount As Double = Convert.ToDouble(txtCurrency.Text) Dim DestAmount As Double ' Variables de cultura para formato de moneda. Dim Europe As New CultureInfo("fr-FR") Dim USA As New CultureInfo("en-US") Dim Mexico As New CultureInfo("es-MX") ' Conversiones segn la cultura el interface de usuario. Select Case Thread.CurrentThread.CurrentCulture.Name Case "en-US" 'Convierte desde dlares DestAmount = SrcAmount * 1.1329 lblCurrency1.Text = DestAmount.ToString("C", Europe) DestAmount = SrcAmount * 9.0655 lblCurrency2.Text = DestAmount.ToString("C", Mexico)

292

Developing Web Applications

Case "es-MX" ' Convierte desde pesos DestAmount = SrcAmount * 0.125 lblCurrency1.Text = DestAmount.ToString("C", DestAmount = SrcAmount * 0.1103 lblCurrency2.Text = DestAmount.ToString("C", Case Else ' Convierte desde euros DestAmount = SrcAmount * 8.0021 lblCurrency1.Text = DestAmount.ToString("C", DestAmount = SrcAmount * 0.1103 lblCurrency2.Text = DestAmount.ToString("C", End Select End Sub

Europe) USA) USA) Mexico)

Visual C#
private void butOK_Click(object sender, System.EventArgs e){ // Obtiene la cantidad. double SrcAmount = Convert.ToDouble(txtCurrency.Text); double DestAmount; // Variables de cultura para formato de moneda. CultureInfo Europe = new CultureInfo("fr-FR"); CultureInfo USA = new CultureInfo("en-US"); CultureInfo Mexico = new CultureInfo("es-MX"); // Conversiones en base a la cultura del interface de usuario, switch (Thread.CurrentThread.CurrentCulture.Name) { case "en-US": //Convierte desde dlares DestAmount = SrcAmount * 1.1329; lblCurrency1.Text = DestAmount.ToString("C", Europe); DestAmount = SrcAmount * 9.0655; lblCurrency2.Text = DestAmount.ToString("C", Mexico); break; case "es-MX": //Convierte desde pesos DestAmount = SrcAmount * 0.125; lblCurrency1.Text = DestAmount.ToString("C", Europe); DestAmount = SrcAmount * 0.1103; lblCurrency2.Text = DestAmount.ToString("C", USA); break; default: //Convierte desde euros DestAmount = SrcAmount * 8.0021; lblCurrency1.Text = DestAmount.ToString("C", USA); DestAmount = SrcAmount * 0.1103; lblCurrency2.Text = DestAmount.ToString("C", Mexico); break; } }

El cdigo anterior crea objetos CultureInfo (Europe, USA y Mexico) para cada conversin cultural. Estos objetos proporcionan el formato de moneda adecuado en los mtodos ToString. El objeto Europe usa el cdigo de cultura para Francia porque este pas usa el euro como moneda. No hay un cdigo de cultura para la Unin Europea. En el ejemplo se incluyen en el cdigo las tasas de cambio. En una situacin real no se hara as; esta es una tarea adecuada para un servicio Web. Vea el Captulo 7, Programacin avanzada de formularios Web.

15.6 Repaso
Las siguientes preguntas estn pensadas para reforzar informacin clave mostrada en este captulo. Si no es capaz de contestar a una pregunta repase la leccin correspondiente e intente de nuevo. Las respuestas se pueden encontrar en el captulo 16. 1. Cul es la diferencia entre la propiedad CurrentCulture y la propiedad CurrentUICulture? 2. Cmo se detecta la cultura del usuario? 3. Qu es una cultura neutral? 4. Cmo afecta la codificacin de caracteres a los formatos de archivo?

293

MCAD/MCSD

294

Developing Web Applications

16 Preguntas y respuestas
Captulo 1: Introduccin a la Programacin Web 1. De tres ejemplos de en que se diferencia una aplicacin Web de una aplicacin Windows tradicional. Las aplicaciones Web y las aplicaciones Windows tradicionales tienen las siguientes diferencias:
Caracterstica Arquitectura Ejecucin Interface de usuario Aplicacin Web ASP.NET Cliente/Servidor Se ejecuta bajo el motor de ejecucin comn de lenguajes usando cdigo administrado El interface de usuario se muestra en un navegador Windows usando formularios Web Aplicacin Windows no administrada Usuario local Corre bajo Windows usando cdigo no administrado El interface de usuario lo muestra la aplicacin usando el API Win32

2.

Cules son las dos partes del marco de trabajo .NET? El motor de ejecucin de lenguaje comn La librera de clases del marco de trabajo .NET

3.

Cmo se restablecen las opciones de ventana predeterminadas en Visual Studio .NET? En el men Herramientas seleccione Opciones y pulse Restablecer Diseo de Ventanas

4.

Por qu no completa automticamente el editor de cdigo la siguiente lnea de cdigo parcial (slo usuarios de Visual C#)?
int intX = system.math

En Visual C# el espacio de nombres System.Math debe llevar maysculas para que IntelliSense lo reconozca 5. Cundo no puede usar ASP.NET para crear una aplicacin? Cuando est desarrollando para servidores Web que no sean de Microsoft, como Linux/Apache Captulo 2: Crear Aplicaciones Web 1. Explique donde guarda Visual Studio .NET los proyectos de aplicacin Web. Los proyectos de aplicacin Web se guardan en un nuevo directorio virtual para cada proyecto. Las propiedades de este directorio virtual determinan donde se almacenan los archivos fsicamente. Estas propiedades se pueden ver en IIS 2. Indique las cuatro diferencias principales entre aplicaciones Web y Windows. Los formularios Web no pueden usar controles Windows estndar. En su lugar usan controles de servidor, controles HTML, controles de usuario o controles creados especficamente. Las aplicaciones Web se muestran en un navegador. Las aplicaciones Windows muestran sus propias ventanas y tienen ms control sobre cmo se presentan estas ventanas. Los formularios Windows se instancian en el servidor, se envan al navegador y se destruyen inmediatamente. Los formularios Windows se instancian, existen todo el tiempo que son necesarios y se destruyen. Las aplicaciones web corren en un servidor y se muestran de forma remota en los clientes. Las aplicaciones Windows corren en la misma mquina en que se muestran. 3. Describa el ciclo de vida de una aplicacin Web: Cundo se instancian los formularios Web y durante cuanto tiempo existen? Una aplicacin Windows se inicia con la primera peticin para un recurso dentro de sus lmites. Los formularios Web se instancian cuando se solicitan. El servidor los procesa y son abandonados tan pronto como el servidor enva su respuesta al cliente. Una aplicacin Web termina despus de que terminen todas las sesiones de clientes. 4. Cmo se conservan los datos persistentes, como variables sencillas, en una aplicacin Web? Puede conservar datos en variables de estado, como Application, Session y ViewState. 5. Qu determina los lmites de una aplicacin Web? IIS determina los lmites de una aplicacin Web mediante la estructura de directorios virtuales de la aplicacin. El lmite de una aplicacin Web comienza en el directorio virtual que contiene la pgina de inicio de la aplicacin y termina en el ltimo directorio subordinado o cuando encuentra otra pgina de inicio en un directorio subordinado. Captulo 3: Trabajar con Objetos Web 1. Cmo organiza el marco de trabajo .NET sus clases? 295

MCAD/MCSD

El marco de trabajo .NET utiliza espacios de nombres para organizar sus clases. 2. En Visual Basic .NET Cul es la diferencia entre un mdulo de clase y un mdulo de cdigo? Los mdulos de clase se instancian en tiempo de ejecucin para crear objetos que proporcionan almacenamiento separado para variables y propiedades en cada instancia. Los mdulos de cdigo no tienen instancias, por lo que las variables a nivel de mdulo que usan se comparten entre diferentes llamadas a los procedimientos del mismo. 3. En Visual C#, Cmo se declara un mtodo para que est disponible sin tener que instanciar un objeto de la clase? Para crear un mtodo que se pueda llamar sin instanciar un objeto declrelo como static. 4. Cmo se llama a un miembro de la clase base desde dentro de una clase derivada? Para hacer referencia a un mtodo de una clase base en Visual Basic .NET use la palabra clave MyBase. Para hacer referencia a un miembro de una clase base en Visual C# use la palabra clave base. 5. Cules son los cuatro objetos principales usados en la programacin de aplicaciones Web? Los cuatro objetos principales en la programacin de aplicaciones Web son Application, Page, Request y Response. 6. Dnde grabara los siguientes elementos de datos de modo que sean persistentes entre peticiones a un formulario Web? Un control creado en tiempo de ejecucin En el objeto ViewState del objeto Page. Un objeto que proporciona servicio a todos los usuarios En el estado de aplicacin (Application) Preferencias de usuario En el estado de sesin (Session) Captulo 4: Crear un Interface de Usuario 1. Cul es la diferencia principal entre el control de servidor Button y el control HTML Button? Cuando se pulsa un control de servidor Button lanza un procedimiento de suceso Click en el servidor. El control HTML Button lanza el procedimiento de suceso indicado en su atributo onclick, que corre en el cliente. 2. Cmo se consigue que varios controles RadioButton interacten en un formulario Web de forma que solo se pueda seleccionar uno a la vez? Indicando un mismo nombre de grupo en la propiedad GroupName de todos ellos. 3. Por qu ASP.NET realiza la validacin en el cliente y en el servidor? La validacin en el cliente evita envos innecesarios al servidor. La validacin en el cliente asegura en la mayora de los casos que los datos son vlidos antes de su envo. Sin embargo, como la validacin se puede desactivar (o trucar de forma maliciosa), es necesario volver a validar los datos en el servidor. Esto proporciona la seguridad absoluta de que los datos son vlidos a la vez que evita todas las idas y vueltas posibles. 4. Qu tipos de validacin debera utilizar para comprobar que un usuario ha introducido un nmero de cliente correcto? Debera usar un RequiredFieldValidator y un RegularExpressionValidator. Si tiene acceso a una lista de los nmeros de cliente que se esperan, podra reemplazar el RegularExpressionValidator por un CustomValidator que compruebe la lista. 5. Qu es incorrecto en la siguiente lnea de cdigo? Visual Basic .NET
Server.Transfer(Default.htm)

Visual C#
Server.Transfer(Default.htm)

No se puede usar el mtodo Transfer con pginas HTML; solo funciona con pginas aspx. 6. Por qu no se puede abrir una nueva ventana de navegador mediante cdigo de servidor? 296

Developing Web Applications

El cdigo de servidor se ejecuta en el servidor, mientras que la nueva ventana se crea en el cliente. Debe usar cdigo cliente para las cosas que afecten al cliente, como subir archivos, mostrar nuevas ventanas o volver atrs en el historial. Captulo 5: ADO.NET 1. Qu pasos debe seguir y qu objetos debe usar para encontrar rpidamente el nmero de registros en una tabla de base de datos? Hay dos formas: Use una conexin con base de datos y un objeto Command para ejecutar un comando SQL que devuelva el nmero de filas de la tabla Use una conexin con base de datos y un objeto adaptador de datos para crear un conjunto de datos para la tabla, y despus lea el nmero de filas del conjunto de datos. 2. En qu se diferencian los conjuntos de datos sin tipo de los conjuntos de datos con tipo, y cuales son las ventajas de los conjuntos de datos con tipo? Los conjuntos de datos con tipo usan nombres y tipos de datos explcitos para sus miembros, mientras que los conjuntos de datos sin tipo usan colecciones para referirse a sus miembros. Los siguientes ejemplos muestran una referencia con tipo en comparacin con una referencia sin tipo en a un elemento de datos. Visual Basic .NET
Referencia con tipo a la columna HomePhone de la tabla Contacts DataSet1.Contacts.HomePhoneColumn.Caption = @Home Referencia sin tipo a la columna HomePhone de la tabla Contacts DataSet1.Tables(Contacts).Columns(HomePhone).Caption = @Home

Visual C#
// Referencia con tipo a la columna HomePhone de la tabla Contacts DataSet1.Contacts.HomePhoneColumn.Caption = @Home; // Referencia sin tipo a la columna HomePhone de la tabla Contacts DataSet1.Tables[Contacts].Columns[HomePhone].Caption = @Home

Los conjuntos de datos con tipo hacen comprobacin de errores en tiempo de diseo. Esta comprobacin de errores ayuda a capturar errores de tipo y de nombres, que con los conjuntos de datos sin tipo solo se advertiran en tiempo de ejecucin. 3. Cmo se reutiliza un componente de conexin de base de datos en una aplicacin Web? Aada el componente de conexin con la base de datos al archivo Global.asax y cree una variable de estado en los procedimientos de suceso Application_Start o Session_Start para compartir la conexin con los formularios Web de la aplicacin. 4. Explique las diferencias entre manejar transacciones a nivel base de datos y a nivel conjunto de datos. Los conjuntos de datos proporcionan transacciones implcitas, ya que los cambios no se aplican a la base de datos hasta que no se llame al mtodo Update. Para manejar transacciones en un conjunto de datos lance el mtodo Update y compruebe si hay errores. Si hay errores en Update no se aplican a la base de datos ninguno de los cambios del conjunto de datos. Puede intentar corregir el error y reenviar la actualizacin , o puede volver atrs los cambios del conjunto de datos usando el mtodo RejectChanges. Las bases de datos proporcionan transacciones explcitas mediante el objeto Transaction. Un objeto Transaction se crea a partir de una conexin con base de datos, y a continuacin se asigna a los comandos que quiere incluir en la transaccin mediante la propiedad Transaction del objeto comando. Cuando se ejecutan los comandos sobre la base de datos se comprueba si hay errores. Si se producen errores puede intentar corregirlos y reenviar el comando o puede restablecer el estado de la base de datos usando el mtodo RollBack del objeto Transaction. Si no se producen errores puede hacer que los cambios sean permanentes llamando al mtodo Commit del objeto transaccin. Captulo 6: Capturar y Corregir Errores 1. Explique por qu es importante el control de excepciones en una aplicacin terminada. Cuando se produce una excepcin no controlada en una aplicacin, la aplicacin se detiene el usuario no puede hacer nada, y todo trabajo que haya hecho antes de la excepcin se pierde. El control de excepcione proporciona una forma de interceptar y corregir errores situaciones inusuales que de otra forma causaran estos problemas. 2. Indique dos aproximaciones al control de excepciones en aplicaciones Web ASP.NET 297

MCAD/MCSD

Las excepciones se pueden controlar en bloques de control de excepciones usando las palabras clave Try, Catch, Finally en Visual Basic .NET o try, catch, finally en Visual C#. Tambin se pueden controlar usando procedimientos de suceso Error a nivel global, aplicacin o pgina usando los mtodos GetLastError y ClearError del objeto Server. 3. Describa el cometido de la pginas de error y por qu son necesarias. Como las aplicaciones Web corren sobre Internet, algunas excepciones se producen fuera del alcance de la aplicacin. Esto significa que la aplicacin no puede responder directamente a estas excepciones. Estos tipos de excepcin se identifican mediante cdigos de respuesta HTTP, a los que IIS puede responder mostrando pginas de error personalizadas indicadas en el archivo de configuracin de la aplicacin Web.config. 4. Explique por qu el seguimiento ayuda con el control de excepciones. El seguimiento permite registrar sucesos no usuales durante la ejecucin de la aplicacin, sin que los usuarios lo perciban. Si se produce una excepcin no anticipada la aplicacin puede escribir un mensaje en el registro de seguimiento, lo que ayuda a diagnosticar problemas durante las pruebas y tras el despliegue. Captulo 7: Programacin Avanzada de Formularios Web. 1. Escriba el HTML para un enlace que enve correo cuando el usuario lo pulse
<a href=mailto:nombre@dominio.com?SUBJECT=Envo de correo desde cliente&BODY=Texto del mensaje.>Enviar correo</a>

2. Muestre el cdigo que escribe una cookie que contiene el nombre de usuario Rob Young y la fecha actual en el ordenador del usuario. Configure la cookie para que permanezca en el ordenador 30 das. Visual Basic .NET
Dim cookUserInfo As New HttpCookie(UserInfo) cookUserInfo(Name) = Rob Young cookUserInfo(Time) = DateTime.Now.ToString() cookUserInfo.Expires = DateTime.Now.AddDays(30) Response.Cookies.Add(cookUserInfo)

Visual C#
HttpCookie cookUserInfo = new HttpCookie(UserInfo); CookUserInfo[Name] = Rob Young; CookUserInfo[Time] = DateTime.Now.ToString(); CookUserInfo.Expires = DateTime.Now.AddDays(30); Response.Cookies.Add(cookUserInfo);

3. Por qu no puede abrir una ventana de navegador desde cdigo de servidor?. Cmo podra mostrar una pgina en una nueva ventana con una secuencia de comandos de cliente? El cdigo de servidor solo puede ejecutar tareas en el servidor. Para ejecutar una tarea en el ordenador del usuario, como abrir una nueva ventana de navegador, el cdigo debe correr en el cliente. Puede abrir una nueva ventana usando el objeto window de DOM. Por ejemplo, el siguiente botn HTML abre una pgina de ayuda en una nueva ventana:
<button id=butHelp onClick=window.open(help.aspx, help, height=200,width=300)>Ayuda</button>

4. Cmo mostrara una pgina en un marco desde un enlace en otro marco?. Utilice el atributo target del elemento <a> para especificar el marco en el que mostrar la pgina. Por ejemplo, el siguiente enlace muestra una pgina en el marco main de un conjunto de marcos:
<a href=unaPagina.aspx target=main>Muestra la pgina</a>

Captulo 8: Mantener la Seguridad. 1. Qu modo de autenticacin de ASP.NET est mejor adaptado a identificar y autorizar usuarios pertenecientes a una red corporativa? La autenticacin Windows integrada es la mejor adaptada para autenticar usuarios de una red corporativa porque usa las cuentas y permisos que ya existen para los usuarios de red. 2. Cul es la diferencia entre las listas de usuarios para autenticacin Windows o de formularios en Web.config? Las listas de usuarios para autenticacin Windows estn incluidas en el elemento <authorization> del archivo Web.config. 298

Developing Web Applications

Las listas de usuarios para autenticacin por formularios se incluyen en el elemento <credentials> del archivo Web.config, o como parte de un archivo o base de datos de usuarios externo. 3. Cmo se exige la autenticacin usando el archivo Web.config?(La respuesta es la misma para todos los modos de autenticacin ASP.NET) Para exigir autenticacin incluya el siguiente elemento <authorization>
<authorization> <deny users=? /> </authorization>

4. Cmo proporciona SSL seguridad en una aplicacin Web? SSL protege los datos intercambiados entre un cliente y una aplicacin Web encriptando los datos antes de que se enven a travs de Internet 5. Cmo se comienza y se termina una comunicacin segura mediante SSL? Para comenzar una comunicacin segura especifique el protocolo https en la direccin, por ejemplo:
<a href=https://www.contoso.com/segure.htm>Pgina segura.</a>

Para terminar una comunicacin segura especifique el protocolo http en la direccin, por ejemplo:
<a href=http://www.contoso.com/Default.htm>No seguro.</a>

Captulo 9: Generar y desplegar aplicaciones Web 1. Bajo qu permisos se ejecutan de forma predeterminada las aplicaciones Web? De forma predeterminada las aplicaciones Web corren como el usuario ASPNET, que tiene permisos limitados equivalentes al grupo Usuarios. 2. Por qu es importante el archivo Machine.config para las aplicaciones Web desplegadas? El archivo Machine.config controla muchos aspectos de la ejecucin de aplicaciones Web, incluyendo cmo se reciclan los procesos, que tipos lmites se imponen a las colas de peticiones y qu intervalo se usa para comprobar si los usuarios siguen conectados. 3. Cmo se configuran las opciones de cach para una aplicacin Web? Use las extensiones de servidor de FrontPage en IIS para establecer las opciones de cach de pgina para una aplicacin Web. 4. Cmo afecta al estado de sesin de una aplicacin Web el despliegue en una granja Web o jardn Web? Las aplicaciones Web que se despliegan en una granja o jardn Web necesitan identificar un proveedor de estado de sesin en su archivo Web.config. Esto se debe a que las peticiones de un mismo cliente se pueden dirigir a diferentes procesos en el curso de su sesin. El proveedor de estado de sesin permite que cada proceso diferente acceda al mismo estado de sesin del cliente. Captulo 10: Probar aplicaciones Web 1. Cmo se relacionan entre s las pruebas de unidad, integracin y regresin?. Las pruebas de unidad son la base que asegura que cada fragmento de cdigo funciona correctamente. Las pruebas de integracin amplan este concepto verificando que los fragmentos funcionan juntos sin errores. Las pruebas de regresin se componen de las pruebas de unidad y de integracin existentes, que se ejecutan de forma regular para asegurar que el cdigo nuevo no introduce errores en el que ya funcionaba. 2. Por qu tiene ms importancia la prueba de carga en una aplicacin Web que en una aplicacin Windows independiente? Porque las aplicaciones Web pueden ser de uso pblico en Internet, pueden tener cientos, miles o incluso millones de usuarios. Las pruebas de carga permiten simular la demanda esperada para localizar conflictos de recursos, cuellos de botella de rendimiento u otros problemas que no aparecen en las pruebas de un solo usuario. 3. Cul es la diferencia entre las clases Debug y Trace? Con la configuracin predeterminada del entorno el cdigo que usa la clase Debug se elimina en la compilacin definitiva, mientras que el que usa la clase Trace se mantiene. Por lo dems, las dos clases son equivalentes. 4. Cules son los dos pasos especiales necesarios para asegurar que un componente COM puede usar un componente de un ensamblado .NET? 299

MCAD/MCSD

Debe registrar el ensamblado .NET en el registro del sistema usando RegAsm.exe Debe asegurarse de que el componente .COM puede localizar el ensamblado .NET, ya sea colocando el ensamblado .NET en la cach de ensamblados global, o colocando los dos componentes en el mismo directorio, o siguiendo otras reglas de localizacin de ensamblados. Captulo 11: Crear sus propios controles Web 1. Describa brevemente los mejores usos para cada uno de los tres tipos de controles Web completando las siguientes frases: Cree un control de usuario si quiere crear rpidamente un grupo de controles que se pueda reutilizar a lo largo de un proyecto para realizar alguna unidad lgica de trabajo. Cree un control personalizado compuesto si quiere combinar uno o ms controles existentes en un ensamblado compilado que se pueda reutiliza fcilmente en varios proyectos diferentes. Cree un control trazado si quiere crear un control completamente nuevo que se pueda compilar en un ensamblado para usar en varios proyectos. 2. Qu importancia tiene la derivacin para crear controles Web personalizados? Los controles personalizados, tanto compuestos como trazados, derivan de la clase base WebControl. Esta clase proporciona los mtodos que se sustituyen para crear la apariencia del control. 3. Cul es el mtodo ms importante que hay que sustituir cuando se crea un control personalizado compuesto? El mtodo CreateChildControls se sustituye para aadir controles existentes a un control personalizado compuesto. 4. Cul es el mtodo ms importante que hay que sustituir cuando se crea un control trazado? Cuando se crea un control personalizado trazado se sustituye el mtodo Render. 5. En que se diferencia lanzar un suceso de vuelta en un control compuesto a hacerlo en un control trazado? En un control compuesto puede usar uno de los controles contenidos para lanzar un suceso de envo. En un control trazado debe implementar el interface IPostBackEventHandler y escribir una secuencia de comandos de lado cliente para lanzar un suceso de envo. Captulo 12: Trabajar con multimedia 1. Por qu normalmente se controla el multimedia desde secuencias de comandos de cliente en lugar de cdigo de servidor? Para interceptar sucesos en el servidor es necesario volver a mostrar la pgina, lo que reinicia la mayor parte de los medios, incluyendo sonido y vdeo. 2. Qu elementos HTML de sonido y video soportan la mayora de los navegadores? La mayora de los navegadores soportan los elementos bgsound, img y embed de HTML. 3. Cmo se da soporte a los usuarios de Netscape Navigator desde dentro de un elemento de objeto ActiveX? Anidando un elemento embed de HTML que contiene un plugin Netscape equivalente dentro del elemento object de HTML para ActiveX. Tambin necesitar modificar o desactivar cdigo de cliente que controla el objeto ActiveX si el navegador del usuario es Netscape Navigator. 4. Qu caracterstica principal proporciona HTML+TIME que no est disponible con otras tcnicas de animacin? HTML+TIME permite sincronizar sucesos temporizados en una pgina. 5. Indique dos formas de crear una nueva lnea de tiempo usando HTML+TIME Usar un elemento de lnea de tiempo como t:SEQ, t:EXCL o t:PAR Aadir un atributo TIMECONTAINER a un elemento HTML estndar. Captulo 13: Dar formato a salida de aplicacin Web 1. Cul es la ventaja de usar CSS en lugar de estilos en lnea para dar formato a una aplicacin Web? El uso de CSS permite mantener el formato por separado del contenido en los formularios Web, de modo que los cambios son ms sencillos y es ms fcil mantener la coherencia de aspecto. 2. Por qu creara un estilo para una clase en lugar de para un elemento HTML?

300

Developing Web Applications

Se crean clases de estilo cuando se quiere aplicar el mismo formato a diferentes tipos de elementos dentro de una aplicacin. Por ejemplo, puede crear una clase de estilo nfasis que aplica el mismo formato a cualquier texto, control, encabezado o imagen hacia los que quiere atraer la atencin. 3. Cmo se relacionan entre s CSS y XSL cuando se trata de dar a una aplicacin Web? CSS y XSL son tcnicas complementarias para dar formato. CSS determina la fuente, color, tamao, fondo y otros aspectos de apariencia de los elementos HTML en una pgina Web. XSL se usa para transformar archivos XML en salida HTML. De esta forma, XSL controla la posicin y apariencia de elementos en base a su contenido. Juntos, XSL realiza las tareas de alto nivel de composicin y diseo mientras que CSS realiza las tareas de bajo nivel de aplicar fuentes, colores y otras caractersticas de aspecto. 4. Cules son las diferencias entre HTML y XML? HTML usa nombres de elemento predefinidos, como <p> y <br>. En XML el usuario crea sus propios nombres de elemento para identificar nodos de datos jerrquicos. La sintaxis XML es mucho ms estricta que HTML: los elementos siempre deben tener etiqueta de cierre, los nombres de elemento diferencian maysculas y minsculas, los valores de los atributos siempre deben ir entre comillas, y los elementos anidados deben terminar dentro de su elemento padre. XML identifica los datos conceptualmente en base al contenido de datos, en lugar de en base al tipo de formato que se aplica. Captulo 14: Proporcionar ayuda al usuario 1. En qu atributo del HTML mostrado por ASP.NET se convierte la propiedad ToolTip de un control de servidor? En tiempo de ejecucin la propiedad ToolTip se convierte en el atributo title. 2. En que se diferencia mostrar ayuda HTML usando el mtodo showHelp del objeto window de mostrarla en una ventana del navegador?. El mtodo showHelp no puede abrir ayuda HTML compilada desde una direccin de red; el archivo compilado se debe descargar antes en la mquina del usuario. Puede mostrar ayuda HTML desde una direccin de red en una ventana del navegador, usando el protocolo ms-its. Sin embargo, desde una ventana de navegador no estn disponibles de forma automtica las caractersticas de contenido, ndice y bsqueda. 3. Cmo se aaden palabras clave de ndice a un tema de ayuda?. Inserte un elemento objeto en el tema de ayuda usando el control ActiveX ayuda HTML. Por ejemplo, el siguiente elemento objeto aade la palabra clave de ndice nmeros
<Object type="application/x-oleobject" classid="clsid:1e2a7bd0-dab9-11d0-b93a-00c04fc99f9e"> <param name="Keyword" value="numbers"> </OBJECT>

Captulo 15: Globalizar aplicaciones Web 1. Cul es la diferencia entre la propiedad CurrentCulture y la propiedad CurrentUICulture? La propiedad CurrentCulture afecta a cmo manipula el marco de trabajo .NET las fechas, monedas, ordenacin y formato. La propiedad CurrentUICulture determina qu ensamblado satlite se usa cuando se cargan recursos. 2. Cmo se detecta la cultura del usuario? Utilice el array UserLanguages del objeto Request. El valor del elemento 0 corresponde a un cdigo de cultura utilizado por la clase CultureInfo. Por ejemplo:
SLang = Request.UserLanguage(0)

3. Qu es una cultura neutral? Las culturas neutrales representan lenguajes generales sin diferencias regionales, como la moneda. Por ejemplo, el cdigo de cultura es representa espaol. 4. Cmo afecta la codificacin de caracteres a los formatos de archivo? Cuando se usan caracteres no ASCII en un formulario Web debe grabar el archivo con una codificacin de caracteres especfica, como UTF-8. ASP.NET puede detectar automticamente la codificacin

301

MCAD/MCSD

UTF-8 si se guarda el archivo con una firma; en caso contrario necesitar especificar la codificacin usada en el atributo fileEncoding del elemento globalization en Web.config.

302

Potrebbero piacerti anche