Curso de Desarrollo web con Visual Studio 2005

En este curso se tratan todas las cuestiones fundamentales que le permitirán crear aplicaciones web con Visual Studio 2005. Al final del curso sabrá todo lo necesario para crear sus propias aplicaciones Web orientadas a datos y con multitud de características avanzadas. Este curso le enseñara entre otras cosas: · · · · · · · · Cómo crear aplicaciones web con Visual Studio 2005 A utilizar controles web y controles HTML Los métodos básicos de acceso a base de datos. Los controles enlazados a datos. A manejar las sesiones desde ASP.NET. El modo de crear aplicaciones con un interfaz de usuario consistente y fácil de personalizar. Control de acceso de usuarios. Cómo exponer funcionalidad a otras aplicaciones mediante servicios Web.

Es recomendable que el alumno disponga de nociones de programación Web en otras plataformas web como ASP, si bien no es indispensable. Para facilitar la transición de los programadores de ASP y Visual Basic 6 al nuevo entorno, en el contenido se hace mención a las diferencias con los lenguajes VBScript y VB6. Si no los conoce simplemente haga caso omiso de esos comentarios. Le recomendamos también que vea la aplicación MSDN Video, que desarrollaremos al finalizar el curso y de la que podrá consultar su código fuente y videos explicativos. ¡Disfrute del curso! Acerca del autor Jose Alarcón Aguín ASP/ASP.NET MVP José Manuel es ingeniero superior industrial y especialista universitario en consultoría de empresa. Es autor de varios libros, habiendo publicado hasta la fecha cerca de 300 artículos sobre informática e ingeniería en publicaciones especializadas. Es colaborador habitual de MSDN y de las más importantes revistas del sector como PC World, dotnetMania o Windows TI Magazine. En la actualidad es socio de Grupo Femxa, "soluciones al servicio del conocimiento", siendo también su responsable técnico. A través de Krasis [www.krasis.com], la empresa tecnológica del grupo, dirige para sus diferentes clientes proyectos y productos orientados a la comunicación, la mejora de procesos y los sistemas de teleformación. Puede usted visitar su Blog sobre tecnología .NET en www.jasoft.org.

Contenido
Este módulo presenta con carácter general la plataforma .NET y cómo ésta se diferencia de otros sistemas de desarrollo tradicionales, como ASP. · · Lección 1: Introducción a la plataforma .NET o ¿Qué es la plataforma .NET? o El entorno de ejecución CLR Lección 2: El lenguaje intermedio y el CLS o El lenguaje intermedio o La especificación común de los lenguajes .NET o El sistema de tipos comunes Lección 3: La biblioteca de clases de .NET o La BCL o Los espacios de nombres Lección 4: Acceso a datos con ADO.NET o ADO.NET o La arquitectura de ADO.NET o Capa conectada de datos o Capa desconectada Lección 5: Aplicaciones Windows Forms o Introducción Lección 6: Aplicaciones Web Forms o Introducción

· ·

· ·

Introducción a la plataforma .NET
Simplificando mucho las cosas para poder dar una definición corta y comprensible, se podría decir que la plataforma .NET es un amplio conjunto de bibliotecas de desarrollo que pueden ser utilizadas por otras aplicaciones para acelerar enormemente el desarrollo y obtener de manera automática características avanzadas de seguridad, rendimiento, etc... En realidad .NET es mucho más que eso ya que ofrece un entorno gestionado de ejecución de aplicaciones, nuevos lenguajes de programación y compiladores, y permite el desarrollo de todo tipo de funcionalidades: desde programas de consola o servicios Windows hasta aplicaciones para dispositivos móviles, pasando por desarrollos de escritorio o para Internet. Son estos últimos de los que nos ocuparemos en este curso. Pero antes conviene conocer los fundamentos en los que se basa cualquier aplicación creada con .NET, incluyendo las que nos interesan.

El entorno de ejecución CLR
.NET ofrece un entorno de ejecución para sus aplicaciones conocido como Common Language Runtime o CLR. La CLR es la implementación de Microsoft de un estándar llamado Common Language Infrastructure o CLI. Éste fue creado y promovido por la propia Microsoft pero desde hace años es un estándar reconocido mundialmente por el ECMA. El CLR/CLI esencialmente define un entorno de ejecución virtual independiente en el que trabajan las aplicaciones escritas con cualquier lenguaje .NET. Este entorno virtual se ocupa de multitud de cosas importantes para una aplicación: desde la gestión de la memoria y la vida de los objetos hasta la seguridad y la gestión de subprocesos.

Todos estos servicios unidos a su independencia respecto a arquitecturas computacionales convierten la CLR en una herramienta extraordinariamente útil puesto que, en teoría, cualquier aplicación escrita para funcionar según la CLI puede ejecutarse en cualquier tipo de arquitectura de hardware. Por ejemplo Microsoft dispone de implementación de .NET para Windows de 32 bits, Windows de 64 bits e incluso para Windows Mobile, cuyo hardware no tiene nada que ver con la arquitectura de un ordenador común.

El Lenguaje Intermedio y el CLS
Al contrario que otros entornos, la plataforma .NET no está atada a un determinado lenguaje de programación ni favorece a uno determinado frente a otros. En la actualidad existen implementaciones para varias decenas de lenguajes que permiten escribir aplicaciones para la plataforma .NET. Los más conocidos son Visual Basic .NET, C# o J#, pero existen implementaciones de todo tipo, incluso de ¡COBOL!. Lo mejor de todo es que cualquier componente creado con uno de estos lenguajes puede ser utilizado de forma transparente desde cualquier otro lenguaje .NET. Además, como ya se ha comentado, es posible ejecutar el código .NET en diferentes plataformas y sistemas operativos. ¿Cómo se consigue esta potente capacidad? Dentro de la CLI, existe un lenguaje llamado IL (Intermediate Language o Lenguaje Intermedio) que está pensado de forma independiente al procesador en el que se vaya a ejecutar. Es algo parecido al código ensamblador pero de más alto nivel y creado para un hipotético procesador virtual que no está atado a una arquitectura determinada. Cuando se compila una aplicación escrita en un lenguaje .NET cualquiera (da igual que sea VB, C# u otro de los soportados), el compilador lo que genera en realidad es un nuevo código escrito en este lenguaje intermedio. Así, todos los lenguajes .NET se usan como capa de más alto nivel para producir código IL. Un elemento fundamental de la CLR es el compilador JIT (just-in-time). Su cometido es el de compilar bajo demanda y de manera transparente el código escrito en lenguaje intermedio a lenguaje nativo del procesador físico que va a ejecutar el código.

Al final, lo que se ejecuta es código nativo que ofrece un elevado rendimiento. Esto es cierto también para las aplicaciones Web escritas con ASP.NET y contrasta con las aplicaciones basadas en ASP clásico que eran interpretadas, no compiladas, y que jamás podrían llegar al nivel de desempeño que ofrece ASP.NET. La siguiente figura muestra el aspecto que tiene el código intermedio de una aplicación sencilla y se puede obtener usando el desemsamblador que viene con la plataforma .NET.

Figura 1.1. Código en lenguaje intermedio obtenido con ILDASM.exe

La especificación común de los lenguajes y el sistema de tipos comunes
Para conseguir la interoperabilidad entre lenguajes no sólo llega con el lenguaje intermedio, sino que es necesario disponer de unas "reglas del juego" que definan un conjunto de características que todos los lenguajes deben incorporar. A este conjunto regulador se le denomina Common Language Specification (CLS) o, en castellano, especificación común de los lenguajes.

. Si nuestras bibliotecas de código utilizan en sus interfaces hacia el exterior datos definidos dentro de la CTS no existirán problemas a la hora de utilizarlos desde cualquier otro código escrito en la plataforma .Int32) se denomina Integer en Visual Basic . Los enteros de 32 bits eran de tipo Long. por ejemplo. la CLS define un conjunto de tipos de datos comunes (Common Type System o CTS) que indica qué tipos de datos se pueden manejar. los metadatos de las aplicaciones. Así. Cada lenguaje . En el siguiente módulo se profundiza en todas estas cuestiones.NET utiliza una sintaxis diferente para cada tipo de datos. un Integer representaba un entero de 16 bits.NET.NET. Téngalo en cuenta cuando empiece a programar. Una de las partes más importantes de la CLS es la que se refiere a los tipos de datos. cómo se declaran y se utilizan éstos y de qué manera se deben gestionar durante la ejecución.0 se suele usar VBScript como lenguaje de programación. Nota: En ASP 3.Entre las cuestiones que regula la CLS se encuentran la nomenclatura. Ver vídeo 1 de esta lección (Lenguaje intermedio) .NET el tipo Integer pensando que es de 16 bits cuando en realidad es capaz de albergar números mucho mayores. Es un fallo muy común usar desde Visual Basic . pero se llama int en C#. la forma de definir los miembros de los objetos. Si alguna vez ha programado la API de Windows o ha tratado de llamar a una DLL escrita en C++ desde Visual Basic 6 habrá comprobado lo diferentes que son los tipos de datos de VB6 y de C++.. al igual que en VB6. Existen tipos por valor (como los enteros que hemos mencionado o las enumeraciones) y tipos por referencia (como las clases). En ambos casos representan el mismo tipo de datos que es lo que cuenta. En este lenguaje interpretado. etc. Para evitar este tipo de problemas y poder gestionar de forma eficiente y segura el acceso a la memoria. el tipo común correspondiente a un número entero de 32 bits (System.

NET. Toda esta funcionalidad está implementada en forma de bibliotecas de funciones que físicamente se encuentran en diversas DLL (bibliotecas de enlazado dinámico). CLR. y la plataforma .) y en qué lugar de se ubican las bibliotecas de clases base: . En ella se pueden observar los elementos que se han mencionado en apartados anteriores (lenguajes. A su conjunto se le denomina Base Classes Library (Biblioteca de clases base o BCL) y forman parte integral de la plataforma . La siguiente figura ilustra a vista de pájaro la arquitectura conceptual de la plataforma . Obviamente esto no es así. creación de aplicaciones Web. Existen funcionalidades básicas (por ejemplo todo lo relacionado con la E/S de datos o la seguridad) y funcionalidades avanzadas en las que se fundamentan categorías enteras de aplicaciones (acceso a datos. no se trata de añadidos que se deban obtener o adquirir aparte.La biblioteca de clases de . Si bien es muy interesante y fundamental. es decir.. por sí mismo no nos serviría de mucho para crear programas si debiésemos crear toda la funcionalidad desde cero.NET Todo lo que se ha estado comentando hasta ahora en el curso constituye la base de la plataforma .NET..)..NET nos ofrece infinidad de funcionalidades "de fábrica" que se utilizan como punto de partida para crear las aplicaciones.NET.. CLS.

. Para solucionar este problema existen en todos los lenguajes . Los espacios de nombres Dada la ingente cantidad de clases que existen debe haber algún modo de organizarlas de un modo coherente.Figura 1. No se preocupe si hay elementos que no conoce.NET los espacios de nombres o namespaces. por no mencionar que crearemos continuamente nuevas clases propias. Además hay que tener en cuenta que podemos adquirir más funcionalidades (que se traducen en clases) a otros fabricantes. Un espacio de nombres no es más que un identificador que permite organizar de modo estanco las clases que estén contenidas en él así como otros espacios de nombres. más adelante los estudiaremos todos. Todo lo que se encuentra en la BCL forma parte de la plataforma . De hecho existe tal cantidad de funcionalidad integrada dentro de estas bibliotecas (hay decenas de miles de clases) que el mayor esfuerzo que todo programador que se inicia en .2.NET y cómo se relacionan entre sí. De todos modos Visual Studio ofrece mucha ayuda contextual (documentación. .) y una vez que se aprenden los rudimentos resulta fácil ir avanzando en el conocimiento de la BCL a medida que lo vamos necesitando. Intellisense.NET. Distintos elementos de la plataforma ..NET debe hacer es el aprendizaje de las más importantes. Resulta muy útil para comprender lo explicado hasta ahora.

todo lo que tiene que ver con el manejo de estructuras de datos XML en la plataforma .Así. que contiene toda la funcionalidad de controles Web para interfaz de usuario..UI. por ejemplo. System. etc.WebControls.Web. La funcionalidad fundamental para crear aplicaciones Web está en el espacio de nombres System..NET se encuentra bajo el espacio de nombres System. Éste a su vez contiene otros espacios de nombres más especializados como System.Web.Xml.Web.Caching para la persistencia temporal de datos. Ver vídeo 1 de esta lección (Utilización de las clases base) .

el mecanismo no es ni de lejos tan potente como el que nos ofrece ADO. La parte de la BCL que se especializa en el acceso a datos se denomina de forma genérica como ADO. Aunque hay quien lo asimila a los clásicos Recordsets su funcionalidad va mucho más allá como se verá en el correspondiente módulo.NET es un modelo de acceso mucho más orientado al trabajo desconectado de las fuentes de datos de lo que nunca fue ADO. Sin embargo. con el ánimo de retirar barreras a su aprendizaje.NET El acceso a fuentes de datos es algo indispensable en cualquier lenguaje o plataforma de desarrollo. Microsoft denominó a su nuevo modelo de acceso a datos con un nombre similar y algunas de sus clases recuerdan a objetos de propósito análogo en el vetusto ADO.NET ofrece una funcionalidad completamente nueva.0 o con ASP. ADO. ha empleado en su código con total seguridad la interfaz de acceso a datos conocida como ADO (ActiveX Data Objects). El objeto más importante a la hora de trabajar con el nuevo modelo de acceso a datos es el DataSet.Acceso a datos con ADO. ADO. todos ellos métodos mucho más antiguos.NET.NET. Sin exagerar demasiado podríamos calificarlo casi como un motor de datos relacionales en memoria. Si bien este último ofrecía la posibilidad de desconectar los Recordsets y ofrecía una forma de serialización de estos a través de las diferentes capas de una aplicación. que tiene poco que ver con lo existente hasta la fecha en el mercado. Si usted ha programado con Visual Basic 6. Si además es usted de los programadores con solera y lleva unos cuantos años en esto es probable que haya usado RDO o incluso DAO. . puede que combinado con ODBC (Open Database Connectivity).

Arquitectura de ADO.Arquitectura de ADO. Así.. Un proveedor de datos de ADO. es decir. Por fin la clase DataReader está especializada en leer los resultados de los comandos mientras se permanece conectado al origen de datos.NET El concepto más importante que hay que tener claro sobre ADO. Capa conectada La primera de ellas contiene objetos especializados en la conexión con los orígenes de datos.NET es una implementación .3. La clase DataAdapter hace uso de las tres anteriores para actuar de puente entre la capa conectada y la desconectada. no tienen una implementación real de la que se pueda hacer uso directamente. Estas clases son abstractas.NET Existen dos capas fundamentales dentro de su arquitectura: la capa conectada y la desconectada. la clase genérica Connection se utiliza para establecer conexiones a los orígenes de datos. Cada origen de datos tiene un modo especial de comunicarse con los programas que los utilizan. que se revela claramente al analizar su arquitectura: Figura 1.NET es su modo de funcionar. La clase Command se encarga de enviar comandos de toda índole al origen de datos. Es en este punto en donde entran en juego los proveedores de datos. además de otras particularidades que se deben contemplar.

Un programador novel puede sentir la tentación de utilizar siempre el proveedor puente para OLEDB y así escribir código compatible con diversos gestores de datos de forma muy sencilla. Su mala utilización es la causa más frecuente de cuellos de botella en las aplicaciones y de que éstas no escalen como es debido. que se utilizan para acceder a través de ODBC u OLEDB cuando no existe un proveedor nativo para un determinado origen de datos. las clases específicas para acceder a SQL Server se llaman SqlConnection.NET ofrece grandes novedades específicamente en este ámbito. Se trata de un error y siempre que sea posible es mejor utilizar un proveedor nativo. Es decir. . Nota: Estos proveedores nativos. ofrecen un rendimiento menor debido a la capa intermedia que están utilizando (ODBC u OLEDB). Así. Nota: El hecho de utilizar clases concretas para acceso a las fuentes de datos no significa que no sea posible escribir código independiente del origen de datos.concreta de las clases conectadas abstractas que hemos visto.NET ofrece grandes facilidades de escritura de código genérico basadas en el uso de herencia e implementación de interfaces.Data. que son los que se comunican directamente con el origen de datos (por ejemplo el de SQL Server o el de Oracle). Existen proveedores nativos. en muchas ocasiones es necesario tratar con datos que no han sido obtenidos desde un origen de datos relacional con el que se requiera una conexión.SqlClient. SqlDataReader y SqlDataAdapter y se encuentran bajo el espacio de nombres System. Capa desconectada Una vez que ya se han recuperado los datos desde cualquier origen de datos que requiera una conexión ésta ya no es necesaria.0 de . Además. Esta afirmación es especialmente importante en las aplicaciones Web en las que se pueden recibir muchas solicitudes simultáneas de cualquier parte del mundo. Todo lo contrario. si bien muy útiles en determinadas circunstancias. La plataforma . que hereda de éstas y que tiene en cuenta ya todas las particularidades del origen de datos en cuestión. Por otra parte las conexiones con las bases de datos son uno de los recursos más escasos con los que contamos al desarrollar. por ejemplo. A veces únicamente necesitamos un almacén de datos temporal pero que ofrezca características avanzadas de gestión y acceso a la información. y proveedores "puente". De hecho la versión 2. SqlCommand. al contrario que en ADO clásico no hay una única clase Connection o Command que se use en cada caso. Es aquí cuando la capa de datos desconectada entra en juego. Sin embargo sigue siendo necesario trabajar con los datos obtenidos de una manera flexible. si no que existen clases especializadas para conectarse y recuperar información de cada tipo de origen de datos.

Es obvio que no se trata de tareas triviales.Finalmente otro motivo por el que es importante el uso de los datos desconectado de su origen es la transferencia de información entre capas de una aplicación. Como podremos comprobar más adelante en este curso es bastante sencillo conseguir estas funcionalidades tan avanzadas y algunas otras simplemente usando de manera adecuada este tipo de objetos. cada una de un origen diferente si es necesario. teniendo en cuenta las restricciones y las relaciones existentes entre ellas.NET. se pueden extender mediante herencia. y permiten el acceso mucho más cómodo a los datos que representan. Por ello es necesario disponer de algún modo genérico y eficiente de poder transportar los datos entre diferentes lugares. Todo esto y mucho más es lo que nos otorga el uso de los objetos DataSet. . Nota: Otra interesante característica de los DataSet es que permiten gestionar simultáneamente diversas tablas (relaciones) de datos. como cualquier otra clase no sellada de . Estas nuevas tipos clases se denominan genéricamente DataSet Tipados. Ello facilita una técnica avanzada que consiste en crear tipos nuevos de DataSet especializados en la gestión de una información concreta (por ejemplo un conjunto de tablas relacionadas). verificando reglas de negocio. y validaciones de tipos de datos más estrictas. Los DataSet. Éstas pueden encontrarse distribuidas por diferentes equipos. utilizarlos en cualquiera de ellos y posteriormente tener la capacidad de conciliar los cambios realizados sobre ellos con el origen de datos del que proceden. e incluso en diferentes lugares del mundo gracias a Internet. pero los objetos DataSet están pensados y diseñados con estos objetivos en mente.

Son el mismo tipo de aplicaciones que antes construiríamos con Visual Basic 6 u otros entornos similares. Windows Forms está constituido por multitud de clases especializadas que ofrecen funcionalidades para el trabajo con ventanas. Visual Studio ofrece todo lo necesario para crear visualmente este tipo de programas. botones. rejillas. En la plataforma . campos de texto y todo este tipo de controles habituales en las aplicaciones de escritorio.NET el espacio de nombres que ofrece las clases necesarias para construir aplicaciones de escritorio bajo Windows se denomina Windows Forms. Este es también el nombre genérico que se le otorga ahora a este tipo de programas basados en ventanas.Aplicaciones Windows Forms Las aplicaciones de escritorio son aquellas basadas en ventanas y controles comunes de Windows que se ejecutan en local. de un modo similar aunque más rico al que ofrecía el entorno de desarrollo integrado de Visual Basic. .

De hecho se trata únicamente de código y no es necesario (aunque sí muy recomendable) emplear el diseñador gráfico de Visual Studio para crearlas. y cuyos controles son miembros de ésta.. Los formularios (ventanas) son clases que heredan de la clase base Form.4. .NET proporciona control sobre todos los aspectos de las ventanas y controles.Figura 1.Diseñador de interfaces de aplicaciones de escritorio con Windows Forms en Visual Studio 2005. Al contrario que en VB6. no dejando nada fuera del alcance del programador y otorgando por lo tanto la máxima flexibilidad. Este es el aspecto que presenta parte del código que genera la interfaz mostrada en la anterior figura: .

.Código autogenerado por Visual Studio para crear la interfaz de la figura anterior. Este tipo de aplicaciones se salen del ámbito de este curso por lo que no se profundizará más en ellas.5.)..Show() Todos los controles heredan de una clase Control por lo que conservan una serie de funcionalidades comunes muy interesantes. en .Figura 1.. . como la capacidad de gestionarlos en el diseñador (moviéndolos.NET es necesario crear un objeto antes de poder hacer uso de los formularios: Dim frm As New MiFormulario frm. alineándolos. Al contrario que en Visual Basic tradicional. de definir márgenes entre ellos o hacer que se adapten al tamaño de su contenedor. en donde siempre existían instancias por defecto de los formularios que podíamos usar directamente.

junto con código que se ejecutaría en el servidor (parte servidora). Por ejemplo. el siguiente código ilustra el código que es necesario escribir en ASP para disponer de una página que rellena una lista de selección con unos cuantos nombres (podrían salir de una base de datos y aún sería más complicado). y que dispone de un botón que escribe un saludo para el nombre que se haya elegido de la lista. Si conoce el diseñador de VB6 o de Windows Forms mencionado en el apartado anterior sabe exactamente a qué nos referimos.Aplicaciones Web Forms Tradicionalmente las aplicaciones Web se han desarrollado siguiendo un modelo mixto que intercalaba código HTML y JavaScript propio de páginas Web (parte cliente). Hacer esto en una aplicación de escritorio no tiene mayor dificultad ya que todo el código se ejecuta en el mismo lugar. En el modelo orientado a eventos se define la interfaz de usuario colocando controles en un contenedor y se escribe el código que actuará como respuesta a las interacciones de los usuarios sobre estos controles. Este modelo contrastaba por completo con el modelo orientado a eventos seguido por las principales herramientas de desarrollo de aplicaciones de escritorio. . La principal característica de las aplicaciones Web sin embargo es que se la interfaz de usuario (lo que los usuarios de la aplicación ven) se ejecuta en un lugar diferente al código de la aplicación que reside en un servidor. Para mayor desgracia estas aplicaciones se basan en el uso del protocolo HTTP que es un protocolo sin estado y que no conserva la conexión entre dos llamadas consecutivas.

sino que tenemos que crear un bucle que genere los elementos HTML necesarios para generarla.Código ASP sencillo que genera una lista de selección y saluda al presionar un botón. Lo único que hay es HTML y JavaScript que se deben generar desde el servidor.Figura 1. . No existe separación entre el diseño y la lógica de las aplicaciones. pero la intención es ilustrar la mezcla de código de cliente y de servidor que existe en este tipo de aplicaciones. Si queremos cambiar sustancialmente la apariencia de la aplicación Web lo tendremos bastante complicado puesto que el código del servidor está mezclado entre el HTML. Tampoco disponemos de un diseñador visual que nos permita gestionar los controles y elementos HTML existentes. En el ejemplo de la figura para generar un control de lista con unos elementos no podemos asignar una propiedad de la lista (porque no existe tal lista). Obviamente se podría haber simplificado sin enviar el formulario al servidor usando JavaScript en el cliente para mostrar el saludo.6. 2. Las principales desventajas de este tipo de codificación son las siguientes: 1. En ASP clásico no existe el concepto de control para la interfaz de usuario.. y menos cuando éstos se encuentran mezclados con el código del servidor.

No disponemos de forma de detectar en el servidor que se ha realizado algo en el cliente. debiéndonos encargar nosotros de averiguar si la petición es la primera vez que se hace o no. No existe el concepto de Propiedad de los controles. Eventos. Si intentamos crear una interfaz avanzada que utilice tablas y otros elementos que no son controles de entrada de datos de formularios de HTML tendremos que inventarnos mecanismos propios para recoger esos datos y enviarlos al servidor. 6. 4. Si estos nombres viniesen de una base de datos esto puede ser todavía más ineficiente y tendremos que buscar métodos alternativos para generarlos ya que en ASP tampoco se deben almacenar en los objetos de sesión y/o aplicación Recordsets resultado de consultas. Estado. En una aplicación Web clásica tenemos que almacenarlas en algún sitio (una variable de sesión o un campo oculto) para conservarlas entre diferentes peticiones de una misma página. En cualquier caso es mucho menos intuitivo que el modelo de respuesta a eventos de una aplicación de escritorio. El cliente se encuentra desconectado desde el momento en que se termina de devolver la página. En una aplicación Windows asignamos el texto de un campo usando una propiedad (por ejemplo Text1. Diseñadores gráficos.Text = "Hola") y ésta se asigna y permanece en la interfaz sin que tengamos que hacer nada. Componentes de interfaz de usuario. incluyendo la lista con todos los nombres dejando seleccionado el mismo que hubiese antes. Sólo se recibe información en el servidor cuando se solicita una nueva página o cuando se envía un formulario tal y como se hace en el ejemplo.3. Esto como se verá marca un antes y un después en la programación para Internet. Enlazado a datos desde la interfaz. La principal aportación de ASP. Por ejemplo si presionamos el botón “Di Hola” tenemos que escribir además de la etiqueta “Hola. tanto estándar como de terceras empresas o propios.NET al mundo de la programación es que ha llevado a la Web el paradigma de la programación orientada a eventos propia de aplicaciones de escritorio. ofreciendo: · · · · · · Separación entre diseño y lógica. No existe constancia del estado de los controles de cada página entre las llamadas. nombre” el resto de la pantalla. En cada ejecución de la página tendremos que recrear completamente la salida. Los controles complejos no tienen forma de enviar sus valores al servidor. y de dar la respuesta adecuada. Ver vídeo 1 de esta lección (Diseñador de formularios Web) . 5.

WriteLine por Response. Si quiere reproducir los ejemplos mostrados en estos videos en una aplicación web puede modificar las instrucciones Console.Nota: Para mayor simplicidad los videos de este módulo están realizados con aplicaciones de consola.Write. Contenido · Lección 1: El sistema de tipos o Tipos primitivos o Variables y constantes o Enumeraciones o Arrays (matrices) Lección 2: Clases y estructuras o Clases o Definir una clase o Instanciar una clase o Estructuras o Accesibilidad o Propiedades o Interfaces Lección 3: Manejo de excepciones o Manejo de excepciones Lección 4: Eventos y delegados o Eventos o Definir y producir eventos en una clase o Delegados · · · .

o · Definir un evento bien informado Lección 5: Atributos o Atributos Ver video de introducción (Crear un proyecto de consola) .

veremos ejemplos de cómo los manejábamos en VBScript/VB6 y cómo tendremos que usarlos desde Visual Basic .NET está totalmente integrado con . A continuación daremos un repaso a conceptos básicos o elementales sobre los tipos de datos.NET Framework pone a nuestra disposición.Introducción En esta primera lección veremos los tipos de datos que .NET . por tanto en los casos que pueda existir esa posibilidad de funcionamiento diferente. Aunque no debemos olvidar que en .NET los tipos de datos tienen un tratamiento. en algunos casos.NET Framework. Tipos de datos de . de esta forma nos resultará más fácil familiarizarnos.NET Visual Basic . que si bien nos serán familiares. por este motivo vamos a empezar usando algunas de las definiciones que nos encontraremos al recorrer la documentación que acompaña a este lenguaje de programación.NET.NET y de paso veremos las equivalencias con respecto a VBScript/VB6. por tanto los tipos de datos que podremos usar con este lenguaje serán los definidos en este "marco de trabajo". especial que pueden llevarnos a confusión. así mismo veremos las diferencias con respecto a los tipos de datos de VBScript/VB6 y las equivalencias entre los tipos de ambos entornos. es importante que lo veamos para poder comprender mejor cómo están definidos y organizados los tipos de datos en . En los siguientes enlaces tenemos los temas a tratar en esta primera lección del módulo sobre las características del lenguaje Visual Basic .

· Tipos primitivos o Sufijos o caracteres y símbolos identificadores para los tipos o Tipos por valor y tipos por referencia Variables y constantes o Consejo para usar las constantes o Declarar variables o Declarar variables y asignar el valor inicial o El tipo de datos Char o Obligar a declarar las variables con el tipo de datos o Aplicar Option Strict On a un fichero en particular o Aplicar Option Stict On a todo el proyecto o Más opciones aplicables a los proyectos Enumeraciones: Constantes agrupadas o El nombre de los miembros de las enumeraciones o Los valores de una enumeración no son simples números Arrays (matrices) o Declarar e inicializar un array o Cambiar el tamaño de un array o Eliminar el contenido de un array o Los arrays son tipos por referencia · · · .

Tipos primitivos Veamos en la siguiente tabla los tipos de datos definidos en .A.1.A.NET Framework y los alias utilizados en Visual Basic 2005.NET Framework System.A. Tipos de datos y equivalencia entre lenguajes . N. Single Double Currency * N.Char System.A.Object System.A.Int32 System.Decimal System. .UInt64 VB.Boolean System.SByte System.Single System. (ChrW) String * Variant / Object * Date * N.Int16 System.String System. así como el equivalente de VBScript/VB6.UInt32 System.UInt16 System. Tabla 1.A. N.Byte System.DateTime System.Double System.NET Boolean Byte Short Integer Long Single Double Decimal Char String Object Date SByte UShort UInteger ULong VBScript/VB6 Boolean * Byte Integer Long N. N.Int64 System.

A.NET.NET es casi como uno de VBScript/VB6.NET o bien como literales. podemos indicarlo añadiendo una letra como sufijo al tipo. Esto quiere decir que una vez que se han creado no se pueden modificar. este es un caso especial del que nos ocuparemos en la próxima lección.A. Todos estos tipos primitivos podemos usarlos tanto por medio de los tipos propios de Visual Basic.. Existe una clase en . de igual forma. Las últimas filas mostradas en la tabla son tipos especiales que si bien son parte del sistema de tipos comunes (CTS) no forman parte de la Common Language Specification (CLS). los marcados con un asterisco (*) no tienen equivalencia directa. y en caso de que queramos cambiar el contenido. Por tanto. Por ejemplo para indicar que queremos considerar un valor entero podemos usar la letra I o el signo %. los tipos definidos en . La única excepción de los tipos mostrados en la tabla 1 es el tipo de datos Object.NET se encarga de usar la anterior y crear una nueva cadena. estos tipos no tienen equivalencia. realmente un String de . un valor de tipo entero largo (Long) lo podemos indicar usando L o &. pero el o los tipos indicados serían los que más se aproximarían.NET que es ideal para estos casos y cuyo rendimiento es superior al de VBScript/VB6: la clase StringBuilder que ya hemos visto someramente en un vídeo del módulo anterior. no debemos usar estos tipos como valores de devolución de funciones ni como tipo de datos usado en los argumentos de las funciones.NET. en la siguiente tabla podemos ver los caracteres o letra que podemos usar como sufijo en un literal numérico para que el compilador lo identifique sin ningún lugar a dudas.NET Framework.En la columna de equivalencias con VBScript/VB6 tenemos algunos indicados con N. . es decir son tipos "elementales" para los cuales cada lenguaje define su propia palabra clave equivalente con el tipo definido en el CTS de .NET. Si nuestra intención es utilizar sin embargo un tipo de datos diferente. El caso del tipo String es un caso especial. % & ! # Carácter S I L F R . Tipo de datos Short Integer Long Single Double Símbolo N. Los tipos mostrados en la tabla 1 son los tipos primitivos de . propiedades o procedimientos públicos. es decir la especificación común para los lenguajes "compatibles" con . con la diferencia de que las cadenas en . Por otro lado.NET y por extensión de Visual Basic 2005. podemos definir un número entero literal indicándolo con el sufijo I: 12345I o bien asignándolo a un valor de tipo Integer o a un tipo Sytem. el rendimiento es inferior incluso al que teníamos en VBScript/VB6. Por ejemplo.Int32 de . Por tanto si usamos las cadenas para realizar concatenaciones (unión de cadenas para crear una nueva). si queremos crear aplicaciones que puedan interoperar con todos los lenguajes de .NET son inmutables. el tipo de datos que por defecto le asigna el compilador es el tipo Double. Sufijos o caracteres y símbolos identificadores para los tipos Cuando usamos valores literales numéricos en Visual Basic 2005.

2. Figura 2.A. si queremos asignar este valor literal a un tipo Decimal: 12345678901234567890. Error de desbordamiento al intentar asignar un valor Double a una variable Decimal Tipos por valor y tipos por referencia Los tipos de datos de . es decir se almacena directamente en la memoria reservada para ese tipo y cualquier cambio que hagamos lo haremos directamente sobre dicho valor. Podemos decir que el acceso al valor contenido en uno de estos tipos es directo. De igual forma cuando copiamos valores de un tipo por valor a otro. pero si le agregamos el sufijo D o @ ya no habrá dudas de que estamos tratando con un valor Decimal.A. estaremos haciendo copias independientes.Decimal UShort UInteger ULong @ N.NET los podemos clasificar en dos grupos: · · Tipos por valor Tipos por referencia Los tipos por valor son tipos de datos cuyo valor se almacena en la pila o en la memoria "cercana". tal como vemos en la Figura 2. N.A. el IDE de Visual Studio 2005 nos indicará que existe un error de desbordamiento (Overflow) ya que esa cifra es muy grande para usarlo como valor Double. Sufijos para identificar los tipos de datos El uso de estos caracteres nos puede resultar de utilidad particularmente para los tipos de datos que no se pueden convertir en un valor doble. .1. como los numéricos que hemos visto. D US UI UL Tabla 1. Por ejemplo. N.

Estos dos casos los veremos en breve con más detalle. Si hacemos copias de tipos por referencia. los tipos por referencia lo único que almacenan es una referencia (o puntero) al valor asignado. Ver video 1 de esta lección (Tipos de datos primitivos) Ver video 2 de esta lección (Tipos por valor y por referencia) . realmente lo que copiamos es la referencia propiamente dicha. A diferencia de los tipos por valor.Por otro lado. pero no el contenido. los tipos por referencia se almacenan en el "montículo" (heap) o memoria "lejana".

Consejo para usar las constantes Siempre que tengamos que indicar un valor constante. las constantes se definen de la misma forma que en VBScript/VB6. De esta forma si ese valor lo usamos en varias partes de nuestro código.Variables y constantes Disponer de todos estos tipos de datos no tendría ningún sentido si no los pudiéramos usar de alguna otra forma que de forma literal. salvo que ahora podemos obligarnos a indicar el tipo de datos que esa constante va a contener. Esto lo veremos en la siguiente sección. las excepciones vienen dadas. como hemos comentado antes. Declarar variables La declaración de las variables en Visual Basic 2005 se hace de la misma forma que en VBScript/VB6/VB6. Pero esto no es algo nuevo. deberíamos usar una constante en lugar de un valor literal. ya sea para indicar el máximo o mínimo permitido en un rango de valores o para comprobar el término de un bucle. Y aquí es donde entran en juego las variables y constantes. de la posibilidad de obligar a definir el tipo de cada variable y de cómo podemos definir más de una variable en una misma instrucción Dim. si en un futuro decidimos que dicho valor debe ser diferente. . Además de que de esta forma nos aseguramos de que el cambio se realiza adecuadamente y no tendremos que preocuparnos de las consecuencias derivadas de no haber hecho el cambio en todos los sitios que deberíamos. o casi. nos resultará más fácil realizar un solo cambio que cambiarlo en todos los sitios en los que lo hemos usado.

veamos ejemplos de cómo definir o declarar variables siguiendo las buenas costumbres. s As String = "Hola" Aunque para que el código sea más legible. b As Integer = 25. Por ejemplo: Dim a As Integer = 10 En esa misma línea podemos declarar y asignar más variables. b. pero realmente solo declara con el tipo indicado a la última variable. para hacerlo. sobre todo si nuestra intención era hacer precisamente lo que VB6. el tipo de datos puede ser cualquiera de los tipos primitivos: Dim a As Integer = 10. con esta declaración: Dim a. y fácil de depurar. simplemente tenemos que indicar ese valor. En Visual Basic 2005 al usar esa misma línea de código estamos declarando tres variables de tipo Integer. Por ejemplo. esto es algo que debemos tener en cuenta. que en los tipos numéricos es un cero. que no todas las variables fuesen del tipo que "supuestamente" habíamos querido indicar. es decir. c As Integer A primera vista estamos declarando tres variables de tipo Integer. normalmente para nuestro pesar. En VB6 era posible definir más de una variable en una misma instrucción Dim. no deberíamos mezclar en una misma instrucción Dim más de un tipo de datos. en las fechas es el 1 de enero del año 1 a las doce de la madrugada (#01/01/0001 12:00:00AM#) y en la cadenas es un valor nulo (Nothing).Para no embrollar mucho la cosa. hacía. Nota: Es importante saber que en las cadenas de Visual Basic 2005 el valor de . es decir. las otras dos. pero todas deben estar indicadas con el tipo de datos: Dim a As Integer = 10. declarar dos variables de tipo Variant y una de tipo Integer. tal como veremos es muy parecido a como se declaran las constantes. indicando siempre el tipo de datos de la variable. Declarar variables y asignar el valor inicial En Visual Basic 2005 también podemos inicializar una variable con un valor distinto al predeterminado. b As Integer = 25 Por supuesto. se declaran con tipo Variant o el tipo de datos predefinido (que es el que tiene por defecto todas las variables en VBScript/VB6 para ASP clásico). aunque dependiendo de cómo hiciéramos esa declaración podía ser que.

aunque para que realmente sea un carácter debemos agregarle una c justo después del cierre de las comillas dobles: Dim c As Char = "A"c Obligar a declarar las variables con el tipo de datos La obligatoriedad. Para ello tenemos que usar la instrucción Option Strict On. Dim c As String c = Chr(65) Dim n As Integer n = Asc("A") En Visual Basic 2005 también podemos usar esas mismas funciones. El tipo de datos Char En Visual Basic 2005 podemos declarar valores de tipo Char. a la que hacíamos referencia anteriormente. Si bien en VBScript/VB6 no existe el tipo de datos Char. (al igual que una cadena). además de la función Chr. nos obliga a declarar todas las variables. la podemos aplicar a todo el proyecto o a un módulo en particular. pero debido a que un valor de tipo Char se puede convertir en una cadena. No debemos confundir Option Strict con el clásico Option Explicit de VB. no de tipo String como ocurre en VBScript/VB6. . no solo a las declaraciones de variable. Este último. el valor que devuelve esta función es un valor de tipo Char. de declarar las variables y constantes con el tipo de datos adecuado. se aplicará a todo el código. ese valor literal estará encerrado entre comillas dobles. aunque en el caso de Chr. Si nuestra intención es asignar un valor Char a una variable. sino también a las conversiones y asignaciones entre diferentes tipos de datos. una vez indicado. constantes o al tipo de datos devuelto por las funciones y propiedades. al igual que en VBScript/VB6.una variable de tipo String no inicializada NO es una cadena vacía como ocurría en VBScript/VB6. podemos hacerlo con un literal. este tipo de datos es un carácter Unicode y podemos declararlo y asignarlo a un mismo tiempo. mientras que el primero lo que hace es obligarnos a que esas declaraciones tengan un tipo de datos. podemos hacer una asignación como la mostrada en el código anterior sin ningún tipo de problemas. sino un valor nulo (Nothing). si podemos convertir un valor numérico en un carácter (realmente en una cadena) o bien podemos convertir un carácter en su correspondiente valor numérico. El problema con el que nos podemos encontrar es a la hora de indicar un carácter literal.

no se producirá ningún error. en este caso no tendríamos que indicarlo en cada uno de los ficheros de código que formen parte de nuestro proyecto. en Visual Basic 2005 esta opción está predefinida y no se agrega a ningún módulo.. para ello simplemente habría que usar esas declaraciones pero usando Off en lugar de On. Para que siempre se usen estas asignaciones en todo el proyecto. (no hace falta crear ningún nuevo proyecto. Abrimos Visual Studio 2005 y una vez que se haya cargado. En la Figura 2 mostrada anteriormente tenemos una captura del editor de Visual Basic 2005 en la que hemos indicado que queremos tener comprobación estricta. Lo mismo podemos hacer con Option Strict On. vamos a ver cómo indicarlo en el entorno de Visual Studio 2005.2: . la expandimos y seleccionamos Valores predeterminados de VB y veremos ciertas opciones. pero eso no significa que no se aplique. esas líneas de código deben aparecer al principio del fichero y solamente pueden estar precedidas de comentarios (instrucciones REM o líneas iniciadas con una comilla simple). tal como podemos comprobar en la Figura 2. si bien Option Explicit On ya viene como valor por defecto. Aplicar Option Strict On a un fichero en particular Cuando en VBScript/VB6 agregábamos un nuevo formulario. es decir. De igual forma. seleccionamos la opción Herramientas>Opciones. que esté activado a todo el proyecto. debemos "conectar" siempre estas dos opciones. independientemente de cómo lo tengamos definido para el ámbito del proyecto. cosa que no ocurre con Option Strict. si ya está definido globalmente y lo indicamos expresamente. en caso de que nos decidamos a hacerlo. módulo BAS o módulo de clase. Aclaremos esto último: si Option Strict (u Option Explicit) está definido de forma global al proyecto. se agregaba automáticamente la instrucción Option Explicit.. que por defecto está desconectado. podemos desactivarlo en cualquiera de los ficheros. Como recomendación para buenas prácticas. aunque siempre podemos escribir esas instrucciones (con el valor On al final) en cada uno de los módulos o ficheros de código que agreguemos a nuestro proyecto. Aplicar Option Strict On a todo el proyecto También podemos hacer que Option Strict funcione igual que Option Explicit. se mostrará un cuadro de diálogo y del panel izquierdo seleccionamos la opción Proyectos y soluciones. Lo importante aquí es saber que siempre se usará el estado indicado en cada fichero. de este detalle nos ocuparemos en breve). si bien solamente será aplicable a los que no tengan esas instrucciones.Tanto una como la otra tienen dos estados: conectado o desconectado dependiendo de que agreguemos On u Off respectivamente.

Por defecto ya estarán seleccionadas las opciones On de Option Explicit y Binary de Option Compare. por tanto no es necesario realizar ningún cambio más. Nota: Aunque en esta captura muestre: C:\vbexpB1 en Default project location. si bien podemos hacer que se muestren todas las disponibles.3: . Opciones de proyectos (opciones mínimas) Nota: La figura mostrada corresponde a la versión Visual Web Developer de Visual Studio. para hacerlo.Figura 2.2. debemos marcar la casilla que está en la parte inferior izquierda en la que podemos leer: Mostrar todas las configuraciones. aparecerá el path por defecto dentro de Mis documentos. seleccionamos On. salvo que lo cambiemos. Como podemos observar. El contenido de su pantalla variará dependiendo de la versión de Visual Studio 2005 de la que disponga. al seleccionar esa opción nos mostrará un número mayor de opciones. aparecen pocas opciones. tal como podemos ver en la Figura 2. presionamos el botón Aceptar. para aceptar los cambios y cerrar el cuadro de diálogo. De la lista despegable Option Strict.

4 al intentar declarar una variable sin indicar el tipo de datos. Figura 2. tal como vemos en la Figura 2.4. Aviso de Option Strict al declarar una variable sin tipo .3. Opciones de proyectos (todas las opciones) Desde este momento el compilador de VB se volverá estricto en todo lo relacionado a las declaraciones de variables y conversiones.Figura 2.

aunque alguna veces puede llegar a parecer fastidioso. para ello seleccionaremos del menú Proyecto la opción Propiedades de <NombreDelProyecto> y tendremos un cuadro de diálogo como el mostrado en la Figura 2. (pronto veremos cómo crear uno). vamos a mostrar otro de los sitios en los que podemos indicar que se haga una comprobación estricta de tipos y.Nota: Una de las ventajas del IDE (Integrated Development Environment. Cuando tengamos un proyecto cargado en el IDE de Visual Studio. nos facilita la escritura de código.5. como veremos. todas ellas relacionadas con el tema que estamos tratando. también podremos forzar algunas "nuevas peculiaridades" de Visual Basic 2005. ya que no tenemos que esperar a realizar la compilación para que tengamos constancia de esos fallos. . entorno de desarrollo integrado) de Visual Studio 2005 es que nos avisa al momento de cualquier fallo que cometamos al escribir el código. este "pequeño" detalle. Más opciones aplicables a los proyectos Aunque en estos módulos no trataremos a fondo el entorno de desarrollo. podemos mostrar las propiedades del proyecto. ya que la finalidad de este curso es tratar más en el código propiamente dicho.

.

(siempre que no le hayamos asignado un valor al declararla). si hemos declarado una variable y no la usamos en el código.6.6: Figura 2. tenemos algo que muchos desarrolladores de Visual Basic siempre hemos querido tener: Que nos avise cuando una variable la hemos declarado pero no la utilizamos (Variable local no utilizada). tal como podemos ver en la Figura 2.5. Ficha Compilar de las opciones del proyecto actual Seleccionando la ficha Compilar. Entre esas condiciones. Al tener marcada esta opción (normalmente como una Advertencia). Aviso de variable no usada Ver video 1 de esta lección (Declarar Ver video 2 de esta lección (Definir constantes) variables) .Figura 2. nos avisará. Option Explicit y Option Compare. además de las típicas opciones de Option Strict. (estas asignaciones solo serán efectivas para el proyecto actual). tendremos cómo queremos que reaccione el compilador si se cumple algunas de las condiciones indicadas.

el tipo de datos de cada miembro de la enumeración será Integer. En Visual Basic 2005 las enumeraciones pueden ser de cualquier tipo numérico entero.Simplemente indicando el nombre de la enumeración y el de sus valores: Enum Colores Rojo Verde Azul End Enum En este primer caso. incluso enteros sin signo. 2.Indicando el tipo de datos que realmente se utilizará: Enum Colores As Long . aunque el valor predefinido es el tipo Integer. Podemos declarar una enumeración de varias formas: 1.Enumeraciones: Constantes agrupadas Una enumeración es un grupo de constantes que están relacionadas entre sí y que queremos utilizar para restringir el rango de posibles valores para una variable o parámetro.

el valor máximo que podemos asignar a los miembros de una enumeración será el que pueda contener un tipo de datos Long. en breve veremos qué significa esto de "no perder el nombre". De hecho. podemos "sumar" los valores definidos en la enumeración. pero esta definición se queda algo corta.Rojo Es decir. pero sin perder el nombre.Rojo Verde Azul End Enum En este segundo caso. <Flags()> _ Enum Colores As Byte Rojo = 1 Verde = 2 Azul = 4 End Enum Nota: Los atributos los veremos con más detalle en otra lección de este mismo módulo. la podemos usar de esta forma: Dim c As Colores = Colores. Se usa también para indicar valores que se pueden "sumar" o complementar entre sí.Indicando el atributo FlagsAttibute. Como hemos comentado.Azul Or Colores. podemos saber "el nombre" de un valor de una enumeración. 3. para ello tendremos que usar el método ToString. (realmente no hace falta indicar el sufijo Attribute cuando usamos los atributos) de esta forma podremos indicar unos valores concretos para los miembros de la enumeración. (el cual se usa . El nombre de los miembros de las enumeraciones Tanto si indicamos o no el atributo Flags a una enumeración. las enumeraciones son constantes con nombres.

la representación numérica del valor contenido: 4 + 1.para convertir en una cadena cualquier valor numérico). Esto es aplicable a cualquier tipo de enumeración. ya que el valor de la constante Azul es 4 y el de la constante Rojo es 1.Azul. Si tenemos este código: Enum Colores As Byte Rojo = 1 Verde = 2 Azul = 4 End Enum Dim c As Colores = Colores.Rojo Dim s As String = c.ToString El contenido de la variable s será "5". Por ejemplo.Azul Or Colores. veamos que es lo que ocurre cuando sumamos valores de enumeraciones a las que hemos aplicado el atributo Flags y a las que no se lo hemos aplicado. si tenemos la siguiente asignación: Dim s As String = Colores. es decir. se haya o no usado el atributo FlagsAttribute. Una vez aclarado este comportamiento de las enumeraciones en Visual Basic 2005.ToString La variable s contendrá la palabra "Azul" no el valor 4. Empecemos por este último caso. Pero si ese mismo código lo usamos de esta forma (aplicando el atributo Flags a la enumeración): <Flags()> _ Enum Colores As Byte Rojo = 1 Verde = 2 Azul = 4 .

ToString El contenido de la variable s será: "Rojo.7: Figura 2. En Visual Basic 2005 esto no es posible.Rojo Dim s As String = c. Azul". no el valor "interno". es decir. por ejemplo. al menos si ese valor está dentro del rango adecuado. en el ejemplo de la figura usar un 1 en lugar de Colores.8 podemos ver ese error al intentar asignar el valor 3 a una variable del tipo Colores (definida con el tipo predeterminado Integer). Los tipos subyacentes posibles de una enumeración Por tanto cabe pensar que podemos usar cualquier valor para asignar a una variable declarada como una enumeración. Es decir. ya que recibiremos un error indicándonos que no podemos convertir. se asignan los nombres de los miembros de la enumeración que intervienen en ese valor.Azul Or Colores.7. un valor entero en un valor del tipo de la enumeración.End Enum Dim c As Colores = Colores. Los valores de una enumeración no son simples números Los miembros de las enumeraciones realmente son valores de un tipo de datos entero (en cualquiera de sus variedades) tal como podemos comprobar en la Figura 2. . En la Figura 2. al menos si lo hacemos de forma "directa" y con Option Strict conectado.Rojo.

pero no solo nos dice cómo corregirlo. Figura 2. el valor 3 podríamos darlo por bueno.9.Figura 2. Es posible que usando CType no asignemos un valor dentro del rango permitido.9. Colores) CType es una de las formas que nos ofrece Visual Basic 2005 de hacer conversiones entre diferentes tipos de datos. Si compilamos y ejecutamos la aplicación. En este caso. en este caso convertimos un valor entero en uno del tipo enumerado Colores. El código final (una vez corregido) quedaría de la siguiente forma: Dim c As Colores = CType(3. Opciones de corrección de errores Lo único que tendríamos que hacer es presionar la sugerencia de corrección. esa ayuda se obtiene presionando el signo de admiración que tenemos justo donde está el cursor del mouse. ya que es la suma de 1 y 2 (Rojo y . sino que también nos da la posibilidad de que el propio IDE se encargue de hacerlo. pero en otros casos pueden ser varias las opciones y tendríamos que elegir la que creamos adecuada. Error al asignar un valor "normal" a una variable del tipo Colores El error nos indica que no podemos realizar esa asignación. ésta funcionará correctamente. que en este caso es la única que hay. tal como podemos apreciar en la Figura 2. pero el entorno integrado de Visual Studio 2005 también nos ofrece alternativas para que ese error no se produzca.8.

pero ¿qué pasaría si el valor asignado es. Ver Ver Ver Ver video video video video 1 2 3 4 de de de de esta esta esta esta lección lección lección lección (Enumeraciones (Enumeraciones (Enumeraciones (Enumeraciones 1) 2) 3) 4) . Nota: La función IsDefined sólo comprueba los valores que se han definido en la enumeración. c) End Sub Este código lo que hace es comprobar si el tipo de datos Colores tiene definido el valor contenido en la variable c. 2.Verde).Con la clásica solución de comprobar el valor indicado con todos los valores posibles.IsDefined(GetType(Colores).Usando funciones específicas del tipo Enum. c) = False Then c = Colores. Aunque en este último caso.WriteLine("El color es {0}". por ejemplo. en caso de que no sea así. Estas validaciones podemos hacerlas de dos formas: 1.Azul End If Console. usar el valor Azul If [Enum]. solo podremos comprobar los valores definidos en la enumeración. usamos un valor predeterminado. incluso aunque hayamos usado el atributo FlagsAttribute. Sub mostrarColor(ByVal c As Colores) ' comprobar si el valor indicado es correcto ' si no está¡ definido. En el siguiente ejemplo podemos hacer esa comprobación. no las posibles combinaciones que podemos conseguir sumando cada uno de sus miembros. 15? En teoría no deberíamos permitirlo.

podemos indicar el número de elementos que contendrá el array: Dim nombres(10) As String Tal como ocurre en VBScript/VB6. En Visual Basic 2005 la declaración de un array la haremos de la misma forma que en VBScript/VB6. esto lo lográbamos usando la cláusula To al definir un array. en el siguiente ejemplo declaramos un array de tipo String llamado nombres: Dim nombres() As String Al igual que en VBScript/VB6. podemos elegir entre cero y uno mediante la instrucción Option Base indicando a continuación un 0 o un 1. Es más en Visual Basic 2005 todos los arrays deben tener como índice inferior el valor cero. En Visual Basic 2005 no existe esa instrucción. en VB6 tenemos la posibilidad de indicar cual es el valor del índice inferior predeterminado de los arrays. si bien la forma en que se almacena en la memoria y la forma en que podemos usarlas en Visual Basic 2005 ha cambiado. al realizar esta declaración lo que conseguimos es definir un array de 11 elementos: desde cero hasta 10. Si bien. por ejemplo: .Arrays (matrices) Los arrays (o matrices) también es algo que podíamos usar en VBScript/VB6. Otra posibilidad que teníamos en VBScript/VB6 era indicar el rango de índices que podíamos asignar.

"Pepe"}. al igual que en VBScript/VB6.NET siempre deben tener el valor cero como índice inferior.0)= nombres(1. por el hecho de que los arrays de .0)= nombres(0. pero a diferencia de VBScript/VB6 no podemos usar ReDim para definir un array. pero en este caso debemos usar doble juego de llaves: Dim nombres(. Lo que también podemos hacer en Visual Basic 2005 es cambiar el tamaño de un array y mantener los valores que tuviera anteriormente. en Visual Basic 2005 siempre hay que declarar previamente los arrays antes de cambiarles el tamaño. En Visual Basic 2005 esto lo hacemos indicando los valores a asignar justo después de la declaración y encerrándolos entre llaves: Dim nombres() As String = {"Pepe". "Eva"}} En este código tendríamos un array bidimensional con los siguientes valores: nombres(0.1)= Juan Pepe Ana Eva Cambiar el tamaño de un array Para cambiar el tamaño de un array. Lo que si podemos hacer en Visual Basic 2005 es usar To para indicar el valor máximo del índice.1)= nombres(1. .) As String = {{"Juan". aunque no tiene la misma "potencia" que en VBScript/VB6. para lograrlo debemos usar ReDim Preserve. "Juan". {"Ana".Dim nombres(10 To 25) As String Pero esta declaración es ilegal en Visual Basic 2005. usaremos la instrucción ReDim. Si el array es bidimensional (o con más dimensiones). también podemos inicializarlos al declararlo. "Luisa"} Con el código anterior estamos creando un array de tipo String con tres valores cuyos índices van de cero a dos. al menos de esta forma el código resultará más legible: Dim nombres(0 To 10) As String Declarar e inicializar un array Lo que no podemos hacer en VBScript/VB6 era declarar un array y al mismo tiempo asignarle valores.

Asignar un valor Nothing al array.NET el índice inferior es cero. Erase elimina totalmente el array de la memoria. en Visual Basic 2005 los arrays son tipos por referencia. Esto funciona en Visual Basic 2005 pero no en VBScript/VB6. podemos hacerlo de tres formas: 1. tendríamos un array de un elemento. para lograrlo. . en los arrays de más de una dimensión solamente podemos cambiar el tamaño de la última dimensión. y tal como comentamos anteriormente. 2. Si mostramos el contenido de ambos arrays nos daremos cuenta de que realmente solo existe una copia de los datos en la memoria.Si bien tanto ReDim como ReDim Preserve se pueden usar en arrays de cualquier número de dimensiones. como hemos comentado anteriormente. Al igual que en VBScript/VB6. es posible que nos interese eliminar esos valores de la memoria. aunque en el mejor de los casos. debido a que en Visual Basic 2005 los arrays son tipos por referencia Los arrays son tipos por referencia Como acabamos de ver. los arrays de . "Pepe". A continuación definimos otro array llamado otros y le asignamos lo que tiene nombres. los tipos por referencia realmente lo que contienen son una referencia a los datos reales no los datos propiamente dichos. Eliminar el contenido de un array Una vez que hemos declarado un array y le hemos asignado valores. Dim nombres() As String = {"Juan". Redimensionando el array indicando que tiene cero elementos. 3. En VBScript/VB6 cada array era independiente del otro y esa asignación a nombres(0) no afectaba al valor contenido en otros(0). y tanto nombres(0) como otros(0) contienen el nombre "Antonio". Por último asignamos un nuevo valor al elemento cero del array nombres. ¿Cual es el problema? Veámoslo con un ejemplo y así lo tendremos más claro. "Eva"} Dim otros() As String otros = nombres nombres(0) = "Antonio" En este ejemplo definimos el array nombres y le asignamos cuatro valores. ya que. "Ana". si no estamos trabajando con arrays de más de una dimensión. Usar la instrucción Erase.

. el uso de la función LBound.Length) nombres. aunque de esto hablaremos en la próxima lección. debemos hacer una copia del array nombres en el array otros. Para finalizar este tema. el cambio realizado en el elemento cero de nombres no afecta al del array otros. Dim nombres() As String = {"Juan". como por ejemplo la propiedad Length usada en el ejemplo para saber cuantos elementos tiene el array nombres. "Pepe".CopyTo(otros. En el siguiente código de ejemplo hacemos una copia del contenido del array nombres en el array otros. El único requisito es que el array de destino debe estar inicializado y tener espacio suficiente para contener los elementos que queremos copiar. en la que también tendremos la oportunidad de profundizar un poco más en los tipos por referencia y en como podemos definir nuestros propios tipos de datos. (que sirve para averiguar el índice inferior de un array). esto es fácil de hacer si usamos el método CopyTo. "Ana". también podemos usar la función UBound. de esta forma. solamente existe una copia de los datos y tanto la variable nombres como la variable otros lo que contienen es una referencia (o puntero) a los datos. que es la que nos servía en VBScript/VB6 para saber esa información. tanto por referencia como por valor. que los arrays de Visual Basic 2005 realmente son tipos de datos derivados de la clase Array y por tanto disponen de todos los miembros definidos en esa clase. no tiene ningún sentido en Visual Basic 2005. "Eva"} Dim otros() As String ReDim otros(nombres.¿Qué ha ocurrido? Que debido a que los arrays son tipos por referencia. ya que todos los arrays siempre tienen un valor cero como índice inferior. solo nos queda por decir. Éste método existe en todos los arrays y nos permite copiar un array en otro empezando por el índice que indiquemos. los arrays tienen otros miembros que nos pueden ser de utilidad. Si realmente queremos tener copias independientes. 0) nombres(0) = "Antonio" Además del método CopyTo. Para averiguar el número de elementos de un array. Sin embargo.

Arrays) Ver video 2 de esta lección (Arrays 2) Ver video 3 de esta lección (Arrays 3) .Ver video 1 de esta lección (Agregar proyectos a una solución.

nos centraremos en las propiedades para ver en detalle los cambios que han sufrido con respecto a las clases de VBScript/VB6. También veremos temas relacionados con la programación orientada a objetos (POO) en general y de forma particular los que atañen a las interfaces.Introducción En la lección anterior vimos los tipos de datos predefinidos en .NET Framework § La herencia: Característica principal de la Programación Orientada a Objetos § Encapsulación y Polimorfismo: Dos viejos conocidos de VB § Object: La clase base de todas las clases de . así como a los distintos miembros de esos tipos de datos. tanto por valor como por referencia. También tendremos ocasión de ver los distintos niveles de accesibilidad que podemos aplicar a los tipos. Clases y estructuras · Clases: Tipos por referencia definidos por el usuario o Las clases: El corazón de . ámbito y miembros compartidos § Parámetros y parámetros opcionales .NET Framework. en esta lección veremos cómo podemos crear nuestros propios tipos de datos. De los distintos miembros que podemos definir en nuestros tipos.NET o Definir una clase § § § Una clase especial: Module Los miembros de una clase Características de los métodos y propiedades § Accesibilidad.

§ § § o § § § § § · Array de parámetros opcionales (ParamArray) Sobrecarga de métodos y propiedades Parámetros por valor y parámetros por referencia Instanciar: Crear un objeto en la memoria Declarar y asignar en un solo paso El constructor: El punto de inicio de una clase Constructores parametrizados Cuando Visual Basic 2005 no crea un automáticamente El destructor: El punto final de la vida de una clase constructor Estructuras: Tipos por valor definidos por el usuario o Definir una estructura o Constructores de las estructuras o Destructores de las estructuras o Los miembros de una estructura o Cómo usar las estructuras Accesibilidad y ámbito o Ámbito § Ámbito de bloque § Ámbito de procedimiento § Ámbito de módulo § Ámbito de espacio de nombres o La palabra clave Global o Accesibilidad § Accesibilidad de las variables en los procedimientos o Las accesibilidades predeterminadas o Anidado de tipos § Los tipos anidables § El nombre completo de un tipo § Importación de espacios de nombres § Alias de espacios de nombres Propiedades o Definir una propiedad o Propiedades de solo lectura o Propiedades de solo escritura o Diferente accesibilidad para los bloques Get y Set o Propiedades predeterminadas § Sobrecarga de propiedades predeterminadas Interfaces o ¿Qué es una interfaz? o ¿Qué contiene una interfaz? o Una interfaz es un contrato o Las interfaces y el polimorfismo o Usar una interfaz en una clase o Acceder a los miembros implementados o Saber si un objeto implementa una interfaz o Implementación de múltiples interfaces o Múltiple implementación de un mismo miembro · · · .

o o ¿Dónde podemos implementar las interfaces? Un ejemplo práctico usando una interfaz de .NET .

Los tipos por referencia realmente son clases. digamos. bien implementando . motor en tiempo de ejecución de . las podemos definir nosotros mismos.NET Framework es precisamente el corazón del propio . ya que como veremos. aunque como veremos tanto la forma de definirlas como de instanciarlas ha cambiado un poco. se crea siempre en la memoria lejana (heap) y las variables lo único que contienen es una referencia a la dirección de memoria en la que el CLR (Common Language Runtime. Antes de entrar en detalles sintácticos. bien ampliando la funcionalidad de alguna clase existente mediante la herencia. en esa librería de clases está todo lo que podemos hacer dentro de este marco de programación. y si no existen. en la forma.NET Framework y como repercuten en las que podamos definir nosotros usando Visual Basic 2005.NET). de la cuales debemos crear una instancia para poder usarlas. Aunque ese cambio es solo.NET Framework Prácticamente todo lo que podemos hacer en . los tipos de datos se dividen en dos grupos: tipos por valor y tipos por referencia. siempre salvando las distancias. las clases de Visual Basic 2005 pueden llegar a ser mucho más versátiles y potentes que las de VBScript/VB6.NET. ya que en el fondo es lo mismo. Esa instancia o copia.NET Framework lo hacemos mediante clases.Clases: Tipos por referencia definidos por el usuario Tal como vimos en la lección anterior. veamos la importancia que tienen las clases en . La librería de clases de . para prácticamente cualquier tarea que queramos realizar existen clases. también podemos crear nuestras propias clases en Visual Basic 2005. Las clases: el corazón de . Al igual que ocurre en VBScript/VB6. ha almacenado el objeto recién creado.

entre ellos el Visual Basic 2005.. La herencia: Característica principal de la Programación Orientada a Objetos El concepto de Programación Orientada a Objetos (POO) es algo intrínsico al propio . Cualquier clase que definamos tendrá el comportamiento heredado de esa clase.0 de Visual Basic y VBScript estaban a nuestra disposición. El ejemplo clásico del polimorfismo es que si tengo un objeto que "sabe" cómo morder.NET. y como decía la documentación de Visual Basic 5. como veremos más adelante. El uso de la clase Object como base del resto de las clases de . por tanto es una característica que todos los lenguajes basados en este "marco de trabajo" tienen de forma predeterminada. siempre será preferible que nos muerda un ratón antes que un dinosaurio. podemos agregar múltiples interfaces.NET. Encapsulación y Polimorfismo: Dos viejos conocidos de VB La encapsulación y el polimorfismo son otras dos características de la programación orientada a objetos. que en breve podemos definir como una característica que nos permite ampliar la funcionalidad de una clase existente sin perder la que ya tuviera previamente. si bien. lo indiquemos o no explícitamente. Esta nueva clase puede cambiar el comportamiento de la clase base (de la cual hereda) y/o ampliarlo. para poder lograrlo se exponen como parte de la clase los métodos y propiedades necesarios para que podamos manejar esos datos sin tener que preocuparnos cómo se realiza dicha manipulación. por la sencilla razón de que estamos usando ciertos mecanismos que siguen unas normas que están adoptadas por la clase.NET Framework.NET Framework soporta es la herencia simple. La herencia nos permitirá aprovechar la funcionalidad de muchas de las clases existentes en la plataforma . siempre y cuando esas dos "clases" expongan un método que pueda realizar esa acción. Gracias a la herencia. es decir. El polimorfismo es una característica que nos permite realizar ciertas acciones o acceder a la información de los datos contenidos en una clase de forma semianónima.NET Todas las clases de . Object: La clase base de todas las clases de . ya que lo único que nos debe preocupar es que podemos hacerlo.0.NET se derivan siempre de forma automática de la clase Object. podemos crear una nueva clase que se derive de otra. Aunque estas dos no nos resultarán desconocidas. al menos en el sentido de que no tenemos porqué saber sobre que tipo objeto realizamos la acción. solo podemos usar una clase como base de la nueva. De las características principales de la POO tenemos que destacar la herencia. La encapsulación nos permite abstraer la forma que tiene de actuar una clase sobre los datos que contiene o manipula.NET es la única excepción a la herencia simple soportada por .. de esta forma podemos adaptar la clase original a nuestras necesidades. ya que desde la versión 5. . El tipo de herencia que . da igual que lo aplique a un ratón o a un dinosaurio.algún tipo de funcionalidad previamente definida o simplemente creándolas desde cero.

Aunque en el caso de los tipos de datos por valor. En la mayoría de los casos. el valor obtenido al usar este método debería ser más intuitivo: por ejemplo los tipos de datos primitivos tienen definido este método para devuelva el valor que contienen. el cual ya lo vimos en la lección anterior cuando queríamos convertir un tipo primitivo en una cadena. ya sean por valor o por referencia siempre están derivados de la clase Object. por tanto podremos llamar a cualquiera de los métodos que están definidos en esa clase. De igual forma. nos ocuparemos en breve. Este método está pensado para devolver una representación en formato cadena de un objeto. Ver video de esta lección (Clases 1) .NET. de manera similar a como un variant servía en VBScript/VB6 para tratar cualquier tipo de objeto. nuestras clases también deberían devolver un valor adecuado al contenido almacenado. El valor que obtengamos al usar este método dependerá de cómo esté definido en cada clase y por defecto lo que devuelve es el nombre completo de la clase. tiene que volver a hacer la conversión inversa (unboxing).Esta característica nos asegura que siempre podremos usar un objeto del tipo Object para acceder a cualquier clase de . Nota: Todos los tipos de datos de .NET. De cómo hacerlo.NET Framework primero debe convertirla en un objeto por referencia (operación denominada boxing) y cuando hemos dejado de usarla y queremos volver a asignar el dato a la variable por valor. De los miembros que tiene la clase Object debemos resaltar el método ToString. . sin embargo. cuando queremos acceder a la clase Object que contienen.

0. Class Cliente Public Nombre As String Public Apellidos As String End Class . cada vez que definimos una clase tenemos que agregar al proyecto un fichero con extensión . porque en VB2005 solo existe un tipo de fichero para escribir el código: un fichero con extensión . En Visual Basic 2005 las clases se definen usando la palabra clave Class seguida del nombre de la clase. Nota: En Visual Basic 2005 cualquier código que queramos escribir estará dentro de una clase.cls. En VBScript (tanto en ASP como en otros entornos) y en Visual Basic 2005 esto se hace mediante el uso de la palabra clave Class. y a partir de ese momento.Definir una clase En Visual Basic 6. Aunque lo habitual es que usemos un fichero independiente para cada clase que escribamos. todo el código escrito en ese fichero formaba parte de la clase. En el siguiente ejemplo definimos una clase llamada Cliente que tiene dos campos públicos. en el que podemos escribir una clase o cualquiera de los tipos que el lenguaje nos permite. esto solo es algo opcional. exactamente igual que en VBScript. esa definición acaba indicándolo con End Class.vb.

Las clases definidas con la palabra clave Module realmente equivalen a las clases en las que todos los miembros están compartidos y por tanto siempre disponibles a toda la aplicación. . Los métodos son las acciones que la clase puede realizar. como vimos en la lección anterior.Una vez definida la clase podemos agregar los elementos (o miembros) que creamos conveniente. Los eventos son mensajes que la clase puede enviar para informar que algo está ocurriendo en la clase. Dependiendo de que el método devuelva o no un valor. Los miembros de una clase Una clase puede contener cualquiera de estos elementos (miembros): · · · · · Enumeraciones Campos Métodos (funciones o procedimientos) Propiedades Eventos Las enumeraciones. La definición se hace usando la instrucción Module seguida del nombre a usar y acaba con End Module. Este tipo de clase tiene un tratamiento especial y es el equivalente a los módulos BAS de VB6. Una clase especial: Module En Visual Basic 2005 también podemos definir una clase especial llamada Module. aunque también podríamos haber definido cualquiera de los miembros permitidos en las clases. hemos agregado dos campos públicos. Las propiedades son las "características" de las clases y la forma de acceder "públicamente" a los datos que contiene. pero es necesario explicar que existe este tipo de clase ya que será el tipo de datos que el IDE de Visual Basic 2005 usará al crear aplicaciones del tipo consola. podemos usar métodos de tipo Function o de tipo Sub respectivamente. Los campos son variables usadas para mantener los datos que la clase manipulará. para simplificar. Normalmente encapsulan el acceso a miembros privados de la clase. por ejemplo para indicar los valores posibles de cualquier "característica" de la clase. De todos estos conceptos nos ocuparemos en las siguientes lecciones. que será el tipo de proyecto que crearemos para practicar con el código mostrado en este primer módulo. podemos usarlas para definir valores constantes relacionados. normalmente esas acciones serán sobre los datos que contiene. En el ejemplo. podemos considerar que el nombre y los apellidos de un cliente son dos características del cliente. Por ejemplo. Cualquier miembro definido en un Module siempre estará accesible en todo el proyecto y para usarlos no tendremos que crear ningún objeto en memoria.

Protected: Acceso limitado a la clase contenedora o a los tipos derivados de esta clase. Es decir. Los modificadores de accesibilidad son: · · · · · Public: Acceso no restringido. cómo podemos acceder a ese elemento y desde dónde podemos accederlo. ya que lo que representan es la "cobertura" o alcance que tienen los miembros de las clases e incluso de las mismas clases que definamos. El ámbito de un elemento de código está restringido por el "sitio" en el que lo hemos declarado. la clase o la estructura donde se ha declarado. desde dónde podremos accederlos. para poder comprender mejor las características de los miembros de una clase o tipo. Ámbito de procedimiento: Disponible únicamente dentro del procedimiento en el que se ha declarado. Estos tipos de "acceso" dependerán del ámbito que queramos que tengan. . Si bien cada uno de ellos tienen su propia "semántica". Estos sitios pueden ser: · · · · Ámbito de bloque: Disponible únicamente en el bloque de código en el que se ha declarado. ámbito y miembros compartidos Aunque estos temas los veremos en breve con más detalle. tal como podemos ver a continuación: Ámbito Es el alcance que la definición de un miembro o tipo puede tener.Características de los métodos y propiedades Accesibilidad. es decir. daremos un pequeño adelanto sobre estas características que podemos aplicar a los elementos que definamos. Ámbito de módulo: Disponible en todo el código del módulo. Aunque en la práctica tienen el mismo significado. Accesibilidad y ámbito son dos conceptos que están estrechamente relacionados. Ámbito de espacio de nombres: Disponible en todo el código del espacio de nombres. Accesibilidad A los distintos elementos de nuestro código (ya sean clases o miembros de las clases) podemos darle diferentes tipos de accesibilidad. Private: Acceso limitado al tipo contenedor. Friend: Acceso limitado al proyecto actual. Protected Friend: Acceso limitado al proyecto actual o a los tipos derivados de la clase contenedora.

podemos declarar miembros privados a una clase.BAS. Lo que Visual Basic 2005 no permite es definir un parámetro opcional de tipo Variant. debemos indicar también el valor por defecto que debemos usar en caso de que no se especifique. son elementos que no pertenecen a una instancia o copia en memoria particular. pero como veremos. como puede ser la limitación del ámbito de un miembro que aparentemente tiene una accesibilidad no restringida. en ese caso. (funciones y métodos Sub). pero no desde fuera de ella. y su tiempo de vida es el mismo que el de la aplicación.Por ejemplo. la accesibilidad y los miembros compartidos nos ocuparemos con más detalle en una lección posterior. Veamos unos ejemplo para aclarar nuestras ideas: . (los no especificados). se usará el valor predeterminado que hayamos indicado. Parámetros y parámetros opcionales En Visual Basic 2005. los miembros compartidos de una clase o tipo. tanto los miembros de una clase. Con los parámetros opcionales lo que conseguimos es permitir que el usuario no tenga que introducir todos los parámetros. en Visual Basic 2005. donde veremos ciertas peculiaridades. ya que una de las "restricciones" de este tipo de parámetros con respecto a VBScript/VB6 es que siempre que indiquemos un parámetro opcional. Miembros compartidos Por otro lado. además se siguen soportando tanto los parámetros opcionales (Optional) como los arrays de parámetros (ParamArray). el ámbito que le estamos aplicando es privado. Esto no es algo nuevo. Nota: Al igual que ocurre en VBScript/VB6. porque ese tipo de datos no existe en VB2005. el ámbito puede ser diferente a privado. dichos miembros solamente los podremos acceder desde la propia clase. Del ámbito. ya que en VB6 podíamos tener parámetros en estos tipos de miembros (o elementos) de una clase. sino solo los que realmente necesite. como las propiedades pueden recibir parámetros. dependiendo del tipo en el que declaremos esa variable. del resto. al declarar una variable con Dim. Esto realmente sigue funcionando igual que en VB6 cuando al parámetro opcional le indicamos el tipo de datos. por regla general. entre otras cosas. Nota: Lo más parecido en VB6 a los miembros compartidos de Visual Basic 2005 son los métodos y campos declarados en un módulo . sino que pertenecen al propio tipo y por tanto siempre están accesibles o disponibles. dentro del nivel del ámbito y accesibilidad que les hayamos aplicado.

es decir. entre otras cosas. pero en el opcional usamos el nombre t = Suma(1. se usará el valor 15 que es el predeterminado. en Visual Basic 2005 siempre debe ser una array de un tipo específico e internamente se trata como un array normal y corriente. Optional n2 As Integer = 15) As Integer Suma = n1 + n2 End Function En este primer ejemplo.indicando los dos parámetros (el resultado será 4= 1 + 3) t = Suma(1.Indicando los dos parámetros. dentro del método o propiedad se accede a él como si de un array se tratara. Para llamar a esta función. 3) ' 2. n2:= 9) El tercer ejemplo solamente tiene utilidad si hay más de un parámetro opcional. este tipo de parámetro opcional nos permite indicar un número indeterminado de parámetros. si no se indica al llamar a esta función. ya que en VBScript/VB6. lo podemos hacer de estas tres formas: ' 1. el primer parámetro es obligatorio (siempre debemos indicarlo) y el segundo es opcional. aunque a algunos puede que le parezca menos "potente"...Indicando solamente el primer parámetro (el resultado será 16= 1 + 15) t = Suma(1) ' 3. al menos si tenemos activado Option Strict. esto no es posible. Pero en Visual Basic 2005. cualquiera de los parámetros podía ser a su vez un array.Function Suma(n1 As Integer. Veamos lo que VB6 permite y cómo hacerlo en VB2005: . aunque el funcionamiento con respecto a VBScript/VB6 es algo diferente. Nota: Los parámetros opcionales deben aparecer en la lista de parámetros del método. en Visual Basic 2005 el uso de los parámetros opcionales con ParamArray es más simple e intuitivo. después de los "obligatorios" Array de parámetros opcionales (ParamArray) En cuanto al uso de ParamArray. ¡porque es un array! En VB6 no siempre era así y algunas veces teníamos verdaderos problemas al acceder a esos datos. por suerte. ya que solo aceptará los parámetros del tipo indicado.

lo demás se puede quedar igual. 5. incluso los tipos de datos. 4. 6) MsgBox(t) Para usar este código en Visual Basic 2005 tendremos que desactivar Option Strict y cambiar el tipo Variant por Object. (cosa que el IDE hará automáticamente si pegamos el código).Function Suma(ParamArray n() As Variant) As Long Dim total As Long Dim i As Long Dim j As Long ' For i = 0 To UBound(n) If IsArray(n(i)) Then For j = LBound(n(i)) To UBound(n(i)) total = total + n(i)(j) Next Else total = total + n(i) End If Next Suma = total End Function ' Para usarlo: Dim t As Long Dim a(2) As Long a(0) = 1: a(1) = 2: a(2) = 3 t = Suma(a. aunque debemos recordar que un Long de VBScript/VB6 es un Integer de VB2005. .

Ya lo hemos visto en uno de los vídeos del módulo anterior. Function Suma(ByVal ParamArray n() As Integer) As Integer Dim total As Integer For i As Integer = 0 To n. 5.Usamos propiedades para saber la cantidad de elementos del array. 3. . esta instrucción debe ser la última de la lista de parámetros de la función (método). realmente ahorra algún ciclo de reloj y es más cómodo para programar. 4.1 total += CInt(n(i)) Next Return total End Function ' Para usarlo: Dim t As Integer = Suma(1.Usamos Return para devolver el valor en lugar de usar el nombre de la función. .Length .Podemos inicializar la variable a usar con el bucle For. . aunque no nos permita usar un array en los parámetros al llamar a la función. esto lo veremos con más detalle cuando tratemos la accesibilidad. 6) ' MsgBox(t) Aquí vemos el nuevo modo de trabajar de Visual Basic 2005: . 2. Nota: Cuando queramos usar ParamArray para recibir un array de parámetros opcionales. vamos a ver el código "bueno" de Visual Basic 2005.Pero como no debemos "acostumbrarnos" a desactivar Option Strict.Comprobamos que en Visual Basic 2005 tenemos otra forma de incrementar el contenido de una variable: t += CInt(n(i)) es lo mismo que t = t + CInt(n(i)). . Tampoco se permite tener parámetros opcionales y ParamArray en la misma función. aunque se sigue soportando. que aunque parezca un snobismo.

En VB6 es imposible hacer esto. el valor que devuelva sea de ese mismo tipo. sino cómo podemos usar esas funciones. ya que será el compilador el que decida la más adecuada al código que usemos. n2 As Integer) As Integer Return n1 + n2 End Function Function Suma(n1 As Double. no tenemos que preocuparnos de cual vamos a usar. 22) . n2 As Double) As Double Return n1 + n2 End Function Como podemos comprobar las dos funciones tienen el mismo nombre. 22) ) ' En este caso se usará la que recibe valores de tipo Double MsgBox( Suma(10. según el tipo de datos usado. Ahora veremos el porqué. Supongamos que queremos tener dos funciones (o más) que nos permitan hacer operaciones con diferentes tipos de datos. Con Visual Basic 2005 podemos sobrecargar funciones.5. tenemos dos funciones que se llaman igual pero una recibe valores de tipo entero y la otra de tipo decimal: Function Suma(n1 As Integer. la primera acepta dos parámetros de tipo Integer y la segunda de tipo Double. y que. pero tanto una como otra reciben parámetros de tipos diferentes. se usará la que recibe dos valores enteros MsgBox( Suma(10.Sobrecarga de métodos y propiedades La sobrecarga de funciones (realmente de métodos y propiedades). pero lo interesante no es que podamos hacerlo. En este ejemplo. realmente no es lo mismo. Aunque nos pueda parecer que la sobrecarga de métodos la podemos "simular" en VB6 con los parámetros opcionales. por ejemplo: ' En este caso. ya sea en número o en tipo. pero en ese caso ya no estaremos usando la sobrecarga. En el código anterior tenemos dos funciones llamadas Suma. Salvo que creemos dos funciones con nombres diferentes. Lo interesante es que cuando queramos usarlas. es una característica que nos permite tener una misma función con diferentes tipos de parámetros.

Lista de parámetros soportados por un método Tal como comentábamos hace unas líneas.10. Optional n2 As Integer = 33) As Integer . ya que el compilador puede producir un error si esa función entra en conflicto con otra "sobrecargada"! Mejor lo vemos con un ejemplo: Function Suma(n1 As Integer. en VB6 se puede simular la sobrecarga mediante los parámetros opcionales. También podemos tener sobrecarga usando una cantidad diferente de parámetros. En el segundo ejemplo de uso. Nota: Para que exista sobrecarga. Pero esa "simulación" nos viene como anillo al dedo para dar un consejo o advertencia: ¡Cuidado con las funciones que reciben parámetros opcionales. intentará usar esta última. Cuando. ya que esta nueva función recibe tres parámetros en lugar de dos: Function Integer Suma(n1 As Integer.El compilador de Visual Basic 2005 es el que decide que función usar. podemos añadir esta declaración al código anterior sin que exista ningún tipo de error. el que mejor coincide es el de los dos parámetros de tipo Double. no en el tipo del valor devuelto. tal como vemos en la Figura 2. nos mostrará una lista de opciones indicándonos las posibilidades de sobrecarga que existen y entre las que podemos elegir. n3 As Integer) As Return n1 + n2 + n3 End Function Por tanto. aunque éstos sean del mismo tipo. la diferencia debe estar en el número o en el tipo de los parámetros. n2 As Integer. queremos usar los métodos sobrecargados. Por ejemplo. aunque realmente no es lo mismo.10: Figura 2. esa decisión la toma a partir de los tipos de parámetros que hayamos indicado. desde el IDE de Visual Studio 2005. cuando el compilador se encuentre con una llamada a la función Suma en la que se usen tres parámetros.

Hasta aquí todo como en VBScript/VB6. el programa no compilará. como sabemos. por tanto si realizamos cambios dentro de la función. serán tratados como parámetros por valor. ya que en VBScript/VB6 también podemos usar ByVal o ByRef para indicar al compilador cómo debe tratar a los parámetros. porque. en los parámetros de las funciones también podemos tenerlos.Return n1 + n2 End Function Si tenemos esta declaración además de las anteriores. ya que si no indicamos si es por valor o por referencia. da igual que lo declaremos por valor o por referencia. el runtime antes de llamar a la función hace una copia de ese parámetro y pasa la copia a la función. para que no haya ningún tipo de dudas. ese cambio si que se verá reflejado en el parámetro usado al llamar a la función. el compilador no sabrá si usar esta última o la primera que declaramos. por tanto producirá un error. el compilador pasa una referencia que apunta a la dirección de memoria en la que están los datos. las variables de los tipos por referencia siempre contienen una referencia a los datos. Nota: Hay que tener en cuenta que si pasamos un objeto a una función. Lo que cambia en Visual Basic 2005 es que ahora los parámetros en los que no se indique si es por valor (ByVal) o por referencia (ByRef). Nota: Si usamos el IDE de Visual Studio para escribir el código. ya que en ambos casos se pasa una referencia a la dirección de memoria en la que están los datos. no los datos en sí. no debemos preocuparnos de este detalle. En VBScript/VB6 era al revés. esto tampoco es una novedad de Visual Basic 2005. por tanto cualquier cambio que hagamos a ese parámetro dentro de la función no afectará al valor usado "externamente". En el caso de que el parámetro sea por referencia (ByRef). Parámetros por valor y parámetros por referencia Al igual que tenemos dos tipos de datos diferentes. ya que si hacemos una llamada a la función Suma con dos parámetros enteros. . automáticamente le añadirá la palabra clave ByVal. Cuando un parámetro es por valor (ByVal).

Ver video 1 de esta lección (Clases 2: Los miembros de las clases) Ver video 2 de esta lección (Clases 3: Las propiedades) Ver video 3 de esta lección (Clases 4: Accesibilidad) .

que por otro lado son importantes. pero hasta que no tenga una "referencia" a un objeto de ese tipo no podremos usarla. Esa variable. veamos algunos ejemplos y así aclararemos esas diferencias. Lo primero que tenemos que hacer es declarar una variable del tipo que queremos instanciar. salvo en pequeños detalles. sabrá todo lo que hay que saber sobre una clase Cliente. esto lo hacemos usando la instrucción Dim: Dim c As Cliente Con esta línea de código lo que estamos indicando al Visual Basic es que tenemos intención de usar una variable llamada c para acceder a una clase de tipo Cliente. cuando llegue el momento de usarla. La forma de crear esos objetos en Visual Basic 2005 no ha cambiado con respecto al VBScript/VB6. La asignación de una referencia a un objeto Cliente podemos hacerla de dos formas distintas: La primera es creando un nuevo objeto en la memoria: c = New Cliente .Instanciar: Crear un objeto en la memoria Una vez que tenemos una clase definida. lo único de lo que disponemos es de una especie de plantilla o molde a partir del cual podemos crear objetos en memoria.

recibiremos un error. el objeto se crea en la memoria y se asigna a la variable.NET) que ya no queremos usar más ese objeto. ya que se supone que sí está creado. si en VBScript/VB6 asignamos un valor nulo (Nothing) a una variable declarada de esta forma y acto seguido usamos la variable. ya que para "asignar" a una variable un nuevo objeto tenemos que usar la instrucción Set. le estamos diciendo al CLR (el runtime de . si asignamos un valor nulo a una variable. A partir de este momento. en Visual Basic 2005 ya no es necesario el uso de esa instrucción. el comportamiento es muy diferente al de Visual Basic 2005. Ese trabajo extra consiste en comprobar si el objeto al que queremos acceder ya está creado. esto tampoco es una novedad. por tanto podremos usarla para asignarle valores y usar cualquiera de los miembros que ese tipo de datos contenga: c.Apellidos = "Ruiz Rodríguez" Declarar y asignar en un solo paso Con las clases o tipos por referencia también podemos declarar una variable y al mismo tiempo asignarle un nuevo objeto. Veamos primero cómo hacerlo y después entraremos en detalles. Dim c As New Cliente O también: Dim c As Cliente = New Cliente Las dos formas producen el mismo resultado. Lo que debemos tener muy presente es que además de la sobrecarga de trabajo que añade VBScript/VB6 a este tipo de instanciación. Por ejemplo. de hecho si la usamos. si después queremos volver a usar la variable. aunque sí lo es la forma de comportarse. En VBScript/VB6 este tipo de declaración y asignación no era recomendable. primero lo crea y después lo usa. por tanto lo elimina de la memoria. el inconveniente es que todas estas comprobaciones las realiza ¡cada vez que usemos la variable! En Visual Basic 2005 este comportamiento ya no es así. a partir de ese momento no se comprueba si ya está creado o no.Nota: En VBScript/VB6 esta forma de crear un nuevo objeto produciría un error. el motor en tiempo de ejecución (runtime) crea un nuevo objeto y asunto arreglado.Nombre = "Antonio" c. por tanto es recomendable usar la primera. Pero en Visual Basic 2005. ya que añade trabajo extra al compilador de VB. en caso de que no sea así. la variable c tiene acceso a un nuevo objeto del tipo Cliente. .

ya que en Visual Basic 2005 no existe la auto-instanciación. también podemos tener constructores sobrecargados.. no es necesario definir el constructor. Esto es así porque todas las clases deben implementar un constructor. lo hará el compilador de Visual Basic 2005. (con New). de no hacerlo.debemos crear otro objeto. abrir un fichero o cargar una imagen gráfica. se producirá un error. en caso de que no necesitemos realizar ningún tipo de inicialización. En VBScript/VB6 el constructor es el método Class_Initialize. En el constructor de una clase podemos incluir el código que creamos conveniente. pero realmente solamente deberíamos incluir el que realice algún tipo de inicialización. Constructores parametrizados De la misma forma que podemos tener métodos y propiedades sobrecargadas.Now End Sub End Class De esta forma podemos crear un nuevo Cliente y acto seguido comprobar el valor del campo FechaCreacion para saber la fecha de creación del objeto. Si nuestra clase Cliente tiene un campo para almacenar la fecha de creación del objeto podemos hacer algo como esto: Class Cliente Public Nombre As String Public Apellidos As String Public FechaCreacion As Date ' Public Sub New() FechaCreacion = Date. etc. aunque en algunos de estos casos nos facilitará la tarea una nueva característica que VBScript/VB6 no tiene. En los constructores también podemos hacer las inicializaciones que. ya que el propio compilador lo hará por nosotros. Sin embargo en Visual Basic 2005 el constructor es un método de tipo Sub llamado New. ya que debemos recordar que . por tanto si nosotros no lo definimos. El constructor: El punto de inicio de una clase Cada vez que creamos un nuevo objeto en memoria estamos llamando al constructor de la clase. por ejemplo permitan a la clase a conectarse con una base de datos.

. podemos indicar el nombre y apellidos del cliente o cualquier otro dato que creamos conveniente.Now End Sub End Class Teniendo esta declaración de la clase Cliente. losApellidos As String) Nombre = elNombre Apellidos = losApellidos FechaCreacion = Date. y como todos los métodos y propiedades de Visual Basic 2005. por ejemplo un fichero a abrir o. podemos crear nuevos clientes de dos formas: Dim c1 As New Cliente Dim c2 As New Cliente("Jose". "Sánchez") Como podemos comprobar. podemos ampliar la clase definida anteriormente para que también acepte la creación de nuevos objetos indicando el nombre y los apellidos del cliente. un constructor realmente es un método de tipo Sub.en Visual Basic 2005. La ventaja de tener constructores que admitan parámetros es que podemos crear nuevos objetos indicando algún parámetro. Class Cliente Public Nombre As String Public Apellidos As String Public FechaCreacion As Date ' Public Sub New() FechaCreacion = Date. en el caso de la clase Cliente. en ciertos casos es más intuitiva la segunda forma de crear objetos del tipo Cliente. además de que así nos ahorramos de tener que asignar individualmente los campos Nombre y Apellidos.Now End Sub ' Public Sub New(elNombre As String. Para comprobarlo. también admite la sobrecarga.

En ese segundo constructor también asignamos la fecha de creación. nos interesa saber siempre la fecha de creación. la verdad es que nos encontraríamos con mucha "duplicidad" de código. al igual que en VBScript/VB6.New() para llamar al constructor sin parámetros. . podemos hacer esto otro: Class Cliente Public Nombre As String Public Apellidos As String Public FechaCreacion As Date ' Public Sub New() FechaCreacion = Date. ya que. una instrucción tiene preferencia sobre el nombre de un método. losApellidos As String) New() Nombre = elNombre Apellidos = losApellidos End Sub End Class Es decir. siempre. podemos recurrir al objeto especial Me el cual nos sirve.Esta declaración de la clase Cliente la podríamos haber hecho de una forma diferente. pero si en lugar de una inicialización necesitáramos hacer varias. por tanto. ya que New es una palabra reservada que sirve para crear nuevos objetos y. Por un lado tenemos un constructor por omisión (el que no recibe parámetros) en el que asignamos la fecha de creación y por otro el constructor que recibe los datos del nombre y apellidos. para que esa declaración de la clase Cliente funcione. en lugar de asignar los datos en dos lugares diferentes. consiguiendo que también se asigne la fecha. Y no compila por la razón tan "simple" de que aquí el compilador de Visual Basic 2005 no sabe cual es nuestra intención. desde el constructor con argumentos llamamos al constructor que no los tiene.Now End Sub ' Public Sub New(elNombre As String. Por tanto. así que. En este ejemplo. por su simpleza no es realmente un problema repetir la asignación de la fecha. se instancie como se instancie la clase. debemos usar Me. para representar al objeto que actualmente está en la memoria. Esta declaración de la clase Cliente realmente no compilará.

en el caso de Me. no podremos crear un nuevo objeto Cliente. también tienen un sitio que se ejecutará cuando el objeto creado en la memoria ya no sea necesario. Pero hay ocasiones en las que nos puede interesar que no exista un constructor sin parámetros.New. El destructor: El punto final de la vida de una clase De la misma forma que una clase tiene su punto de entrada o momento de nacimiento en el constructor.11. tanto Sub como New se muestran coloreadas. ya que en este caso New es el nombre de un procedimiento y los procedimientos no son parte de las instrucciones y tipos de . Figura 2. tal como vemos en la Figura 2. pero este no es el motivo de esta nota. siempre es un constructor sin parámetros. y cuando lo hace automáticamente. sin embargo cuando usamos Me. (NIF). Coloreo erróneo de New Cuando Visual Basic 2005 no crea un constructor automáticamente Tal como hemos comentado. por ejemplo.NET. si definimos un constructor con parámetros en una clase y queremos que también tenga uno sin parámetros. lo tenemos que definir nosotros mismos. podemos crear una clase Cliente que solo se pueda instanciar si le pasamos.11. por ejemplo el número de identificación fiscal. solo se colorea Me y no New que es correcto. si nosotros no definimos un constructor (Sub New). lo que no debe confundirnos es que cuando declaramos Sub New. Seguramente por ese motivo. si nosotros definimos un constructor con parámetros. cuando solo se debería colorear Sub. tal y como lo hace el de VBScript/VB6. . VBScript/VB6 no la colorea. nos aseguramos siempre de que el NIF siempre esté especificado. Por tanto. lo hará el propio compilador de Visual Basic 2005. cuando acabe la vida del objeto creado. en caso de que no se indique ese dato. es decir. Visual Basic 2005 no crea uno automáticamente sin parámetros. de esta forma.Nota: El IDE de Visual Studio 2005 colorea las instrucciones y tipos propios del lenguaje.

ya que. Nunca podremos tener la certeza de cuando se destruye. El propio CLR se encargará de llamar a ese método cuando el objeto ya no sea necesario. Esto es así debido a que en . y esto es algo que. En VBScript/VB6. puede ser un inconveniente. según que casos. pero ese método debemos llamarlo de forma manual. el cual se hereda de la clase Object. el destructor es el método Class_Terminate. Este recolector de objetos no usados se encarga de comprobar constantemente cuando un objeto no se está usando y es el que decide cuando hay que llamar al destructor. si nuestra clase hace uso de recursos externos que necesiten ser eliminados cuando la el objeto ya no se vaya a seguir usando. aunque este último tiene un significado especial y por convención solo debemos usarlo siguiendo las indicaciones de la documentación.NET la forma en que se destruyen los objetos es diferente. debemos definir un método que se encargue de liberarlos y a ese método debemos encargarnos de llamarlo cuando ya no lo necesitemos.El destructor de Visual Basic 2005 es un método llamado Finalize.NET existen formas de hacer que esa llamada sea automática. Ver video de esta lección (Clases 5: Constructores) . por ejemplo un fichero o una base de datos. GC). Debido a esta característica de .NET los objetos no se destruyen inmediatamente y existe un "sistema" que se encarga de realizar esta gestión de limpieza: El recolector de basura o de objetos no usados (Garbage Collector. es que en VBScript/VB6 si a un objeto le asignamos un valor nulo (Nothing) el destructor se ejecuta inmediatamente y el objeto se elimina de la memoria. Por definición a este tipo de métodos se les suele dar el nombre Close o Dispose.NET. La principal diferencia con VBScript/VB6 en lo referente a la forma en que se destruyen los objetos. incluso si le asignamos un valor nulo. Recomendación: Si nuestra clase utiliza recursos externos. pero en . debemos definir un método que sea el encargado de realizar esa liberación. nunca tenderemos la seguridad de que se llame en el momento oportuno. aunque en . por tanto no es necesario que escribamos nada en él.

Visual Basic 2005 nos permite crear nuestros propios tipos por valor. por tanto es de esperar que también exista una instrucción para crear nuestros tipos por valor. ya que es un tipo por valor y los tipos por valor no necesitan ser instanciados para que existan. ya que el propio compilador siempre se encarga de crearlo. tal como tendremos oportunidad de comprobar en esta lección.Estructuras: Tipos por valor definidos por el usuario De la misma forma que podemos definir nuestros propios tipos de datos por referencia. usamos la "instrucción" Class. Nota: El equivalente en VB6 a una estructura de Visual Basic 2005 es Type (se le solía denominar tipo definido por el usuario o UDT) aunque es solo eso: un parecido. por eso en Visual Basic 2005 a los tipos por valor definidos por el usuario se denominan estructuras. Para crear nuestros tipos de datos por referencia. Las estructuras pueden contener los mismos miembros que las clases. aunque algunos de ellos se comporten de forma diferente o al menos tengan algunas restricciones. y esa instrucción es: Structure. Otra de las características de las estructuras es que no es necesario crear una instancia para poder usarlas. para así poder inicializar todos los campos definidos. al menos al 100%. como que los campos definidos en las estructuras no se pueden inicializar al mismo tiempo que se declaran o no pueden contener constructores "simples". pero realmente no es equivalente. .

sería algo redundante. es decir. podemos tener varias sobrecargas de constructores parametrizados en las estructuras. por tanto deberíamos tener la precaución de no crear estructuras con muchos campos o con muchos miembros. tal como ocurre con cualquier método o como ocurre en las clases. Las estructuras siempre se almacenan en la pila. Structure Punto Public X As Integer Public Y As Integer End Structure Para usarla podemos hacer algo como esto: Dim p As Punto p. Por tanto. ya que esto implicaría un mayor consumo del "preciado" espacio de la pila. La forma de definir esos constructores es como vimos en las clases: usando distintas sobrecargas de un método llamado New.Y = 75 También podemos usar New al declarar el objeto: Dim p As New Punto Aunque en las estructuras. en el caso de las estructuras también podemos usar la palabra clave Me para referirnos a la instancia actual. tal como ocurre en el constructor mostrado en la siguiente definición de la estructura Punto. Constructores de las estructuras Tal y como hemos comentado. . siempre existe y es el que el propio compilador de Visual Basic 2005 define.X = 100 p. este constructor no lo podemos definir nosotros. si queremos agregar algún constructor a una estructura.Definir una estructura Las estructuras se definen usando la palabra Structure seguida del nombre y acaba usando las instrucciones End Structure. El siguiente código define una estructura llamada Punto en la que tenemos dos campos públicos. usar New. Esto es particularmente práctico cuando los parámetros del constructor se llaman de la misma forma que los campos declarados en la estructura. las estructuras siempre definen un constructor sin parámetros. este debe tener parámetros y.

deberíamos indicarlo a los usuarios de nuestra estructura y proveer un constructor que realice las inicializaciones correspondientes. las variables declaradas a nivel del tipo. lo más que conseguiríamos al asignarle un valor nulo (Nothing) sería eliminar el contenido de la variable. pero nunca podemos destruir ese valor. ByVal y As Integer) Me.Y = y End Sub End Structure Nota: Tanto en las estructuras como en las clases podemos tener constructores compartidos. los miembros o elementos que podemos definir en una estructura son los mismos que ya vimos en las clases. no podemos destruir este tipo de datos. Por tanto aquí veremos las diferencias que existen al usarlos en las estructuras. en el caso de las estructuras. si necesitamos que los campos tengan algún valor inicial antes de usarlos.Structure Punto Public X As Integer Public Y As Integer ' Sub New(ByVal x As Integer.X = x Me. Por tanto. en las estructuras no podemos definir destructores. este tipo de constructor es el único que podemos declarar sin parámetros. Por tanto. La principal diferencia con respecto a las clases. pero debemos recordar que ese . son los campos. que en el caso de los campos de tipo numéricos es un cero. Campos Como vimos. Los miembros de una estructura Como hemos comentado. Destructores de las estructuras Debido a que las estructuras son tipos por valor y por tanto una variable declarada con un tipo por valor "contiene el valor en si misma". es que los campos de una estructura no pueden inicialiarse en la declaración y el valor que tendrán inicialmente es un valor "nulo".

si estos tipos fuesen por referencia. estén o no compartidos. para usar los tipos por valor no es necesario instanciarlos explícitamente. Métodos y otros elementos El resto de los miembros de una estructura se declaran y usan de la misma forma que en las clases. pero en el caso de las estructuras (y de los tipos por valor). dejando intacto el valor original de la variable p. Cómo usar las estructuras Tal como hemos comentado las estructuras son tipos por valor. métodos y/o propiedades.constructor debe tener algún parámetro.X vale 200 En este trozo de código definimos e instanciamos una variable del tipo Punto. si bien debemos tener en cuenta que el modificador de accesibilidad predeterminado para los miembros de una estructura es Public. a continuación declaramos otra variable del mismo tipo y le asignamos la primera. Veámoslos con un ejemplo. . ya que el predeterminado sin parámetros no podemos "reescribirlo". tanto una como la otra estarían haciendo referencia al mismo objeto en memoria.X = 200 ' p. aunque no las hayamos instanciado. y cualquier cambio realizado a cualquiera de las dos variables afectarían al mismo objeto. Por tanto. a diferencia de las clases o tipos por referencia. Otro detalle a tener en cuenta es que en una estructura siempre debe existir al menos un evento o un campo no compartido. por tanto la asignación del valor 200 al campo X de la variable p1 solo afecta a esa variable. 75) Dim p1 As Punto p1 = p p1. Esta característica de las estructuras nos permite hacer copias "reales" no copia de la referencia (o puntero) al objeto en memoria como ocurre con los tipos por referencia. ya que el mero hecho de declararlos indica que estamos creando un nuevo objeto en memoria. no se permiten estructuras en las que solo tienen constantes.X vale 100 y p1. (incluso si son campos declarados con D¡m). cada cambio que realicemos se hará sobre un objeto diferente. estos campos serán accesibles por cualquier variable declarada y cualquier cambio que realicemos en ellos se verá reflejado en el resto de "instancias" de nuestro tipo. pero como tendremos oportunidad de ver. Dim p As New Punto(100. cada variable definida como un tipo de estructura será independiente de otras variables declaradas. Los únicos campos que podemos inicializar al declararlos son los campos compartidos.

Ver video de esta lección (Estructuras) .

la clase o la estructura donde se ha declarado. A continuación veremos con detalle los ámbitos en los que podemos declarar los distintos elementos de Visual Basic 2005. podremos acceder a él desde otros puntos de nuestro código. Ámbito Dependiendo de donde declaremos un miembro o un tipo. Por ejemplo. la accesibilidad depende de cómo declaremos cada uno de esos elementos. también estarán disponibles en los procedimientos declarados en el módulo · · . dependiendo de dónde y cómo estén declarados los tipos de datos y los miembros definidos en ellos. Recordemos que el ámbito es el alcance con el que podemos acceder a un elemento y depende de dónde esté declarado. o lo que es lo mismo.Accesibilidad y ámbito Tal y como comentamos anteriormente. Ámbito de módulo: Disponible en todo el código del módulo. · Ámbito de bloque: Disponible únicamente en el bloque de código en el que se ha declarado. éste tendrá mayor alcance o cobertura. Cualquier variable declarada dentro de un procedimiento (método o propiedad) solo estará accesible en ese procedimiento y en cualquiera de los bloques internos a ese procedimiento. Ámbito de procedimiento: Disponible únicamente dentro del procedimiento en el que se ha declarado. si declaramos una variable dentro de un bucle For o un If Then. tendremos o no acceso a esos elementos. por otro lado. Las variables con ámbito a nivel de módulo. esa variable solo estará accesible dentro de ese bloque de código. dependiendo del ámbito en el que usemos un elemento.

Ámbito de espacio de nombres: Disponible en todo el código del espacio de nombres. End If Next ' . En VBScript/VB6 los ámbitos disponibles solamente eran los de módulo y procedimiento. Nota: Por regla general. cuando declaramos una variable en un ámbito. En Visual Basic 2005 podemos definir una variable dentro de un bloque de código. Do. Select). estructuras y enumeraciones. en ese caso dicha variable solo será accesible dentro de ese bloque. Ámbito de bloque En los siguientes ejemplos veremos cómo podemos definir variables para usar solamente en el bloque en el que están definidas.· (clase o estructura) y por extensión a cualquier bloque dentro de cada procedimiento. dentro de un procedimiento podemos tener varios de estos bloques y por tanto podemos definir variables "internas" a esos bloques: Dim n As Integer = 3 ' For i As Integer = 1 To 10 Dim j As Integer j += 1 If j < n Then '. Los bloques de código en los que podemos declarar variables son los bucles. como veremos a continuación.. Aunque. en estos casos.. aunque veremos que en Visual Basic 2005 existen ciertas restricciones dependiendo de dónde declaremos esas variables. estén o no dentro de un bloque de código. y los bloques condicionales. Este es el nivel mayor de cobertura o alcance. dicha variable "ocultará" a otra que tenga el mismo nombre y esté definida en un bloque con mayor alcance. Por ejemplo. While). (If. cualquier variable declarada en un procedimiento oculta a una definida en un módulo. (For. en un procedimiento solamente podremos definir variables que no se oculten entre sí. ya que los procedimientos solamente se pueden declarar dentro de un tipo. aunque en este nivel solo podemos declarar tipos como clases.

En el primer bucle For. no habrá ningún problema para . que nada tiene que ver con el resto de variables declaradas con el mismo nombre en los otros bloques. Lo mismo ocurre con la variable j. En el primer If definimos otra variable j. pero esa solo será accesible dentro de este bloque If y por tanto no tiene ninguna relación con la definida en el bucle For anterior. a esa variable la podemos acceder solo desde el propio bucle Do y cualquier otro bloque de código interno. Error al ocultar una variable definida en un procedimiento Esta restricción solo es aplicable a las variables declaradas en el procedimiento. definimos la variable i como la variable a usar de contador. en el que nuevamente declaramos una variable llamada i.12.If n < 5 Then Dim j As Integer = n * 3 End If ' Do Dim j As Integer For i As Integer = 1 To n j += i Next If j > 10 Then Exit Do Loop La variable n estará disponible en todo el procedimiento. Figura 2.12. esta variable solamente estará accesible dentro de este bucle For. el compilador de Visual Basic 2005 nos indicará que no podemos ocultar una variable previamente definida fuera del bloque. como es el caso del bucle For. ya que al estar declarada en el procedimiento. tal como podemos ver en la Figura 2. Lo único que no podemos hacer en cualquiera de esos bloques. por tanto podemos acceder a ella desde cualquiera de los bloques. ya que si declaramos una variable a nivel de módulo. En el bucle Do volvemos a definir nuevamente una variable j. es declarar una variable llamada n.

Nombre & ". salvo cuando están en el mismo nivel de ámbito. si en VBScript/VB6 declaramos una variable con el mismo nombre. tendremos que usar la instrucción o palabra clave Me. las variables declaradas dentro de un tipo de datos serán visibles desde cualquier parte de ese tipo. ese ámbito incluye también cualquier bloque de código declarado dentro del procedimiento. siempre se usará el estado de mayúsculas/minúsculas de la última definición. si bien. podremos acceder a esas variables "externas" indicando el nombre completo del módulo o bien usando la instrucción Me. siempre teniendo en cuenta las restricciones mencionadas en los casos anteriores. En el siguiente código. en Visual Basic 2005 no se cambia automáticamente las mayúsculas y minúsculas de las variables. . para acceder a la variable declarada en la clase. y como hemos visto. definimos una clase en la que tenemos un campo llamado Nombre. Esto es así porque en un procedimiento podemos declarar variables que se llamen de la misma forma que las declaradas a nivel de módulo. también definimos un método en el que internamente se utiliza una variable llamada nombre.usarla dentro de un bloque.NET. tal como vimos en el código del constructor parametrizado de la estructura Punto. si bien. nos estamos refiriendo a una clase. en cambio. Estas variables ocultarán a las que se hayan declarado fuera del procedimiento. aunque esté en un ámbito diferente. interno= " & nombre End Function End Class En este ejemplo. Ámbito de procedimiento Las variables declaradas en un procedimiento tendrán un ámbito o cobertura que será el procedimiento en el que está declaradas. aunque éstas ocultarán a las del "nivel" superior. Pero mejor veámoslo con un ejemplo. Ámbito de módulo Cuando hablamos de módulos. el hecho de que una variable esté declarada con la letra ene en mayúscula o en minúscula no implica ninguna diferencia. ya que Visual Basic 2005 al igual que VBScript/VB6 no hace distinciones de este tipo. a una estructura o a cualquier otro tipo de datos que nos permita . Public Class Cliente Public Nombre As String = "Juan" Function Mostrar() As String Dim nombre As String = "Pepita" Return "Externo= " & Me. En estos casos. dependiendo del tipo de módulo.

Int32 End Class End Namespace El problema es que el compilador de Visual Basic 2005 nos indicará que el tipo Int32 no está definido. por tanto para poder acceder al tipo Int32 definido en el espacio de nombres "global" System de . si definimos un tipo en un espacio de nombres. es decir.NET tendremos que usar la instrucción Global. la declaración que nosotros hemos hecho de System. en cada caso se aplicará el ámbito correspondiente y. tal como vemos en la Figura 2.13: . para evitar conflictos de ámbitos.NET Framework. tal como vimos anteriormente. y sirven para contener definiciones de clases. enumeraciones y delegados como ya comentamos en el primer módulo. podemos usar la palabra clave Global para acceder a los que se han definido de forma "global" en .Ámbito de espacio de nombres Los espacios de nombres son los contenedores de tipos de datos de mayor nivel. si tenemos el siguiente código en el que definimos una clase dentro de un espacio de nombres llamado System y queremos acceder a uno de los tipos definidos en el espacio de nombres System de . La palabra clave Global En Visual Basic 2005 podemos definir espacios de nombres cuyos nombres sean los mismos que los definidos en el propio .NET. Al igual que ocurre en el resto de ámbitos "inferiores". por suerte el IDE de Visual Studio 2005 reconoce este tipo de error y nos ofrece ayuda para poder solventar el conflicto. ya que intentará buscarlo dentro del ámbito que actualmente tiene. estructuras.NET. tendremos un problema: Namespace System Class Cliente Public Nombre As String Public Edad As System. tendremos que usar nombres únicos para poder acceder a los nombres definidos en niveles diferentes. Por ejemplo. podemos usar ese mismo nombre para nombrar a un procedimiento o a una variable. Cualquier tipo definido en el ámbito del espacio de nombres estará disponible para cualquier otro elemento definido en el mismo espacio de nombres.

Dependiendo de la accesibilidad declarada tendremos distintos tipos de accesos a esos elementos.Figura 2. propiedades y campos. interfaces. por la sencilla razón de que los espacios de nombres de . podemos acceder a cualquier miembro público desde cualquier parte de nuestro código. Protected: Acceso limitado a la clase contenedora o a los tipos derivados de esta clase. Protected Friend: Acceso limitado al proyecto actual o a los tipos derivados de la clase contenedora. este acceso no restringido puede verse reducido dependiendo de dónde lo usemos.13. como veremos. Es el más restrictivos de todos los modificadores de accesibilidad y en el caso de los campos declarados en las clases (Class) equivale a usar Dim. Ayuda del IDE en los conflictos de espacios nombres globales Nota: Afortunadamente este conflicto con los espacios de nombres no será muy habitual para los desarrolladores que usemos el idioma de Cervantes. Este es modificador de accesibilidad con mayor "cobertura". Los modificadores de accesibilidad que podemos aplicar a los tipos y elementos definidos en nuestro código pueden ser cualquiera de los mostrados en la siguiente lista: · Public: Acceso no restringido. Accesibilidad La accesibilidad es la característica que podemos aplicar a cualquiera de los elementos que definamos en nuestro código. .NET Framework suelen estar definidos usando palabras en inglés. Visual Basic 2005 aplica este modificador de forma predeterminada a los procedimientos declarados en las clases. Aunque. estructuras. Friend: Acceso limitado al proyecto actual. · · · · Estos modificadores de accesibilidad los podemos usar tanto en clases. eventos. Este modificador solamente se usa con clases que se deriven de otras. Una mezcla de los dos modificadores anteriores. delegados. Private: Acceso limitado al tipo contenedor. métodos. enumeraciones.

Así mismo. Nota: La palabra clave Static.Aunque no serán aplicables en espacios de nombres (Namespace) ni clases de tipo Module. éste tendrá un ámbito de tipo Public si lo definimos en una estructura y si el lugar en el que lo declaramos es una clase (o Module). N. en este caso solo se puede aplicar el ámbito privado. sin embargo. aunque no podremos usar la instrucción Private. estos tendrán un ámbito igual que si le hubiésemos aplicado el modificador Public. así como de las variables declaradas con Dim y de los procedimientos en los que no se indican el modificador de accesibilidad. esto contrasta con el resto de variables declaradas en un procedimiento cuya duración es la misma que la vida del propio procedimiento. esa misma variable declarada en una clase (Class o Module) tendrá una accesibilidad Private. En la siguiente tabla tenemos la accesibilidad predeterminada de cada tipo (clase. éste será Friend.A. sino Dim o Static. Las accesibilidades predeterminadas La accesibilidad de una variable o procedimiento en la que no hemos indicado el modificador de accesibilidad dependerá del sitio en el que la hemos declarado. estructura. etc. (los miembros siempre son públicos) N. las variables no estáticas pierden el valor al terminar la ejecución del procedimiento.A. Public Class Module Structure Enum Friend Friend Friend Public Friend Interface Friend .A. Accesibilidad de las variables en los procedimientos Las variables declaradas dentro de un procedimiento solo son accesibles dentro de ese procedimiento. y nos permite definir una variable privada (o local) al procedimiento para que mantenga el valor entre diferentes llamadas a ese procedimiento. en estos dos casos siempre tendrán cobertura pública. si el elemento que declaramos es un procedimiento y no indicamos el modificador de ámbito. tiene el mismo significado que en VB6. Por ejemplo. si bien no se permite el uso de ningún modificador. en las estructuras si definimos los campos usando Dim.). Tipo del tipo de las variables de los declaradas con procedimientos Dim Private Friend Private Friend Public Public N. por tanto.

Tipo Class del tipo Public Friend Private Protected Protected Friend Public Friend Public Friend Private Public Friend Private Public Friend Private Protected Protected Friend de los miembros Public Friend Private Protected Protected Friend Public Friend Private Public Friend Private N. En esta otra tabla tenemos la accesibilidad permitida en cada tipo así como las que podemos indicar en los miembros de esos tipos. .4. Accesibilidades permitidas en los tipos Algunos de los modificadores que podemos indicar en los tipos dependen de dónde declaremos esos tipos. aunque en las interfaces y en las enumeraciones no se permiten declarar variables. accesible a todo el proyecto.A. La última columna es la correspondiente a los procedimientos.3.(no se pueden (no se declarar variables) indicarlo) Tabla 1. La accesibilidad predeterminada de los tipos permite Tal como podemos ver en la tabla 1. los modificadores Protected y Protected Friend solo podremos aplicarlos cuando están declaradas dentro de una clase (Class). en el resto de los casos será Public. (la que tienen cuando no se indica expresamente con un modificador). En la tercera columna tenemos la accesibilidad predeterminada cuando declaramos las variables con Dim. si está declarada a nivel de espacio de nombres será Friend. aunque en el caso de las enumeraciones el modificador depende de dónde se declare dicha enumeración. de todos los tipos es Friend. por ejemplo. es decir. la accesibilidad predeterminada. Module Structure Enum Interface N. Siempre son públicos Tabla 1. En el caso de las clases e interfaces.A. en el caso de las interfaces no se puede aplicar ningún modificador de accesibilidad y de forma predeterminada son públicos. tan solo podremos indicar el modificador privado de las enumeraciones cuando estas se declaren dentro de un tipo.3.

si declaramos una clase con acceso Friend. ya que para acceder a los tipos declarados dentro de otros tipos siempre tendremos que indicar la clase que los contiene. incluso tipos Module. . no puede usarse como tipo anidado. excepto las enumeraciones. cualquier tipo que esta clase contenga siempre estará supeditado al ámbito de esa clase. aunque en estos casos no habrá ningún tipo de confusión. Una enumeración siempre puede usarse como tipo anidado.Anidado de tipos Tal como hemos comentado en el párrafo anterior. Por ejemplo. nunca estará más accesible que la clase contenedora. Tal como podemos comprobar. Friend Class Cliente Public Nombre As String Public Class Salario Public Importe As Decimal End Class End Class ' Para usar la clase Salario debemos declararla de esta forma: Dim s As New Cliente.4.4. Nota: Los espacios de nombres también pueden anidarse y contener a su vez cualquiera de los tipos mostrados en la tabla 1. pueden contener a su vez otros tipos. aunque lo declaremos como Public. ya que la única forma de acceder a una clase anidada es mediante la clase contenedora. En el siguiente código podemos ver cómo declarar dos clases "anidadas". por tanto el ámbito y accesibilidad de esos tipos dependen del ámbito y accesibilidad del tipo que los contiene. podemos declarar tipos dentro de otros tipos. La excepción es el tipo Module que aunque puede contener a otros tipos. para acceder a la clase Salario debemos indicar la clase Cliente. por tanto si declaramos otro tipo interno.Salario s.Importe = 2200 Los tipos anidables Cualquiera de los tipos mostrados en la tabla 1.

Namespace Uno Public Class Clase1 Public Nombre As String End Class End Namespace Namespace Dos Public Class Clase2 Public Nombre As String Sub Main() Dim c1 As New Uno. por ejemplo si la clase Cliente definida anteriormente está a su vez dentro del espacio de nombres Ambitos.Nombre = "Pepe" End Sub End Class End Namespace Esto mismo lo podemos aplicar en el caso de que tengamos dos clases con el mismo nombre en espacios de nombres distintos. . para poder hacerlo debemos indicar el nombre completo. al menos si la queremos usar desde cualquier otro tipo declarado dentro de ese espacio de nombres. cada uno de ellos declara una clase y desde una de ellas queremos acceder a la otra clase. al poder declarar tipos dentro de otros tipos y estos a su vez pueden estar definidos en espacios de nombres.El nombre completo de un tipo Tal como hemos visto.Salario. Por ejemplo. ya que en caso contrario.Cliente.Clase1 c1. podemos decir que el nombre "completo" de un tipo cualquiera estará formado por el/los espacios de nombres y el/los tipos que los contiene. en el siguiente código tenemos dos espacios de nombres que no están anidados. Aunque para acceder a la clase Cliente no es necesario indicar el espacio de nombres. el nombre completo será: Ambitos. el compilador de Visual Basic 2005 sería incapaz de saber a que clase queremos acceder.Cliente y el nombre completo de la clase Salario será: Ambitos. pero si nuestra intención es usarla desde otro espacio de nombre externo a Ambitos. en ese caso si que tendremos que usar el nombre completo.

si queremos indicar de forma . o también podemos encontrarnos en ocasiones en las que nos interese usar un nombre corto para acceder a las clases contenidas en un espacio de nombres. ya que mostrará una gran cantidad de clases. si tenemos el código anterior y hacemos la importación del espacio de nombres en el que está definida la clase Clase1: Imports Uno podremos acceder a esa clase de cualquiera de estas dos formas: Dim c1 As New Uno. Importación de espacios de nombres Tal como hemos comentado. Por ejemplo. de forma que al declarar una variable. el problema con el que nos podemos encontrar es que el IntelliSense de Visual Basic 2005 no sea de gran ayuda. podemos crear una especie de "Path". Para evitar estar escribiendo todos los espacios de nombres en los que está la clase que nos interesa declarar.Clase1 Dim c1 As New Clase1 Alias de espacios de nombres Si hacemos demasiadas importaciones de nombres. si esta no está definida en el espacio de nombres actual. el compilador busque en todos los espacios de nombres incluidos en esas rutas (paths). para poder acceder a una clase que no esté dentro del mismo espacio de nombres debemos indicar el "nombre completo". podemos usar una especie de acceso directo o para que lo entendamos mejor. en estos casos el compilador lo tomará como si todas las clases definidas estuvieran dentro del mismo espacio de nombres. aunque estos estén definidos en ficheros diferentes. Esto lo conseguimos usando la instrucción Imports seguida del espacio de nombres que queremos importar o incluir en el path de los espacios de nombres. Podemos usar tantas importaciones de espacios de nombres como necesitemos y estas siempre deben aparecer al principio del fichero.Nota: En el mismo proyecto podemos tener más de una declaración de un espacio de nombres con el mismo nombre. los espacios de nombres pueden contener otros espacios de nombres y estos a su vez también pueden contener otros espacios de nombres o clases. y seguramente nos resultará más difícil encontrar la clase a la que queremos acceder. justo después de las instrucciones Options. por ejemplo. y como hemos visto.

VisualBasic.14. En las figuras 1.15 podemos ver las dos formas de acceder a las clases del espacio de ese espacio de nombres. en el primer caso sin usar un alias y en el segundo usando el alias vb. Figura 2. Los miembros de un espacio de nombres usando el nombre completo .VisualBasic De esta forma podemos usar el "alias" vb para acceder a las clases y demás tipos definidos en ese espacio de nombres.explícita las clases de un espacio de nombres como el de Microsoft.14 1. podemos hacerlo de esta forma: Imports vb = Microsoft.

Figura 2.15. Acceder a los miembros de un espacio de nombres usando un alias Ver video 1 de esta lección (Ámbito y accesibilidad. herencia) Ver video 2 de esta lección (Ámbito 2) .

NET Framework no lo interpreta como tal. esos datos. Debido a que el uso de las propiedades realmente nos permite acceder a los valores de una clase (o tipo). de forma controlada. al menos en el fondo. realmente estamos definiendo un procedimiento con el cual podemos controlar cómo se acceden a esos datos. al menos en el sentido de que el propio . podemos poner en práctica una de las características de la programación orientada a objetos: la encapsulación. ya que se utilizan de la misma forma. Lo primero que debemos tener presente es que gracias a esta diferenciación que hace . dejando a las propiedades la posibilidad de que externamente se manipulen. De hecho en VBScript/VB6 si definimos una variable pública. De esta forma tendremos mayor control sobre cómo se acceden o se asignan los valores a esos datos. debemos diferenciar en nuestro código las propiedades de los campos. con respecto a como lo . se suelen confundir los campos con las propiedades. ésta se convierte en una propiedad de la clase. de forma que el campo sea el que realmente contenga el valor y la propiedad simplemente sea una especie de método a través del cual podemos acceder a ese valor. aunque en la práctica nos puede parecer que es así. que la manipulación de los datos que una clase contiene siempre se deben hacer de forma "interna" o privada a la clase. ya que al definir una propiedad.NET Framework. (realmente VBScript/VB6 también la hace). de forma. Normalmente una propiedad está relacionada con un campo.Propiedades Las propiedades son los miembros de los tipos que nos permiten acceder a los datos que dicho tipo manipula. Este concepto no ha cambiado. Pero no debemos dejarnos llevar por la comodidad y si no queremos perder funcionalidad. tal como hemos comentado. pero realmente un campo (o variable) público no es una propiedad. En Visual Basic 2005 casi ocurre lo mismo.

debemos hacerlo en partes. que nos permite acceder al valor de la propiedad. en VBScript/VB6 existen dos formas de asignar valores a una propiedad de una clase. siempre tendremos un campo relacionado con una propiedad. por otra parte. El campo será el que contenga el valor y la propiedad será la que nos permita manipular ese valor. lo hacemos mediante Property Let. aunque la forma de hacerlo en Visual Basic 2005 si que ha cambiado un poco. Definir una propiedad Debido a que una propiedad realmente nos permite acceder a un dato que la clase (o estructura) manipula. las debemos indicar en dos bloques dentro de la propia declaración de la propiedad. por ejemplo. las propiedades las declaramos usando la instrucción Property y la definición de la misma termina con End Property. En Visual Basic 2005 esas dos acciones. de hecho no se puede usar Set para realizar asignaciones a propiedades en VB2005. Veamos como definir una propiedad en Visual Basic 2005: Public Class Cliente Private _nombre As String Public Property Nombre() As String . el cual lo usamos cuando la propiedad representa un objeto y queremos asignar dicho objeto a la propiedad. ya que en estos lenguajes también podemos declarar procedimientos del tipo propiedad. En Visual Basic 2005. declaramos esa acción usando las instrucciones Property Get y para definir la parte de la propiedad que asigna un nuevo valor. pero en Visual Basic 2005 no existe ese "conflicto" en la forma de asignar los valores. ya que siempre que se asigna un valor a una propiedad se hace sin usar la instrucción Set. aunque el compilador de VBScript/VB6 realmente usará uno u otro según asignemos el valor directamente a la propiedad o usemos la instrucción Set para hacer esa asignación.hacemos con VBScript/VB6. si queremos definir cuando accedemos al valor. el bloque usado para asignar un valor a la propiedad se define mediante la instrucción Set y acaba con End Set. Propery Let. tal como tendremos ocasión de ver a continuación. Tal como indicamos en la nota anterior. La diferencia entre Let y Set es que el primero se usará en valores de tipos por valor y el segundo en tipos por referencia. Nota: En VBScript/VB6 realmente disponemos de tres bloques o partes en la definición de una propiedad: Property Get. Property Set. esto es prácticamente igual (o casi) que en VBScript/VB6. el bloque que nos permite acceder al valor de la propiedad estará indicado por la instrucción Get y acaba con End Get. la de lectura (GET) y asignación (LET). La diferencia principal es que en VBScript/VB6 cuando definimos una propiedad. que nos permite asignar un valor a la propiedad.

. de forma que el valor que representa no pueda ser cambiado.Now End Get End Property . y una vez que nos acostumbremos lo veremos como una forma más "compacta" de hacerlo. En Visual Basic 2005 también se hace de esa forma. este bloque tiene definido un parámetro (value) que representa al valor que queremos asignar a la propiedad. Propiedades de solo lectura En ciertas ocasiones nos puede resultar interesante que una propiedad sea de solo lectura.Get Return _nombre End Get Set(ByVal value As String) _nombre = value End Set End Property End Class Como podemos comprobar tenemos dos bloques de código. pero debemos indicar expresamente que esa es nuestra intención. El bloque Set es el usado cuando asignamos un valor a la propiedad. sino que debemos usar el modificador ReadOnly para que el compilador de Visual Basic 2005 acepte la declaración: Public ReadOnly Property Hoy() As Date Get Return Date. el bloque Get que es el que se usa cuando queremos acceder al valor de la propiedad. Por tanto no solo basta con definir solo el bloque Get. por tanto devolvemos el valor del campo privado usado para almacenar ese dato. esta forma de definir las propiedades no se diferencia demasiado a como lo hacemos en VBScript/VB6. En VBScript/VB6 para definir una propiedad de solo lectura bastaba con definir solo la parte Get de la propiedad. Aunque en Visual Basic 2005 las definiciones para obtener o asignar el valor de la propiedad se hacen en bloques definidos dentro de un procedimiento del tipo Property.

y el bloque Set como Private. podemos definir diferentes niveles de accesibilidad a cada uno de los dos bloques que forman una propiedad. Por ejemplo. pero al igual que ocurre con las propiedades de solo lectura. Por ejemplo. el salario de un empleado podríamos declararlo para que desde cualquier punto se pueda saber el importe. podríamos definir el bloque Get como público.Propiedades de solo escritura De igual forma. pero la asignación de dicho importe solo estará accesible para los procedimientos definidos en la propia clase: Public Class Empleado Private _salario As Decimal Public Property Salario() As Decimal Get Return _salario End Get Private Set(ByVal value As Decimal) _salario = value End Set . si queremos definir una propiedad que sea de solo escritura. (siempre accesible). debemos indicar expresamente que esa es nuestra intención. de forma que solo se puedan realizar asignaciones desde dentro de la propia clase. para ello usaremos la palabra clave WriteOnly: Public WriteOnly Property Password() As String Set(ByVal value As String) If value = "blablabla" Then ' ok End If End Set End Property Diferente accesibilidad para los bloques Get y Set En las propiedades normales (de lectura y escritura). solo definiremos el bloque Set.

porque en caso de que no se indique ninguna. Al menos podemos definir como predeterminada la que más nos interese. una propiedad por defecto puede ser de solo lectura y también de solo escritura o de lectura/escritura. Para evitar conflictos o tener que usar alguna instrucción "extra" para que se sepa si lo que queremos asignar es un valor o un objeto. ya que debido a como se realizan las asignaciones de objetos en . éste será el mismo que el de la propiedad. Aunque existen no son exactamente igual que en VB6. siempre debemos indicar la propiedad a la que queremos asignar el valor.NET (sin necesidad de usar Set).. En VBScript/VB6 podemos hacer esto mismo definiendo como público la declaración de Property Get y como privado la de la asignación: Property Let. Nota: El nivel de accesibilidad de los bloques Get o Set debe ser igual o inferior que el de la propiedad. en Visual Basic 2005 las propiedades predeterminadas siempre deben ser parametrizadas. En Visual Basic 2005 no podemos definir como predeterminada cualquier propiedad. el compilador interpretará que lo que queremos asignar es un objeto y no un valor a una propiedad. En VB6 podemos definir como propiedad predeterminada cualquiera de las propiedades de la clase. tener como mínimo un parámetro. al no indicar ningún modificador en el bloque Get. lo indicamos con el modificador de accesibilidad Private. Propiedades predeterminadas Una cosa que echamos en falta en Visual Basic 2005 son las propiedades predeterminadas. End Get End Property Como vemos en este ejemplo. . no podemos definir como público los bloques Get o Set.End Property End Class Para hacer que el bloque Set sea privado. es decir. aunque la forma de hacerlo es bastante "rebuscada" y poco intuitiva. por tanto si la propiedad la declaramos como Private.. Para indicar que una propiedad es la propiedad por defecto lo debemos hacer usando la instrucción Default: Default Public ReadOnly Property Item(ByVal index As Integer) As Empleado Get ' .

el tipo o número de argumentos deben ser distintos entre las distintas sobrecargas..Para usar esta propiedad. aunque debemos recordar que para que esa sobrecarga pueda ser posible. End Get End Property Default Public Property Item(ByVal index As String) As Empleado Get ' . aunque si así lo deseamos podemos indicarla.. no es necesario indicar el nombre de la propiedad. por ejemplo podríamos tener una sobrecarga que reciba un parámetro de tipo entero y otra que lo reciba de tipo cadena: Default Public ReadOnly Property Item(ByVal index As Integer) As Empleado Get ' . aunque en este caso no tendría mucha utilidad el haberla definido como propiedad por defecto: Dim e As New Empleado Dim e1 As Empleado = e(2) ' También podemos usarla indicando el nombre de la propiedad: Dim e2 As Empleado = e. al ser la propiedad por defecto... End Get Set(ByVal value As Empleado) ' End Set End Property .Item(2) Sobrecarga de propiedades predeterminadas Debido a que las propiedades predeterminadas de Visual Basic 2005 deben recibir un parámetro. podemos crear sobrecargas de una propiedad predeterminada.

por ejemplo. Por tanto es habitual que las clases de tipo colección sean las más indicadas para definir propiedades por defecto. Aunque no siempre el valor devuelto debe ser un elemento de una colección o array. Las propiedades predeterminadas tienen sentido en Visual Basic 2005 cuando queremos que su uso sea parecido al de un array. ya que podemos usar las propiedades predeterminadas para acceder a los miembros de una clase "normal".Incluso como vemos en este código una de las sobrecargas puede ser de solo lectura y la otra de lectura/escritura.ToString Case 2 Return Existencias. acceder a los miembros de la clase desde un bucle For. Si definimos una propiedad predeterminada como en el siguiente código: Public Class Articulo Public Descripción As String Public PrecioVenta As Decimal Public Existencias As Decimal Default Public ReadOnly Property Item(ByVal index As Integer) As String Get Select Case index Case 0 Return Descripción Case 1 Return PrecioVenta. de forma que se devuelva un valor según el parámetro indicado. Lo que realmente importa es que el número o tipo de parámetros de cada sobrecarga sea diferente. esto nos permitiría.ToString Case Else Return "" End Select End Get End Property End Class La podemos usar de esta forma: For i As Integer = 0 To 2 .

Console. es decir. Ver video de esta lección (Clases 3: Las propiedades) . Por convención. el nombre de la propiedad predeterminada suele ser Item. se use como indizador de la clase. cuando se usan como indizador. para que su uso se asemeje a un array.WriteLine( art(i) ) Next Resumiendo: Las propiedades predeterminadas en Visual Basic 2005 siempre deben tener un parámetro.

NET y cómo aplicar algunas de las definidas en la biblioteca base. etc. realmente estamos haciendo dos cosas: 1. solo definen los miembros.Definiendo una interfaz con cada uno de los miembros que la clase contiene: métodos.0. ¿Qué es una interfaz? Las interfaces son una forma especial de una clase. 2. podemos decir que una interfaz define cada uno de los miembros de una clase. si los métodos tienen parámetros. Desde ese punto de vista. ya que de hecho se utiliza con bastante frecuencia. También veremos que papel juegan en . que propiedades o eventos define la clase. En Visual Basic 6. En esta lección veremos que son las interfaces y como utilizarlas en nuestros proyectos. . cuantos y de que tipos son. veamos las interfaces desde el punto de vista de Visual Basic 6.Definiendo el código a utilizar por cada uno de esos miembros. cuando definimos una clase. es decir.0.NET Framework.Interfaces Las interfaces son un elemento bastante importante en . que tipo de método es. eventos. aunque la diferencia principal con las clases es que las interfaces no contienen código ejecutable. Para entenderlo mejor. propiedades. etc.

lo más que podemos hacer es definir una clase sin código ejecutable. En el siguiente código definimos una interfaz que contiene los cuatros tipos de miembros típicos de cualquier clase: Public Interface IPrueba Sub Mostrar() Function Saludo(ByVal nombre As String) As String Property Nombre() As String Event DatosCambiados() End Interface . End Interface Nota: Según las indicaciones de nomenclatura de . solo la "firma" o el prototipo de cada uno de esos miembros. Esa definición la haremos como cualquier otra.NET Framework. y como hemos indicado anteriormente. podemos decir que la interfaz de una clase indica los miembros que dicha clase expone. va aún más lejos. Para definir una interfaz en VB2005 tenemos que usar la instrucción Interface seguida del nombre y terminar la declaración con End Interface: Public Interface IAnimal '. ¿Qué contiene una interfaz? Al principio de esta lección hemos comentado que las interfaces no contienen código.. cuando queremos definir una interfaz en VB6. Es más. solo define los miembros que contiene.Por tanto. de hecho en Visual Basic 6. también estamos definiendo una interfaz. ya que las interfaces las definimos de forma independiente de las clases. cuando definimos una clase NO estamos definiendo una interfaz.. con la diferencia de que no incluimos ningún código.0 no hay forma de definir interfaces como algo independiente de una clase. se recomienda que todas las interfaces empiecen con una I mayúscula seguida del nombre al que hacer referencia la interfaz. Pero Visual Basic 2005. cuando en VB6 definimos una clase.

El siguiente método es una función que devuelve un valor de tipo String y recibe un parámetro también de tipo cadena. debe implementar. un medio para poner en práctica esta característica de la programación orientada a objetos. por tanto las interfaces pueden ser. (de hecho lo son). esa clase tiene todos los miembros de la interfaz. el polimorfismo es una característica que nos permite acceder a los miembros de un objeto sin necesidad de tener un conocimiento exacto de ese objeto (o de la clase a partir del que se ha instanciado). Tal como acabamos de ver. Por último. Cuando una clase implementa una interfaz está firmando un contrato con el que se compromete a definir todos los miembros que la clase define.El primer miembro de esta interfaz. por tanto podemos acceder a esa clase.3. tal como indicábamos en la tabla 2. lo único que tenemos que hacer es indicar el tipo de miembro y si recibe o no algún parámetro o argumento. A continuación definimos una propiedad que devuelve una cadena. Las interfaces y el polimorfismo Como comentamos anteriormente. lo único que tenemos que saber es que ese objeto tiene ciertos métodos (u otros miembros) a los que podemos acceder.Los miembros de las interfaces siempre son públicos. 2. definimos un evento. también implementa todos los miembros definidos en dicha interfaz. De esta forma nos aseguramos de que si una clase implementa una interfaz. es un método de tipo Sub que no recibe parámetros. . pero no el código a usar en cada uno de ellos. las interfaces solo definen los miembros. Veamos que nos quieren decir con esa frase. esa clase debe definir cada uno de los miembros que la interfaz expone. Dos cosas importantes sobre las interfaces: 1. Como podemos observar. Si una clase implementa una interfaz. o mejor dicho.No se pueden definir campos. desde un objeto del mismo tipo que la interfaz. Si en una clase indicamos que queremos "implementar" una interfaz. También hemos comentado que las interfaces representan un contrato entre las clases que las implementan. de hecho el propio compilador nos obliga a hacerlo. esto es así precisamente porque el papel que juegan las interfaces es el de solo indicar que es lo que una clase o estructura puede. lo primero con lo que nos solemos encontrar es que una interfaz es un contrato. Una interfaz es un contrato Siempre que leemos sobre las interfaces. que en principio pude sernos desconocida.

dejando para nosotros el trabajo de escribir el código.DatosCambiados Public Sub Mostrar() Implements IPrueba. por eso es el propio Visual Basic el encargado de crear automáticamente los métodos y propiedades que la interfaz implementa. el código que añadirá VB será el siguiente: Public Class Prueba Implements IPrueba Public Event DatosCambiados() Implements IPrueba.Mostrar End Sub Public Property Nombre() As String Implements IPrueba.Nombre Get End Get Set(ByVal value As String) End Set End Property . Usando la definición de la interfaz IPrueba que vimos antes. aunque solo inserta el "prototipo" de cada uno de esos miembros.Usar una interfaz en una clase Para poder utilizar una interfaz en una clase. o dicho de otra forma: para "implementar" los miembros expuestos por una interfaz en una clase debemos hacerlo mediante la instrucción Implements seguida del nombre de la interfaz: Public Class Prueba Implements IPrueba Y como comentábamos. cualquier clase que implemente una interfaz debe definir cada uno de los miembros de esa interfaz.

en ese caso simplemente cambiamos el nombre del método de la clase para que implemente el método Mostrar de la interfaz: Public Sub Imprimir() Implements IPrueba. si implementamos esta interfaz en una clase que solo utilizará la impresora. podemos acceder a esos miembros de forma directa. usando un objeto creado a partir de la clase: Dim prueba1 As New Prueba prueba1. realmente hace referencia al método de la interfaz. sino que también añade código extra a cada uno de esos miembros: la instrucción Implements seguida del nombre de la interfaz y el miembro al que se hará referencia. es que podemos usar nombres diferentes al indicado en la interfaz. Por ejemplo. cuando implementamos una interfaz también se crean automáticamente las definiciones de los miembros que contiene la interfaz. aunque el formato utilizado por VBScript/VB6 es: <Nombre de la interfaz> <guión bajo> <nombre del método>. Acceder a los miembros implementados Una vez que tenemos implementada una interfaz en nuestra clase. al método Mostrar lo podríamos llamar Imprimir que sería más adecuado.Public Function Saludo(ByVal nombre As String) As String _ Implements IPrueba. por ejemplo: Private Sub IPrueba_Mostrar(). es decir. aunque en la clase se llame de forma diferente. ya que en ese lenguaje. La utilidad de que en cada uno de los miembros se indique expresamente el método al que se hace referencia. Nota: Si el lector antes ha utilizado las interfaces en VB6. esto no le resultará extraño.Saludo End Function End Class Como podemos apreciar.Mostrar() . no solo ha añadido las definiciones de cada miembro de la interfaz.Mostrar End Sub De esta forma.

Para realizar esta comprobación podemos usar en una expresión If/Then la instrucción TypeOf.Mostrar() ¿Qué ha ocurre aquí? Como ya comentamos anteriormente. Implementación de múltiples interfaces En Visual Basic 2005.O bien de forma indirecta.Mostrar() End If De esta forma nos aseguramos de que el código se ejecutará solamente si la variable prueba1 contiene una definición de la interfaz IPrueba. de forma que si la variable indicada después de TypeOf contiene el tipo especificado después de Is. por tanto la variable interfaz1 está haciendo referencia al mismo objeto que prueba1. es normal que en Visual Basic tengamos algún mecanismo para descubrir si un objeto implementa una interfaz. Saber si un objeto implementa una interfaz Si las interfaces sirven para acceder de forma anónima a los métodos de un objeto. realmente lo que asignamos son referencias a los objetos creados en la memoria. cuando asignamos variables por referencia. Is. una misma clase puede implementar más de una interfaz. aunque esa variable solo tendrá acceso a los miembros de la clase Prueba que conoce. los miembros definidos en IPrueba. Si la clase define otros miembros que no están en la interfaz. la variable interfaz1 no podrá acceder a ellos. la condición se cumple: If TypeOf prueba1 Is IPrueba Then interfaz1 = prueba1 interfaz1. Para indicar que implementamos más de una interfaz podemos hacerlo de dos formas: 1. por medio de una variable del mismo tipo que la interfaz: Dim prueba1 As New Prueba Dim interfaz1 As IPrueba interfaz1 = prueba1 interfaz1.Usando nuevamente la instrucción Implements seguida del nombre de la interfaz: ... es decir.

en este ejemplo mostrar algo. la declaración podría quedar de esta forma: Public Interface IMostrar Sub Mostrar() End Interface Public Sub Mostrar1() Implements IMostrar. ya que el propio Visual Basic crearía dos métodos con nombres diferentes y a cada uno le asignaría la implementación de ese método definido en cada interfaz. pero separándolas con comas: Public Class Prueba Implements IPrueba. no habría problemas. aunque en ambos casos siempre debemos definir los miembros de cada una de esas interfaces. y esto nos puede causar una duda: ¿Qué ocurre si dos interfaces definen un método que es idéntico en ambas? En principio.Mostrar End Sub Aunque si ambos métodos hacen lo mismo. Múltiple implementación de un mismo miembro Como acabamos de comprobar. una misma clase puede implementar más de una interfaz. si tenemos otra interfaz que define el método Mostrar y la implementamos en la clase Prueba. Por ejemplo.Mostrar . IMostrar. IComparable De cualquiera de las dos formas es válido implementar más de una interfaz.Public Class Prueba Implements IPrueba Implements IComparable 2.Indicando las otras interfaces en la misma instrucción Implements. podríamos hacer que el mismo método de la clase sirva para implementar el de las dos interfaces: Public Sub Mostrar() Implements IPrueba.Mostrar.

es decir.End Sub Es decir. la definición de los miembros quedaría de la siguiente forma: . dónde podemos implementar las interfaces. la nueva clase también incorporará esa interfaz. en lugar de usar esa instrucción debemos usar Inherits. entre otras cosas. estructuras (Structure) y en otras interfaces (Interface). por ejemplo. en que tipos de datos podemos usar Implements. Public Interface IPrueba2 Inherits IMostrar Si en una clase implementamos una interfaz que a su vez implementa otras interfaces. éstas no se pueden indicar mediante Implements. Debido a que una interfaz puede implementar otras interfaces. ¿Dónde podemos implementar las interfaces? Para ir acabando este tema nos queda por saber. si tenemos la siguiente definición de la interfaz IPrueba2 que "implementa" la interfaz IMostrar: Public Interface IPrueba2 Inherits IMostrar Function Saludo(ByVal nombre As String) As String Property Nombre() As String Event DatosCambiados() End Interface Y la clase Prueba2 implementa IPrueba2. esa clase tendrá definiciones de todos los miembros de todas las interfaces. lo único que tendríamos que hacer es indicar la otra implementación separándola con una coma. lo mismo ocurre con una clase que "se derive" de otra clase que implementa alguna interfaz. si en una clase implementamos una interfaz que a su vez implementa otras. Nota: Cuando una interfaz implementa otras interfaces. esa clase tendrá definidas cada una de las interfaces. La implementación de interfaces la podemos hacer en las clases (Class).

Nombre Get End Get Set(ByVal value As String) End Set End Property Public Function Saludo(ByVal nombre As String) As String _ Implements IPrueba2.Mostrar.DatosCambiados Public Property Nombre() As String Implements IPrueba2. Si dejamos que Visual Basic cree los miembros.16: . ya que IPrueba2 también lo implementa (o hereda). éste nos ayuda indicándonos que interfaces implementamos y qué miembros son los que se adecuan a la declaración que estamos usando. el método Mostrar se indica mediante la interfaz IMostrar. pero también se puede hacer por medio de IPrueba2. Pero si lo hacemos manualmente.Public Class Prueba2 Implements IPrueba2 Public Sub Mostrar() Implements IMostrar. no tendremos problemas a la hora de definirlos.Mostrar End Sub Public Event DatosCambiados() Implements IPrueba2.Saludo End Function End Class En este código.02. aunque dentro del IDE de Visual Basic. tal como podemos comprobar en la Figura 2.

por tanto.02. comparamos los nombres. el propio .Figura 2. que es el encargado de clasificar los elementos. En el siguiente código tenemos la definición de una clase llamada Empleado que implementa la interfaz IComparable y en el método CompareTo hace la comprobación de que objeto es mayor o menor.NET Tal como comentamos al principio. ' Si no es del tipo Empleado. si queremos definir una clase que pueda ser clasificada por el propio . Public Function CompareTo(ByVal obj As Object) As Integer _ Implements System. hará una llamada al método IComparable. si la clase no ha definido esa interfaz. no podremos clasificar los elementos que contenga. devolvemos un cero ' que significa que los dos objetos son iguales.CompareTo de cada uno de los objetos que queremos clasificar.CompareTo If TypeOf obj Is Empleado Then . por ejemplo. si el de la propia clase o el indicado en el parámetro de esa función: Public Class Empleado Implements IComparable Public Nombre As String Public Sub New(ByVal nombre As String) Me. ya que el método Sort.Nombre = nombre End Sub ' Si el objeto es del tipo Empleado.16 IntelliSense solo muestra los métodos que mejor se adecuan a la declaración Un ejemplo práctico usando una interfaz de .NET.IComparable.NET está "plagado" de interfaces. (de la clase que contiene los elementos del tipo definido por nosotros). esa clase debe implementar la interfaz IComparable. cada una de ellas tiene un fin concreto.

empleados.List(Of Empleado) ' Añadimos varios empleados a la colección. Si el objeto que recibe el método no es del tipo Empleado. ya que si no indicamos el valor que debe devolver una función.Nombre.Compare(Me. empleados. e1.Collections. al menos en este caso.Add(New Empleado("Ana")) ' Clasificamos los empleados de la colección.Add(New Empleado("Bernardo")) empleados.Sort() ' Mostramos los datos una vez clasificados. ya que ese valor indica que los dos objetos son iguales.Add(New Empleado("Pepe")) empleados.Add(New Empleado("Juan")) empleados. Empleado) Return String. devolverá un valor cero. ya que el tipo a devolver es un número entero. en ese caso convertimos el objeto pasado en uno del tipo Empleado y comparamos los nombres. Esta comparación no es estrictamente necesaria.Dim e1 As Empleado = CType(obj. Esta clase la podemos usar de esta forma: ' Una colección de datos del tipo Empleado.Generic. For Each e1 As Empleado In empleados .Nombre) Else Return 0 End If End Function End Class En el método CompareTo hacemos una comprobación de que el objeto con el que debemos realizar la comparación es del tipo Empleado. para indicar que no haga ninguna clasificación. devolvemos un cero. Dim empleados As New System.

Nombre) Next Ver video 1 de esta lección (Interfaces Ver video 2 de esta lección (Interfaces Ver video 3 de esta lección (Interfaces 3 y herencia) 1) 2) .WriteLine(e1.Console.

como es lógico. será de los errores que se produzcan en tiempo de ejecución. Para estos casos.NET Framework. ya que. Veamos pues cómo utilizarlo.Introducción Es indiscutible que por mucho que nos lo propongamos. sobre todo el sistema de excepciones estructuradas que es el recomendable para cualquier desarrollo con . el IDE (Integrated Development Envirnment. Visual Basic pone a nuestra disposición el manejo de excepciones. Pero de lo que no nos avisará. y no nos referimos a errores sintácticos. entorno de desarrollo integrado) de Visual Studio 2005 nos avisará de cualquier error sintáctico e incluso de cualquier asignación no válida (al menos si tenemos activado Option Strict On). afortunadamente. Manejo de excepciones · Manejo de excepciones o Manejo de excepciones no estructuradas o Manejo de excepciones estructuradas § Bloque Try § Bloque Catch § Varias capturas de errores en un mismo bloque Try/Catch § Evaluación condicional en un bloque Catch § Bloque Finally o Captura de errores no controlados . nuestras aplicaciones no estarán libres de errores.

. utilizar los errores estructurados. de esta forma podemos detectar los errores que se produzcan en nuestras aplicaciones de una forma más "ordenada". el "clásico" On Error. Debemos adaptar nuestra mente al formato estructurado.Manejo de excepciones En Visual Basic 2005 el tratamiento de errores (excepciones) ha cambiado con respecto a como lo hacemos en VBScript/VB6.. pero a todas luces no es la forma recomendada.. que ahora se llama tratamiento de errores no estructurado. La forma de utilizar On Error es la misma que en VBScropt/VB6. ya que en un principio nos parecerá que no es tan efectivo como On Error. es preferible. Esta forma no estructurada de tratar los errores se sigue soportando en Visual Basic 2005. es decir. solo aclarar un par de cosas que debemos tener en cuenta: La primera es: intentar no usar esta forma de detectar errores. en Visual Basic 2005 también podemos usar el "viejo" sistema de tratamientos de errores. En VBScript/VB6 la única forma de detectar errores es usando On Error. por tanto no vamos a entrar en detalles de cómo usar esta forma de interceptar errores. ahora podemos usar un tratamiento de excepciones estructurado. aunque al principio cueste adaptarse. Manejo de excepciones no estructuradas Como hemos comentado. ya que el "viejo" On Error sigue funcionando de la misma forma que en VBScript/VB6. En esta lección veremos cómo tratar los errores de forma estructurada.

IO. será el propio compilador el que nos avise cuando mezclemos las dos formas de detectar los errores. En el bloque Catch podemos indicar que tipo de excepción queremos capturar. o utilizamos On Error o utilizamos Try/Catch. Por ejemplo. aunque el primero: Try sí es necesario. por lo menos en un mismo método o propiedad. si utilizamos el IDE (entorno integrado) de Visual Basic. ya que es el que le indica al compilador que tenemos intención de controlar los errores que se produzcan. Bloque Catch Si se produce una excepción. ésta la capturamos en un bloque Catch. al estilo de If / Else. etc. si sabemos que nuestro código puede producir un error al trabajar con ficheros. independientemente de que se produzca o no una excepción. usando Try y Catch o usando Try y Finally. Por último. ya que en el momento que se produzca el error se usará (si hay) el código del bloque Catch. Cuando creamos una estructura de control de excepciones no estamos obligados a usar los tres bloques. Cuando queramos controlar una parte del código que puede producir un error lo incluimos dentro del bloque Try. Estas instrucciones realmente son bloques de instrucciones. Por tanto podemos crear un "manejador" de excepciones usando los tres bloques.La segunda es que no podemos usar los dos sistemas al mismo tiempo. podemos ejecutar el código que incluyamos en el bloque Finally. la cual pude ser del tipo de error específico que queremos controlar o de un tipo genérico. Manejo de excepciones estructuradas Las excepciones en Visual Basic 2005 las podemos controlar usando las instrucciones Try / Catch / Finally. El código a usar será un código normal. Veamos ahora con más detalle cada uno de estos bloques y que es lo que podemos hacer en cada uno de ellos. Catch ex As System. éste lo podemos detectar en el bloque Catch. Bloque Try En este bloque incluiremos el código en el que queremos comprobar los errores. es decir. para indicar el final del bloque de control de excepciones lo haremos con End Try.IOException ' el código a ejecutar cuando se produzca ese error . no tenemos que hacer nada en especial. De todas formas. para ello usaremos una variable de tipo Exception. Si se produce un error. podemos usar un código como este: Try ' código para trabajar con ficheros.

es decir. de forma que siempre nos aseguremos de que las capturas de errores más específicas se intercepten antes que las genéricas. podemos usar la clase Exception como tipo de excepción a capturar. podemos hacerlo de esta forma: Try ' código que queremos controlar Catch ' el código a ejecutar cuando se produzca cualquier error End Try Varias capturas de errores en un mismo bloque Try/Catch En un mismo Try podemos capturar diferentes tipos de errores. no queremos hacer un filtro con errores específicos. Visual Basic buscará la captura que mejor se adapte al error que se ha producido. pero siempre lo hará examinando los diferentes bloques Catch que hayamos indicado empezando por el indicado después del bloque Try. Es importante tener en cuenta que cuando se produce un error y usamos varios bloques Catch. Try ' código que queremos controlar Catch ex As Exception ' el código a ejecutar cuando se produzca cualquier error End Try Aunque si no vamos usar la variable indicada en el bloque Catch. pero queremos que no se detenga la aplicación cuando se produzca un error. en un bloque Catch podemos añadir la cláusula When para evaluar una expresión. para ello podemos incluir varios bloques Catch. Si la evaluación de la expresión . cada uno de ellos con un tipo de excepción diferente.End Try Si nuestra intención es capturar todos los errores que se produzcan. por tanto deberíamos poner las más genéricas al final. La clase Exception es la más genérica de todas las clases para manejo de excepciones. Evaluación condicional en un bloque Catch Además de indicar la excepción que queremos controlar. por tanto capturará todas las excepciones que se produzcan.

se ignorará esa captura de error. Captura de errores no controlados Como es lógico.Message) End Try Bloque Finally En este bloque podemos indicar las instrucciones que queremos que se ejecuten. y. si no controlamos las excepciones que se puedan producir en nuestras aplicaciones. r) Catch ex As Exception When y = 0 Console.ReadLine()) y = CInt(Console. En estos casos la aplicación se detiene y se muestra el error al usuario. Pero . en otro caso se utilizará el que no tiene la cláusula When: Dim x.NET.indicada después de When devuelve un valor verdadero. estas serán inicialmente controladas por el propio runtime de . en caso de que devuelva un valor falso. Nota: Hay que tener en cuenta de que incluso si usamos Exit Try para salir del bloque de control de errores.WriteLine("El resultado es: {0}". se evalúa el bloque Catch solo cuando el valor de la variable y es cero.") Catch ex As Exception Console. De esta forma nos aseguramos de que siempre se ejecutará un código. En el siguiente ejemplo. se ejecutará el código indicado en el bloque Finally.ReadLine()) r = x \ y Console.WriteLine("No se puede dividir por cero. se procesará el bloque Catch. pero cada una de ellas pueden tener diferentes expresiones indicadas con When. se produzca o no una excepción. r As Integer Try x = CInt(Console. Esto nos permite poder indicar varios bloques Catch que detecten el mismo error. se haya producido un error o no. por ejemplo para liberar recursos.WriteLine(ex.

el la al lo Este evento se "dispara" cuando se produce un error que no hemos interceptado. Ver video 1 de esta lección (Excepciones 1) Ver video 2 de esta lección (Excepciones 2) Ver video 3 de esta lección (Excepciones 3) . independientemente de que tengamos o no definida la captura de errores desde el evento UnhandledException. de esta forma. aunque recomendamos lector que esta sección la vuelva a leer después de ver todo relacionado con los eventos. en Visual Basic 2005 tenemos dos formas de interceptar los errores no controlados: · · La primera es iniciando nuestra aplicación dentro de un bloque Try/Catch. pero como evento UnhandledException está directamente relacionado con captura de errores.Application. Nota: Cuando ejecutamos una aplicación desde el IDE (entorno de desarrollo). Ya que cuando se produce el evento UnhandledException. se capturará en el bloque Catch. Por suerte. La segunda forma de interceptar los errores no controlados es mediante el evento: UnhandledException. es muy probable que no siempre podamos conseguirlo. por tanto podríamos usarlo para prevenir que nuestra aplicación se detenga o bien para guardar en un fichero . disponible por medio del objeto My.log la causa de dicho error para posteriormente actualizar el código y prevenirlo. lo mostramos en esta. en particular la propiedad Exception nos indicará el error que se ha producido y por medio de la propiedad ExitApplication podemos indicar si terminamos o no la aplicación. Nota: De los eventos nos ocuparemos en la siguiente lección. Ese evento solo se producirá cuando ejecutemos la aplicación fuera del IDE de Visual Basic. Esa información la obtenemos mediante propiedades expuestas por el segundo parámetro del evento. los errores no controlados siempre se producen. pero a pesar de que lo intentemos. Siempre deberíamos detectar todos los errores que se produzcan en nuestras aplicaciones. cuando se produzca el error.esto es algo que no deberíamos consentir. podemos averiguar el error que se ha producido e incluso evitar que la aplicación finalice.

éstos siempre están relacionados con los delegados. Eventos y delegados · Eventos o Interceptar los eventos de los controles de un formulario § Interceptar eventos en Visual Basic 6. En esta lección veremos que son los delegados y que relación tienen con los eventos. aunque seguramente siempre que hemos leído sobre el tema aparece la palabra delegado.0 § Interceptar eventos en Visual Basic 2005 o Asociar un evento con un control o Formas de asociar los eventos con un control § 1. es por medio de eventos. Los eventos no les son desconocidos a los desarrolladores de VB6. En Visual Basic 2005 se siguen usando de la misma forma que en VB6.Asociar el evento manualmente por medio de Handles § 2.Introducción La forma que tienen nuestras clases y estructuras de comunicar que algo está ocurriendo.Asociar el evento desde la ventana de código § 3.Asociar el evento desde el diseñador de formularios o Asociar varios eventos a un mismo procedimiento . aunque primero empezaremos viendo cómo declarar y utilizar eventos en nuestros tipos de datos. ya que también existen y se pueden definir en ese lenguaje. Y es que. también veremos que podemos tener mayor control sobre cómo se interceptan los eventos e incluso cómo y cuando se asocian los eventos en la aplicación cliente. aunque VB2005 nos oculte (o facilite) el trabajo con los eventos.

o ·

Declarar una variable para asociar eventos con Handles

Definir y producir eventos en una clase o Definir eventos en una clase o Producir un evento en nuestra clase o Otra forma de asociar los eventos de una clase con un método § Asociar eventos mediante AddHandler § Desasociar eventos mediante RemoveHandler Delegados o ¿Qué ocurre cuando se asigna y se produce un evento? o ¿Qué papel juegan los delegados en todo este proceso? o Definición "formal" de delegado o Utilizar un delegado para acceder a un método Definir un evento bien informado

·

·

Eventos
En Visual Basic 2005 podemos usar los eventos de la misma forma que en Visual Basic 6.0. Al menos en lo que se refiere a la forma de declararlos en nuestras clases y cómo "lanzarlos", ya que la forma de interceptarlos en una aplicación ha cambiado un poco, pero como veremos, incluso puede ser más fácil definir los métodos o procedimientos que utilizamos para interceptarlos.

Interceptar eventos en Visual Basic 2005
La forma más sencilla de asociar el evento de un control con el código que se usará, es haciendo doble-click en el control; por ejemplo, si en nuestro formulario tenemos un botón, al hacer doble pulsación sobre él tendremos asociado el evento Click del botón. Esto es así para los eventos predeterminados de los controles. La declaración del código usado para interceptar el evento difiere un poco de VB6, tal como podemos apreciar en el siguiente código:
Private Sub Button1_Click(ByVal sender As Object, ByVal e As EventArgs) _ Handles Button1.Click

End Sub

Lo primero que podemos notar es que en Visual Basic 2005 utiliza dos argumentos, esto siempre es así en todos los eventos producidos por los controles. El primero

indica el control que produce el evento, (en nuestro ejemplo sería una referencia al control Button1), y el segundo normalmente contiene información sobre el evento que se produce. Si el evento en cuestión no proporciona información extra, como es el caso del evento Click, ese parámetro será del tipo EventArgs. Sin embargo en otros eventos el segundo argumento tendrá información que nos puede resultar útil, por ejemplo para saber qué elemento se ha seleccionado en una lista o cual es el elemento seleccionado en una rejilla Web. En la figura 2.04.1 podemos ver las propiedades relacionadas con el evento RowDataBound de un control GridView:

Figura 2.04.01 Propiedades relacionadas con un evento de una rejilla Asociar un evento con un control Siguiendo con el código que intercepta el evento Click de un botón, podemos apreciar que el IDE de Visual Studio 2005 añade al final de la declaración del procedimiento de evento la instrucción Handles seguida del control y el evento que queremos interceptar: Handles Button1.Click. Eesta la forma habitual de hacerlo en VB2005, ya que, a diferencia de VB6, aquí no hay nombres "mágicos" para asociar un evento con un control o incluso con el propio formulario, sino que esa asociación se hace de forma explícita y la forma que tiene Visual Basic 2005 de hacerlo es usando la cláusula Handles. Nota: En Visual Basic 2005 el nombre del procedimiento de evento no está relacionado con el evento, a diferencia de VB6, en el que si que hay una relación directa entre el evento a interceptar y el nombre del procedimiento. Aunque por defecto, el nombre usado sería el equivalente al de VB6, en la nueva versión puede tener cualquier nombre. Tal como resaltamos en la nota anterior, en Visual Basic 2005, el nombre asociado a un evento puede ser el que queramos, lo realmente importante es que indiquemos la instrucción Handles seguida del evento que queremos interceptar. Formas de asociar los eventos con un control Cuando estamos trabajando con el diseñador de formularios, tenemos tres formas de asociar un evento con el código correspondiente:

La forma más sencilla es la expuesta anteriormente, es decir, haciendo doble click en el control, esto hará que se muestre el evento predeterminado del control. En el caso del control Button, el evento predeterminado es el evento Click. Si queremos escribir código para otros eventos podemos hacerlo de tres formas, aunque la primera que explicaremos no será la más habitual, ya que debemos saber exactamente qué parámetros utiliza el evento.

1- Asociar el evento manualmente por medio de Handles
Con esta forma, simplemente escribimos el nombre del procedimiento (puede ser cualquier nombre), indicamos los dos argumentos que recibe: el primero siempre es de tipo Object y el segundo dependerá del tipo de evento (aunque en los controles Web suele ser a menudo del tipo System.EventArgs), y finalmente por medio de la cláusula Handles lo asociamos con el control y el evento en cuestión.

2- Asociar el evento desde la ventana de código
Al igual que en VB6, en Visual Basic 2005 también podemos seleccionar los eventos disponibles de una lista desplegable. Esto lo haremos desde la ventana de código. En la parte superior derecha tenemos una la lista con los controles que hemos añadido al formulario, seleccionamos el control que nos interese y en la lista que hay a su izquierda tenemos los eventos que ese control produce. Por tanto podemos seleccionar de esa lista de eventos el que nos interese interceptar, tal como podemos ver en la Figura 2.04.02

Figura 2.04.02 Lista de eventos de un control De esta forma el propio IDE será el que cree el "esqueleto" del procedimiento de evento usando los parámetros adecuados.

3- Asociar el evento desde el diseñador de formularios
La tercera forma de asociar un evento con un control, es hacerlo desde el diseñador de formularios. En la ventana de propiedades del control, (tal como podemos apreciar en la Figura 2.04.3), tenemos una lista con los eventos más importantes de cada

control, seleccionando el evento de esa lista y haciendo doble-click en el que nos interese, conseguiremos exactamente el mismo resultado que con el paso anterior.

Figura 2.04.03 seleccionado

Ventana de

propiedades

con

los

eventos

del

control

Asociar varios eventos a un mismo procedimiento Cuando utilizamos Handles para asociar eventos, podemos indicar que un mismo procedimiento sirva para interceptar varios eventos. Veamos un caso práctico en el que tenemos varios controles de tipo Button y queremos que cuando se pulsen siempre se ejecute el mismo código. Podemos hacerlo indicando después de la cláusula Handles todos los controles que queremos asociar con ese procedimiento. En el siguiente código indicamos dos controles Button (uno arriba y otro abajo de la página, por ejemplo):
Private Sub Button_Click( _ ByVal sender As System.Object, _ ByVal e As System.EventArgs) _ Handles Button1.Click, Button2.Click End Sub

Esta asociación la podemos hacer manualmente, simplemente indicando en la cláusula Handles cada uno de los eventos a continuación del anterior separándolos por comas. O bien desde el diseñador de formularios. En este segundo caso, cuando seleccionamos un control y desde la ventana de propiedades, seleccionamos un evento, nos muestra los procedimientos que tenemos definidos en nuestro código que utilizan los mismos parámetros que el evento en cuestión, si seleccionamos uno de esos procedimientos, el propio IDE añadirá ese control a la lista Handles.

Declarar una variable para asociar eventos con Handles Para que podamos usar la instrucción Handles para asociar manualmente un procedimiento con un evento, o para que el diseñador de Visual Basic 2005 pueda hacerlo, la variable del control o clase que tiene los eventos que queremos interceptar tenemos que declararla con la instrucción WithEvents. Esto es exactamente lo mismo que en Visual Basic 6.0, lo que ocurre es que cuando trabajamos con formularios desde VB6, no nos tenemos que preocupar de este detalle, en Visual Basic 2005 tampoco debemos preocuparnos, ya que el propio diseñador de formularios lo hace por nosotros. Aunque a diferencia de VB6, hay que hacerlo de forma explícita, ya que en la versión anterior de Visual Basic no teníamos ningún control sobre como se definían o declaraban los controles a usar en nuestro formulario, mientras que en esta nueva versión siempre tendremos acceso a ello. No vamos a entrar en más detalles, simplemente mostraremos cómo se declara el control Button1 para que exponga los eventos:
Friend WithEvents Button1 As System.Web.UI.WebControls.Button

Si en lugar de estar trabajando con formularios y controles, lo hacemos con clases "normales", la forma de declarar una variable que tiene eventos es por medio de la instrucción WithEvents. Por ejemplo, en esta declaración indicamos que tenemos intención de usar los eventos que la clase Empleado exponga:
Private WithEvents unEmpleado As Empleado

Y posteriormente podremos definir los métodos de eventos usando la instrucción Handles:
Private Sub unEmpleado_DatosCambiados() unEmpleado.DatosCambiados Handles

End Sub

Nota: Usar WithEvents y Handles es la forma más sencilla de declarar y usar una variable que accede a una clase que produce eventos, pero no es la única forma que tenemos de hacerlo en Visual Basic 2005, tal como tendremos oportunidad de comprobar.

Ver video de esta lección (Eventos 1)

y de esta forma notificar a quién quiera interceptarlo. la forma de definir un evento en una clase de Visual Basic 2005 es idéntica a como lo hacemos actualmente con VB6.0.04. Producir un evento en nuestra clase Para producir un evento en nuestra clase. simplemente usaremos la instrucción RaiseEvent seguida del evento que queremos producir. En el siguiente trozo de código definimos un evento llamado DatosModificados que no utiliza ningún argumento: Public Event DatosModificados() Esto es todo lo que necesitamos hacer.04: . Lo mismo ocurre cuando queremos "lanzar" o producir el evento: en Visual Basic 2005 se hace igual que en Visual Basic 6. Incluso cuando escribimos esa instrucción en el IDE. nos mostrará los distintos eventos que podemos producir. tal como vemos en la Figura 2.Definir y producir eventos en una clase Como comentábamos anteriormente. Esto tampoco ha cambiado en Visual Basic 2005 con respecto a VB6. Definir eventos en una clase Para definir un evento en una clase usamos la instrucción Event seguida del nombre del evento y opcionalmente indicamos los argumentos que dicho evento recibirá.

DatosCambiados. De esta forma podemos seleccionar la variable y posteriormente elegir el evento a interceptar. . realmente lo que estamos usando es un constructor a un delegado. Aunque en este caso es algo más "manual" que todo lo que hemos visto y. que al igual que en VB6 sirve para pasar una referencia a una función o procedimiento.Figura 2. realmente esta sería la única forma de asociar un procedimiento de evento con una variable que no hemos declarado con WithEvents. La forma de de asociar eventos con su correspondiente método es por medio de la instrucción AddHandler. (y sin que nos enteremos). es que podemos hacerlo con variables que no están declaradas con WithEvents. tal como vimos en la Figura 2. A esta instrucción le pasamos dos argumentos. el primero es el evento a asociar y el segundo es el procedimiento que usaremos cuando se produzca dicho evento. ahora solamente mostraremos la forma de hacerlo y después veremos con algo de más detalle cómo funciona. La ventaja de usar esta forma de asociar eventos con el procedimiento.02. de alguna forma está más ligado con los delegados. no solo por la facilidad de hacerlo.04. Este último parámetro tendremos que indicarlo mediante la instrucción AddressOf. Asociar eventos mediante AddHandler Pero Visual Basic 2005 también proporciona otra forma de asociar un procedimiento con un evento. AddressOf unEmpleado_DatosCambiados En este caso. y como los delegados los veremos dentro de poco. sino porque también tenemos la ventaja de que todas las variables declaradas con WithEvents se muestran en la lista desplegable de la ventana de código. el uso de AddressOf es una forma "fácil" que tiene Visual Basic 2005 de asociar un procedimiento de evento con el evento.04. y precisamente eso es lo que queremos hacer: indicarle que procedimiento debe usar cuando se produzca el evento: AddHandler unEmpleado. Aunque por detrás.04 Lista de eventos que podemos producir Otra forma de asociar los eventos de una clase con un método Tal como hemos estado comentando. la forma más sencilla de declarar una variable para interceptar eventos es declarándola usando WithEvents y para interceptar los eventos lo hacemos por medio de la instrucción Handles. Esta forma es la más recomendada.

Esto último es así porque cuando nosotros definimos los procedimientos de eventos usando la instrucción Handles. Saber esto nos facilitará comprender mejor cómo funciona la declaración de eventos mediante la instrucción Custom. usando la instrucción RemoveHandler podemos hacer el proceso contrario: desligar un procedimiento del evento al que previamente estaba asociado. Ver video 1 de esta lección (Eventos 2) Ver video 2 de esta lección (Eventos 3) . aunque de este detalle nos ocuparemos después de ver que son los delegados. Podemos usar RemoveHandler tanto con variables y eventos definidos con AddHandler como con variables declaradas con WithEvents y ligadas por medio de Handles. es el propio Visual Basic el que internamente utiliza AddHandler para ligar ese procedimiento con el evento en cuestión. Los parámetros a usar con RemoveHandler son los mismos que con AddHandler.Desasociar eventos mediante RemoveHandler De la misma forma que por medio de AddHandler podemos asociar un procedimiento con un evento.

Delegados Como hemos comentado anteriormente los eventos son acciones que una clase puede producir cuando ocurre algo. lo que hace es añadir la dirección de memoria de ese método a una especie de array. puede que nos ayude a comprender mejor todo lo relacionado con los eventos. Nosotros solo vemos una pequeña parte de todo el trabajo que en realidad se produce. ya sea mediante AddHandler o mediante el uso de Handles.05 podemos ver un diagrama en el que un mismo evento lo interceptan tres clientes. Visual Basic 2005 esconde al desarrollador prácticamente todo lo que ocurre cada vez que decidimos interceptar un evento. 1.04. De esta forma podemos notificar a las aplicaciones que hayan decidido interceptar esos mensajes para que tomen las acciones que crean conveniente. pero si tenemos conciencia de que es lo que ocurre. . En la Figura 2. También es cierto que no debe preocuparnos demasiado si no sabemos lo que está pasando. cuando decimos que un cliente intercepta un evento. y el que no lo veamos no quiere decir que no esté ocurriendo nada. ¿Qué ocurre cuando se asigna y se produce un evento? Intentemos ver de forma sencilla lo que ocurre "por dentro" cada vez que definimos un método que intercepta un evento y cómo hace el Visual Basic para comunicarse con el receptor de dicho evento. Cuando Visual Basic se encuentra con el código que le indica que un método debe interceptar un evento. realmente nos referimos a que hay un método que lo intercepta y el evento realmente guarda la dirección de memoria de ese método.

Cuando definimos un evento. (que en el fondo es una clase con un tratamiento especial). estamos definiendo un delegado. 1. 3. de esta forma.05 El evento guarda la dirección de memoria de cada método que lo intercepta 2. solo se llamará a los métodos que actualmente estén en la lista. Cuando usamos la instrucción RemoveHandler. la próxima vez que se produzca el evento.Figura 2. Cuando indicamos que un método intercepte un evento. por medio de AddHandler y RemoveHandler respectivamente. Tanto el agregar nuevos métodos a esa lista como quitarlos. Es más. lo podemos hacer en tiempo de ejecución. realmente estamos llamando al constructor del delegado. ¿Qué papel juegan los delegados en todo este proceso? Veamos primero que papel tienen los delegados en todo este proceso y después veremos con más detalle lo que "realmente" es un delegado. y un método del mismo tipo que el delegado 2. lo que realmente ocurre es que se hace una llamada a cada uno de los métodos. podemos incluso indicar que un mismo evento procese más de un método en una misma aplicación o que un mismo método sea llamado por más de un evento. le estamos indicando al evento que elimine de la lista el método indicado en esa instrucción. al que le pasamos la dirección de . En este caso. se examina esa lista de direcciones y se manda el mensaje a cada uno de los métodos que tenemos en el "array". Ya que lo que realmente necesita cada evento es que exista un método que tenga una "firma" concreta: la indicada al declarar el evento.04. Ya que la instrucción Handles solo la podemos usar en tiempo de diseño. Cuando usamos la instrucción RaiseEvent para producir el evento. de forma que se ejecute el código al que tenemos acceso mediante la dirección de memoria almacenada en la lista.

Para que lo entendamos un poco mejor. A diferencia de otras clases. no tienen forma de comprobar si están accediendo a una dirección de memoria correcta o. y para decirlo de forma simple.NET. un parámetro de tipo String. el método que intercepte este evento debe ser del tipo Sub y no recibir ningún parámetro.memoria del método.NET para definir un puntero. el evento DatosCambiados definido anteriormente. y éstos solamente pueden acceder a direcciones de memoria que tienen la misma "firma" con el que se han definido. un delegado realmente es la forma que tiene . La diferencia principal es que los punteros. veamos a continuación una definición "formal" de qué es un delegado y veamos varios ejemplos para que lo comprendamos mejor." Esta definición. Cuando se produce el evento. a una dirección de memoria "adecuada". Por ejemplo. (por medio de RaiseEvent). y la principal razón es que hemos empezado la casa por el techo. es como si los delegados solo pudieran acceder a sitios en la memoria que contienen un método con la misma "interfaz" que el que ha definido el propio delegado. los "punteros" solo se pueden usar mediante delegados. Seguramente es difícil de entender. (no vamos a entrar en demasiados detalles sobre los punteros. viene a decir que los delegados determinan la forma en que debemos declarar los métodos que queramos usar para interceptar un evento. los delegados tienen un prototipo (firma) y pueden guardar referencias únicamente a los métodos que coinciden con su prototipo. Si nuestro evento utiliza. por ejemplo. Definición "formal" de delegado Veamos que nos dice la documentación de Visual Basic 2005 sobre los delegados: "Un delegado es una clase que puede contener una referencia a un método. ya que no estamos en un curso de C/C++). El delegado almacena cada una de esas direcciones de memoria para posteriormente usarlas 3. En . al menos en lo que respecta a su relación con los eventos. en realidad estamos llamando al delegado para que acceda a todas las "direcciones" de memoria que tiene almacenadas y ejecute el código que hayamos definido en cada uno de esos métodos Como podemos comprobar. para decirlo de otra forma. también lo podríamos definir de la siguiente forma: Public Delegate Sub DatosCambiadosEventHandler() Public Event DatosCambiados As DatosCambiadosEventHandler Es decir. la definición del delegado quedaría de la siguiente forma: . Por tanto.

en este caso sin necesidad de que defina un evento. Visual Basic 2005 nos permite definir los eventos de dos formas distintas: definiendo un delegado y un evento que sea del tipo de ese delegado o definiendo el evento con los argumentos que debemos usar. un delegado realmente es una clase que puede contener una referencia a un método.Public Delegate Sub NombreCambiadoEventHandler(ByVal nuevoNombre As String) Y la definición del evento quedaría de esta otra: Public Event NombreCambiado As NombreCambiadoEventHandler Como vemos al definir el evento ya no tenemos que indicar si recibe o no algún parámetro. Declaremos como declaremos los eventos. podemos declarar una variable del tipo del delegado y por medio de esa variable acceder al método que indiquemos. Parece complicado ¿verdad? Y no solo lo parece. los podemos seguir usando de la misma forma. ya que esa definición la hemos hecho en el delegado. Definimos un delegado de tipo Sub que recibe un valor de tipo cadena: Delegate Sub Saludo(ByVal nombre As String) Definimos un método con la misma firma del delegado: Private Sub mostrarSaludo(ByVal elNombre As String) Console. Utilizar un delegado para acceder a un método Ahora veamos brevemente cómo usar los delegados. lo haríamos así: Public Event NombreCambiado(ByVal nuevoNombre As String) Como podemos comprobar. vamos a definir un delegado. " & elNombre) End Sub . Si nos decidimos a definir este evento de la forma "normal" de Visual Basic. que iremos mostrando poco a poco. Comprobemos esta "complicación" por medio de un ejemplo. En este código. Como hemos comentado. Sabiendo esto.WriteLine("Hola. además define el prototipo del método que podemos usar como referencia. tanto para producirlo mediante RaiseEvent como para definir el método que reciba ese evento. es que realmente lo es. siempre que ese método tenga la misma "firma" que el delegado. un método con la misma firma para que podamos usarlo desde una variable definida con el mismo tipo del delegado.

Segundo intento: Por lógica y. En Visual Basic esa misma asignación la podemos simplificar de esta forma: . por tanto podemos usar New Saludo y. Por tanto. ¿seguramente porque le falta el parámetro? saludando = New Saludo(mostrarSaludo("Pepe")) Pues tampoco. La variable saludando es del mismo tipo que el delegado Saludo. porque hemos comentado que un delegado contiene (o puede contener) una referencia a un método. y "Pepe" no es un método ni una referencia a un método. ya que un delegado puede contener una referencia a un método. según parece. saludando = New Saludo(mostrarSaludo) Esto tampoco funciona. Para usar un delegado debemos indicarle la dirección de memoria de un método. sobre todo.Ahora vamos a declarar una variable para que acceda Para ello debemos declararla con el mismo tipo del delegado: Dim saludando As Saludo a ese método. deberíamos pasarle un nombre como argumento. para indicarle al delegado dónde está ese método tendremos que usar cualquiera de estas dos formas: saludando = New Saludo(AddressOf mostrarSaludo) Es decir. Algo así: saludando = New Saludo("Pepe") Pero esto no funciona. desde la versión 5. Y en Visual Basic. máxime cuando hemos declarado un método con la misma "firma" que el delegado. a eso se refiere la definición que vimos antes. una referencia a un método no es ni más ni menos que la dirección de memoria de ese método. La cuestión es ¿cómo o que asignamos a esta variable? Primer intento: Como hemos comentado. por sentido común. deberíamos pensar que lo que debemos pasar a esa variable es el método. tenemos una instrucción para obtener la dirección de memoria de cualquier método: AddressOf.0. le pasamos al constructor la dirección de memoria del método que queremos "asociar" al delegado. entre otras cosas. los delegados realmente son clases.

no sabe dónde está definido ese método. solo sabe que el método recibe un parámetro de tipo cadena y aparte de esa información. en nuestro caso. en cuanto lo hacemos. cuando producimos el evento con RaiseEvent es como si llamáramos a cada uno de los métodos que se han ido agregando al delegado. ya que en caso de que no haya ningún método asociado a ese evento. por la sencilla razón de que no habrá ningún código al que llamar. no será muy habitual que usemos los delegados de esta forma. sabiendo esto.saludando = AddressOf mostrarSaludo Ya que el compilador "sabe" que saludando es una variable de tipo delegado y lo que esa variable puede contener es una referencia a un método que tenga la misma firma que la definición del delegado. de forma que se ejecute de la misma forma que si lo llamásemos directamente: mostrarSaludo("Pepe") Con la diferencia de que la variable "saludando" no tiene porqué saber a qué método está llamando. Si queremos. éste no se producirá. aunque no está de más saberlo. sobre todo si de así comprendemos mejor cómo funcionan los eventos. Realmente es complicado y. ¿cómo podemos usar esa variable? La variable saludando realmente está apuntando a un método y ese método recibe un valor de tipo cadena. salvo que lo necesitemos para casos especiales. también podemos declarar la variable y asignarle directamente el método al que hará referencia: Dim saludando As New Saludo(AddressOf mostrarSaludo) Y ahora. tendremos que indicarle el valor del argumento. Realmente lo que hacemos con esa llamada es acceder al método al que apunta la variable y como ese método recibe un argumento.. ese método recibe los mismos parámetros que los definidos por el evento (realmente por el delegado). si es que se ha agregado alguno.. un evento solo tiene la dirección de memoria de un método. y lo más importante. por tanto si queremos llamar a ese método (para que se ejecute el código que contiene). así se mostraría por la consola el saludo (Hola) y el valor indicado como argumento. que sea de tipo Sub y reciba una cadena. la llamada podría ser de esta forma: saludando("Pepe") Y efectivamente. debemos pasárselo. Así es como funcionan los eventos. .NET se encarga de localizar el método y pasarle el argumento. no tiene porqué saber nada más. el runtime de .

Ver video de esta lección (Delegados) .

al llamar a RaiseEvent Para declarar este tipo de evento. tal como indicamos en el título de la sección. vamos a ver otra forma de definir un evento. es lo que la documentación de Visual Basic llama evento personalizado (Custom Event). Cuando se "liga" el evento con un método. Esta es exclusiva de Visual Basic 2005 y por medio de esta declaración. tendremos mayor información sobre cómo se declara el evento. Veamos un ejemplo de una declaración de un evento usando Custom Event: Public Delegate Sub ApellidosCambiadosEventHandler(ByVal nuevo As String) .Definir un evento bien informado Para terminar con esta lección sobre los eventos y los delegados. ya sea por medio de AddHandler o mediante Handles 2. Cuando se produce el evento. Cuando se desliga el evento de un método. Cuando declaramos un evento usando la instrucción Custom estamos definiendo tres bloques de código que nos permite interceptar el momento en que se produce cualquiera de las tres acciones posibles con un evento: 1. cómo se destruye e incluso cómo se produce. por medio de RemoveHandler 3. siempre debemos hacerlo por medio de un delegado.

Public Custom Event ApellidosCambiados As ApellidosCambiadosEventHandler AddHandler(ByVal value As ApellidosCambiadosEventHandler) ' este bloque se ejecutará cada vez que asignemos un método al evento End AddHandler RemoveHandler(ByVal value As ApellidosCambiadosEventHandler) ' este bloque se ejecutará cuando se desligue el evento de un método End RemoveHandler RaiseEvent(ByVal nuevo As String) evento ' este bloque se ejecutará cada vez que se produzca el End RaiseEvent End Event Como podemos apreciar. Nota: Los eventos Custom Event solamente podemos definirlos e interceptarlos en el mismo ensamblado. Dentro de la definición tenemos tres bloques. . cada uno de los cuales realizará la acción que ya hemos indicado en la lista numerada. utilizando el mismo formato que al definir un evento con un delegado. debemos definir un delegado con la "firma" del método a usar con el evento. Después definimos el evento por medio de las instrucciones Custom Event.

Atributos · Atributos o Tipos de atributos que podemos usar en una aplicación § Atributos globales a la aplicación § Atributos particulares a las clases o miembros de las clases o Atributos personalizados § Acceder a los atributos personalizados en tiempo de ejecución o Atributos específicos de Visual Basic o Marcar ciertos miembros de una clase como obsoletos . como el compilador de Visual Basic. Otras aplicaciones." En esta lección veremos algunos ejemplos de cómo usarlos en nuestras propias aplicaciones y. cómo usar y aplicar algunos de los atributos definidos en el propio . aunque sea de forma general. campos. "Los atributos son etiquetas descriptivas que proporcionan información adicional sobre elementos de programación como tipos. métodos y propiedades.Introducción Esta es la definición que nos da la ayuda de Visual Basic sobre lo que es un atributo.NET Framework. al menos los que más directamente nos pueden interesar a los desarrolladores de Visual Basic. pueden hacer referencia a la información adicional en atributos para determinar cómo pueden utilizarse estos elementos.

Por otra parte. el uso de los atributos nos sirve para ofrecer cierta funcionalidad extra a nuestro código.NET Framework los pueda usar para realizar ciertas tareas o para obtener información extra sobre nuestro código. ya que el propio compilador los utiliza para generar los metadatos del ensamblado. la información sobre todo lo que contiene el ejecutable o librería que hemos creado con Visual Basic 2005. los atributos son etiquetas que podemos aplicar a nuestro código para que el compilador y. el propio . aunque nosotros no nos enteremos. Tipos de atributos que podemos usar en una aplicación Como hemos comentado. Atributos globales a la aplicación Estos se indican usando Assembly: en el atributo y los podremos usar en cualquier parte de nuestro código. mediante atributos podemos indicarle al diseñador de formularios si debe mostrar ciertos miembros del control en la ventana de propiedades.vb. etc. existen atributos que son globales a toda la aplicación y otros que podremos aplicar a elementos particulares. como una clase o un método. por extensión. De hecho en cualquier aplicación que creemos con Visual Basic 2005 estaremos tratando con atributos. es decir. aunque lo habitual es usarlos en el fichero AssemblyInfo.Atributos Como hemos comentado en la introducción. por ejemplo. . cuando creamos nuestros propios controles.

ya que esta instrucción indica que el atributo es a nivel del ensamblado. este debe estar en la misma línea del elemento al que se aplica. por definición las clases para usarlas como atributos deben terminar con la palabra Attribute después del nombre "real" de la clase.Attribute ' . Veamos primero el código del atributo personalizado: <AttributeUsage(AttributeTargets. ya que se utilizan los signos de menor y mayor para encerrarlo.Nota: La palabra o instrucción Assembly: lo que indica es que el atributo tiene un ámbito de ensamblado. En el siguiente código tenemos la declaración de una clase que se utilizará como atributo personalizado. el formato es parecido a los atributos globales.NET o Visual Basic. Estos los vamos a usar poco o nada en una aplicación Web. Atributos particulares a las clases o miembros de las clases Estos atributos solo se aplican a la clase o al miembro de la clase que creamos conveniente.VisualBasic.Attribute y que podemos definir las propiedades que creamos conveniente utilizar en ese atributo para indicar cierta información a la que podemos acceder en tiempo de ejecución. esa "extensión" al nombre de la clase no se utiliza. podemos crear nuestros propios atributos. que como veremos en el código que utiliza ese atributo. aunque si queremos darle mayor legibilidad al código podemos usar un guión bajo para que el código continúe en otra línea: <Microsoft.HideModuleName()> _ Module MyResources Atributos personalizados Además de los atributos que ya están predefinidos en el propio . de forma que en tiempo de ejecución podamos acceder a ellos mediante las clases del espacio de nombres Reflection. Cuando aplicamos un atributo "particular". Este tema se sale un poco de la intención de este curso. con la diferencia de que en este tipo de atributos no debemos usar Assembly:. notamos que. pero simplemente indicaremos que los atributos personalizados son clases que se derivan de la clase System.All)> _ Public Class AutorAttribute Inherits System.

Private _ModificadoPor As String Private _Version As String Private _Fecha As String ' Public Property ModificadoPor() As String Get Return _ModificadoPor End Get Set(ByVal value As String) _ModificadoPor = value End Set End Property ' Public Property Version() As String Get Return _Version End Get Set(ByVal value As String) _Version = value End Set End Property ' Public Property Fecha() As String Get Return _Fecha End Get Set(ByVal value As String) _Fecha = value End Set .

los parámetros se indican por el orden alfabético de las propiedades.0". Fecha:="13/Abr/2005")> _ Public Class PruebaAtributos Nota: Cuando utilizamos el atributo. Acceder a los atributos personalizados en tiempo de ejecución Para acceder a los atributos personalizados podemos hacer algo como esto. _ Version:="1.0. tal como podemos ver en el código de ejemplo anterior. en el constructor que de forma predeterminada crea Visual Basic. (suponiendo que tenemos la clase AutorAttribute y una clase llamada PruebaAtributos a la que hemos aplicado ese atributo personalizado): Sub Main() Dim tipo As Type tipo = GetType(PruebaAtributos) Dim atributos() As Attribute atributos = Attribute. AutorAttribute) .GetCustomAttributes(tipo) For Each atr As Attribute In atributos If TypeOf atr Is AutorAttribute Then Dim aut As AutorAttribute aut = CType(atr.End Property End Class Para usar este atributo lo podemos hacer de la siguiente forma: <Autor(ModificadoPor:="Guillermo 'guille'".0. pero que nosotros podemos alterar usando directamente los nombres de las propiedades.

En estos casos nos puede venir muy bien el uso del atributo <Obsolete>. principalmente cuando queremos acceder al API de Windows o cuando queremos usar esa estructura para guardar información en un fichero. lo podremos usar para declarar arrays de tamaño fijo.WriteLine("Versión: " & aut. Si ese código lo hemos declarado en una interfaz.Version) End If Next End Sub Atributos específicos de Visual Basic Visual Basic utiliza una serie de atributos para indicar ciertas características de nuestro código. ya que así romperíamos el contrato contraído por las clases que implementan esa interfaz. al menos si las declaramos en una estructura. · Marcar ciertos miembros de una clase como obsoletos En ocasiones nos encontraremos con que escribimos cierto código que posteriormente no queremos que se utilice. Habitualmente se aplica a campos o miembros de una estructura. VBFixedStringAttribute o Este atributo se utiliza para crear cadenas de longitud fija en Visual Basic 2005.Fecha) Console.WriteLine("Fecha: " & aut. En el constructor de este atributo podemos indicar la cadena que se mostrará al usuario. al igual que el anterior.WriteLine("Modificado por: " & aut.Console.ModificadoPor) Console. en particular son tres: · · COMClassAttribute o Este atributo se utiliza para simplificar la creación de componentes COM desde Visual Basic. por ejemplo porque hemos creado una versión optimizada. ya que así podemos informar al usuario de que ese atributo no debería ser usado. pero utilizando una cantidad fija de caracteres. VBFixedArrayAttribute o Este atributo. ya que por defecto. no deberíamos eliminarlo de ella. los arrays de Visual Basic son de tamaño variable. En el siguiente código se declara un método con el atributo Obsolete: Public Interface IPruebaObsoleto .

utiliza el método Mostrar")> _ Sub MostrarNombre() Sub Mostrar() End Interface Si trabajamos con el IDE de Visual Basic.<Obsolete("Este método ya está obsoleto.01 Mensaje de que un método está obsoleto .05. tal como podemos apreciar en la Figura 2.05: Figura 2. ese mensaje se mostrará al compilar o utilizar los atributos marcados como obsoletos.05.

Al terminar el módulo estarás preparado para trabajar en el entorno y crear aplicaciones Web sin enlace a datos (esto se aprenderá más adelante. · Lección 1: Introducción al desarrollo con ASP.0 o Las páginas ASPX o El entorno de desarrollo: Visual Studio 2005 o Trabajo con formularios y controles Web Lección 2: Los controles de ASP. en el módulo correspondiente).NET 2.0. y en concreto mediante el uso de Visual Studio 2005.NET o Controles HTML o Controles Web o Controles de validación Lección 3: Los controles de usuario o Introducción o Definición de la funcionalidad pública o Uso de los controles de usuario o Carga dinámica de controles de usuari Lección 4: Técnicas de trabajo y consejos varios o Navegación entre páginas o Envío de datos entre páginas o Transferir el control entre páginas o Reutilización de código en una aplicación · · · .NET 2.Contenido En este módulo aprenderemos todo lo fundamental acerca del desarrollo de aplicaciones Web con ASP.

enlace a datos. ¿en qué hemos mejorado? El entorno de desarrollo: Visual Studio 2005 o Visual Studio 2005 o Explorando el entorno o Explorador de soluciones o Área de documentos o Cuadro de herramientas o Editor de propiedades o Barras de herramientas y menús Trabajo con formularios Web y controles o Trabajo con formularios web o Creando la interfaz del ejemplo o Respondiendo al evento del botón · · . · Las páginas ASPX o Páginas ASPX o Más código o Estupendo..NET 2. salvando las inherentes dificultades que ello conlleva de forma transparente al programador. transparencia acerca de dónde se ejecuta cada parte del código.NET 2. rejillas. pero. ASP. Los programadores de ASP.0 Más que una evolución sobre ASP. y no sólo en el ámbito relacionado con Microsoft.Introducción al desarrollo con ASP. asistencia avanzada contextual.0 y Visual Studio es que ha equiparado la creación de aplicaciones para Internet a lo que era común en entornos de escritorio. etc.NET es una auténtica revolución en el mundo del desarrollo Web... Lo que mejor define al desarrollo combinado con ASP.NET disponen de todo lo que "siempre" han disfrutado los programadores de Windows: diseñadores visuales.. código compilado de alto rendimiento.

.vb de lógica de la aplicación El nexo entre interfaz y lógica . ¿Cómo funciona esto por debajo? El archivo ..§ § § § Pero.aspx de interfaz de usuario El archivo .

. se puede usar en gran medida todo lo que conocemos de ASP 3. lo cual no quiere decir que sea lo más recomendable.NET usando el bloc de notas y sin saber nada de la plataforma .NET y de sus diferentes espacios de nombre. Las páginas de servidor de ASP.Las páginas ASPX Si nos vamos a lo fundamental es posible crear una página ASP. Por ello se les denomina de modo genérico páginas ASPX. por compatibilidad. Sin embargo para familiarizarnos haremos un ejemplo sencillo.aspx'.NET son en esencia archivos de texto que contienen HTML y etiquetas y que tienen una extensión '. Al igual que las páginas ASP clásicas soportan el uso de etiquetas <% %> para delimitar bloques de código. De hecho.0.

.1. Si lo modificamos para que tenga el siguiente aspecto: .Resultado del código anterior De todos modos.1. aunque no podamos percibirla.aspx en lugar de .Página ASPX sencilla El código de la figura no se distingue de una página ASP clásica salvo por la extensión del archivo (. pero es importante conocer esta característica pues nuestras aplicaciones obtendrán un mayor rendimiento por el mero hecho de ser ASP. Más código Siguiendo con el ejemplo vamos a añadir un poco más de código para comprobar hasta que punto son compatibles las páginas ASPX con el código ASP.Figura 3.NET. Obviamente en este caso no ofrece ventaja alguna. en lugar de haberse interpretado como en ASP. ya existe una sustancial diferencia con una página ASP: el pequeño fragmento de código que hemos incluido se ha compilado antes de ejecutarlo.1.asp).2.. Sin embargo si navegamos hasta esta página (ubicada en el raíz de nuestro servidor IIS) veremos que el resultado es el que esperábamos: Figura 3.

Figura 3. que como veremos enseguida nos ofrece una forma visual de trabajo junto con una separación estricta entre el código y la interfaz de usuario. en cuyo caso sustituimos la caja de texto por un saludo al nombre que se le esté pasando: Figura 3. Si bien podemos escribir código ASP.Más código añadido a la página ASPX Ahora durante la carga (o la recarga) de la página verificamos si se le está pasando un parámetro por POST.NET de la manera correcta sólo con el bloc de notas. no habríamos ganado demasiado: seguiríamos con código de cliente y de servidor entremezclado y difícil de mantener y no tendríamos ninguna de las ventajas que hemos mencionado antes.NET es usando Visual Studio 2005.. que es lo que pretendíamos. pero. y que sólo por este hecho ya mejoraremos la escalabilidad de las páginas... aunque así fuera.4.. ¿en qué hemos mejorado? Este ejemplo nos ha servido para ver qué ASPX sigue siendo compatible en cierta medida con ASP. Estupendo.1. la mejor forma de desarrollar páginas Web con ASP. De todos modos el cambio de la extensión del archivo sólo funcionará en las páginas más sencillas. Además. Ver vídeo de esta lección (código compilado) .Resultado de la ejecución. En código no trivial tenemos una probabilidad tendente a 1 de que no haya esa suerte.3.1.

y en general todo lo que se espera de un entorno de desarrollo rápido moderno y mucho más todavía. un servidor web de desarrollo.0 de la plataforma . ayuda a la escritura de código.NET.NET utilice el menú Archivo·Nuevo·Sitio Web.El entorno de desarrollo: Visual Studio 2005 Visual Studio 2005 es el entorno de desarrollo de aplicaciones Web para la versión 2. Para crear un nuevo proyecto ASP. asistentes de uso de bases de datos. Al hacerlo aparecerá un diálogo como el de la figura: . Ofrece todo tipo de herramientas para facilitar el trabajo del programador: diseñadores gráficos de páginas y clases.

Explorando el entorno Tras crear un proyecto nuevo. Existen diferentes lenguajes que nos sirven para crear el código de nuestras páginas.El diálogo de nuevo proyecto web. vamos a elegir Visual Basic 2005 como lenguaje de todos nuestros ejemplos. En él tenemos la oportunidad de elegir qué tipo de proyecto vamos a crear (por defecto un sitio web de ASP. Dado que este curso está orientado fundamentalmente a programadores que vienen de ASP o VB6..5. En cualquier caso todo lo explicado para éste es perfectamente válido para los otros lenguajes y le servirá igual si se decide por ellos. Por simplicidad se muestra el diálogo de la versión Visual Web Developer Express.NET). en qué ubicación física queremos crearlo (lo normal será en nuestro disco duro pero podríamos elegir un sitio gestionado por FTP o HTTP) y con qué lenguaje de programación.Figura 3. el más simple. Dado que en la práctica todos tienen las mismas capacidades escoger uno u otro es una cuestión de elección personal.1. el entorno tiene un aspecto similar a este: . Nota: Las plantillas disponibles en el diálogo de nuevo proyecto web puede diferir dependiendo de la versión de Visual Studio 2005 que utilice.

6. Nada más crear un nuevo proyecto Web sólo existe una carpeta llamada App_Data. y una página ASPX creada de forma predeterminada que está vacía y es con la que comenzaremos a trabajar.1.El entorno de desarrollo de Visual Studio 2005 tras crear un proyecto. Explorador de soluciones Este elemento contiene un árbol con los proyectos en los que estamos trabajando y los diferentes archivos y carpetas que forman parte de ellos. Antes de aprender a manejar Visual Studio 2005 vamos a ponernos en situación conociendo los distintos elementos que forman parte del entorno. .. Los botones de la parte superior se usan para realizar diversas acciones sobre el elemento que tengamos seleccionado.Figura 3. Por ejemplo en el caso de la página podemos abrir su diseño o su código presionando respectivamente el tercer y cuarto botones por la derecha.

Contiene los diferentes editores de código así como diseñadores de diversos tipos (de interfaz de usuario.1...Área de documentos Figura 3. Es en donde pasaremos la mayor parte del tiempo trabajando.Área de documentos mostrando un editor de HTML. de clases. Cuadro de herramientas . de DataSets. Es la zona situada en el centro del entorno de desarrollo.7..).

0. Se pueden ver las propiedades ordenadas alfabéticamente o bien agrupadas en diferentes categorías (opción por defecto). Esto racionaliza el acceso a los elementos de la interfaz que de otro modo serían inmanejables. Está situado por defecto en el lateral izquierdo del entorno. El cuadro de herramientas contiene los diferentes elementos que podemos utilizar para la definición de la interfaz de usuario de nuestra aplicación. así como algunos otros componentes no visuales que también se pueden arrastrar hacia el diseñador visual de páginas Web.. Barras de herramientas y menús Se sitúan en la parte superior y dan acceso al resto de las características de la herramienta de trabajo. Frontpage y otros entornos. Algunas propiedades se editan directamente en el espacio disponible y otras lanzan un asistente o un diseñador que nos ayuda con la tarea.Figura 3. Este editor sirve para ajustar las propiedades de todos los objetos que podamos utilizar en el entorno: tanto de los controles que se arrastran sobre un diseñador como de los propios archivos del explorador de soluciones y las etiquetas HTML o XML. el editor de propiedades nos permite ajustar los valores de las propiedades en tiempo de diseño de los objetos que hayamos seleccionados.. Visual Studio se encarga de mostrar y ocultar la ingente cantidad de barras disponibles mostrando en cada caso sólo las que necesitemos. Editor de propiedades Al igual que en Visual Basic 6.1.Cuadro de herramientas y detalle de un algunos grupos de éste. Según el contexto en el que nos encontremos las barras de herramientas que veremos serán distintas. En la parte inferior se obtiene una concisa ayuda sobre cada propiedad seleccionada. Ver vídeo de esta lección (El entorno de desarrollo) . etc. Además de las propiedades también se pueden ajustar los gestores de eventos de los objetos usando el penúltimo botón por la derecha..8.

Creemos un ejemplo sencillo desde cero para ver cómo se trabaja. · Trabajo con formularios Web y controles o Creando la interfaz gráfica del ejemplo § Respondiendo al evento del botón o Pero. diseñador de HTML y editor de código de VB.vb de lógica de la aplicación § El nexo entre interfaz y lógica .Trabajo con formularios Web y controles El entorno de trabajo que hemos explorado es muy intuitivo y fácil de utilizar. ¿Cómo funciona esto por debajo? o Los archivos de código § El archivo . El ejemplo es el mismo que hemos creado en la primera lección del módulo pero utilizando el modo de programar de ASP.aspx de interfaz de usuario § El archivo .. Luego estudiaremos la estructura de los archivos generados para comprender su funcionamiento.NET..NET y no el código "espaguetti" típico de ASP clásico que hemos utilizado antes. En la mayor parte de los casos vamos a hacer uso únicamente de los tres diseñadores que hemos visto en el vídeo de la lección anterior: diseñador visual de formularios Web.

A continuación introduzca un botón (Button) y asígnele el texto "Saludar" (propiedad Text) y otórguele el nombre de "cmdSaludar".aspx) haciendo doble click sobre ella. Por fin añada una etiqueta más con el nombre lblSaludar.Creando la interfaz gráfica del ejemplo Desde Visual Studio cree un nuevo proyecto de sitio Web. y establezca su propiedad ID como "Nombre". eligiendo un tipo de letra de tamaño grande y color rojo. Añada un control de tipo etiqueta (Label) en la parte superior y establezca su propiedad Text con el valor "¡Bienvenido a ASP. Width como 200px y MaxLength ajústela a 40. Abra el diseñador de la página por defecto que se crea (Default. Cuando acabe el aspecto del formulario debería ser muy similar a éste: . Justo debajo agregue un control TextBox. y ajuste su propiedad Visible a False para que no se vea en el formulario web una vez que lo ejecutemos.NET! ".

Manejador del evento Click generado automáticamente por el editor. que es el predeterminado de los botones: Figura 3. En ASP clásico tendríamos que enviar un formulario a otra página (o a la misma) y ver qué valores no es están pasando para actuar en consecuencia. Para ello haga doble-clic sobre el botón en el diseñador. Pues lo único que tendremos que hacer es escribir un manejador para el evento Click del botón. Respondiendo al evento del botón Para saludar al usuario con el nombre que introduzca en el campo de texto debemos responder a la pulsación del botón. En ASP. Al igual que en VB6 desde el código del evento (que se ejecutará en el servidor. Esto hará que se abra el editor de código y que automáticamente aparezca un manejador de eventos para el evento Click.NET esto no es necesario ya que trabajaremos según el clásico paradigma orientado eventos. respondiendo a las acciones del usuario.9. Nota: Si no tiene claro cómo hacerlo vea el primer vídeo de esta lección al pie de este documento en donde se desarrolla el ejemplo completo. ¡atención!) podemos hacer referencia a cualquier control de la página y acceder a sus métodos y propiedades.10.. En este caso debemos interceptar la pulsación del botón por parte del usuario ¿verdad?. algo que resultará familiar e intuitivo a los programadores de VB6.Aspecto del ejemplo tras haber añadido los controles.1..1.Figura 3. De este modo se puede escribir el siguiente código simple: .

No hemos usado HTML y (hasta cierto punto) nos da igual que el código se ejecute en el servidor o en el cliente.11.1. Nótese que no hemos añadido formulario alguno. se concatena un saludo al nombre introducido en el campo de texto asignándoselo como texto a mostrar a la etiqueta oculta.Nuestro ejemplo antes y después de presionar el botón.Es decir.. Ver vídeo 1 de esta lección (Creación y ejecución del ejemplo) Ver vídeo 2 de esta lección (Pequeñas mejoras del ejemplo) . y que en realidad para nosotros es transparente el modo en como se gestionan los eventos e incluso que lo que estamos creando sea una aplicación Web. Si ejecutamos ahora el ejemplo (presionando F5 o el botón correspondiente en la barra de herramientas) veremos que funciona sin problemas: Figura 3. ni tampoco JavaScript. y se hace visible ésta usando su propiedad Visible.

A excepción de una pequeña demora por el viaje de ida y vuelta al servidor.Viewstate de una página sencilla.recoge de manera automática el estado y el contenido de los controles de una página. existe también bastantes líneas de código JavaScript y algunos campos ocultos. Figura 3..1. El ViewState se encarga de ello. Uno de los campos ocultos más importantes es el que se refiere al ViewState.Pero. ¿Cómo funciona esto por debajo? Si echamos un vistazo al código de la página generada veremos que.. para el usuario no debe haber sensación de recarga de la página. Los campos ocultos se utilizan para almacenar información sobre la página y el código JavaScript se ocupa de su mantenimiento y de enviar el formulario al servidor ante determinadas acciones del usuario (simulando los eventos).12. El ViewState . Nota: A cada viaje de ida y vuelta de nuestra página al servidor como . aparte del HTML que es más o menos obvio que debería haber dados los controles que hemos utilizado. Esta información se utiliza para dejarlos como estaban en cada recarga de la página. Cuando presionamos el botón de nuestro ejemplo la página se recarga y todo lo que contiene debe estar igual que antes de hacerlo o no podríamos asimilarlo a un formulario..que se podría traducir como "Estado de Visualización" .

a efectos prácticos. procesarlo e inicializar de nuevo el estado de cada control según la información facilitada. Cuando se efectúa alguna acción el JavaScript de la página se encarga de rellenar estos campos y provocar un PostBack de la página.. se emplean también dos campos ocultos y un poco de JavaScript: Figura 3.NET. sin necesidad de trabajo por nuestra parte. ¡Imagínate tener que gestionar eso tú mismo con código propio! .. El evento es detectado en el servidor a través de estos campos ocultos y se gestiona adecuadamente por ASP.14.1.consecuencia de un evento en el cliente se le denomina PostBack.JavaScript asociado a la notificación de eventos al servidor.Campos ocultos de información sobre eventos Figura 3. Al recibirla. para determinar qué evento se ha producido. Por otra parte. Como se aprecia en la figura se trata de información sobre la jerarquía de controles de la página codificada para su envío al servidor. Se puede averiguar si la carga actual de la página es la primera o se trata de un PostBack consultando el valor booleano de la propiedad IsPostBack de la página (Me.1. Los mecanismos de ViewState y de PostBack son los responsables de que. podamos trabajar en la Web utilizando el paradigma de programación orientada a eventos.IsPostback). la clase Page de la que hereda nuestra página se encarga de decodificarlo. que se encarga de notificar los eventos.13.

no en el cliente. Existen dos: uno que define la interfaz de usuario y otro para la lógica de la aplicación. Por detrás lo que ha estado ocurriendo es que el código HTML de la página ha estado creciendo hasta ser como el siguiente: . Veamos cómo están formados y cuál es el nexo de unión entre ellos. Veamos cómo funciona. En realidad todo el código se ejecuta en el servidor y. el evento desencadenado por la pulsación se gestiona en el servidor. El archivo .Los archivos de código Centremos nuevamente nuestra atención en los archivos de código de servidor que tenemos en Visual Studio 2005.aspx de interfaz de usuario. Para crear la interfaz de usuario sólo hemos tenido que arrastrar controles Web desde el cuadro de herramientas al diseñador. por poco intuitivo que sea para un programador Web tradicional.

vb.NET instancia dichas clases y las pone a disposición de nuestro código pasando todo ello inadvertido para nosotros.. se ha creado un formulario (Form1) que al carecer de un atributo ACTION se enviará a si mismo. . Al compilar la página ASP. que es además el formulario que incluye automáticamente el entorno de desarrollo. como por ejemplo nuestro manejador del evento.UI. Nota: En las páginas ASPX sólo se recomienda el uso de un formulario. Éste se usa para indicar que son controles de servidor y que.15. sin que conscientemente lo hayamos hecho. Lo cierto es que no se trata de limitación alguna puesto que la filosofía de desarrollo es completamente distinta a la tradicional y no los vamos a necesitar.WebControls. dependiente.vb de lógica de la aplicación Por otro lado existe un archivo con extensión .Figura 3. deberán estar disponibles para el código que se ejecuta en el servidor. Vemos que. El archivo . Este prefijo indica que son controles web de ASP.1.NET. y como tales son objetos de las clases contenidas en el espacio de nombres System. según el explorador de proyectos.Web. El resto de elementos que aparecen son etiquetas HTML normales (p. del archivo .aspx anterior. como tales.Código HTML de la interfaz de usuario ASPX. Este formulario (y otros elementos tienen asignado el atributo runat="server".ej<br/> para cambio de línea) y unas etiquetas especiales que llevan el prefijo asp:.

lo que no sean eventos normalmente) en otros archivos y clases desligados de páginas aspx. lo que hace que una interfaz de usuario se comporte de un determinado modo. Veremos cómo hacerlo en breve en este curso.vb de lógica de la aplicación Éste contiene la "lógica" de la aplicación. Si nos fijamos en el código de la página ASPX de la figura anterior.0. .Archivo . Esta constituye también una de las grandes ventajas de ASP. En una aplicación real podría contener multitud de cosas más. Desde este archivo de código podemos responder a cualquier evento de los controles de interfaz de usuario o de la propia página. suele ser mucho más recomendable repartir toda aquella funcionalidad que no se refiera a la interfaz de usuario (es decir.NET. cada uno encargado de una cosa. En nuestro caso contiene el manejador del evento con lo que deseamos que ocurra al presionar el botón. la primera línea es una directiva @Page con diversos atributos. Nota: Aunque es muy tentador abusar de la capacidad de crecimiento de estos archivos de código. y acceder a sus métodos y propiedades. A los efectos de este curso no hablaremos más de él.1. De hecho incluso se podría programar con dos equipos distintos. ¿En dónde se encuentra el nexo entre interfaz y lógica? Tras esta pregunta tan aparentemente filosófica se encuentra una respuesta muy sencilla: la directiva de página @Page y la existencia de clases parciales en . · · AutoEventWireUp: indica si los eventos se deben generar de forma automática o no.16.NET 2.. Gracias a la existencia de estos dos archivos podemos independizar el aspecto de la aplicación (la interfaz) de lo que queremos hacer con ella. CodeFile: este atributo es específico de Visual Studio y le indica cuál es el archivo de código (.Figura 3.vb) que contiene la definición de la lógica de la página. es decir.

NET tal y como se demostró en el primer vídeo de este módulo. veremos que se define parcialmente una clase _Default. Nota: Todo lo explicado es muy fácil de verificar si se accede a la carpeta temporal de ASP. Nota: A esta novedosa forma de separar (y al mismo tiempo unir en tiempo de ejecución) la interfaz de la lógica hay quien la denomina "codebeside". Se trata de una iniciativa muy didáctica. denominado 'code-behind'.· Inherits: indica de qué clase heredará la clase auto-generada por ASP.0 y modifica el modelo utilizado en Visual Studio 2002 y 2003 para crear código de lógica de negocio para las páginas. Cuando ASP. Nota: Inherits es un atributo nuevo en ASP.10 anterior). . como homenaje al hasta ahora utilizado "code-behind" de ASP. Si has trabajado algo con estas versiones anteriores te sorprenderá ver este cambio y lo mucho que con él se reduce el código necesario para crear las páginas ASPX.NET para gestionar los contenidos de la página ASPX actual (repase el primer vídeo de este módulo acerca de código compilado). Es por este motivo que ahora los manejadores de eventos de la clase se declaran con accesibilidad protected. Si ahora os fijamos en el código de lógica de la página (figura 3.NET en los que podremos comprobar línea por línea todo lo que he comentado.NET 1.1. para que puedan utilizarse desde la clase derivada. ya que no hay que declarar los controles ni inicializarlos en el código de lógica.x. Y este es el nexo de unión entre ambos archivos. En él encontraremos los archivos de código autogenerados por .NET genera la página primero completa automáticamente el código de la clase _Default con otra implementación parcial de ésta en la que se definen los controles de la página (el código que ha desaparecido respecto a las versiones anteriores del entorno). Luego define una nueva clase específica para la página que hereda de _Default y es en ella donde inicializa los controles y hace el nexo entre la interfaz y la lógica.NET 2.

con más detalle. En esta lección vamos a conocer desde un punto de vista general los tipos de controles existentes y aprenderemos.NET ASP.Los controles de ASP. Durante la lección anterior hemos podido ver algunos de ellos en funcionamiento mientras que supimos de la existencia de otros al verlos en el cuadro de herramientas. · Controles HTML o Controles HTML o Jerarquía de controles HTML Controles Web o Controles Web o Adaptación al navegador o Jerarquía de controles Web o Controles propios Controles de validación o Controles Web de validación o Uso de los controles de validación o Validadores personalizados o Colocar el foco en el error · · . la utilización unos controles muy útiles: los controles de validación.NET ofrece una gran cantidad de controles que se pueden usar en los desarrollos de aplicaciones Web.

por ejemplo: . Sólo aparecerá su sintaxis HTML pura y dura. Podemos arrastrarlos y soltarlos sobre nuestro formulario al igual que los otros.NET cuando necesitábamos usar un control en una página empleábamos alguno de los definidos en HTML: controles de tipo <input>. Antes de ASP. Desde el cuadro de herramientas disponemos del grupo HTML (ver figura adjunta) que son controles equivalentes a los de HTML. Los controles que hemos utilizado se definen usando una sintaxis especial (<asp:.. <textarea> o <img> entre otros.Los controles HTML Hasta ahora hemos visto lo sencillo que resulta trabajar con controles de servidor arrastrándolos y soltándolos en los formularios Web. Se trata de controles muy útiles en determinadas ocasiones en las que no necesitamos todas las ventajas que nos ofrecen los controles de servidor. pero al contrario que éstos no se ejecutarán por defecto en el servidor.>) y como hemos podido comprobar responden a un comportamiento complejo.. Con ASP.NET disponemos también de la posibilidad de usarlos.

· El uso del campo oculto ViewState puede cargar la página en exceso si hay muchos controles.· No vamos a acceder a sus métodos y propiedades desde el servidor. Figura 3.Distinción entre Controles de servidor y HTML Los controles HTML. por no mencionar que hay que crear clases en el servidor que los representen cuando se procesa la página. Son más adecuados cuando no requerimos una gran flexibilidad y queremos cargar la página lo mínimo posible.1. En el área de diseño del formulario es muy fácil distinguir los controles de servidor de los HTML porque los primeros tienen un pequeño triángulo verde que los marca. · Quizá no necesitamos que mantengan su estado o respondan a evento alguno. Por supuesto podemos convertirlos en controles de servidor simplemente asignando su atributo runat... Esta figura ilustra la jerarquía de los controles HTML en ASP. en cualquier caso. Todo ello reduce la respuesta de la página. Sólo con esto hemos conseguido que el control esté disponible desde nuestro código de servidor (como en el ejemplo) y disfrutaremos de todas las cualidades conocidas: acceso a sus propiedades y métodos. conservación del estado. Tienen menos propiedades y eventos.. son mucho más sencillos que los otros controles Web. los cuales se suelen corresponder además con los mismos que tienen en HTML+Javascript.NET: .2. etc. En la siguiente figura todos los controles se ejecutan en el servidor excepto el botón "button" de la derecha. así: <input id="Button1" type="button" value="button" runat="server" /> Como vemos es un botón corriente de HTML al que se la ha añadido el atributo runat.

Jerarquía de los controles HTML Todos ellos.Web. heredan de la clase Object.NET. por lo que la nomenclatura utilizada no es consistente con la utilizada en el resto de la plataforma ASP.Control. Sus propiedades se corresponden con los atributos HTML del control correspondiente.. Ver vídeo de esta lección (controles HTML) .UI.Figura 3. obviamente.2.2. pero también heredan de la clase base HtmlControl que está contenida en el espacio de nombres System.

. etc. aunque algunos son relativamente sencillos (como una etiqueta.0 de ASP. Por ejemplo. Aunque algunos parecen asimilables a controles HTML. En esta nueva versión 2.) y de forma autónoma adapta el código que muestra a las capacidades y restricciones concretas del navegador utilizado. existen controles muy complejos que sería difícil recrear desde cero con HTML y JavaScript. etc. las rejillas de datos. Sus métodos y propiedades tienen nombres consistentes con el resto de la plataforma.NET va un paso más allá permitiendo la adaptación automática de los controles a diferentes navegadores y dispositivos incluso móviles . ASP.. Esta adaptación tiene en cuenta el soporte de HTML y JavaScript. pero también cuestiones como si se deben usar etiquetas básicas en lugar de hojas de estilo CSS para el aspecto.NET tienen otra característica que los hace únicos y es la adaptación automática al navegador.NET.Los controles Web Son controles nativos de ASP. Para establecer el color de fondo todos usan BackColor. los controles maestro-detalle. validadores.NET detecta con qué cliente se está accediendo (un navegador moderno o antiguo. para fijar el texto de un botón o de una etiqueta se usa la misma propiedad Text.. Internet Explorer o Netscape. un botón o un cuadro de texto). un PDA.. Adaptación automática al cliente Los controles Web que vienen con ASP. todos van mucho más allá en cuanto a características y capacidades. Por ejemplo el control calendario. De hecho. Esto hace que sea más fácil el desarrollo porque no hay que memorizar nomenclaturas diferentes para cada control.

2. está el hecho de que no hay que aprender todo un conjunto diferente de habilidades para poder programar para dispositivos móviles. La siguiente figura muestra la jerarquía de algunos controles Web de servidor incluidos con ASP.(teléfonos y PDA de cualquier marca).. A esta característica se la conoce como renderización adaptativa. Por otra parte.3. ¡Podemos reutilizar lo que estamos aprendiendo en este curso!. y tal vez más importante.NET 2.Renderización adaptativa: navegador y visto desde un móvil WAP. un mismo calendario en un La renderización adaptativa tiene implicaciones importantes ya que (hasta cierto punto) no hay que tener en cuenta de antemano si un desarrollo será para un navegador concreto o incluso para dispositivos móviles basados en WAP. Figura 3.0: .

Jerarquía de controles Web de servidor. Controles de terceras empresas Aparte de los controles que vienen con ASP..0 también es posible utilizar desde nuestras aplicaciones cualquier otro control Web diseñado por terceras empresas.2. Figura 3.NET 2.5.2. . Existen infinidad de ellos de todos los tipos.Algunos ejemplos de controles Web de terceras empresas.4.Figura 3.. algunos realmente potentes.

Investigue por su cuenta la funcionalidad de algunos de los controles disponibles en ASP.net/controlgallery/ podrá encontrar un extenso catálogo clasificado de controles Web de servidor.NET 2. Deje de momento los enlazados a datos pues serán objeto de un módulo posterior y suelen tener más complicación. aunque el soporte para configurarlos en tiempo de diseño es mucho más reducido que en el caso de los anteriores.NET no nos limitará a la hora de crear controles propios para reutilizar funcionalidad en nuestras aplicaciones o incluso para venderlos a otras empresas. Sin embargo son muy fáciles de crear y ofrecen un método sencillo de encapsular funcionalidades que incluyan interfaz de usuario. Existen dos tipos de controles que podremos crear: · · Controles Web: son controles como los que hemos visto hasta ahora y equiparables en todos sus aspectos a los controles nativos de ASP. Es la mejor forma de aprender.0. Sin embargo en la siguiente lección veremos la forma de crear nuestros propios controles de usuario. ASP. La creación de controles Web (primer tipo) es una cuestión compleja que se sale del ámbito de este curso. Descubrirá que la mayoría son muy fáciles de utilizar y sus propiedades y métodos son de uso sencillo. Controles de usuario: permiten la reutilización de partes completas de la interfaz de usuario y de la lógica asociada a ésta. Ver vídeo de esta lección (Adaptación al navegador) . por lo que no los estudiaremos.NET. Controles propios Como no podría ser de otra manera.asp.En www.

sobre todo. Esto permite una primera barrera que no implica el envío de datos innecesarios al servidor. Por ello debemos validar todos los datos siempre en el servidor.NET nos ofrece los controles de validación. como máxima de cualquier desarrollo deberíamos tomar siempre la siguiente: "Jamás deberé fiarme de nada que me llegue de un origen fuera de mi control". Esta doble validación suele ser bastante engorrosa y supone un esfuerzo de desarrollo adicional que sería estupendo poder obviar. Pensando en facilitarnos este tipo de tareas ASP. en el navegador de los usuarios) utilizando para ello código JavaScript. Si hay que quitar una validación que sea siempre la del cliente. Por un lado se suele implementar una primera validación en el cliente (es decir. Bastaría con que un usuario no tuviese JavaScript habilitado para que no funcionara en absoluto. Como principales desventajas de usar JavaScript para la validación se encuentran la de ser código tedioso de escribir y. En este caso aunque hayamos habilitado una primera validación en el cliente con Javascript no debemos fiarnos en absoluto de que ésta se haya realizado.Controles Web de validación Dentro de la plétora de controles de ASP. En aras de la seguridad. . contiene una serie de controles que permiten realizar de manera cómoda la validación de datos introducidos por los usuarios. que es muy fácil evitarla. como es fácil imaginarse. Por otra parte también se suele realizar una segunda comprobación en el servidor. Lo habitual en las aplicaciones Web es realizar una doble validación.NET existe un grupo "Validación" que.

Ello facilita mucho el desarrollo y el mantenimiento de las reglas de validación. Mientras no se produce una situación en la que la validación fracasa serán invisibles. Las condiciones típicas son. Veremos que al hacerlo se muestran como si fueran etiquetas normales. Lo contrario no es cierto. Cada control de validación que arrastremos se debe asociar al control del que deberá "estar pendiente". es decir. La principal ventaja de estos controles es que permiten la definición de reglas de validación de forma declarativa. por ejemplo. Las comprobaciones del lado del servidor nos evitan problemas cuando. Por supuesto es posible arrastrar varios validadores y asociarlos a un mismo control para así verificar varias condiciones. Una vez que definamos las reglas para un formulario los controles de validación se encargan automáticamente de validarlas tanto en el cliente como en el servidor. Podemos deshabilitar la validación del lado cliente de todos los controles estableciendo la propiedad ClientTarget de la página actual con la cadena "DownLevel" desde el evento de carga de la página. En el lado cliente se convertirán en código JavaScript muy parecido al que nosotros usaríamos. Este es el aspecto que tendrán si se hace necesaria su actuación. es decir. Con ello sólo se realizará la validación en el servidor. Dichas reglas se asocian con otros controles que forman parte del formulario web. actuando de primera barrera y evitando viajes innecesarios al servidor. El control a verificar se asigna mediante la propiedad ControlToValidate del control de validación. Toda esta funcionalidad se consigue utilizando JavaScript. aunque con el texto de color rojo. no han actuado las validaciones en el cliente. que un campo no se puede quedar vacío. es decir. que no se envía nada al servidor (no se hace un post-back). la siguiente tabla indica el uso apropiado de cada uno de los controles disponibles: Control RequiredFiledValidator Utilidad Verifica que el control asociado no . por el motivo que sea.Estos controles permiten definir reglas de validación en la entrada de datos. Uso de los controles de validación Para hacer uso de uno de estos útiles controles basta con arrastrarlos al formulario. Nota: Se puede desactivar la validación en el lado del cliente de un control estableciendo su propiedad EnableClientScript a False. que tiene que estar comprendido dentro de un rango determinado o incluso que debe cumplir con una expresión regular que indiquemos. Por supuesto es posible también definir reglas propias personalizadas. y se combinan entre ellos para especificar múltiples restricciones sobre los datos introducidos. no hace falta escribir código para usarlos. no se puede usar un solo validador para verificar varios controles. Aunque su utilidad es bastante intuitiva.

El control ValidationSummary (abajo de todo en el grupo de controles de la figura anterior) se usa para mostrar un resumen de todo lo que está mal en un formulario en lugar de mostrar cada uno de los mensajes de error individualmente. Tabla 3. Ésta será False si alguno de los controles de validación ubicados en la página no ha pasado la prueba de verificación.Value SelectedItem. Aparte de mostrar la información de error al usuario.Value Value Figura 3..2.se encuentra vacío. CompareValidator Permite comparar el valor introducido por el usuario con una constante o con el valor de la propiedad de otro control.2. fechas y cadenas de texto. En cualquier caso los incluidos cubren la mayor parte de las necesidades normales de introducción de datos. .1.Controles que se pueden validar y las propiedades que se validan en ellos. No todos los controles se pueden validar con los controles de validación. CustomValidator Se usa para implementar lógica de validación propia tanto en el cliente como en el servidor. y son los siguientes: Control Tipo HtmlinputText Entrada de texto HtmlTextArea Entrada de texto TextBox Entrada de texto HtmlSelect Lista de selección ListBox Lista de selección DropDownList Lista de selección RadioButtonList Botones de selección HtmlInputFile Envío de archivos Propiedad Value Value Text Value SelectedItem. Permite validar intervalos numéricos (enteros o decimales o monedas).2. RangeValidator Genera un mensaje de error cuando el contenido de su control asociado está fuera de un rango de valores dado.Value SelectedItem. De hecho sólo un pequeño subconjunto de todos los controles Web son adecuados para un uso conjunto. RegularExpressionValidator Compara un texto introducido por el usuario con una expresión regular.. en los eventos de la página gestionados en el servidor podemos comprobar el valor de la propiedad IsValid del objeto Page. Esto es muy útil para realizar acciones complementarias en el servidor en caso de haber errores.Controles de validación y su utilidad.

Las funciones de validación en el cliente se escriben en JavaScript o en VBScript y se asocian con el control mediante la propiedad ClientValidationFunction.Sabiendo todo esto es fácil utilizar cualquiera de los controles de este tipo. para validar que el número introducido en un control es impar. args) { if (args.IsValid = false.Value % 2 == 0) //Si es divisible entre 2 es par args. arrastraríamos un control CustomValidator al formulario Web. argumentos) { } El primer argumento. Consulte el vídeo de esta lección para ver una práctica de uso. Validadores personalizados Tal vez el validador que necesite más explicación es el CustomValidator. else args. asignaríamos su propiedad ControlToValidate para que apunte a un campo de texto. origen. La segunda se usa para indicar si la validación ha tenido éxito o no.IsValid = true. El segundo argumento es más importante puesto que se trata de un objeto con dos propiedades: Value y IsValid. Para conseguirlo se definen funciones de validación en el cliente y en el servidor. Como su propio nombre indica se usa para crear normas de validación propias que no se adapten a ninguna de las contempladas con los demás controles. y estableceríamos la propiedad ClientValidationFunction con el valor "ValidaImpar" que es el nombre de la función JavaScript. así: function miValidador(origen. la función definida puede tener cualquier nombre pero debe tomar dos argumentos. A continuación incluiríamos en la cabecera de la página un fragmento de JavaScript como este: <script language="javascript"> function ValidaImpar(origen. } </script> . Por ejemplo. La primera contiene el valor a validar que está extraído del control asignado en la propiedad ControlToValidate. obtiene una referencia al control de validación (un elemento <span></span> de HTML que contiene el mensaje a mostrar) que nos permite mostrarlo u ocultarlo o cambiar el contenido del mensaje.

Sin embargo es posible forzar la validación incluso con el campo vacío si establecemos la propiedad ValidateEmptyText del CustomValidator a True. Podemos hacer que los controles de validación hagan esto por nosotros con sólo establecer a True su propiedad SetFocusOnError.NET 2. Ver vídeo de esta lección (Uso de los controles de validación) .NET. Este evento obtiene argumentos del tipo ServerValidateEventArgs que son funcionalmente equivalentes a los que acabamos de ver en el caso del cliente.0 trabaja de la misma manera. En éstas el evento de validación no se notificaba cuando el control a validar estaba vacío. Para rematar nuestro ejemplo con la validación en el servidor sólo es necesario escribir el siguiente código VB. De este modo se facilita al usuario la introducción del nuevo valor pues no tiene que activar el control con el ratón.Ahora todavía falta la validación en el servidor que de hecho es la más importante.NET 2. Colocar el foco en el error Otra acción muy común a la hora de validar datos en un formulario es colocar el foco sobre el control que contiene información errónea. Nota: Este control de validación personalizada ya existía en versiones anteriores de ASP. Hay que gestionar el evento ServerValidate del control CustomValidator. Su funcionamiento es igual de sencillo.0. es decir. Esta característica es nueva en ASP. Para conservar la compatibilidad el control CustomValidator de ASP. disponen de las propiedades Value e IsValid.NET: Como se puede observar es funcionalmente idéntico al código que escribimos para el cliente en JavaScript.

NET. existe una forma rápida y sencilla de reutilizar partes completas de funcionalidad e interfaz de usuario. Se trata de los controles de usuario. aparte de la compleja creación de controles Web personalizados del estilo de los que vienen con ASP.NET.Controles de usuario Como ya hemos adelantado en la lección anterior. Para ello no es necesario tener profundos conocimientos de la plataforma . En esta lección veremos qué son. cómo se crean y cómo se utilizan. · Controles de usuario o Introducción o Definición de la funcionalidad pública o Uso de los controles de usuario o Carga dinámica de controles de usuario . Ni siquiera hacen falta conocimientos de HTML.

En el diálogo que aparece (ya sobradamente conocido) seleccione el icono correspondiente a Control de usuario Web.Controles de usuario Los controles de usuario son tan fáciles de crear que. De hecho cualquier formulario Web (página ASPX) puede transformarse directamente en un control reutilizable con sólo unos pocos cambios de sintaxis.. ya conoce casi todo lo que necesita para construirlos. de hecho. Para añadir un nuevo control de usuario pulse con el botón secundario sobre el nodo raíz del proyecto en el explorador de soluciones y escoja la opción "Agregar elemento.. Se crean exactamente igual que los formularios Web y disponen de un diseñador visual idéntico que permite arrastrar otros controles sobre su superficie.". como se ilustra en la siguiente figura: .

Del mismo modo están disponibles para arrastrar sobre la superficie de diseño los mismos controles web que en el caso de los formularios Web..Figura 3.ascx en lugar de . El archivo resultante se distingue fácilmente en el explorador de proyectos porque Visual Studio le asigna un icono diferente (vea la figura lateral). no hay diferencia alguna con añadir un nuevo formulario Web.aspx. salvo por el icono elegido. Al igual que un formulario Web corriente un control de usuario dispone de un diseñador visual con doble vista (Diseño y Origen) y de un editor de código asociado en caso de haber escogido la separación de código e interfaz (opción marcada en la figura anterior). Si se fija en la figura detenidamente verá que.Diálogo para añadir un nuevo control de usuario. que es . En los formularios aparece al principio una directiva <%@Page %>. De hecho la única diferencia existente en este punto es la extensión que se le otorgará al archivo resultante.1.3. pero en los controles la directiva se llama <%@Control %> si bien se usa de un modo muy similar: . La primera diferencia con una página ASPX la encontramos al ver las etiquetas que constituyen la parte de interfaz de usuario del control.

podemos extenderla añadiéndole nuestros propios métodos y propiedades.2. . en el que se ve que ésta hereda de UserControl .Código origen de un control de usuario sobre el que se han arrastrado tres controles Web.Código de la clase code-beside de un control de usuario. por lo que conservan multitud de características en común. Sin embargo ambas clases base heredan a su vez de la clase TemplateControl. Por supuesto.3. Esto es muy útil para encapsular el acceso a ciertas funcionalidades que hayamos incluido. Figura 3. UserControl_Load) como se observa en la figura.Figura 3.NET. Podemos arrastrar cualquier control Web desde el cuadro de herramientas sobre la superficie del control. como en esencia un control de usuario no es más que una clase de . Definición de la funcionalidad pública del control de usuario Todo a partir de ahora es exactamente igual que en el caso de los formularios Web.3. Otra diferencia fundamental de un control con una página es que hereda de la clase UserControl y no de Page. por ejemplo. Todos los miembros públicos que agreguemos estarán disponibles desde la página que albergue al control del mismo modo que lo están las propiedades y métodos de cualquier control Web normal... asignar sus propiedades y recibir post-backs que generan eventos en los controles que hemos incluido. De hecho la similitud es tal que el entorno de desarrollo le asigna al manejador del evento Load del control el nombre Page_Load (en lugar de.3.

En versiones anteriores de Visual Studio . conservando su estado en el ViewState. Cuando observamos el código de la página ASPX desde la que estamos utilizando el control de usuario.3. El valor asignado a él será el que se utilice para distinguir de manera única un control de usuario dentro de la página.. vemos que al principio de ésta se ha incluido una directiva Register: Quizá el atributo más importante de esta directiva sea el último.4. Así. según la línea anterior podríamos definir en la página un control del tipo Micontrol usando una sintaxis como esta: . etc. esto es.NET lo único que se veía de estos controles era un cuadro de color gris con su nombre y eran por tanto más difícil trabajar con ellos y encajarlos en un diseño general. recibiendo eventos. TagPrefix.. Nota: Visual Studio 2005 ofrece un mayor soporte en tiempo de diseño para los controles de usuario que permite ver el contenido del control y ajustar sus propiedades desde el explorador de propiedades.Control de usuario arrastrado sobre la superficie de un formulario Web (los puntos rojos se usan para destacarlo.. El modo más sencillo de incluir un control de usuario en una página ASPX es simplemente arrastrándolo desde el explorador de proyectos sobre su superficie de diseño.Por supuesto los controles que coloquemos en la superficie del control se verán adecuadamente en la página que lo contenga y se comportarán del modo esperado. no estaban en la imagen original). De este modo se pueden utilizar sin problemas controles de usuario con el mismo nombre en una misma página. Uso de los controles de usuario Ahora que ya sabemos crear controles de usuario veamos la forma de usarlos desde los formularios Web. Esto hará que se visualice el control completo dentro de la página: Figura 3.

ascx") Me.Form. Carga dinámica de controles de usuario Otro modo de hacer uso de los controles de usuario es cargarlos dinámicamente según los necesitemos. de modo similar a este: Dim c As Control c = Me. El método LoadControl de la clase Page o del formulario de la página es el que nos va a ayudar a conseguirlo.ValorInicial = "Bienvenido a esta página" Me.Add(c) En lugar de usar un tipo genérico (Control) como en este fragmento también podemos usarlo como el verdadero tipo del control y así llamar a sus métodos y propiedades antes de añadirlo al formulario: Dim c As Control Dim miC As Micontrol c = Me.LoadControl("Micontrol. Sólo hay que pasarle como argumento el nombre del archivo ASCX que contiene la definición del control de usuario. Micontrol) miC.ascx") miC = CType(c.Form.Controls.Add(miC) En este ejemplo hemos usado el control con su verdadero tipo para poder asignar la propiedad ValorInicial antes de agregarlo a la página. Ver vídeo 1 de esta lección (controles de usuario) Ver vídeo 2 de esta lección (ampliando la capacidad básica de los controles de usuario) . por ejemplo) siempre que se trate de tipos simples.LoadControl("Micontrol. Podemos modificar la directiva Register para incluir un prefijo que nos guste más o sea más descriptivo que el que Visual Studio ha puesto por defecto.Las propiedades que hayamos definido para la clase Micontrol se pueden establecer mediante atributos (al igual que ID en la línea anterior.Controls.

NET vamos a comentar algunas técnicas de trabajo comunes que le serán de ayuda en su quehacer diario. · Técnicas de trabajo y consejos varios o Navegación entre páginas o Envío de datos entre páginas o Transferir el control entre páginas o Reutilización de código en una aplicación .Técnicas de trabajo y consejos varios Para finalizar con este intenso módulo de fundamentos de las aplicaciones ASP.

la página ASP a la que se envían los datos del formulario y puede que una página o dos para informar al usuario del éxito o del fracaso de su acción.0 clásica para recoger los datos de un usuario con mucha probabilidad escribiríamos dos (o incluso tres o cuatro) páginas: la página HTML con el formulario.Técnicas de trabajo y consejos varios Navegación entre páginas Antes de nada me parece necesario comentar que en las aplicaciones ASP. gracias a los postback y los correspondientes eventos de servidor se encapsula más la funcionalidad en un sólo archivo. un evento de servidor y probablemente mostrando y ocultando controles Web desde dicho evento.NET todo esto se resolvería con una sola página ASPX. Existen diversas maneras de dirigir a un usuario hacia otra página o recurso de la aplicación. La primera de ellas. y la más sencilla. Por supuesto una aplicación estará formada de todos modos por un número más o menos elevado de páginas a las que se debe dirigir al usuario. Si la página es una de las que pertenecen a nuestra aplicación será muy fácil seleccionarla gracias al diálogo especial que aparece para ello: . HyperLink que tiene este aspecto en el cuadro de herramientas: Estableciendo su propiedad NavigateUrl estaremos indicando a qué página queremos enviar al usuario cuando pulse sobre el enlace resultante. Esto se debe a que.NET se utilizan seguramente muchas menos páginas que en el caso de que la misma aplicación estuviese escrita con ASP clásico. En ASP. consiste en utilizar controles del tipo . Por ejemplo en una aplicación ASP 3.

Además si ajustamos la propiedad Text de este control ese será el texto que se muestre para el enlace de la página. Es posible utilizar un gráfico en lugar de texto para el enlace si se utiliza la propiedad ImageUrl.4. Por ejemplo.Redirect("opcion1. Nota: Existen controles especializados en crear árboles de navegación en una página pero por debajo usan enlaces como éstos.Redirect("opcion2. Así podremos controlar desde un evento de servidor a dónde enviaremos al usuario.aspx") End If El método Redirect envía al navegador del usuario una cabecera especial de redirección que le indica que.ListIndex = 0 Then Response. si queremos enviarlo a una página diferente según lo que haya escogido en un control de selección podríamos escribir algo similar a esto en el evento de pulsación de un botón: If opciones.aspx") Else Response.1.. La otra manera de enviar a los usuarios a una página propia o ajena consiste en hacer uso del método Redirect de la clase HttpResponse del contexto de llamada de la página. Los estudiaremos en un próximo módulo. en lugar de descargar los contenidos de la página .Figura 3.Diálogo de selección de páginas de nuestra aplicación.

Es una ejecución en el servidor. se necesita realizar ese envío de datos a otra página diferente. Se trata de un objeto Page reconstruido a partir del ViewState recibido. El método Transfer de la clase HttpServer ejecuta dinámicamente el código de una página desde otra cualquiera. sin redirección en el cliente. Envío de datos entre páginas Como hemos visto el comportamiento normal durante la pulsación de un botón u otro evento de controles servidor es el de realizar un post-back a la página actual.0 ha añadido una nueva funcionalidad denominada Cross Page Posting. por el motivo que sea.aspx") Al contrario que el uso de Redirect. Si la usamos así. También es posible determinar desde una página si los datos que está recibiendo son de su propio Post-back o pertenece a otra página mediante la propiedad IsCrossPagePostBack. Server. Para conseguirlo lo único que hay que hacer es ajustar la propiedad PostBackUrl del control cuyos eventos queremos gestionar desde otra página asignándole la ruta virtual de ésta última. propiedades y controles. pero eso sí.Transfer("otrapagina. Esto provoca una nueva petición de página desde el navegador por lo que no es la forma de navegación de mayor rendimiento (hay el doble de viajes al servidor que en un enlace directo). Sin embargo dota de gran flexibilidad a la hora de decidir qué hacer ante la solicitud de página de un usuario o para redirigir al final de un proceso ejecutado en el servidor. que es muy similar a la propiedad IsPostBack que ya hemos estudiado. conservando el acceso a todos los controles y datos de la página original (que como sabemos están contenidos en el ViewState). tendremos que utilizar el método FindControl de la clase Page para localizar cualquier control que hubiese en la página original. Sin embargo puede haber ocasiones en las que. Esta técnica es de un uso poco frecuente pero se trata de una novedad poco conocida que me ha parecido interesante incluir aquí. .Transfer no cambia la URL que el usuario ve en su navegador ya que desde fuera no se observa ninguna variación en la página ejecutada. de modo genérico. ASP.NET 2.actual. Transferir el control entre páginas A veces puede ser útil procesar el código de una página y justo después transferir el control a otra página ejecutando también su código. que permite precisamente esto. debe solicitar una nueva. Los datos se reciben en la otra página pero todavía tenemos acceso a los datos de la página original a través de la propiedad PreviousPage de la nueva. Por supuesto si ambas páginas pertenecen al mismo espacio de nombres (o lo hemos declarado) podemos forzar el uso de la página como la clase original de ésta usando CType y acceder directamente a sus métodos. La forma de hacerlo es la siguiente: Server.

que debemos añadirla a App_Code si queremos que funcione. al escribir una aplicación.Advertencia para colocar código en App_Code.2. Todo esto sonará de perogrullo a cualquier programador experimentado. La excepción a esta regla es el código que coloquemos en la carpeta App_Code que se compila automáticamente al comenzar la aplicación. . si bien en ASP. existen maneras mucho mejores y más recomendables de reutilizar código de uso común en las páginas. Tal y como hemos estudiado anteriormente. Reutilización de código en una aplicación A menudo. En ASP clásico. Si bien esto constituía una manera básica de reutilizar código no ofrecía la flexibilidad de un lenguaje capaz de crear bibliotecas de objetos y métodos. por ejemplo. En . al cargar una página y demás eventos. archivos de texto (para comentarios. Por ello sería absurdo escribir una y otra vez el mismo código dentro de los manejadores. como veremos. De hecho si presionamos con el botón secundario sobre el proyecto en el explorador de soluciones y agregamos un nuevo elemento de tipo Clase se nos mostrará una advertencia diciendo.. tenemos necesidades similares en diversas partes de ésta. grosso modo.NET es posible crear nuevas clases que encapsulen funcionalidades comunes y que sean reutilizables en cualquier punto de la aplicación. a medida que se accede a las diferentes partes de una aplicación se va compilando por completo. Dadas las características de Visual Studio.NET 2.0 existen una serie de carpetas con nombres especiales que cuelgan de la carpeta principal de la aplicación y que llevan asociado un comportamiento especial.4. Incluso si intentamos agregar un nuevo elemento a la carpeta App_Code sólo se nos ofrecerá la posibilidad de incluir nuevas clases. todo el código que se coloque bajo esta carpeta se compila de manera automática. Una de estas carpetas es 'App_Code'. En ASP.#include -->. Lo mejor es encapsular el código en diversos métodos y llamar a éstos cuando sea necesario. Incluso se crea automáticamente la carpeta si no lo hemos hecho ya con anterioridad: Figura 3.Este método es análogo al del mismo nombre en ASP clásico. el código residente en archivos que no sean páginas o clases parciales de "code-beside" no se compila ya que jamás navegamos por él ni se referencia desde otras páginas. cuando se solicita una página ésta se compila de manera automática junto con su archivo de "code-beside" de forma que. se solían agrupar las funciones de uso común dentro de archivos de inclusión que luego se utilizaban en las diferentes páginas gracias a una directiva <!-. Básicamente. una buena forma de reutilizar código entre páginas es agregar clases especializadas a la carpeta App_Code.NET su utilidad es menor puesto que. Por ello.

NET por lo que podremos derivarlas de otras clases para obtener funcionalidad "gratis". incluso en distintos tipos de proyectos como Aplicaciones Web y Aplicaciones Windows. puede crear un proyecto de tipo librería de clases. Si lo que desea es compartir código entre distintas aplicaciones o encapsular funcionalidad en una librería independiente. Una vez creadas nuevas clases en estas carpeta podemos añadirle métodos. Por supuesto son clases normales de . Estos últimos son DataSets tipados que no dejan de ser clases con un diseñador asociado como veremos en el siguiente módulo. Este proyecto genera un archivo .DLL que puede compartir entre distintas aplicaciones. Nota: Si dispone de la versión Visual Web Developer no podrá generar bibliotecas DLL.por ejemplo) o DataSets. Ver vídeo de esta lección (Reutilización de código) . Con esto podrá reutilizar sus clases en tantos proyectos como quiera. propiedades y campos para dotarlas de la funcionalidad que requiramos. hacer que implementen interfaces o incluirlas dentro de módulos o espacios de nombres para ordenarlas.

NET. · Lección 1: Introducción a ADO. Los conocimientos adquiridos en este módulo le servirán para cualquier tipo de desarrollo con . Sí. Se le conoce con el nombre genérico de ADO.0.NET.NET.NET o Introducción o La capa conectada o La capa desconectada o Vinculación de datos a controles Web Lección 2: Acceso a datos manual · .NET no casi nada que ver con el anterior ADO utilizado en los tiempos de ActiveX y COM. comandos e incluso una clase que recuerda a los Recordset. y por lo tanto ASP.NET.NET no sólo para la 2. Le gustará saber que la plataforma . dispone de conexiones.Contenido Sin lugar a dudas uno de los ámbitos más importantes de un lenguaje o entorno de programación es su capacidad de acceso a datos. Tanto la filosofía de trabajo como la tecnología son diferentes por completo y es mejor que utilice una estrategia de "ojos limpios" para acercarse correctamente a la nueva tecnología. Los conceptos explicados son válidos también para cualquier versión de . pero créame cuando le digo que es mejor que se olvide para siempre de todos ellos. Prácticamente todas las aplicaciones conllevan la realización de accesos a datos. no sólo para aplicaciones Web. Nota: No se deje engañar por el nombre: ADO. ofrecen un potente modelo de acceso a fuentes de datos.

· o Escritura manual de código o DataAdapter: puente entre dos mundos o Consultas parametrizadas o Altas bajas y modificaciones Lección 3: Acceso a datos con Visual Studio 2005 o Controles de datos § Orígenes de datos § Controles enlazados § Concurrencia optimista § Uso de los controles enlazados en la práctica o DataSets tipados .

NET. Una vez que sepamos por donde pisamos pasaremos a estudiar más a fondo cada uno de los conceptos analizados aquí.NET o Introducción o La capa conectada o La capa desconectada o Vinculación de datos a controles Web .NET Esta lección presenta los fundamentos de ADO. · Lección 1: Introducción a ADO.Introducción a ADO. su arquitectura y sus principales clases.

Este espacio de nombres define clases genéricas de acceso a datos que posteriormente son extendidas para ofrecer características y funciones específicas de cada proveedor. Arquitectura de ADO.NET El concepto más importante que hay que tener claro sobre ADO. Las clases genéricas expuestas por ADO.Introducción a ADO. El objeto más importante a la hora de trabajar con el nuevo modelo de acceso a datos es el DataSet.NET es un conjunto de clases relacionadas entre sí que están especializadas en ofrecer toda la funcionalidad que un programador necesita para realizar acceso a datos y manejarlos una vez los ha obtenido. Aunque hay quien lo asimila a los clásicos Recordsets su funcionalidad va mucho más allá como se verá en breve.NET se encuentran bajo el espacio de nombres System. Sin exagerar demasiado podríamos calificarlo casi como un motor de datos relacionales en memoria. ADO.NET es su modo de funcionar.Data. que se revela claramente al analizar su arquitectura: .NET Como cualquier otro modelo de acceso a datos.

1..NET Existen dos capas fundamentales dentro de su arquitectura: la capa conectada y la desconectada. .Figura 4.Arquitectura de ADO.

NET ofrece facilidades de . La plataforma . si no que existen clases especializadas para conectarse y recuperar información de cada tipo de origen de datos. La clase Command se encarga de enviar comandos de toda índole al origen de datos. Un proveedor de datos de ADO. Así. es decir.NET contiene objetos especializados en la conexión con los orígenes de datos.NET es una implementación concreta de las clases conectadas abstractas que hemos visto.La capa conectada La capa conectada de ADO. Cada origen de datos tiene un modo especial de comunicarse con los programas que los utilizan. las clases específicas para acceder a SQL Server se llaman SqlConnection. Así. Estas clases son abstractas. La clase DataAdapter hace uso de las tres anteriores para actuar de puente entre la capa conectada y la desconectada como veremos después. que hereda de éstas y que tiene en cuenta ya todas las particularidades del origen de datos en cuestión. además de otras particularidades que se deben contemplar. Es decir.Data.SqlClient. la clase genérica Connection se utiliza para establecer conexiones a los orígenes de datos. Nota: El hecho de utilizar clases concretas para acceso a las fuentes de datos no significa que no sea posible escribir código independiente del origen de datos. SqlCommand. al contrario que en ADO clásico no hay una única clase Connection o Command que se use en cada caso. Por fin la clase DataReader está especializada en leer los resultados de los comandos. Todo lo contrario. por ejemplo. Es en este punto en donde entran en juego los proveedores de datos. no tienen una implementación real de la que se pueda hacer uso directamente. SqlDataReader y SqlDataAdapter y se encuentran bajo el espacio de nombres System.

que se utilizan para acceder a través de ODBC u OLEDB cuando no existe un proveedor nativo para un determinado origen de datos. Se trata de un error y siempre que sea posible es mejor utilizar un proveedor nativo.NET System. por supuesto.OracleClient Proveedor de datos para . Un programador novel puede sentir la tentación de utilizar siempre el proveedor puente para OLEDB y así escribir código compatible con diversos gestores de datos de forma muy sencilla. Si bien éstos optimizan el acceso a estos orígenes de datos nosotros siempre podremos realizarlo mediante ODBC u OLEDB si tenemos necesidad. Existen proveedores nativos. que son los que se comunican directamente con el origen de datos (por ejemplo el de SQL Server o el de Oracle). sus propiedades y métodos. En resumen: con la capa conectada de ADO. incluyenbdo la última versión SQL Server 2005.NET Data acceder a Oracle. Éstos los desarrolla normalmente la empresa responsable del producto. Nota: Estos proveedores puente.NET proporciona "de serie" los siguientes proveedores de acceso a datos.NET ofrece grandes novedades específicamente en este ámbito. Proveedor Espacio de nombres ODBC .Data.0 de .NET System. Los proveedores de acceso a datos que distribuye Microsoft en ADO. contienen los mismos objetos.Data. y proveedores "puente".NET y algunos desarrollados por otras empresas o terceros. La plataforma .NET Data System. Oracle Client System. pueden ser diferentes. aunque los nombres de éstos. ofrecen un rendimiento menor debido a la capa intermedia que están utilizando (ODBC u OLEDB).OleDb Realiza la conexión Data Provider utilizando un proveedor OLEDB.0 o posterior. proveedores para tipos de orígenes de datos de cualquier gestor de datos existente en el mercado. Existen.SqlClient Permite la conexión Data Provider optimizada a SQL Server 7. OLE DB .Odbc Provider Descripción Permite conectar nuestras aplicaciones a fuentes de datos a través de ODBC.escritura de código genérico basadas en el uso de herencia e implementación de interfaces. al igual que el ADO clásico.Data.Data. Cada proveedor de datos implementa su . si bien muy útiles en determinadas circunstancias.NET realizamos la conexión y comunicación con los orígenes de datos. Provider SQL Server . De hecho la versión 2.

· · · Las clases derivadas de Connection se utilizan para realizar la conexión y enviar y recibir información.propia versión de las clases Connection. DataReader y DataAdapter (entre otras). Las clases derivadas de DataReader se emplean para obtener los posibles resultados de un comando utilizando para ello el conducto de comunicación establecido por Connection. Ver vídeo de esta lección (Las clases de datos conectadas) . Command. Las clases derivadas de Command permiten ejecutar sentencias SQL y procedimientos almacenados en el gestor de datos.

utilizarlos en cualquiera de ellos y posteriormente tener la capacidad de conciliar los cambios realizados sobre ellos con el origen de datos del que proceden. cada . en muchas ocasiones es necesario tratar con datos que no han sido obtenidos desde un origen de datos relacional con el que se requiera una conexión. Todo esto y mucho más es lo que nos otorga el uso de los objetos DataSet. A veces únicamente necesitamos un almacén de datos temporal pero que ofrezca características avanzadas de gestión y acceso a la información. Sin embargo sigue siendo necesario trabajar con los datos obtenidos de una manera flexible. núcleo central de la capa desconectada de ADO. Su mala utilización es la causa más frecuente de cuellos de botella en las aplicaciones y de que éstas no escalen como es debido. Por ello es necesario disponer de algún modo genérico y eficiente de poder transportar los datos entre diferentes lugares. e incluso en diferentes lugares del mundo gracias a Internet. Esta afirmación es especialmente importante en las aplicaciones Web en las que se pueden recibir muchas solicitudes simultáneas de cualquier parte del mundo. Además.NET. Éstas pueden encontrarse distribuidas por diferentes equipos. Nota: Otra interesante características de los DataSet es que permiten gestionar simultáneamente diversas tablas (relaciones) de datos.La capa desconectada Una vez que ya se han recuperado los datos desde un origen de datos la conexión a éste ya no es necesaria. Por otra parte las conexiones con las bases de datos son uno de los recursos más escasos con los que contamos al desarrollar. Finalmente otro motivo por el que es importante el uso de los datos desconectado de su origen es la transferencia de información entre capas de una aplicación. Es aquí cuando la capa de datos desconectada entra en juego.

Unión entre capa conectada y desconectada La clase DataAdapter se ha incluido anteriormente en la capa conectada por que está implementada por cada proveedor de un modo diferente. verificando reglas de negocio. Ello facilita una técnica avanzada que consiste en crear tipos nuevos de DataSet especializados en la gestión de una información concreta (por ejemplo un conjunto de tablas relacionadas). bien por ser muchos registros o por contener datos muy grandes. Nota: Aunque este es el comportamiento habitual de una aplicación de datos existen casos en los que no es recomendable almacenar en memoria (en un DataSet) todos los resultados de una consulta. El proceso general de trabajo de ADO. como cualquier otra clase no sellada de . Los DataSet. por ejemplo. teniendo en cuenta las restricciones y las relaciones existentes entre ellas.una de un origen diferente si es necesario. se pueden extender mediante herencia. Así. Estas nuevas tipos clases se denominan genéricamente DataSet Tipados. De todos modos lo más frecuente es realizar el proceso descrito. En este tipo de casos se puede usar u objeto DataReader directamente para leer la información. Command y DataReader) y proporciona métodos para trasegar información desde el servidor a DataSets desconectados y viceversa haciendo uso de dichos objetos específicos del proveedor. y se almacenan en memoria los resultados dentro de un objeto DataSet. y permiten el acceso mucho más cómodo a los datos que representan. Del mismo modo su método Update se utiliza para conciliar automáticamente con el origen de datos los datos modificados en un DataSet mientras no había conexión. Este es el concepto más importante que debemos recordar. se lanza una consulta SQL o procedimiento almacenado mediante un objeto de la clase Command. el método Fill de un DataSet se utiliza para introducir los resultados de una consula dentro de un DataSet para luego trabajar con ellos sin preocuparnos de su origen.NET. y validaciones de tipos de datos más estrictas.NET para acceder a un gestor de datos (SQL Server. Los objetos DataSet no dependen de proveedor de datos alguno y su funcionamiento es independiente de cómo hayan sido obtenidos los datos que contienen. cerrando la conexión. tratarla y no almacenarla en lugar alguno. En realidad es una clase que pone sus pies en ambos mundos (conectado y sin conexión) y sirve de nexo entre ellos. por ejemplo) es casi siempre el mismo: se abre una conexión (clase Connection). . Un DataAdapter sabe omo manejar correctamente los objetos proporcionados por su proveedor específico (fundamentalmente los vistos: Connection.

como en una base de datos "real". Todas las tablas disponen de una vista por dfecto (propiedad DefaultView) que ofrece los datos tal y como se han introducido en ésta y es la vista que se usa habitualmente. · · Ver vídeo de esta lección (Un vistazo a un DataSet) . Contiene tantos elementos como campos tiene la tabla. Constraint: las clases Constraint se emplean para definir resticciones en los tipos de datos contenidos en un DataTable. DataRow: representa un registro de la tabla virtual definida por el DataTable. DataView: representa una vista concreta de un DataTable. Normalmente se suelen utilizar un identificador común a ambas tablas aunque pueden ser combinaciones de más de uno de ellos. Normalmente se trata de ordenaciones o filtros sobre los datos originales. DataColumn: ofrece información sobre cada uno de los campos de los registros almacenados en un DataTable. De este modo se sabe cómo obtener información de una tabla a partir de información en otra. como su nombre o su tipo. por ejemplo) puede servir para relacionar su registro con los registros de detalle de factura que están contenidos en otra tabla. incluso forzando que se cumplan restricciones de creación y actualización.Otras clases dependientes de DataSet Como hemos dicho antes un DataSet podría asimilarse a un pequeño gestor de datos en memoria. Se puede asimilar a una tabla de un gestor de datos. cada uno del tipo definido por el objeto DataColumn correspondiente. Por ejemplo el identificador de una factura (su número. Para ello se apoya en el uso de otras clases especializadas que son las siguientes: · · · · DataTable: representa una tabla o relación de datos. Los datos obtenidos de una consulta de tipo SELECT de SQL se almacenan en un objeto de esta clase. Como tal un DataSet permite mantener diversas tablas así como las relaciones entre ellas. Por ejemplo se puede usar un objeto de esta clase para indicar que un determinado campo debe ser único o que se trata de una clave externa que debe ser tenida en cuenta en actualizaciones o borrados en cascada. DataRelations: define la relación existente entre dos objetos DataTable.

NET (idéntico en Web.NET que lo convierte en una herramienta ventajosa para el desarrollo de aplicaciones Web es la capacidad de vincular datos a controles Web. Ello facilita mucho el trabajo con datos desde la interfaz de usuario ya que no hay que molestarse en generar tablas con ellos. En este módulo veremos también lo sencillo que resulta crear interfaces para explotar los datos desde una página Web. gracias a ASP.NET para abstraernos de estas dificultades (ViewState.) consiguen el "milagro"..NET y Visual Studio. escritorio y otros entornos) junto con las capacidades nativas de ASP. El uso de un modelo consistente como ADO. . La mayor parte de los controles que podemos arrastrar sobre una página ASPX se pueden vincular a los objetos DataSet. equipara en muchos aspectos el desarrollo Web al clásico desarrollo de aplicaciones de escritorio donde este tipo de facilidades han estado disponibles desde hace años. Todo ello.. Sin embargo en una aplicación Web donde no existe una conexión permanente disponible entre la visualización (navegador) y el lugar en el que se ejecuta el código no es algo fácil de conseguir. escribir JavaScript o proporcionar complejos medios propios para permitir su edición o navegación si hacemos un uso adecuado de la vinculación y los controles disponibles. DataTable y DataReader o a informaciones concretas contenidas en éstos. Postback.Vinculación de datos a controles Web Otra característica fundamental de ASP.

NET a continuación explicaremos cómo se utilizan las clases de acceso datos para escribir código de acceso a datos de manera manual. Si bien es un tema algo árido y además en un gran porcentaje de los casos utilizaremos herramientas que nos faciliten la creación automática de código. · Lección 2: Acceso a datos manual o Escritura manual de código o DataAdapter: puente entre dos mundos o Consultas parametrizadas o Altas bajas y modificaciones . Así que ánimo y estudie con detenimiento esta lección. es fundamental conocer la forma de trabajar sin ayuda para entender el funcionamiento real de los objetos de datos.Acceso a datos manual Tras haber aprendido un poco de teoría sobre ADO.

Escritura manual de código
En este apartado vamos a analizar cómo es el código necesario para recuperar y actualizar datos con ADO.NET. Posteriormente veremos como sacar partido a las facilidades del entorno de desarrollo Visual Studio 2005 para no tener que escribir el código a mano. Sin embargo es útil aprender a hacerlo de esta manera para entender bien su funcionamiento. Comandos de selección simples La mayor parte de las consultas que se lanzan contra una base de datos suelen utilizarse para obtener un conjunto de registros para tratar. Este tipo de consultas suelen ser expresiones SQL de tipo SELECT. El siguiente fragmento de código muestra los pasos necesarios para mostrar en una página los registros resultantes de una consulta:

No se trata de un código optimizado (es más bien burdo) pero nos ayudará a entender perfectamente el proceso. Los datos los obtendremos de la conocida base de datos de ejemplo Northwind (que viene con todas las versiones de SQL Server). Nota: Para poder escribir código de acceso a datos en nuestro módulo debemos agregar referencias a los espacios de nombres que contienen las clases que vamos a utilizar. Para ello usamos las dos sentrencias Imports siguientes:

La primera de ellas agrega las clases genéricas de acceso a datos (como DataSet) y la siguiente las específicas de SQL Server. Si no lo hacemos recibiremos un error. Lo primero que se debe hacer es instanciar un objeto que represente la conexión a la base de datos. Dado que nos estamos conectando a SQL Server esta conexión será del tipo SqlConnection. Es lo que se hace en la primera línea del código anterior. La conexión debe realizarse con un servidor de datos y un esquema de datos concreto. Esto se indica mediante la cadena de conexión (al igual que se hacía en ADO tradicional). En este caso la cadena de conexión es la típica de SQL Server. Cada gestor de datos tiene la suya y hay que construirla de manera adecuada. El entorno de desarrollo Visual Studio 2005 nos ayuda a crearlas como veremos luego. Una vez creado el objeto con el que nos conectaremos hay que definir el comando a lanzar a la base de datos. Para ello se utiliza un objeto SqlCommand. Las propiedades básicas que hay que establecer para éste son la consulta que se lanzará (propiedad

CommandText) y la conexión que se empleará Connection) que es lo que se refleja en las líneas 6 y 7.

para

lanzarla

(propiedad

Ahora que ya sabemos cómo nos conectaremos y qué queremos obtener debemos lanzar la consulta y recoger el resultado de alguna manera. La clase Command dispone de diversos métodos para ejecutar consultas: · ExecuteReader: este método lanza la consulta a la base de datos y devuelve una referencia a una instancia de la clase DataReader (SqlDataReader en el caso de SQL Server). Podemos utilizar el DataReader para recorrer los datos y procesarlos. ExecuteNonQuery: ejecuta la consulta sin devolver resultado alguno. Simplemente envía la consulta al servidor y devuelve el número de registros afectados por ésta. Útil para realizar consultas de inserción (INSERT), actualización (UPDATE) y borrado (DELETE). ExecuteScalar: lanza la consulta y devuelve un objeto con el valor del primer campo del primer registro que se obtenga de dicha consulta. Es útil para lanzar consultas de agregación como sumas (SUM), cuentas (SELECT COUNT * ....) y similares de las que sólo necesitamos un valor como resultado.

·

·

En el ejemplo hemos utilizado el primer método ya que requerimos que devuelva varios registros con diferentes campos. Entonces lo que hacemos es (líneas a partir de la 9): 1. Abrir la conexión. 2. Crear una variable para contener una referencia a un objeto de la clase DataReader que es el que nos permitirá acceder a los resultados. Fíjese en que no se puede instanciar un DataReader (la declaración no lleva la palabra clave New). 3. Se obtiene el resultado mediante el método ExecuteReader, recogiéndolo en la variable (dr) recién declarada. 4. Se procesan los resultados (líneas 14-18). 5. Se cierra la conexión. El objeto DataReader es asimilable a un cursor de servidor de sólo lectura y hacia adelante (conocidos como de manguera de bombero o firehose). Es decir, los datos devueltos por el DataReader sólo se pueden leer y no actualizar. Además de esto sólo se pueden leer en secuencia hacia adelante (no hay forma de regresar sobre lo andado). La propiedad HasRows nos indica si hay o no resultados devueltos. El método Read avanza una posición en los registros devolviendo True si quedan registros pendientes de leer. Con esta información es muy fácil entender las líneas 14 a 18. La cláusula Using ¿Qué ocurre si se produce un error durante el procesamiento del bucle anterior en el que se trata el DataReader?. La respuesta es que la conexión, que debemos tener abierta durante el procesamiento, no se cerrará pues el código no llega al final.

Esto es algo muy grave ya que las conexiones que no se cierran no se pueden reutilizar y por lo tanto puede llegar un momento en que no tengamos conexiones disponibles, lo que limita enormemente la escalabilidad del sistema. Podemos evitar el problema escribiendo:

De este modo, con la cláusula Finally nos aseguramos que siempre se va a cerrar la conexión. De todos modos escribir este código es algo tedioso sobre todo si queremos que la excepción se replique y sólo metemos la cláusula Finally por el hecho de cerrar la conexión. Para facilitar el trabajo VB.NET en .NET 2.0 incluye una cláusula especial denominada Using que habilita la destrucción automática de los objetos a los que se hace referencia. Así el código anterior quedaría simplemente:

Al terminar la cláusula Using (aunque haya un error por medio) se llama de manera automática al método Dispose del objeto utilizado (en este caso una conexión). Entre

otras cosas este método se encarga de cerrar el objeto si estaba abierto, por lo que no nos tendremos que preocupar de este aspecto. Grupos de registros Aunque los DataReader se asemejan al funcionamiento de un cursor firehose, en realidad difieren bastante de éstos. Imaginemos que conectamos con la base de datos en el ejemplo anterior y, mientras estamos procesando el bucle de los registros, se interrumpe la conexión a la base de datos pr el motivo que sea. En principio en el caso de un cursor firehose tradicional obtendríamos un error porque se ha roto la conexión con el servidor. En el caso de un DataReader es posible que sigamos ejecutando varias vueltas más del bucle sin problemas. Esto se debe a que, en realidad, el DataReader obtiene los registros en grupos a través de la conexión y va solicitando nuevos grupos a medida que los necesita. Es algo que hay que tener en cuenta a la hora de utilizarlos. Ventajas e inconvenientes El código anterior, aunque sencillo, es un poco lioso y el uso de los DataReader está algo limitado dada su idiosincrasia (de sólo lectura y hacia adelante). Este código es adecuado si no necesitamos almacenar los resultados de la consulta en memoria ni regresar sobre ellos una vez procesados una primjera vez. También es muy útil para obtener resultados con miles o millones de registros que queremos tratar secuencialmente pero no almacenar en memoria. Sin embargo para un uso cotidiano se trata de un código muy poco útil y complicado de utilizar salvo para cosas muy sencillas. Además sólo hemos utilizado clases de la capa conectada de ADO.NET. Todavía debemos aprender a obtener los resultados dentro de un DataSet para su explotación de manera cómoda. Hay que tender un puente entre ambos mundos (conectado y desconectado): el DataAdapter.

DataAdapter: puente entre mundos
Si lo que deseamos es poder almacena temporalmente en memoria los datos obtenidos de una consulta debemos recurrir al uso de objetos de la clase DataSet. Como sabemos se trata de un almacenamiento en memoria desvinculado por completo del origen de los datos. Si el ejemplo anterior lo modificamos para convertirlo en una función que nos devuelva un DataSet con los datos obtenidos a partir de la consulta, el resultado sería similar a este:

El objeto DataSet Los objetos DataSet contienen a su vez objetos DataTable que son los que contienen realmente los datos. Un DataAdapter es una clase que conoce las particularidades de la capa conectada de un determinado proveedor y es capaz de "comunicar" información entre ésta y la capa desconectada formada por los DataSet. Lo que difiere bastante es la segunda parte. Se crean una conexión y un comando. No se abre ni se cierra la conexión a la base de datos. Se puede acceder a las tablas por posición (números enteros) o por nombre si lo sabemos. El método Fill de un DataAdapter se encarga e rellenar un DataSet con los datos obtenidos a partir de una consulta (o procedimiento almacenado) definida a través de un comando. 2. . Sin embargo es muy cómodo y nos evita problemas y el tener que "reinventar la rueda" en cada proyecto. Hay varias diferencias importantes: 1. 3. Internamente el método Fill emplea el objeto DataReader devuelto por ExecuteReader y rellena el DataSet con él por lo que sería factible crear un código equivalente.La primera parte del código es como la anterior. Se crea un nuevo DataSet y aparece un objeto de la clase DataAdapter. Ya no aparece en el código objeto DataReader de tipo alguno. Para acceder a las tablas de un DataSet se utiliza su colección Tables. Su propiedad SelectCommand se usa para indicar qué comando se utilizará para rellenar el DataSet.

Emplee el método Add de la colección Columns para crear nuevos campos..En un ejemplo sencillo como el anterior (y por otro lado uno de los más comunes) se crea una única tabla en el DataSet de nombre "Table1" y posición 0.). realizando el proceso contrario al de obtención de datos. Rows: colección de objetos de la clase DataRow que contienen información concreta sobre cada campo de un registro de la base de datos. Podemos acceder directamente a cualquier registro de la tabla usando su posición en la colección de filas. Luego lo veremos. Posteriormente se puede sincronizar el DataSet con el servidor usando un DataAdapter. Nota: Es muy sencillo definir objetos DataTable que dispongan de los campos que deseemos sin depender de origen alguno de datos.Tables(0). así como hacer un mantenimiento en memoria de los datos (altas.. .Rows(4) (nótese que las colecciones comienzan a numerarse en 0. etc. así: ds. algunos de los cuales pueden ser incluso derivados mediante una fórmula de los valores de otros. bajas y modificaciones).Rows(4)("CompanyName") que devolverá un objeto del tipo adecuado para el campo que representa (una cadena.).. Ventajas del uso de objetos DataSet Es posible cargar datos de varias tablas en un mismo DataSet.. tipo. un booleano.Tables(0). Podemos acceder a cualquier campo del registro usando su posición o bien su nombre. longitud. un objeto de fecha. incluso aunque procedan de bases de datos diferentes. Esto permite definir estructuras de almacenamiento a medida en memoria sin preocuparnos de usar una base de datos para ello. Las tablas contienen dos colecciones interesantes: · · Columns: conjunto de objetos de tipo DataColumn que ofrecen información sobre los campos de la tabla (nombre. Es posible establecer relaciones entre ellas para mantener la consistencia. y relacionarlas en memoria. de ahí que el quinto registro tenga índice 4). Por ejemplo para acceder al quinto registro de una tabla basta con escribir: Dim dr As DataRow dr = ds. Con esta información resulta muy sencillo tratar los datos de una consulta.

. trabajar con ellos en remoto. se pueden vincular con elementos de la interfaz gráfica para mostrar los datos automáticamente.La principal ventaja de un DataSet es que podemos almacenarlo en donde queramos (en una variable global. recuperarlos y finalmente transferirlos en cualquier momento de nuevo al origen (enteros o sólo los cambios) para sincronizarlos. Es posible moverse con libertad entre los registros de una tabla y sus registros relacionados en otras tablas. De hecho se pueden transferir DataSet completos entre diferentes máquinas o por Internet. almacenarlos. Y sobre todo. incluso a disco a una base de datos) para trabajar con él sin estar conectado a una base de datos. en caché.

En la realidad las consultas son mucho más complejas. si en la base de datos Northwind queremos obtener sólo aquellos clientes de un país determinado.Consultas parametrizadas Las consultas simples como la que acabamos de utilizar en los ejemplos anteriores son muy raras. Por ejemplo. Podríamos escribir de nuevo la función DameClientes para que se pareciese a la siguiente: . suelen intervenir varias tablas y dependen de diversos parámetros que le añaden condiciones.

3. Sin embargo presenta multitud de problemas seguramente no demasiado obvios para los programadores noveles. éste no tiene modo de saber que son las mismas y sacar factor común. Esto. Esto puede poner en peligro fácilmente nuestra aplicación e incluso todo nuestro sistema en casos graves. Los más importantes son los siguientes: 1. Si se solicitan 100 consultas idénticas al servidor en las que sólo varía el nombre del país por el que se filtra. Este código es más difícil de transportar a otros sistemas de bases de datos ya que hay que incluir los delimitadores y notaciones específicos de cada gestor. no se puede reutilizar el plan de consulta de la primera de ellas para las demás por lo que se debe calcular de nuevo cada vez. Obviamente en consultas más compllicadas es un problema más importante que en esta.Esta función acepta un país como parámetro y lo único qe hace es concatenar a la consulta una nueva condición que introduce el país. incidiendo en el rendimiento y la escalabilidad de la aplicación. Este código es vulnerable a problemas de seguridad provocados por ataques de inyección de SQL. Por ejemplo en SQL Server los delimitadores de fechas son comillas simples ('). La forma correcta de realizar este tipo de consultas es utilizar parámetros en la consulta. El estudio de esta problemática se sale del ámbito de este curso. mientras que en Access son almohadillas (#) y la sentencia usada no se puede reutilizar. pero créame cuando le digo que se trata de un gravísimo problema que debemos evitar a toda costa. funcionaría. 2. Es decir. sin duda. Ello evita los problemas enumerados. .

La función anterior empleando parámetros sería la siguiente: Se ha resaltado los cambios. Luego hay que declarar el parámetro añadiéndolo a la colección de parámetros. Éstos previamente se definen en la consulta utilizando comodines que marquen su ubicación. El proveedor de datos crea la consulta de la manera correcta. usando los delimitadores adecuados y tratando los datos del modo que sea preciso para asegurar . En otros proveedores no se puede definir nombre para los parámetros.Los objetos de tipo Command disponen de una colección llamada Parameters que sirve para asignar dichos parámetros. Como vemos en lugar de concatenar cadenas se marca la posición de las partes de la consulta que varían con un parámetro que consta de una arroba seguida de un identificador. En el caso de SQL Server se indican con una arroba '@' seguida de un identificador. Por fin se asigna su valor concreto antes de lanzar la consulta. sólo se marca su posición con un caracter especial. Para ello se indica su nombre y el tipo de datos que representa (en este caso un NVarChar de SQL Server. Nota: Cada proveedor de datos utiliza su propia convención para indicar la posición de los parámetros en una consulta. que es una cadena de longitud variable).

Ello elimina los problemas de los que hablábamos anteriormente y permite optimizar el uso de consultas. .que es correcta.

Altas bajas y modificaciones Con lo que hemos visto hasta ahora ya estamos en condiciones de escribir código para realizar altas. DELETE o UPDATE) que se deben enviar al servidor. Así pues. bajas y modificaciones de registros. para crear un nuevo cliente podemos escribir una función como la siguiente: . Al fin y al cabo éstas son simplemente consultas SQL del tipo adecuado (INSERT.

entre las diferentes capas de una aplicación e incluso se mueven entre contextos de ejecución y máquinas (por ejemplo a través de un servicio Web como veremos). Hemos dicho que son como pequeñas bases de datos. por lo que la forma habitual de trabajar con ellos es añadir. En lugar de usar ExecuteReader o un DataAdapter en este caso se utiliza el método ExecuteNonQuery. Las actualizaciones y eliminaciones de registros se podrían conseguir de modo similar. Los DataSet normalmente circulan.Es un código muy similar al anterior que realizaba una selección de datos. En este caso se ha definido una consulta de inserción con tres parámetros. . sin pensar en la ubicación real de estos datos. eliminar y modificar registros directamente sobre sus tablas. se inserta el nuevo registro) y devuelve el número de registros afectados por la consulta (que en el caso de una inserción siempre es 1 si se inserta correctamente o 0 si ha habido un error y lo capturásemosr). Éste lanza la consulta (es decir. independientes de cualquier origen de datos. Trabajando desconectados El código anterior funciona perfectamente pero no es la forma óptima de trabajar cuando tenemos que tratar con datos desconectados contenidos en objetos DataSet.

ahora debemos utilizar las propiedades InsertCommand.Así pues. se rellenan sus campos y se añade a la colección de filas con el método Add de ésta. el trasiego en el otro sentido se realiza con la ayuda del puente que representa la clase DataAdapter. para crear un nuevo registro en un DataSet debemos usar el método NewRow de la DataTable en la que lo queremos insertar. al no estar vinculado el DataSet con origen de datos alguno. Al igual que utilizábamos la propiedad SelectCommand para indicar cómo se recuperaban los datos hacia un DataSet. para modificar la dirección del cliente cuyos datos están en el quinto registro de nuestra tabla sólo hay que escribir: Por fin. La actualización de datos es más sencilla aún ya que basta con acceder directamente al registro que nos interesa modificar y cambiar los valores de sus campos. Así por ejemplo si tenemos almacenado un DataSet con una tabla con los datos de los clientes obtenidos con la función de ejemplo DameClientes. Por ejemplo. para eliminar un registro sólo hay que usar su método Delete. se crea la nueva fila/registro. Una vez rellenados añadiremos el nuevo registro a la colección de filas de la tabla. El nuevo registro tiene la misma estructura (el mismo "esquema") que el resto de registros y sólo tendremos que rellenar sus datos. así: que borraría el quinto registro de nuestra tabla en memoria. . Al igual que cuando los recuperamos. UpdateCommand y DeleteCommand para indicar qué comandos se deben usar para agregar. Conciliando los cambios con el origen Es muy fácil trabajar con los Dataset en memoria de este modo. no los veremos reflejados en la base de datos que es lo que buscamos. modificar y eliminar los registros modificados en memoria a través del DataSet. Debemos realizar una sincronización entre la representación en memoria de los datos y su ubicación física real. para lo cual debemos hacer que los cambios trasciendan a la capa conectada. Sólo hay un "pequeño" problema: los cambios se realizan en memoria pero. podríamos agregar uno nuevo de la siguiente manera: Es decir.

se define la consulta apropieada y sus parámetros. así: En este caso se define el parámetro "@Dirección". de tipo NVarChar y longitud 60 que se refiere siempre al valor del campo "Address" dela tabla. Definición de los comandos Los comandos de inserción. una DataTable o incluso un DataRow si sólo queremos actualizar un único registro. Por ejemplo. modificación o borrado para el DataAdapter se definen del mismo modo que en el código de ejemplo al principio de este apartado. Una vez definidos los tres parámetros de alta. baja y modificación sólo resta llamar a Update para que el DataAdapter se ocupe de toda la sincronización. . Ventajas Este modelo está lleno de ventajas aunque a primera vista pueda parecer algo engorroso. Para empezar podemos trabajar con los datos en total libertad sin preocuparnos de si existe conexión o no con el origen y aunque el DataSet se manipule en una ubicación física a miles de kilómetros del origen y desconectado de éste o los cambios se almacenen a disco y se concilien días más tarde. En esta ocasión como los parámetros serán rellenados automáticamente por el DataAdapter hay qeu utilizar una sobrecarga del método Add de la colección de parámetros que incluye el nombre del campo asociado con el parámetro. para definir la consulta de eliminación de registros de la tabla de clientes usaríamos el siguiente código: siendo CustomerID la clave primaria de la tabla. es decir.Una vez especificados estos comandos sólo resta llamar al método Update del DataAdapter para que se ocupe de sincronizar automáticamente todos los cambios que hayamos realizado en las tablas en memoria. Nota: Luego veremos que podemos usar las herramientas que nos proporciona Visual Studio 2005 para definir de manera automática los comandos de manipulación de datos sin necesidad de pasar el trabajo de hacerlo manualmente. Este método acepta como argumentos un DataSet completo.

borrados) y mover entre capas exclusivamente estos. Ahora basta con pasar un DataSet. si sólo hemos modificado 2 sólo será necesario trasegar la información de estos a la hora de enviarlos a otra capa o función para sincronizarlos con la base de datos. .Se pueden realizar multitud de modificaciones en los datos y luego conciliarlas simultáneamente en lugar de hacerlo en tiempo real de una en una. se pasaba una clase creada a medida que representaba lo valores del registro. La propiedad HasChanges de los DataSet. lo que se indica con un valor de la enumeración DataRowState: Valor Added Deleted Modified UnChanged Detached Significado Registros que no estaban originalmente. Lo mejor es que es posible saber mediante ciertas propiedades qué registros han cambiado (nuevos. aunque en un DataSet tengamos 1000 registros. modificados. Esto es lo que hace un DataAdapter tras haber sincronizado los cambios con el origen de datos. DataTable y DataRow nos informa de si el objeto ha sufrido cambios de algún tipo. El método GetChanges de los objetos DataSet y DataTable devuelve un subconjunto de los datos que contiene exclusivamente los cambios. Por ejemplo. Registros que se han eliminado Registros cuyos valores se han modificado Registros que no se han modificado Registros que se han desasignado de una tabla (pero no borrado con Delete) Se puede dejar un DataSet en estado sin modificar llamando a su método AceptChanges. Así. El método GetChanges se puede invocar sin parámetros o indicando qué tipo de cambios queremos obtener. un DataTable o un dataRow que ya contiene toda la información que necesitamos saber sobre los registros y su tabla asociada. El paso de datos entre capas y funciones se simplifica. para insertar un registro en una tabla que tiene 20 campos se definía una función con 20 parámetros (muchos de ellos opcionales) o. Lo habitual antes era definir funciones con tantos parámetros como datos se quisieran modificar en un registro. en el mejor de los casos.

nos permiten hacer casi cualquier tarea de datos sin necesidad de escribir código. · Lección 3: Acceso a datos con Visual Studio 2005 o Controles de datos § Orígenes de datos § Controles enlazados § Concurrencia optimista § Uso de los controles enlazados en la práctica o DataSets tipados .NET y dominamos los fundamentos.Acceso a datos con Visual Studio 2005 Ahora que ya hemos visto la forma de trabajo manual con ADO. como veremos. vamos a sacar partido a todas las ventajas que nos proporciona un entorno como Visual Studio 2005 que.

Controles de datos Aparte de la escritura manual de código y el uso directo de objetos de ADO. Estos controles nos abstraen por completo de las complejidades de manejo de las clases de ADO. Estos controles se encuentran agrupados en el cuadro de herramientas bajo el nombre de "Datos".NET. No disponen de apariencia visual pero se arrastran igualmente sobre los formularios Web para trabajar con ellos visualmente y poder usar sus paneles de tareas.NET 2. ASP. Abstraen al programador de las complejidades relacionadas con el manejo de los datos.0 presenta dos nuevos tipos de controles Web que participan en este modelo declarativo de enlace a datos.NET por un lado. Orígenes de datos Estos controles de datos representan conexiones con diferentes tipos de orígenes de información que van desde bases de datos a objetos de negocio. ASP. Equiparan en muchos aspectos el desarrollo web al tradicional desarrollo de aplicaciones de escritorio. . y de las dificultades inherentes al modo de trabajo desconectado de las páginas Web. tal y como se ve en la figura.0 proporciona un nuevo modelo de trabajo declarativo para acceso a datos que nos permite realziar tareas comunes de acceso a datos sin escribir código alguno.NET 2.

NET. ASP. no sólo para enlazar con SQL Server. ordenarlos. lo cierto es que si se analiza con detenimiento la posibilidad de conflicto en un sistema grande tiende a ser realmente pequeña en la mayoría de los casos. XmlDataSource Trata datos contenidos en documentos XML.0. En otras sin embargo no resulta de utilidad y sí añade una gran sobrecarga al acceso a datos. Concurrencia optimista Durante la configuración de un origten de datos SQL (luego lo verá en el primer vídeo de esta lección) una de las opciones avanzadas que se presenta habla de la Concurrencia optimista. manera automática selecionarlos.NET 2.NET disponible. Y de todos modos el sobreescribir cierta información no suele ser . No se deje despistar por su nombre. La concurrencia optimista evita la actualización de registros en el caso de que haya variado cualquiera de sus campos desde que se obtuvieron de la fuente de datos. etc. Se le denomina concurrencia optimista porque parte de la base de que la posibilidad de coincidencia de dos usuarios sobre el mismo registro es baja y es un caso que apenas se dará. ¡ATENCIÓN!: El control SqlDataSource sirve para enlazar con cualquier gestor de datos relacional para la que haya proveedor ADO. AccessdataSource Esta especializado en trabajar con bases de datos Microsoft Access.. SiteMapDataSource Se enlaza con la jerarquía de clases expuesta por el modelo de navegación de sitios de ASP. cuando queremos preservar los cambios realizados por cualquier usuario.permitiendo de paginarlos. ObjectDataSource Se enlaza con objetos de negocio y capas personalizadas de acceso a datos. Este comportamiento puede ser bueno en ciertas ocasiones.0 ofrece los siguientes controles de origen de datos que se pueden ver en la figura anterior: Control SqlDataSource Descripción Enlaza con cualquier base de datos para que exista un proveedor de ADO. Nota: En mi opinión debería llamarse "concurrencia realista" ya que. actualizarlos. Al caso contrario a la concurrencia optimista se le denomina concurrencia pesimista.NET 2.

Controles enlazados a datos Se trata de controles de interfaz de usuario que. etc. filtrado y paginación de los datos entre otras cosas. muestran la información a través de la página. de hecho. De todos modos se recomienda utilizar el nuevo modelo declarativo de acceso a datos. ordenación.un problema grave salvo cuando hablamos de cuestiones de dinero. Nota: Si usted ya conoce los controles enlazados a datos de ASP.. Así de facil.x como el DataGrid. Para conectar un control enlazado a un DataSource sólo hay que establecer su propiedad DataSourceID indicando el nombre apropiado. Incluso si lo desea puede añadirlos al cuadro de herramientas. es la que usted utiliza normalmente si escribe las funciones a mano de manera independiente. facturas y similares. haciendo uso de los anteriores. . por ejemplo: DELETE FROM [Customers] WHERE [CustomerID] = @original_CustomerID AND [CompanyName] = @original_CompanyName AND [ContactName] = @original_ContactName AND [ContactTitle] = @original_ContactTitle AND [Address] = @original_Address AND [City] = @original_City AND [Region] = @original_Region AND [PostalCode] = @original_PostalCode AND [Country] = @original_Country AND [Phone] = @original_Phone AND [Fax] = @original_Fax mientras que en un caso de concurrencia pesimista se emplea simplemente la clave primaria del registro para localizarlo: DELETE FROM [Customers] WHERE [CustomerID] = @original_CustomerID Es decisión suya qué tipo de actualización utilizar pero en la mayor parte de los casos usará seguramente la pesimista que.. eliminación. el DataRepeater. Pueden sacar partido a todas las propiedades de los orígenes de datos y por lo tanto habilitan de manera sencilla la edición. estos controles le resultarán más cómodos de utilizar pues al contrario que con aquellos no hay que escribir código alguno. Aunque estos controles "antiguos" no aparecen en el cuadro de herramientas siguen estando soportados y los puede seguir utilizando.NET 1. Cuando se establece la concurrencia optimista las consultas que genera el asistente de Visual Studio incluyen todos los campos del registro como condición de búsqueda del mismo.

examínelo con atención y luego trate de practicarlo por su cuenta con ejemplos similares. Ver vídeo 1 de esta lección (Configurar un origen de datos) Ver vídeo 2 de esta lección (Explotar el origen de datos) Ver vídeo 3 de esta lección (Crear vistas maestro-detalle) . edición y eliminación.Uso de los controles de datos en la práctica La mejor forma de conocer la manera de trabajar con estos controles es viéndolos actuar en la práctica. Por favor. Los vídeos de esta lección muestran un ejemplo completo de uso de los controles en el que se explotan unos datos para su visualización.

la idea que subyace bajo los DataSet tipados de Visual Studio 2005. podemos crear un DataSet especial que tengan en cuenta las particularidades de los datos que maneja para validarlos antes de permitir su inserción. puede ser extendida mediante herencia para añadirle nuevas funcionalidades y aprovechar las ya existentes. que verifique las relaciones con otros datos o que los transforme o controle el acceso a los mismos. Si creamos una nueva clase que herede de DataSet y ésta la especializamos en el tratamiento de un conjunto de datos determinado que conocemos de antemano nos encontramos un DataSet especializado. Además Visual Studio nos permite crear este tipo de DataSet de forma visual y usando asistentes.xsd' porque lo que en . en esencia. Nosotros sólo tendríamos que ocuparnos de estas tareas dejando a la clase DataSet de la que hemos heredado todos los puntos complejos que tienen que ver con la gestión de datos pura y dura. Por ejemplo. En el vídeo se ilustra la manera de conseguirlo. La extensión del archivo generado es '. Esta es. Los DataSet tipados parten del conocimiento preciso de la estructura de una base de datos para definir su funcionalidad. Para agregar un DataSet tipado a nuestro proyecto sólo hay que presionar con el botón secundario sobre la carpeta App_Code y en el diálogo que aparece elegir el icono de DataSet.NET. como cualquier otra clase no sellada de . Se trata de clases especializadas derivadas de DataSet que ofrecen una forma más rápida y sencilla de acceder a los datos que albergan. Ganan en especialización y pierden en versatilidad.DataSet tipados La clase DataSet. Esta es su principal diferencia con los DataSet normales puesto que éstos son genéricos y no saben nada acerca de los datos que albergan. Los tipados sólo sirven para albergar una información muy concreta.

Además el método Update sirve para conciliar automáticamente los cambios del un DataSet tipado con la base de datos original. Esto hará que se abra el archivo de código auto-generado por ASP. Este asistente nos permite configurar un objeto TableAdapter que se encargará de trasegar datos entre el DataSet tipado que estamos creando y la base de datos. por defecto.. Update. sólo que los correspondientes comandos estarán creados de manera automática o asistiéndonos en ello.realidad albergan es un esquema XML que define la estructura de los datos en los que se van a especializar.. crear nuevos registros. por defecto.NET desde la ubicación real de . se definen un par de métodos para obtener los datos subyacentes rellenando un DataSet que se le pase (método Fill) o devolviendo directamente un DataTable (método GetData). Un TableAdapter es una clase que encapsula a un DataAdapter especializado en los datos que vamos a procesar con la tabla del dataSet tipado que estamos definiendo. actualizarlos y eliminarlos.5. Una vez agregado el DataSet aparece una superficie de diseño y un asistente como el de la figura. Con él dispondremos de métodos para recuperar información.Primer paso del asistente de configuración de un TableAdapter. Así. De hecho sus métodos son. los mismos que los de un DataAdapter normal (Fill.). Truco: Podemos ver el código que se genera de manera automática para crear el DataAdapter si hacemos doble-clic sobre él desde el examinador de objetos de Visual Studio (CTRL+ALT+J).. No vamos a analizar desde el texto la definición de estos objetos adaptadores pero puede conocerlo viendo el vídeo de esta lección. Figura 4.

Tables(0).ToString() que obviamente es mucho menos legible. En este caso sin embargo podemos acceder a las tablas y a sus campos utilizando directamente sus nombres en lugar de recorrer la colección de tablas.Rows(0)("Nombre"). uno tipado consta de un conjunto de tablas y relaciones entre ellas. Cada una de las tablas del DataSet lleva asociado como mínimo un TableAdapter. por ejemplo. El DataSet tipado dispone de propiedades que coinciden con los nombres de los objetos que contienen.Nombre que nos daría el nombre del primer cliente de la tabla de clientes en el DataSet 'ds'.. En estos casos es más complicada la actualziación y se suelen usar únicamente para recuperar datos. Por ejemplo si la tabla se llama 'Clientes' existirá una clase ClientesRow que dispone de propiedades con el mismo nombre y tipo que los campos . La cosa no termina aquí ya que además se definen clases específicas para representar los registros de las tablas.. esta propiedad nombre además ya sería un campo de tipo String que es el tipo adecuado para la información albergada. Nota: Como sabemos (y veremos en el vídeo también) las tablas de un DataSet no tienen porqué coincidir con tablas reales de una base de datos ya que pueden ser resultados obtenidos de una consulta compleja que involucre a varias tablas. En un DataSet normal para obtener lo mismo tendríamos que haber escrito: ds.ejecución (normalmente una ruta del estilo C:\Windows\Microsoft. Entre los dos objetos (el DataTable y el o los TableAdapter relacionados) se reparten el trabajo. si tenemos una tabla "Clientes" con un campo "Nombre" podemos acceder a él directamente con este código: ds. El DataTable tipado mantiene en memoria la información y el TableAdapter actúa de puente con la tabla real en la base de datos.). lo cual lo hace más fácil de usar. Partes de un DataSet tipado Al igual que un DataSet normal. Es muy interesante echarle un vistazo a este código para aprender el funcionamiento interno de los DataSet tipados. Así. la alternativa habitual es tratar de replicar la estructura física de la base de datos en la estructura en memoria del DataSet de modo que se tiene acceso estructurado a la misma información y gracias a las relaciones y restricciones se conserva la consistencia de los datos tambiñen estando desconectados..NET\.. por lo que se simplifica mucho su uso.Clientes(0).

ds.Clientes(0). Así. si se hace necesario en el futuro.Nombre = "Pepe" .Nombre = "Pepe" ...ClientesTableAdapter() ta. pero su función es idéntica.Clientes. Para rellenar una tabla de un DataSet tipado se usa su correspondiente TableAdapter así: Dim clientes As New ClientesDS Dim ta As New ClientesTableAdapters. El uso de DataSet tipados es muy recomendable puesto que simplifica mucho el trabajo puesto que podemos realizar casi todo el trabajo utilizando asistentes y accediendo a la información de manera muy cómodo..GetData() clientes(0). se puede exponer esta parte de manera independiente mediante un. Para un mismo DataTable tipado se pueden definir diversos TableAdapter especializados aparte del básico que permite llenar todos los datos: para filtrar podr diversos parámetros normalmente.Nombre = "Pepe" .. para añadir un cliente podríamos escribir: Dim cliente As New Cliente cliente.. por ejemplo.correspondientes en la tabla de la base de datos y que hemos usado en la línea de ejemplo.ClientesDataTable Dim ta As New ClientesTableAdapters. o también usando el método GetData para obtener la tabla directamente si sólo nos interesa esa parte concreta del DataSet (que puede constar de varias tablas): Dim clientes As Clientes.ClientesTableAdapter() clientes = ta... Además es un modo muy sencillo de separar la funcionalidad de la base de datos del resto del código. Así.Fill(clientes.Clientes) clientes.AddClientesRow(cliente) Nótese que el método Add del DataTable se ha sustituido por uno con nombre especializado que nos ayuda a saber mejor por donde pisamos.. un servicio Web que utilice el DataSet tipado y sus TableAdapters para acceder a los datos desde una ubicación remota.. Ver vídeo de esta lección (Dataset tipados) .

0 que nos ayudarán a crear aplicaciones más potentes y con menos esfuerzo que con cualquier otra herramienta de desarrollo.NET 2.0. También conoceremos los nuevos controles de seguridad que vienen con ASP.Contenido En este módulo vamos a aprender ciertas cuestiones avanzadas de ASP. Veremos como conseguir páginas con un aspecto y funcionalidad consistentes a lo largo de toda la aplicación Web. incluyendo versiones anteriores de .NET.skin § Propiedades que se pueden personaliza o Asignación de temas § Asignación global de temas § Precedencia de propiedades § Deshabilitar temas en controles concretos § Clases de un mismo tipo de control § Inclusión automática de hojas de estilo · .NET o Temas y máscaras (Skins) § La carpeta App_Themes § Estructura de un archivo .NET 2. · Lección 1: Páginas principales o Master Pages o Introducción o ¿Qué son las Master Pages? o Definición de una Master Page o Master Pages anidadas o Acceso a los elementos de una Master Page Lección 2: Temas y Skins o Hojas de estilo § Soporte de estilos en ASP. y estudiaremos la forma de mantener información en memoria para agilizar las aplicaciones.

· · § Rutas de imágenes Lección 3: Estado de las aplicaciones o Mantenimiento de sesiones § Variables de sesión § Funcionamiento básico de las sesiones § Sesiones sin cookies § Almacenamiento de sesiones § Tipos de objetos almacenables o Información común § Variables de aplicación § Concurrencia en variables de aplicación § Almacenamiento en caché o Caché de salida § Directiva Outputcache § Atributos de OutputCache § ¿Donde se hace la caché? § Almacenamiento en disco § Sustitución post-caché Lección 4: Seguridad de las aplicaciones o Autenticación y autorización de usuarios § Autenticación de IIS/Windows § Autenticación Forms en ASP.NET o Autorización de usuarios § Autorización de URLs § Autorización declarativa § Autorización imperativa o La nueva API: Membership y Roles § Membership § Roles § Administración de seguridad de sitios Web o Los controles Web de seguridad § El control Login § El control LoginStatus § El control LoginName § El control LoginView § Los controles restantes .

mientras que en otra zona de la aplicación el diseño es completamente diferente pero sus páginas se parecen todas entre sí.Páginas principales o Master Pages Lo más habitual cuando se crea una aplicación o un sitio Web es que las páginas que lo conforman sean todas bastante parecidas o al menos que existan varios grupos de páginas similares que sólo varían ciertos contenidos entre ellas. Por ejemplo. Por ejemplo. la siguiente figura muestra capturas de dos páginas pertenecientes al portal MSDN: . puede haber una categoría de páginas para mostrar artículos en el que todas son iguales excepto por el contenido del propio artículo en su parte central.

El motivo es que este término es el más aceptado y el que veremos con más frecuencia.. ASP. En el primero de los casos (retocar una a una) cualquier cambio estético de un sitio medianamente grande era poco menos que una locura de realizar. ¿Qué son las Master Pages? Una Master Page proporciona una forma de definir una estructura e interfaz comunes para un grupo de páginas pertenecientes a un mismo sitio Web. Ello facilita mucho su . en este caso haré una excepción y durante el resto del texto emplearé el término anglosajón Master Pages (o MP) para referirme a esta característica.Ejemplo de dos páginas similares en MSDN Ambas páginas difieren únicamente en el contenido y los menús que muestran en el lateral (los banners del lateral son rotativos). y conservan una estática y una serie de elementos que permanecen constantes en todas las páginas del sitio. Aún en este último caso la capacidad de modificación era limitada y normalmente se reducía a las cabeceras y pies de las páginas y poco más. Nota: Aunque normalmente soy partidario de utilizar los términos en castellano siempre que los haya. Tradicionalmente para conseguir esta similitud entre páginas había que crearlas individualmente o recurrir a artificios propios como por ejemplo el de utilizar archivos de inclusión para renderizar ciertas partes de las páginas desde un mismo origen en disco.1. Esta estructura común se almacena en un único archivo independiente.Figura 5.NET 2.0 ofrece una nueva característica destinada a paliar esta tradicional carencia y permite definir páginas cuyo aspecto y funcionalidad deriva de unas páginas especiales comunes llamadas Páginas principales o Master Pages.

mantenimiento puesto que.2. Sin embargo posee una extensión diferente (. Al abrir una MP aparece un diseñador idéntico al de una página ASPX normal. Una página ASPX normal puede derivar su estructura a partir de una MP simplemente añadiendo un atributo MasterPageFile a su directiva de página. La sintaxis de este control es análoga a la siguiente: Su única propiedad interesante es precisamente su identificador ya que este tipo de control se utiliza para marcar las posiciones en las que irán los diferentes contenidos de las páginas derivadas dentro de la plantilla de estructura que es una Master Page.Plantilla de Master Page. para actualizar todas las páginas que lo utilizan. Por lo demás se pueden considerar prácticamente equivalentes. La única diferencia apreciable a simple vista respecto a una página normal es que contiene por defecto un control de tipo ContentPlaceHolder. Podemos arrastrar sobre su superficie cualquier control así como editar su HTML de la manera usual. así: que indica el archivo de página principal que se utilizará para su estructura. Una MP es en realidad como una página ASPX normal que contiene código.. elementos HTML y controles Web de servidor. . basta con editar dicho archivo. Esto es importante porque significa que ya sabemos todo lo necesario para crearlas. También lleva un archivo de código asociado en el que se puede responder a sus diversos eventos. Definición de una Master Page Para agregar una Master Page a nuestro proyecto sólo hay que elegir el icono Página Principal en el diálgo de agregar nueva referencia de cualquier carpeta del mismo: Figura 5.master) y utilizan una directiva <% @ master %> en lugar de una directiva <% @ page %>.

3. Al editar una página que deriva de una Master Page aparece el aspecto y estructura de la página principal en el diseñador. Esto nos evita tener que escribir el atributo MasterPageFile manualmente. Master Pages anidadas Una Master Page a su vez puede derivar de otra que previamente hayamos definido. antes de crearla.De este modo. Al igual que en el caso de las páginas normales sólo hace falta establecer el atributo MasterPageFile. por lo que heredará la estructura y contenidos de ésta. Esta característica se suele utilizar para definir en una de ellas la estructura general del sitio Web. cuando una página normal derive de una MP.Selección de una MP al crear una nueva página. La única "pega" que tiene el uso de Master Pages anidadas es que no están soportadas por el diseñador de Visual Studio. En otra de las MP se define únicamente la estructura de los contenidos que contiene la estructura general.. pero sólo se pueden tocar las partes correspondientes a los comodines de contenido. nos permita seleccionar de qué MP derivará: Figura 5. . Cuando añadimos una nueva página ASPX a nuestro proyecto y existe al menos una Master Page. por lo que habrá que añadir los controles directamente a mano desde la vista de marcado de la página. podemos marcar una opción para que. sólo se podrá introducir código dentro de las zonas definidas por estos comodines de contenido. Siempre podremos diseñarlas visualmente antes de hacerlas derivar de una Master Page anidada y así salvar esta limitación.

microsoft.gif" que nos aislará de lo que ocurra debajo para gestionar ese logo.Acceso a los elementos de una Master Page Es posible acceder a los controles y elementos de una página principal desde el código de una página derivada a través de una directiva especial llamada MasterType.Logo = "http://www. es definir propiedades en la Master Page que encapsulen el acceso a sus elementos.com/logo_msdn. Ver vídeo de esta lección (Master Pages) . El código anterior devuelve un objeto de tipo Control que deberemos convertir en un control de imagen y asignarle la ruta al logo a utilizar. así: Una vez hecho esto podemos acceder a los elementos de la página de la que deriva la actual a través de su propiedad Master. menos propenso a errores y de mejor mantenimiento futuro el definir una propiedad 'Logo' en nuestra Master Page y acceder a ella escribiendo. si nuestra Master Page tiene un elemento de imagen llamado 'Logo' y queremos variarlo en cada página mediante código sólo habría que escribir: Master. Por ejemplo. Sólo hay que indicar la ruta de la Master Page a la que queremos acceder. sin embargo.FindControl("Logo") Lo mejor. por ejemplo: Master. Es más mucho más fácil.

Podemos configurar su aspecto estableciendo las propiedades de apariencia del control (como BackColor. Veamos las opciones que nos ofrece ASP. · Lección 2: Temas y Skins o Hojas de estilo § Soporte de estilos en ASP. El problema que tiene este método es que. Sin embargo aún no hemos resuelto todas las cuestiones sobre el mantenimiento de la interfaz que habíamos planteado.NET o Temas y máscaras (Skins) § La carpeta App_Themes § Estructura de un archivo . Font. Esta no es una opción admisible en cuanto la aplicación dispone de más de unas pocas páginas.Temas y Skins Gracias a las Master Pages podemos definir una estructura común para las páginas de nuestra aplicación Web.. tendríamos que tocar una por una todas las páginas.).NET 2. si deseamos cambiar por completo la apariencia de estos controles.skin § Propiedades que se pueden personaliza o Asignación de temas § Asignación global de temas § Precedencia de propiedades § Deshabilitar temas en controles concretos § Clases de un mismo tipo de control § Inclusión automática de hojas de estilo § Rutas de imágenes . Los controles que añadamos a las zonas de contenido de nuestras páginas todavía tendrán el aspecto predeterminado.. etc.0 para solventar esta otra parte de un mismo problema.

Así. es posible crear archivos con extensión '. hacerlo así les hace perder su verdadero sentido que no es otro que el de separar la definición del aspecto. padding: 0. background-repeat: repeat. Aunque se pueden definir dentro de la propia página.css' que se vinculan a las diferentes páginas de un sitio y definen el aspecto de sus elementos. background-image: url(Images/background. } body { background-color: #656565.gif). color: #DBB94F.Hojas de estilo HTML ofrece una interesante opción para independizar el aspecto de sus elementos del contenido de las páginas a través del uso de las hojas de estilo en cascada (Cascading Style-Sheets o CSS). Dentro de una hoja CSS se definen fundamentalmente dos tipos de estilos: · Redefinición de etiquetas: indican qué aspecto deben tener todas las etiquetas de un determinado tipo en las páginas a las que esté vinculado el archivo. . Las hojas CSS permiten definir el aspecto de cualquier elemento HTML contenido en una página. margin: 0. Por ejemplo: a { text-decoration: none.

. sans-serif.com" class="EstiloSimple">MSDN</a> En este caso se define la clase llamada EstiloSimple. Para asignar un archivo CSS a una página sólo hay que incluir en su cabecera una linea análoga a esta: <link href="mi_hoja. font-size: 0. Por supuesto ASP. color: #DBB94F.NET. Se puede añadir una etiqueta <LINK> a la cabecera de una página ASPX y los elementos HTML que se generan a partir de los controles que contiene se mostrarán siguiendo las indicaciones de la misma..7em.css" rel="StyleSheet" /> La gran ventaja de esta técnica es que basta con tocar el archivo CSS para que todas las páginas que lo utilizan vean su aspecto modificado de manera acorde a los cambios. . Soporte de estilos en ASP. color: #FFFFFF.} text-align: center. Arial.microsoft. Da igual que sea sólo una o haya miles. font-family: Verdana. y cualquier etiqueta HTML a la que se le asigne mediante su atributo class adquirirá el aspecto marcado.NET tiene en cuenta y soporta perfectamente las hojas CSS. Helvetica. las etiquetas definen el aspecto que deben tomar los enlaces y el cuerpo de la página. · Clases: definen aspectos que no están asociados a una etiqueta HTML concreta sino que se pueden asignar mediante el atributo class a cualquiera de ellas. Por ejemplo: EstiloSimple { text-decoration: none... <a href="http://msdn. } . En este fragmento. Al tener el aspecto centralizado en una ubicación única el mantenimiento es muy sencillo.NET Lo anterior es una característica de HTML independiente de lenguajes de programación como ASP.

4. como por ejemplo: .Diálogo de configuración de estilo para un control HTML. tanto en tiempo de diseño como durante la ejecución. También se puede aplicar un estilo concreto a ciertos controles directamente desde el marcado de la página ASPX.El entorno de desarrollo de Visual Studio permite definir los estilos de los controles HTML de servidor de ASP. El diseñador de páginas ASPX incluso ofrece un diálogo especializado para crear los estilos.. y además disponen de una propiedad llamada CssClass para establecer mediante código el nombre de las clase que se quiere aplicar al control (se traduce en un atributo Class normal de HTML en tiempo de ejecución).NET utilizando su propiedad Style. Figura 5. En el caso de los controles Web de servidor se utilizan sus propiedades de aspecto (que se traducen en estilos al renderizarse en un navegador moderno).

<ASP:Calendar ... runat="server"> <TitleStyle BorderColor="blue" BorderWidth="1" BackColor="olivedrab" Height="50px" /> </ASP:Calendar> si bien en este caso no se usan atributos normales de CSS. .

NET 2. Los temas de ASP. Esta carpeta de nombre especial es App_Themes.NET son como hojas de estilo que se aplican a controles Web y sus elementos tienen una sintaxis prácticamente idéntica a la de los controles cuyo aspecto definen. La funcionalidad ofrecida por los temas de ASP.0 está formado por uno o varios archivos de tipo . ASP.NET. Podemos añadir una carpeta de temas con el menú de agregar carpeta de un proyecto de Visual Studio: .NET 2.0 se entiende fácilmente si los asemejamos con las hojas de estilo. Además dejan fuera algunas funcionalidades. como los valores por defecto de propiedades de controles (por ejemplo el texto inicial de un campo) o el aspecto de controles Web complejos como calendarios o rejillas que no se pueden expresar únicamente con un estilo CSS. La carpeta App_Themes Un tema de ASP. no se adaptan por completo a los controles ASP.Temas y máscaras (Skins) Si bien las hojas de estilo resuelven en gran parte el problema de independizar el aspecto de la definición de contenidos de una página. Enseguida lo entenderemos. que se almacenan dentro de una carpeta con el nombre del tema dentro de una carpeta especial.skin junto con las imagenes y hojas de estilo CSS que éstos utilicen.0 introduce una interesante novedad que se complementa la perfección con las Master Pages para solventar el problema del aspecto: los temas y máscaras de controles Web.NET 2.

En el diálogo que aparece seleccionaremos un archivo de máscara.. como se muestra en la figura: Figura 5.Nueva carpeta especial App_Theme.skin para comenzar a definir con él nuestro primer tema.Nuevo archivo de máscara (Skin) .Figura 5. Para ello agregaremos un nuevo elemento. Una vez creada la carpeta de temas deberemos crear un archivo .6.5..

Por ejemplo. Por ejemplo el gráfico del lateral muestra una carpeta App_Theme que contiene dos temas y cada uno de ellos a su vez contiene un archivo . hojas CSS y gráficos específicos del tema. Estructura de un archivo . si escribimos los siguiente en el archivo . Propiedades que se pueden personalizar Aunque los archivos de máscara están pensados para facilitar la aplicación de propiedades estéticas de los controles. Podemos definir manualmente tantas carpetas de tema como queramos usando el menú de agregar nuevas carpetas. la única diferencia entre un elemento del archivo de máscara y el marcado de un control está en que los primeros carecen del atributo de identificación ID.El primer archivo de máscara que agreguemos definirá automáticamente una carpeta de tema con su mismo nombre para contenerlo. Las rejillas que se utilicen automáticamente tendrán el fondo blanco y las líneas pares azules. Por lo demás son prácticamente idénticos. Luego sólo hay que copiar su definición al archivo . Por ejemplo. TRUCO: Dado que Visual Studio no proporciona asistencia para crear archivos de máscara (es un simple editor de texto). hojas de estilo y gráficos como necesitemos.skin eliminando todos los atributos ID.skin de un tema: . Dentro de cada una de esas carpetas puede haber tantos archivos de máscara.skin.NET a los que se le establecen valores de propiedades que serán aplicadas de modo automático cuando aparezcan en una página que use el tema al que pertenece la máscara. si un archivo .skin Un archivo de máscara contiene definiciones de controles ASP. Si nos fijamos.skin contiene el siguiente código: conseguiremos que las páginas que lo apliquen dispongan de controles TextBox con el fondo gris claro y el borde punteado de 1 pixel de ancho. una forma sencilla de definir sus elementos es utilizar una página ASPX vacía para arrastrar y configurar controles con los aspectos deseados. lo cierto es que se puede definir casi cualquier otra propiedad de un control.

Nota: Los creadores de controles pueden emplear el atributo ThemeableAttribute para indicar que una propiedad no es personalizable mediante una máscara. . En realidad cualquier propiedad de un control web puede personalizarse mediante un archivo de máscara a menos que su creador haya indicado explícitamente lo contrario. Esta particularidad puede resultar muy interesante en ciertos casos.todos los controles de tipo TextBox de nuestra aplicación mostrarán el texto "(valor)" al cargar las página que usen este tema (nótese el atributo Text en la primera línea).

. Nota: Lo más interesante de este atributo Theme es que se puede establecer en cualquier momento.Asignación de temas Ahora que ya conocemos la teoría acerca de los temas y sabemos crear archivos de máscara para los temas vamos a aprender a utilizarlos en la práctica. y añadírselos sin demasiado esfuerzo al final con sólo asignarlo. Nada más establecer el atributo la página se personaliza en tiempo de ejecución siguiendo los dictados de los archivos . podemos desarrollar una aplicación completa sin pensar siquiera en los temas. Dado que podemos disponer de varios temas se puede asignar uno diferente a cada grupo de páginas de una aplicación según las necesidades. Para que una página se adapte automáticamente a un tema definido en la carpeta App_Themes lo único que tenemos que hacer es asignar un atributo Theme en la directiva de la página. Es decir. así: El segundo atributo indica el tema que se va a aplicar. El entorno de desarrollo de Visual Studio nos ofrece de manera automática una lista de temas disponibles al escribir este atributo por lo que es muy fácil escribirlo. Ello permite además separar la labor de diseño de la de desarrollo que incluso la puede hacer un equipo de trabajo diferente.skin que haya definidos para el tema.

. Consiste en añadir un nuevo nodo de tipo <pages theme=./> al archivo de configuración de la aplicación.skin del tema que utiliza la página este color indica que debe ser gris.config. con lo que perderíamos bastante de la productividad ganada.config.config heredarán el tema principal del sitio..config específicos para indicar el tema en cada una de ellas. Nota: Dado que una aplicación Web puede disponer de varios archivos de configuración (uno por cada carpeta) si queremos que la aplicación emplee un tema diferente en diferentes zonas sólo tenemos que guardar todas las páginas de cada zona en una carpeta diferente y crear archivos web. Precedencia de propiedades Cuando un elemento de una máscara define un atributo para un control. éste tiene precedencia sobre el mismo atributo en caso de que se haya asignado también en la página. La entrada sería similar a la siguiente: Al hacerlo todas las páginas de la aplicación utilizarán el tema indicado sin necesidad de establecerlo manualmente. Para evitar esta situación ASP.Asignación global de temas El uso del atributo Theme es muy adecuado cuando sólo tenemos unas pocas páginas a las que aplicárselo. De hecho si deseamos que una página no utilice tema alguno sólo hay que establecer su atributo Theme a una cadena vacía (""). Las carpetas que no dispongan de su propio web.NET ofrece otra forma de establecer los temas de forma global. éste tendrá precedencia sobre el ajuste de Web. Una forma alternativa de definir un tema para una página que cambia este orden de precedencia es emplear el atributo StylesheetTheme en lugar del más común Theme que hemos visto hasta ahora: . Por ejemplo. el archivo web. pero en el archivo . En aplicaciones grandes el hecho de tener que recorrer las páginas una por una para asignarlo puede ser muy tedioso. Si se define un tema específico para una página.. si en una página tenemos un TextBox cuyo color de fondo lo hemos establecido en amarillo. .. al ejecutar la aplicaicón se verá de color gris.

2. Se aplican los atributos del tema especificado en Theme que en caso de coincidencia tienen por tanto preferencia sobre los anteriores. En este caso la precedencia lo que ocurre es lo siguiente: 1. Clases de un mismo tipo de control El hecho de declarar un elemento genérico dentro de un archivo de máscara es útil pero no lo suficiente. cada una con unos atributos específicos. Justo al contrario que en el caso habitual. Se aplican los atributos del tema especificado en StylesheetTheme. Considere el siguiente ejemplo: En este caso se han definido tres clases de controles TextBox. Los dos primeros tienen asignado un SkinID y sólo se aplicarán a aquellos controles TextBox cuya propiedad SkinID coincida con el SkinID de la definición. Al igual que en el caso de las hojas de estilo en los temas se pueden definir distintas clases de un mismo control. Se aplican los atributos definidos en la página que sobreescriben a los del paso anterior en caso de coincidencia. Lo más normal es que no todas las etiquetas o botones (por poner un ejemplo) tengan exactamente el mismo aspecto sino más bien que existan varios tipos de etiquetas y botones que se empleen según la ocasión. La forma de conseguirlo es asignando su propiedad EnableTheming a False. Deshabilitar temas para controles concretos En ocasiones es útil dejar un control con su aspecto habitual de forma que no se vea afectado por el tema asignado a la página. La última definición no tiene asignado identificador alguno por lo que se considera la clase por defecto y se aplicará a todos los controles de texto que no hayan indicado específicamente un SkinID. 3.En este caso el valor establecido en la página para una propiedad tiene preferencia sobre el valor del archivo de máscara en caso de haber coincidencia. Una posibilidad poco frecuente es utilizar ambos atributos (Theme y StylesheetTheme) simultáneamente. La forma de distinguir unos de otros es a través del atributo SkinID. .

NET se encarga de modificar las rutas para que apunten al lugar correcto tras la aplicación del tema. Ver vídeo de esta lección (Uso de temas) . cosa que todas las páginas cumplen de manera predeterminada.skin dentro de la carpeta de un tema.Lo habitual es separar los distintos grupos de controles es varios archivos . ASP. éstas se añaden de manera automática a la cabecera de las páginas que utilizan el tema mediante etiquetas <link>. Rutas de imágenes Por supuesto en las propiedades de los elementos de una máscara se pueden utilizar imágenes como en este ejemplo: Debemos guardar las imágenes en alguna subcarpeta de la carpeta de recursos del tema y utilizar rutas relativas a ésta para los atributos que las utilicen. La única condición para que esto funcione es que el atributo <head> de lapágina (que representa la cabecera) tenga el atributo de ejecución en el servidor runat="server". como en el ejemplo. Se reconocerán como si estuvieran todos en el mismo archivo pero es más ordenado gestionarlos por separado. Inclusión automática de hojas de estilo Dentro de la carpeta de un tema tienen cabida también hojas de estilo como ya hemos mencionado. Cuando se copia una o más hojas de estilo enla carpeta.

· Lección 3: Estado de las aplicaciones o Mantenimiento de sesiones § Variables de sesión § Funcionamiento básico de las sesiones § Sesiones sin cookies § Almacenamiento de sesiones § Tipos de objetos almacenables o Información común § Variables de aplicación § Concurrencia en variables de aplicación § Almacenamiento en caché o Caché de salida § Directiva Outputcache § Atributos de OutputCache . entre otras: · · · · Almacenar temporalmente datos costosos de obtener para mejorar el rendimiento. Mejorar el rendimiento evitando que se rendericen por completo o en parte las páginas de nuestro sitio Web. distinguiéndola por cada usuario o de manera común a todos. Guardar detalles de un usuario entre diferentes visitas a una aplicación. Compartir información entre todas las páginas de una aplicación. Existen diferentes métodos para mantener el estado de una aplicación y sus utilidades en la práctica son muchas.Estado de las aplicaciones En esta lección vamos a aprender la manera de mantener información en memoria durante la vida de una aplicación.

§ § § ¿Donde se hace la caché? Almacenamiento en disco Sustitución post-caché .

Mantenimiento de sesiones
HTTP es un protocolo sin estado y como tal no existe forma a priori de distinguir entre las diferentes peticiones realizadas a un servidor Web. Sin embargo las aplicaciones Web necesitan mantener de algún modo un estado que les permita agrupar de manera lógica las llamadas. Sin ello no habría forma, por ejemplo, de distinguir dos llamadas a una misma página de dos usuarios diferentes. Para conseguir este artificio sobre un protocolo sin estado ASP.NET proporciona las sesiones. Nota: Cabría pensar que una buena forma de distinguir unas llamadas de otras en una aplicación Web es a través de la dirección IP del cliente. Nada más lejos de la realidad. Dos usuarios diferentes que accedan detrás de un mismo router (por ejemplo, dos personas en una misma oficina) tienen la misma IP exactamente. Además, desde el punto de vista de la seguridad es muy mala idea usar invariantes de este estilo pues son fáciles de falsear. Variables de sesión ASP.NET ofrece una colección llamada Session en el objeto Page que nos permite almacenar parejas de claves y valores que están disponibles desde todas las páginas de una aplicación y se distinguen automáticamente para cada cliente que las utilice. Esto implica que podremos almacenar valores de cualquier tipo a los que podremos cuando sea necesario mientras el usaurio que solicite las páginas sea el mismo. Por convención a las parejas de claves y valores almacenados en el objeto Session se les denomina variables de sesión.

Por ejemplo, si quiero contar cuantas veces ha pasado un usuario por una página 'a.aspx' puedo escribir en su evento Load lo siguiente:
Session("Cuenta") += 1;

Esto haría que el valor asociado con la clave "Cuenta" se incrementara en uno cada vez que se cargue la página. Es decir, en palabras llanas, incrementa en la unidad el valor de la variable de sesión "Cuenta". Si creamos una segunda página 'b.aspx' en la que mostramos el valor de la variables de sesión mediante:
Response.Write(Session("Cuenta"))

veremos que la variable se incrementa en cada ocasión como esperábamos, a pesar de que, en principio, cada petición HTTP es independiente de las demás. Si abrimos un nuevo navegador veremos que las páginas en éste generan una cuenta independiente. Funcionamiento básico de las sesiones Si cada llamada HTTP es independiente de las demás, ¿cómo es posible el comportamiento anterior?. Por defecto ASP.NET mantiene la ilusión de las sesiones mediante el uso de cookies de sesión. Este es un sistema análogo (aunque diferente) al que ya ofrecía ASP 3.0 clásico para el mismo propósito. Una cookie de sesión no es más que una cabecera HTTP con un identificador único que el servidor envía al cliente en la primera petición que éste hace y que el navegador se encarga de reenviar automáticamente en las sucesivas peticiones. Así, basta con comprobar esta cabecera en el servidor en cada petición para averiguar qué usuario es el que la realiza. Así de simple. Este es el aspecto de una cookie de sesión de ASP.NET:
ASP.NET_SessionId=43s3ir55u0vvlj55smesaj45

Este fragmento es el que se envía en la cabecera de las peticiones, siendo el valor después del igual el identificador único utilizado para esa sesión. Estas cookies de sesión no se almacenan jamás a disco y sólo existen mientras el navegador está abierto. Si cerramos el navegador no podremos recuperar la anterior sesión. Sesiones sin cookies El sistema de cookies de sesión descrito funciona muy bien en la mayor parte de los casos pero tiene algunos inconvenientes, el principal de los cuales es que si el usuario ha deshabilitado las cookies de sesión todo dejará de funcionar. Para evitar este problema ASP.NET dispone de un método alternativo para mantenimiento de sesión que no utiliza cookies ni cabeceras, sino que introduce una

ruta virtual aleatoria en todas las peticiones de modo que todas son distintas. Si la llamada a una página se efectuaba en esta URL:
http://www.miservidor.com/miapp/pagina.aspx

al habilitar las cookies sin sesión la llamada se convierte en algo similar a:
http://www.miservidor.com/miapp/(S(1rhk5t45tlxy3e45swjibe55))/pagina .aspx

Como vemos se introduce una última carpeta virtual con un identificador aleatorio y cifrado (del estilo del que iba en las cabeceras HTTP). Esta carpeta obviamente no existe pero uno de los gestores de la llamada a las páginas de ASP.NET es capaz de distinguir que se trata de un identificador de sesión y actuar de manera transparente para mantenerla y enviar las peticiones a las páginas correctas. Este método es menos propenso a fallos que el anterior pero tiene el inconveniente de que se generan URLs mucho más largas y menos atractivas. Las sesiones sin cookies no existían en ASP 3.0. Habilitar este tipo de sesiones es muy sencillo. Basta con abrir el archivo de configuración de la aplicación (web.config) y añadir el siguiente ajuste dentro del nodo <system.web>:
<sessionState cookieless="UseUri" />

Almacenamiento de sesiones La información referente a los datos de sesión se almacena por defecto en la memoria del servidor. Ello suscita un problema importante cuando la aplicación debe ser muy escalable y tener capacidad para gestionar miles de peticiones simultáneas. En estos casos es frecuente ubicarla en varios servidores balanceados. A medida que llegan nuevas petición a la granja de servidores, éstas se reparten por las distintas máquinas que la constituyen, bien aleatoriamente, bien siguiendo algún sistema de cuotas o asignándolas por orden (round-robin). Dado que cada máquina mantiene su propia copia de las sesiones, a menos que cada usuario se redirija siempre al mismo servidor, no habrá forma de mantener una sesión coherente, pues no existe una ubicación compartida para almacenar los datos de las sesiones. Nota: Existe forma de configurar las granjas de servidores con afinidad de manera que cada usuario siempre se redirija al mismo servidor. Aún así existen otros problemas con la sincronización de datos compartidos en toda la aplciación y además el sistema reduce la escalabilidad. ASP.NET 2.0 permite configurar el almacenamiento de sesiones para utilizar cualquier proveedor de almacenamiento de sesión diferente al que usa por defecto (y que

guarda todo en la memoria RAM local). Con la plataforma .NET se entregan dos proveedores de almacenamiento de sesión adicionales que permiten almacenar los datos en un servidor ASP.NET central o en una base de datos SQL Server respectivamente. Se establece el modo de almacenamiento a través del archivo web.config:

Figura 5.7.- Configuración del modo de sesión La configuración detallada de estas opciones avanzadas se sale del ámbito de este curso, pero conviene saber que existe esta posibilidad y entenderla bien para poder emplearla en casos de necesidad. Nota: Gracias al modelo de extensibilidad mediante proveedores que ofrece ASP.NET 2.0 es posible escribir nuestros propios proveedores para almacenar la sesión del modo que más nos convenga, si bien no es lo habitual. Esta característica incluso nos permite definir un formato propio para los identificadores de sesión aunque hacerlo no es en general una buena idea. Duración de las sesiones Una sesión se mantiene en memoria en el servidor mientras no transcurra más de un determinado tiempo sin recibir actividad por parte de un usuario. Por defecto Internet Information Server mantiene vivas las sesiones durante 20 minutos, pero se puede cambiar este ajuste desde las propiedades avanzadas de cualquier servidor o directorio virtual.

Figura 5.8.- Establecimiento del tiempo de sesión en IIS También se puede establecer desde la configuración de la aplicación (web.config) usando el atributo timeOut del mismo nodo que hemos estado usando hasta ahora:
<sessionState timeout="10"/>

También se puede asignar mediante cádigo usando la propiedad Timeout del objeto Session.
Session.Timeout = 10

Si transcurre el número de minutos marcados sin recibir nuevas peticiones de un mismo usuario los datos de la sesión se eliminan automáticamente. Hay que tener cuidado con esto porque nunca sabemos cuando puede ocurrir, por lo que jamás debemos dar por hecho que una determinada variable de sesión existe. Podemos forzar el abandono de una sesión desde el código llamado al método Abandon del objeto Session:
Session.Abandon()

Tipos de objetos almacenables En ASP 3.0 estaba limitado el tipo de objetos que podíamos almacenar en variables de sesión. Por ejemplo, no se debían almacenar objetos RecordSet de datos o perdíamos escalabilidad, y había otros tipos de objetos que generaban un error al intentar almacenarlos. El uso directo de ciertos objetos como las matrices desde variables de sesión penalizaba el rendimiento.

En el caso de ASP.NET no existen estas limitaciones y podemos almacenar cualqueir objeto .NET sin problema cuando usamos el modelo en memoria. En el caso de los modelos de almacenamiento centralizado los objetos a almacenar deben ser serializables.

Ver vídeo de esta lección (Sesiones de usuario)

implementar un contador de llamadas a páginas de una aplicación es muy sencillo si utilizamos el objeto Application. De hecho es bastante probable que existan muchas coincidencias a la hora de escribir en la variable anterior si metemos ese código en todas las páginas de una aplicación y hay bastantes usuarios. Las variables de aplicación se gestionan exactamente de la misma manera que las de sesión pero usando la propiedad Application de la página en lugar de Session. Concurrencia en variables de aplicación El código anterior presenta un problema poco evidente que tiene que ver con la concurrencia de uso de las variables de aplicación.Información común Variables de aplicación Las variables de sesión permiten guardar información que concierne a un usuario concreto y que no es accesible para los demás. . Por ejemplo. Las variables de aplicación por el contrario están pensadas para almacenar en memoria datos que están accesibles para todos los usuarios al mismo tiempo. En una aplicación Web pueden estar ejecutándose al mismo tiempo varias páginas. ya que sólo tendríamos que escribir en la carga de cada página: Application("Contador") += 1 Esta variable estará accesible desde cualquier otra página de cualquier sesión de usuario.

En ASP. Response.NET ofrece un potente sistema de almacenamiento en caché que guarda los objetos en memoria y es privado para cada aplicación.UnLock() De este modo se bloquea el acceso de las demás páginas a las variables de aplicación mientras no se llame al método de desbloqueo y se evitan así los problemas de concurrencia. Si usamos una variable de aplicación ¿cómo nos enteraremos de que el contenido del archivo ha cambiado y que. Para evitar estos problemas de concurrencia se definen dos métodos del objeto HttpApplication que permiten el acceso en exclusiva a las variables de sesión por parte de una página. por lo tanto debemos recargar los datos? . La ventaja fundamental de la caché de ASP. Almacenamiento en caché ASP. a la larga. La forma correcta del código anterior sería: Application. Nota: En ASP 3.0 esta era la única manera de compartir memoria en el ámbito de aplicación. existe un objeto Cache que proporciona una interfaz indexada que permite establecer y recuperar pares de clave-valor. imaginemos que llemos en la variable 'datos' el contenido de un archivo XML y queremos guardarlo en memoria para uso común y evitar así el contínuo acceso a disco para leer el contenido.. Así podemos escribir: Cache("MiClave") = miValor . que el contenido de la variable no contuviera el verdadero número de peticiones realizadas.NET se soporta un método mucho mejor a través de objetos de caché que ahora veremos y se desaconseja el uso de las variables de aplicación en la medida de lo posible. pero no está exenta de problemas.Lock() Application("Contador") += 1 Application.Write( Cache("MiClave") ) La caché se usa habitualmente para almacenar datos que son costosos de obtener y que pueden ser aprovechados por todos los usuarios..Ello provocaría inconsistencias en los valores y. como por ejemplo un DataSet resultante de una compleja consulta a una base de datos. Hay que tener cuidado sin embargo con el uso que se hace de esta característica pues puede afectar a la escalabilidad por bloqueos en las otras páginas..NET frente a las variables de aplicación es que es muy fácil conseguir la caducidad automática de sus elementos. De forma análoga a los dos casos anteriores. Por ejemplo.

pero la solución dista mucho de ser óptima.MapPath("misdatos.Now.Insert("MisDatos". Cache. Incluso es posible especificar un delegado a una función a la que queremos llamar automáticamente cuando el elemento expire y así recargarlo de inmediato. . TimeSpan.xml' cambia.Zero) datos. Nothing. Si estamos trabajando con SQL Server 2005 podemos aprovechar la existencia de su sistema de encolado de mensajes (Message Broker) para crear dependencias de caché en consultas. el elemento desaparece de la caché y lo volveremos a cargar la próxima vez que se consulte. basta con escribir la siguiente línea: Cache.Insert("MisDatos". DateTime. New CacheDependency(Server. Conseguirlo con la caché de ASP. Esta línea agrega el elemento sin dependencia en objeto alguno y con una fecha de caducidad para dentro de dos horas.FromMinutes(30)) datos. La clase CacheDependency se puede heredar para crear nuestros propios criterios de caducidad de caché. Se pueden agregar dependencias a archivos en disco y a claves en el registro y también combinaciones de estas dependencias.Insert("MisDatos". de forma que cuando se modifiquen los datos de una base de datos se reciba una notificación automática. También se puede establecer la fecha de caducidad de un elemento de la caché con otra versión sobrecargada del método Insert: Cache. En este caso la caducidad es relativa e indica que el valor caducará en cuanto nadie haga uso de el durante 30 minutos. TimeSpan. Este mecanismo es muy potente y conviene aprender a usarlo bien.xml"))) En lugar de usar la interfaz de indexación directa de elementos del objeto Cache usamos su método Insert que en una de sus versiones sobrecargadas permite agregar una dependencia a un archivo. A partir de ese momento si el archivo 'misdatos.NET es muy sencillo. datos. DateTime. Nothing.No hay forma de hacerlo.AddHours(2). Podemos establecer un mecanismo propio que cada cierto tiempo recargue la variable.MaxValue.

tras la primera petición. de algún parámetro.. etc.. Directiva OutputCache Para poder hacer caché del contenido de una página o un control de usuario hay que indicar a ASP. Su uso es extremadamente sencillo y pueden aumentar de forma espectacular el rendimiento de cualquier aplicación. ASP..Caché de salida La caché de salida de ASP..NET de qué depende la caducidad de dicho contenido. Como se pueden aplicar las directivas de caché de salida a los controles de usuario.NET no tiene que generarlos ni crear instancias de objetos. Por ejemplo. Si se defineuna directiva de caché para una página o un control de usuario.NET es un mecanismo que nos permite decidir qué partes de una página deben generarse en cada solicitud y cuáles pueden ser aprovechadas para posteriores peticiones. la siguiente directiva: . Para ello se utiliza la directiva OutpuCache. por lo que se obtiene un rendimiento muy elevado ya que sólo debe leer el resultado de memoria y devolverlo. podemos convertir éstas en controles de usuario y conseguir el efecto buscado. si necesitamos hace caché sólo de determinadas partes de una página y no de la página entera. La caducidad puede depender del tiempo. de una cabecera. etc.

visualizan muchos resultados obtenidos de una base de datos y que varían con poca frecuencia puede aumentar muchísimo el rendimiento. No es válido en directivas de página. si tenemos una página a la que se le pasa un parámetro "pais" y que devuelve un listado de clientes en dicho país.NET.asax) a la cual se le pasa el valor del atributo para que pueda decidir cómo actuar. Si indicamos que debe hacerse el cliente. sin procesar la página. no que permanezca invariable sin más durante un determinado tiempo. No vamos a entrar en más detalles en este curso. al indicar VarByparam="Pais" conseguiremos una caché de resultados diferente para cada valor del parámetro. · · · ¿Dónde se hace la caché? En muchos casos (VarByParam y VarByHeader) es posible especificar en dónde queremos que se realice la caché. por ejemplo. La caché se realiza en el servidor por ASP. por lo que todavía se gana más rendimiento al evitar la petición. VaryByCustom: permite implementar nuestro propio criterio de caché. las peticiones ni siquiera se reciben en el servidor. Se debe implementar la función global GetVaryByCustomString (dentro de Global. Cuando se le pasa un nuevo valor se ejecuta la página y se almacena el resultado para las restantes veces que se solicite con el mismo parámetro (durante el tiempo especificado). Atributos de OutputCache Lo más normal en muchas páginas es que el contenido varíe en función de diferentes características. sólo de controles de usuario y se debe especificar siempre el VarByparam aunque sea con valor "None". VaryByHeader: guarda una caché para cada valor de la cabecera HTTP indicada. Por ejemplo. Si hay más de un parámetro se pueden especificar separándolos por punto y coma. . Se pueden especificar varias cabeceras separándolas por punto y coma. Para amoldarse a diferentes situaciones la directiva Outputcache dispone de varios atributos que permiten elegir el criterio de caché de los contenidos y que son los siguientes: · VaryByParam: permite especificar que se haga una caché por cada valor diferente que tome un parámetro que se le pasa a la página y que se indica en este atributo. Tras pasar los 60 segundos la página se elimina de la caché y la siguiente petición se procesa de modo normal volviendo a guardar el resultado en la caché durante otros 60 segundos.indica que el contenido completo de la página o control deberá mantenerse en caché durante 60 segundos y que la página no varía en función de parámetro GET o POST alguno que se le pase. Por ejemplo si se indica varByHeader="User-Agent" conseguiremos una versión en caché de la página por cada tipo de navegador utilizado para acceder a la página. Todas las peticiones a esta página recibidas mientras está en caché se obtienen directamente de ahí. La ubicación de la caché se indica mediante el atributo Location de la directiva OutputCache y sus valores posibles son: · Server: valor por defecto. VaryByControl: en el caso de controles de usuario su caché se fragmentará por cada valor de las propiedades del control indicadas en el atributo. En páginas que.

None: no se realiza caché alguna. Se puede deshabilitar este almacenamiento a disco estableciendo el atributo DiskCacheable a False en la directiva de caché de la página o control. En ASP.NET 2. . definimos la siguiente función: y añadimos un control Substitution como este: Si hacemos caché de la página se mantendrá todo el contenido excepto el de este control que mostrará en cada caso el valor devuelto por la función compartida DameLahora. ASP.x si hacíamos caché de una página en la que todo permanecía invariable excepto una pequeña región que mostraba.0 añade un nuevo tipo de control llamado Substitution que permite hacer excepciones a la hora de almacenar en caché una zona de una página. Este control está ubicado normalmente en la última posición de la lista de controles estándar en el cuadro de herramientas.NET 2. no sólo en memoria. Esto sirve para disponer de una caché aunque haya poca memoria disponible y hace que ésta sobreviva incluso al reinicio del servidor. estábamos obligados a dividir la página en controles de usuario para evitar la caché de esa pequeña parte. Las peticiones ni siquiera se envían al servidor.NET 1. por ejemplo. Por ejemplo. la hora. El control dispone de una propiedad MethodName que permite especificar el nombre de un método compartido (estático) que devuelve una cadena con el texto o HTML a mostrar en su lugar cuando se genere la página a partir de la caché.NET. Este método toma como parámetro un objeto HttpContext que nos permite acceder al contexto de la llamada.· · · Client: la caché la hace el propio navegador. Downstream: se intenta que la caché se haga en el servidor Proxy que realiza las peticiones (de haberlo). Almacenamiento en disco En ASP.0 las versiones en caché de las páginas y controles se almacenan de manera predeterminada también en disco.NET 2. Sustitución post-caché Esta es otra característica de ASP.0 que no estaba disponible en versiones anteriores de la plataforma .

Ver vídeo 1 de esta lección (Uso de la caché de salida) Ver vídeo 2 de esta lección (Controles de usuario y post-caché) .

· Lección 4: Seguridad de las aplicaciones o Autenticación y autorización de usuarios § Autenticación de IIS/Windows § Autenticación Forms en ASP.Seguridad de las aplicaciones Prácticamente cualquier aplicación que creemos va a necesitar seguridad en el acceso a sus diversas secciones.NET 2.0. Esta lección habla sobre la seguridad de aplicaciones desde el punto de vista de la autenticación y la autorización de usuarios.NET 2.NET o Autorización de usuarios § Autorización de URLs § Autorización declarativa § Autorización imperativa o La nueva API: Membership y Roles § Membership § Roles § Administración de seguridad de sitios Web .0 ofrece multitud de novedades en este aspecto que nos van a simplificar mucho el trabajo. Aprenderemos los fundamentos de gestión de acceso usando las nuevas características de ASP. Lo habitual es tener apartados a los que sólo pueden acceder miembros registrados o una zona de administración restringida a los gestores del sistema. ASP.

o Los controles Web de seguridad § El control Login § El control LoginStatus § El control LoginName § El control LoginView § Los controles restantes .

Autenticación y autorización de usuarios Disponemos de diversas barreras a la hora de controlar el acceso a los recursos en nuestras aplicaciones Web. La primera de ellas la constituye el propio servidor de aplicaciones que en entornos de producción es normalmente Internet Information Server (IIS). Autenticación IIS/Windows IIS permite definir mediante su configuración tanto el modo en el que se autentica a los usuarios como los permisos de acceso genéricos que se ofrecen a los recursos que sirve. La siguiente figura muestra el aspecto de las ventana que permite ajustar los métodos de autenticación de usuarios que solicitará IIS a los usuarios: .

en este caso es el programador el que debe establecer su propio mecanismo de autenticación..NET Desde la primera versión de ASP. y en este último caso cómo se autenticarán éstos contra el sistema. incluso en entornos de seguridad centralizada con Directorio Activo. por ejemplo lanzando consultas contra una base de datos (más adelante volveremos sobre este asunto). fundamentalmente para averiguar si pertenecen a un determinado perfil de usuario. Se puede restringir también el acceso a un recurso (carpeta.Configuración de seguridad de IIS La ventana de la figura permite configurar si se admiten o no usuarios anónimos.NET ofrece un gran soporte para trabajar con los usuarios una vez autenticados con el sistema. ASP. directorio virtual o archivo) en función de direcciones IP y dominios. No vamos a profundizar en este aspecto pues se sale del ámbito del curso. En lugar de utilizar usuarios del sistema (IIS debe permitir el acceso anónimo a los recursos).9. para sitios Web grandes accesibles desde Internet la autenticación de IIS (que se basa en usuarios de Windows) no es la más habitual porque se necesitaría una licencia de acceso or cada usuario con nombre.Figura 5.NET existe un método de autenticación conocido genéricamente como "Forms" que permite a los programadores crear un sistema propio de autenticación de usuarios. Autenticación Forms de ASP. El funcionamiento es el siguiente: . pero baste decir que.

NET comprueba si éste se encuentra ya autenticado o no. Activar la autenticación Forms en una aplicación es muy sencillo. y de hecho suele estar activada por defecto cuando programamos con Visual Studio 2005. ASP.10.x para utilizar la autenticación Forms.0 soporta la autenticación sin cookies de un modo muy similar al que hemos visto para sesiones sin cookies: introduciendo una ruta virtual codificada en todas las peticiones.Figura 5.NET 1. Lo sabe porque cuando un usuario se ha autenticado previamente esta información se almacena en una cookie encriptada.web>: <authentication mode="Forms"/> Por defecto la página a la que se redirige a los usuarios anónimos para que se autentiquen se llama "login. En caso de no estar autenticado se le dirige de forma automática a una página que le solicita las credenciales de acceso. Nota: El uso de cookies era obligatorio en ASP.aspx" pero se puede especificar cualquier otra usando el atributo loginUrl. Sólo hay que utilizar el ajuste <forms cookieless="UseUri"> en el archivo de configuración.Lógica de autenticación personalizada en ASP. Basta con editar el archivo web.NET Cuando un usuario solicita una página protegida ASP.. Si está autenticado se le permite el acceso al recurso siendo responsabilidad del programador definir cualquier comprobación de autorización posterior. por ejemplo: .NET 2.config y añadir la siguiente línea en la configuración de <system.

aspx"/> </authentication> A partir de ahora todos los usuarios anónimos se redirigirán a "entrada. .aspx" para solicitarle las credenciales de acceso.<authentication mode="Forms"> <forms loginUrl="entrada.

Autorización de usuarios
Una vez que un usuario está autenticado, el proceso que regula a qué recursos tendrá acceso se denomina autorización. Para realizar el control de acceso no sólo llega con indicar qué método de autenticación se usará (en este caso Forms) . Además hay que especificar a qué recursos se debe controlar el acceso y de qué manera. En ASP.NET existen diversos modos de definir la autorización de acceso. Autorización de URLs Consiste en la autorización de acceso a determinados recursos de la aplicación Web (páginas ASPX, carpetas, archivos...) refriéndose a ellos a través de su ruta relativa en el archivo de configuración de la aplicación. Se especifica el nivel de acceso requerido mediante una o varias entradas en el nodo raíz de web.config (nodo <configuration>) que tienen un aspecto análogo al siguiente:
<location path=“facturas.aspx”> <system.web> <authorization> <allow users=“jose, hector, pablo”> <allow roles=“clientes, administradores”>

<deny users="?"/> </authorization> </system.web> </location>

Como se puede observar, la sintaxis es muy sencilla y bastante evidente. - El nodo location especifica la ruta relativa al directorio actual cuyo acceso se desea controlar. - Los nodos allow y deny se emplean para permitir o denegar el acceso a determinados usuarios o roles de usuario. Se pueden especificar nombres concretos para éstos o utilizar comodines especiales, como en el caso del nodo deny del ejemplo: · · ? : representa a los usuarios anónimos. En el ejemplo anterior se deniega el acceso a todos los usuarios que no se hayan autenticado previamente. * : indica que el criterio se aplica a todos los usuarios, tanto anónimos como autenticados, independientemente de su perfil de usuario.

Pueden incluirse tantos nodos location como sea necesario dentro del archivo de configuración. Lo habitual es incluir junto con el nodo de autenticación un nodo de autorización explícito que deniegue el acceso a todos los recursos a los usuarios anónimos, así:
<authentication mode="Forms"/> <authorization> <deny users="?"/> </authorization>

Dado que puede existir un archivo web.config por cada carpeta de la aplicación se pueden establecer distintos criterios de acceso a cada una, agrupando en ellas los archivos con el mismo nivel de acceso. Autorización declarativa El sistema de autorización por URL es muy potente pues permite definir los permisos de acceso de los usuarios a cualquier archivo controlado por ASP.NET y además hacerlo sin tocar el código. Mediante la autorización declarativa de ASP.NET es posible obtener un control mucho más granular, llegando incluso a controlar accesos a clases o métodos concretos dentro de éstas. Es decir, regula la autorización dentro del código de la aplicación, definiendo a qué partes de éste se debe conceder el acceso y cómo.

Mediante simples atributos se controla el acceso a cada método o propiedad de una clase o a la clase misma:
<PrincipalPermission(SecurityAction.Demand, Authenticated:=true)> _ Class CuentaBancaria <PrincipalPermission(SecurityAction.Demand, Role:=“Cajero")> _ Public Function Consultar() As Integer ... End Function <PrincipalPermission(SecurityAction.Demand, Role:="Interventor")> _ Public Sub ModificarSaldo() ... End Sub End Class

En este ejemplo se dispone de una clase llamada CuentaBancaria que representa un componente de negocio de nuestra aplicación (ubicado, por ejemplo, en la carpeta App_Code. Con los atributos especificados se está indicando lo siguiente: · · · Para poder utilizar cualquier miembro de la clase es necesario que el usuario actual se haya autenticado. Sólo los usuarios que pertenezcan al perfil "Cajero" tienen acceso a consultar las cuentas. Sólo los usuarios que pertenezcan al rol "Interventor" pueden actualizar el saldo de las cuentas.

Esta característica requiere agregar una referencia a System.Security.Permissions en la sección Imports de la clase. Autorización imperativa Este tipo de autorización es la que nos permite entremezclar explícitamente en nuestro código comprobaciones acerca de la identidad de los usuarios, tomando decisiones en función de éstas. Ofrece un control todavía más granular, ya que puede estar en cualquier lugar del código, dentro de un miembro de una clase. Se fundamenta en el uso de la propiedad User de la clase Page . Esta propiedad devuelve una referencia a un objeto homónimo, es decir, de tipo User. Su método IsInRole permite averiguar la pertenencia del usuario actual a un determinado perfil o rol y tomar decisiones en función del resultado. Por ejemplo en la clase CuentaBancaria del ejemplo anterior permitiría limitar el importe de una transferencia en función del tipo de usuario que la realice, así:

Public Sub Transferencia(cantidad As Decimal) If cantidad > 1000 Then If User.IsInRole(“interventor”) Then 'Transferir End if End If End Sub

En este fragmento vemos como se usa el mencionado método para comprobar si el usuario es un interventor antes de permitir cualquier transferencia de más de 1.000 euros. La principal ventaja de esta forma de autorización es el fino control que concede. Sin embargo conviene no abusar de su uso en la medida de lo posible ya que cualquier cambio implica tocar el código convirtiéndolo enseguida en muy dificil de mantener.

La nuevas API: Membership y Roles
Todo lo mencionado hasta ahora esmuy interesante pero todavía carece de lo más importante: ¿cómo autenticamos a los usuarios? ¿Cómo sabemos a qué roles pertenecen? Hasta ahora estas preguntas las debía contestar el propio programador ya que en ASP.NET 1.x era su responsabilidad definir los métodos de autenticación de sus aplicaciones. Ello implicaba normalmente escribir código de consulta contra bases de datos que validase las credenciales de los usuarios y obtuviese los roles de los mismos. Luego se creaban objetos de seguridad asignándole estos valores y asociándolos al contexto de la aplicación. ASP.NET 2.0 nos libera por fin de todo ello y ofrece de serie una completa API de gestión de usuarios que nos evita tener que reinventar la rueda en cada aplicación. Membership Se trata de una nueva API que proporciona una sencilla interfaz de programación para almacenar y recuperar información sobre los usuarios de nuestras aplicaciones. Lo más interesante de todo es que, al igual muchas otras características nuevas de ASP.NET 2.0, está basado en un patrón de diseño de proveedores, lo que permite cambiar los métodos de trabajo y almacenamiento sin tocar el código de la aplicación. La figura siguiente ilustra mejor este concepto:

Figura 5.11.- Patrón de Proveedores para gestión de usuarios Por defecto esta API utiliza SQL Server 2005 para almacenar toda la información de seguridad de una aplicación y va a ser lo que utilicemos durante toda esta lección. Pero dada su arquitectura basada en proveedores podemos cambiar el modo de gestión con sólo un ajuste en el archivo de configuración. incluso, como se ve aprecia en la figura, es posible definir métodos de gestión de usuarios propios sin modificar el código de nuestras aplicaciones. Esto nos permite reutilizar infraestructuras de seguridad preexistentes que hubiésemos creado para ASP.NET 1.x sin perder el trabajo. Membership consta de una clase con este nombre que contiene ciertos métodos compartidos para poder crear, eliminar y validar usuarios entre otras cosas. Así, por ejemplo, para crear un usuario escribiríamos:
Membership.CreateUser("usuario", "clave")

y para validarlo sólo hay que usar su método ValidateUser:
Membership.ValidateUser("usuario", "clave")

que devuelve verdadero o falso en función de si las credenciales son o no válidas.

Aún así todavía queda trabajo. mediante el uso de una cookie HTTP encriptada. Sólo hay que establecer la autenticación Forms de ASP.Existe también una clase MembershipUser que representa las propiedades de los usuarios de la aplicación.0 tampoco nos va a dejar solos con esto. Para obtener los roles a los que pertenece un usuario podemos escribir: Roles. al igual que ésta. Roles Esta API complementa a la anterior para permitir la gestión de los roles de un usuario y. Para ello sólo tenemos que presionar sobre el menú Sitio web·Configuración de ASP. antes de nada. se pueden autenticar usuarios contra una base de datos SQL Server y obtener los roles desde el Directorio Activo o las cuentas locales. No es necesario utilizar el mismo proveedor para los roles que para los usuarios. . Esto aumenta el rendimiento en muchas aplicaciones. almacena los roles del usuario durante la duración de las sesiones para no tener que consultar el origen de datos cada vez que comprobemos la pertenencia a roles.NET 2. está basada en el mismo patrón de proveedores. Si dejamos el parámetro usuario en blanco nos devuelve los roles del usuario actualmente autenticado. Hay que crear formularios de autenticación y. La API de roles ofrece también una característica de caché automática de credenciales que. hay que gestionar los usuarios y los roles de la aplicación. "administradores") Este fragmento agrega un usuario al rol de administradores.getRolesforuser("usuario") que devuelve una matriz de cadenas de texto.NET y se abrirá una web que nos permite configurar la seguridad de la aplicación.AdduserToRole("usuario". Administración de seguridad de sitios Web Con todo lo visto hasta ahora crear la seguridad de un sitio web es muy sencillo. Antes de nada hay que administrar usuarios y roles. Al igual que en el caso anterior los métodos de la clase Roles son todos estáticos y podemos usarlos sin instanciar nuevos objetos. ASP. ni siquiera nos obliga a crear interfaces comunes de autenticación y gestión de sesiones. Por ejemplo. Por ejemplo: Roles. Ofrece una completa herramienta de administración ya creada de serie y. como veremos enseguida.NET y utilizar Membership y Roles para gestionar a los usuarios.

Al utilizarla se encarga de modificar el archivo web.NET 2.12. Disponemos de su código fuente completo en la carpeta .0 Con esta herramienta podemos dar de alta. Este archivo es una base de datos de SQL Server 2005 que se usa para almacenar toda la información de seguridad de los usuarios. El administrador de sitios Web utiliza las clases MemberShip y Roles para realizar su trabajo.mdf' en la carpeta App_data.config de nuestra aplicación si es necesario realizar algún ajuste.Figura 5. Además crea un archivo de base de datos llamado 'ASPNETDB. modificar o borrar usuarios y roles. Cualquier clave que introduzca le devolverá el enigmático mensaje "Introduzca otra contraseña" a menos que use claves de al menos 7 caracteres de longitud e incluya en ellas un espacio o un caracter no alfanumético como un asterisco o un guión bajo. además de realizar algunos otros ajustes. Este ajuste se puede cambiar mediante configuración.. Nota: Si hace uso de esta herramienta para crear usuarios en la base de datos tenga en cuenta que por defecto hay un ajuste de seguridad que implica el uso de claves complejas.Sitio de configuración de la seguridad de ASP. Se hace uso de la nueva característica de enlazado dinámico de bases de datos de SQL Server para poder distribuir esta base de datos con la aplicación y enlazarla al motor de base de datos sólo cuando se vaya a utilizar.

xxxxx\ASP.NETWebAdminFiles\ interesante examinarlo.0.C:\WINDOWS\Microsoft. y es Ver vídeo de esta lección (Uso de la administración de sitios y de la API Membership) .NET\Framework\v2.

En el caso de los asistentes tenemos libertad de añadir nuevos pasos o modificar los predeterminados a voluntad. el control Login permite disponer de un completo diálogo de autenticación con sólo arrastrarlo sobre un formulario Web.0 nos facilita todavía más el trabajo relacionado con la seguridad gracias a la inclusión de los nuevos controles Web de seguridad.NET 2. Estos controles nos dan ya hechas multitud de operaciones comunes de seguridad relacionadas con la interfaz de usuario. Todos ellos permiten la personalización. que además soporta el uso de temas. Los podemos encontrar en el grupo Inicio de sesión del cuadro de herramientas de Visual Studio. la gestión de la seguridad de nuestras aplicaciones se ha simplificado muchísimo con ASP. como absoluta usando plantillas. ASP. El control Login Este control permite definir un completo diálogo de autenticación en cualquier página. El CreateUserWizard es un asistente con varios pasos que permite la creación automática de nuevos usuarios. ¿Podría ser más fácil? Pues lo cierto es que sí.0. . Gracias a los objetos Membership y Roles crear una interfaz de administración de usuarios y control de acceso es casi trivial. tanto parcial por medio de propiedades.NET 2. Por ejemplo.Los controles Web de seguridad Como hemos podido comprobar en los epígrafes anteriores.

Lo que ello provoca es que se elimine la referencia al usuario actual en la propiedad User de la clase Page y que se reenvíe a la página de autenticación especificada en web. El control LoginStatus Se utiliza para mostrar el estado actual de conexión de un usuario y permitir su desconexión. si ya hay un usuario autenticado. Para validar a los usuarios utiliza el método ValidateUser de la clase Membership. Así se permite cambiar la sesión de usuario. y en caso de estarlo incluso en función del rol o roles a los que esté asociado. El control LoginName Muestra el nombre del usuario actualmente autenticado. muestra mensajes de fallo de autenticación. Cuando no hay usuario alguno autenticado en el sistema el enlace apunta automáticamente a la página de autenticación definida.Control de inicio de sesión personalizado estéticamente. Este comportamiento se cambia con la propiedad AutoHide en caso de necesitarlo.Figura 5.config para una iniciar nueva sesión. Cuando hay un usuario autenticado el control muestra por defecto un enlace que permite desconectarse. Por defecto.. El control LoginView Se trata de un completo control que permite definir el contenido de una zona de la página en función de si el usuario está o no autenticado. Además de los elementos obvios permite configurar enlaces para acceder a la creación de nuevos usuarios.. etc.. Es interesante observar su panel de tareas: . Todo ello se controla con facilidad desde la ventana Propiedades de Visual Studio. redirige automáticamente a otras páginas al autenticar si es necesario.13. este control se oculta automáticamente salvo cuando se ubica en la página principal. Se puede personalizar por completo para mostrar cualquier otra cosa en la superficie del control.

tendríamos que añadir un RoleGroup con el texto "Administradores" ya que los otros dos casos siempre están definidospor defecto. Al elegir un elemento cualquiera de esta lista cambia la plantilla mostrada en el diseñador.. Gracias a estos controles y a la utilidad de administración de seguridad de ASP.NET podemos construir la seguridad completa de una aplicaicón Web en cuestión de minutos.Figura 5. el cambio de clave y la creación de usuarios respectivamente. por ejemplo.Control LoginView y su correspondiente panel de tareas. Todos ellos utilizan la API de Membership para trabajar y responden a los ajustes impuestos en la configuración de la aplicación. La lista Vistas contiene un elemento por cada RoleGroup además de los correspondientes ausuarios anónimos y autenticados en general. el control de cambio de contraseña o el de creación de usuarios exigirán a las contraseñas la complejidad indicada en la configuración. En la plantilla podemos introducir controles y cualquier otro elemento. Por ejemplo si queremos mostrar un mesnaje diferente según sea un usuario anónimo. cuando lo habitual sería que tardásemos horas o días.14. Editar RoleGroups. permite definir los casos que existirán en función de los roles. Al igual que los anteriores ofrecen una altísima capacidad de personalziación que en el caso del control de creación de usuarios permite incluso añadir nuevos pasos en el asistente (se trata de un control heredado del control de tipo Wizard que nos permite crear asistentes con facilidad). un usuario autenticado en general y un usuario que pertenece al rol de administradores. Gracias al control RoleView es extremadamente sencillo personalziar las vistas para cada usuario diseñándolo visualmente. Los controles restantes PasswordRecovery. y eso será lo que verá el usuario indicado por el RoleGroup correspondiente. y el de recuperación de clave le hará una pregunta de seguridad si así está definido. La primera de las acciones. Ver vídeo de esta lección (Uso de controles Web de seguridad) . ChangePassword y CreateUserWizard nos facilitan la recuperación de claves. Así pues.

0 § Generación del proxy § cambio de ubicación del servicio § Credenciales de acceso · · . · Lección 1: Introducción a los servicios Web o ¿Qué son los servicios Web? o Comunicación entre componentes o SOAP § Breve historia de SOAP § Las bases tecnológicas de SOAP § Descubrimiento de servicios: WSDL y UDDI Lección 2: Creación de un servicio Web con ASP.NET 2.NET 2.NET o Consumiendo un servicio Web desde ASP.0 o Proyectos de servicios Web o Archivos del servicio Web o Tipos de datos o Descripción de métodos o Parámetros opcionales y sobrecarga de métodos Lección 3: Consumo de un servicio Web o Examinando manualmente un servicio Web creado con ASP.0 usando Visual Studio 2005. Tras una introducción a los servicios Web y sus conceptos asociados se ve la forma de crear y consumir servicios Web desde ASP.NET 2.Contenido Este módulo presenta al alumno los fundamentos de los Servicios Web y las Arquitecturas Orientadas a Servicios (SOA).

Lo cierto es que no se trata de un concepto tan novedoso como cabría esperar y las innovaciones que conlleva no son tanto tecnológicas. cómo funcionan. "monolíticas": . En esta lección explicaremos desde un punto de vista no-técnico los conceptos relacionados con los Servicios Web. de dónde vienen y a dónde van. Un poco de historia: modelos de desarrollo El hecho de poder comunicar componentes de software entre sí tiene una enorme importancia.¿Qué son los servicios Web? La expresión "Servicio Web" se oye con fuerza desde hace unos años en el ámbito del desarrollo de aplicaciones e incluso en ambientes poco técnicos y de dirección. como conceptuales. Hasta no hace tantos años era muy típico hacer aplicaciones de una sola pieza.

Figura 6. Se suelen conocer también como "fat clients". Estos programas podían acceder a un sistema gestor de datos a través de la red.Aplicación "monolítica" aunque distribuida. pero toda la lógica del flujo de datos. .2. la seguridad y las interacciones con las personas se encontraban en el ordenador del usuario en forma de un gran ejecutable.1.Aplicación Cliente Servidor en tres capas. La situación descrita no es la ideal ya que implica problemas de toda índole a la hora de instalar las aplicaciones y sobre todo cuando se modifican o actualizan (mantenimiento complejo y engorroso)... Una metodología de desarrollo mucho mejor aunque más laboriosa a la hora de programar es el modelo Cliente-Servidor en tres capas: Figura 6.

La arquitectura de desarrollo en n-capas (n-tier que dicen los anglosajones) lleva el concepto cliente-servidor un paso hacia adelante.3.Arquitectura de desarrollo basada en componentes.En este modelo toda la lógica de los datos. dividiendo la capa intermedia en muchas otras capas especializadas cada una de las cuales puede residir en un servidor diferente: Figura 6. y esto es muy interesante también. por ejemplo. sino que basta con sustituir un componente en . es decir. no es necesario reinstalar la aplicación en cada cliente. la autenticación y seguridad o el acceso a datos. y todo ello sin que los clientes sean conscientes de ello. Ello aumenta mucho la escalabilidad de las aplicaciones. pues basta con añadir nuevos servidores e instalar los componentes en ellos para poder atender más peticiones. los permisos. gestionando la información que circula entre el usuario y el servidor de datos. Dichos componentes deben trabajar unos con otros como piezas de un mecanismo. En este modelo existe una gran variedad de componentes especializados en tareas específicas como la validación de datos. residen en un servidor intermedio y son utilizados por todos los clientes a través de una red. La belleza de este modelo radica en que cada uno de ellos (o cada grupo de ellos) puede residir en un servidor diferente. Obviamente esto ofrece más ventajas aún ya que. mientras sus interfaces de programación sean las mismas. actúa de intermediario entre el usuario y las reglas de negocio residentes en la capa intermedia. Este modelo es más eficiente y está muy evolucionado respecto al anterior pero aún se puede ir más allá. En este caso en el ordenador del usuario lo único que hay es una capa de presentación que se ocupa básicamente de recoger y recibir datos.. es posible sustituir cualquier componente por otro actualizado o que actúe de manera distinta para corregir errores o cambiar el modo de trabajo de la aplicación global. siendo transparente su ubicación para los clientes que los utilizan. etc. Por otra parte. su validación.

Aunque muchos programadores piensan que SOA está relacionado únicamente con los Servicios Web lo cierto es que se pueden conseguir arquitecturas SOA con otras tecnologías como veremos.un único lugar y automáticamente todos los usuarios tendrán su aplicación actualizada. El concepto de Arquitectura Orientada a Servicios o SOA se basa en el uso de este tipo de componentes que suplen las necesidades de una o varias aplicaciones. son independientes entre sí y trabajan independientemente del sistema operativo o la plataforma. .

No se centra en la definición de interfaces para compatibilidad binaria de componentes. Para responder a estas necesidades de los programadores. Los parámetros son transmitidos a través de la red mediante un formato binario propio llamado NDR (Network Data Representation).Comunicación entre componentes Existen diversas dificultades técnicas a la hora de llevar a la práctica las arquitecturas orientadas a servicios. y se basa en la existencia de un cliente y un servidor que actúan de intermediarios entre los componentes que se quieren comunicar. es la metodología de llamada remota a procedimientos de Java. • RMI (Remote Method Invocation). la gestión de peticiones y el balanceado de carga entre servidores cuando un mismo componente reside en varios de ellos (para aplicaciones muy grandes con muchos clientes). Es una tecnología bastante simple que es fácil de utilizar para aplicaciones básicas. Aunque existe una gran variedad. la gestión de transacciones entre componentes y algunas otras cosas más. de todos ellos los más importantes sin duda son: • DCOM (Distributed Common Object Model). ni en otros conceptos avanzados. Se trata de algo más que un protocolo de invocación remota de procedimientos (RPC) ya que su última encarnación. la propuesta de Microsoft. Entre éstas están la comunicación entre las distintas capas y componentes que constituyen la aplicación. COM+. incluye servicios avanzados para balanceado de carga. gestión de transacciones o llamadas asíncronas. ligada a sus sistemas Windows. . pero por supuesto se trata de una opción muy poco realista dada la complejidad que conllevaría. Existe la posibilidad de escribir un protocolo de comunicaciones propio que se ocupe de todas estas cuestiones. diversos fabricantes y asociaciones de la industria crearon servicios y protocolos específicos orientados a la interacción distribuida de componentes.

Se trata de una serie de convenciones que describen cómo deben comunicarse los distintos componentes. pero su utilización es difícil y añaden una nueva capa de complejidad a las aplicaciones además de disminuir su rendimiento.• CORBA (Common Object Request Broker Architecture). lo que dificulta la comunicación entre ellas Su utilización a través de Internet se complica debido a cuestiones de seguridad de las que enseguida hablaremos. Existen diversas implementaciones de distintos fabricantes. cumpliendo bien su trabajo pero tienen algunas limitaciones importantes siendo las principales las siguientes: · · · · Es difícil la comunicación entre los distintos modelos Están ligados a plataformas de desarrollo específicas. Estos modelos son buenos y muy eficientes. Existen en el mercado puentes CORBA/DCOM que permiten la comunicación entre componentes COM y componentes CORBA. Su método de empaquetado y transmisión de datos a través de la red se llama CDR (Common Data representation). . cómo deben transferir los datos de las llamadas y sus resultados o cómo se describen las interfaces de programación de los componentes para que los demás sepan cómo utilizarlos. Fue desarrollado por el OMG (Object Management Group) en la segunda mitad de la década de los '90 y es el modelo que más éxito ha tenido en el mundo UNIX.

y la integración de las aplicaciones. la transparencia de los datos y la independencia de la plataforma que según hemos visto. Este acrónimo (Simple Object Access Protocol) describe un concepto tecnológico basado en la sencillez y la flexibilidad que hace uso de tecnologías y estándares comunes para conseguir las promesas de la ubicuidad de los servicios. Breve historia de SOAP SOAP empezó como un protocolo de invocación remota basado en XML diseñado por Dave Winer de UserLand. Al igual que podemos usar un navegador web para acceder a cualquier página independientemente del sistema operativo del servidor en que resida. La tecnología que está detrás de todo ello se llama SOAP (jabón en inglés). Esto es precisamente lo que ofrecen los Servicios Web. en la que participo activamente Microsoft y el archiconocido experto en programación Don Box. la ubicuidad de sus componentes y su reutilización a través de la red se convierten en una realidad. Esta primera versión fue más o menos despreciada por los principales fabricantes de software que en esa época tenían en marcha un proyecto más ambicioso llamado . se hacen necesarios en las aplicaciones actuales. llamado XML-RPC.0 de SOAP. A partir de éste se obtuvo en Septiembre de 1999 la versión 1. ¿por qué no podríamos invocar métodos de componentes a través de la red independientemente de dónde se encuentren. del lenguaje en el que estén escritos y de la plataforma de computación en la que se ejecuten?. Gracias a ellos se derriban la antiguas divisiones resultantes de los modelos de componentes descritos.SOAP Las expectativas actuales respecto a los componentes han aumentado.

IBM. Esto puso en peligro en su nacimiento la existencia de SOAP ya que si los grandes no lo apoyaban poco se podía hacer. ampliamente conocidos y usados en el mundo web.NET y Visual Studio son los entornos más avanzados en la adopción de SOAP.w3. Este soporte mayoritario hace que su éxito y pervivencia estén asegurados y hoy todas las herramientas de desarrollo del mercado ofrecen en menor o mayor medida soporte para SOAP. El hecho de que los tres gigantes del software (Microsoft. . o conjuntos de servidores web que trabajan como si fueran uno solo para así poder atender a más clientes simultáneamente.1 de SOAP). aunque se pueden usar otros puertos distintos al 80. El uso de HTTP como protocolo principal de comunicación hace que cualquier servidor web del mercado pueda actuar como servidor SOAP. Por otra parte la escalabilidad se obtiene a través del propio servidor web o incluso del sistema operativo. · Dado que los mensajes entre componentes y los datos de los parámetros para llamadas a métodos remotos se envían en formato XML basado en texto plano. ya que la mayoría de ellos (por ejemplo IIS) poseen capacidades de ampliación mediante clusters de servidores.ebXML. así como otras muchas pequeñas empresas de software. David Ehnebuske y Noah Mendelsohn. Además en la mayoría de los casos se puede hacer uso de SOAP a través de los cortafuegos que defienden las redes. reduciendo la cantidad de software a desarrollar y haciendo la tecnología disponible inmediatamente. son autores de la especificación 1. por supuesto). La última versión de la especificación se puede encontrar en www. enrutadores que discriminan las peticiones y otras técnicas para crear Web Farms. Por fortuna uno de estos grandes fabricantes. · La seguridad se puede conseguir a través de los métodos habituales en los servidores web y por tanto se dispone de autenticación de usuarios y cifrado de información de forma transparente al programador. IBM y Sun) apoyen SOAP ha hecho que muchos fabricantes de Middleware y puentes CORBA-DCOM (como Roguewave o IONA) ofrezcan productos para SOAP. decidió apoyarlo y en la actualidad no sólo acepta SOAP sino que es uno de lo motores detrás de su desarrollo (dos importantes personas de IBM y su filial Lotus. ya que no suelen tener bloqueadas las peticiones a través del puerto 80. el puerto por defecto de HTTP (de ahí la ubicuidad.org/TR/SOAP/. consiguiendo la ansiada ubicuidad de los componentes. Por supuesto . Sun Microsystems también anunció oficialmente en Junio de 2000 que soportaba el estándar. La base tecnológica de SOAP Lo interesante de SOAP es que utiliza para su implementación tecnologías y estándares muy conocidos y accesibles como son XML o el protocolo HTTP. usando protocolos y técnicas como IPSec o SSL. SOAP se puede utilizar para comunicarse con cualquier plataforma de computación. El paso definitivo para asegurar el éxito de SOAP y los servicios web es su envío al W3C (World Wide Web Consortium) para proponerlo como estándar.

MSMQ (Microsoft Messaging Queue) para enviar de manera asíncrona las llamadas a procedimientos con SOAP. Si nos referimos a la esencia del estándar. De este modo las áreas cubiertas por la especificación se refieren a cómo se codifican los mensajes XML que contienen las llamadas a procedimientos y sus respuestas. El estudio de éstos se sale del ámbito de este curso.0. Se ha definido también un formato estándar para publicación de información de servicios web llamado UDDI (Universal Description Discovery and Integration). Por citar unos pocos. Nota: Para aquellos programadores que conocen otras arquitecturas podemos decir que WSDL es el equivalente en XML a los lenguajes IDL (Interface Description Language) de DCOM y CORBA. Descubrimiento de servicios: WSDL y UDDI Otro de los estándares que se definen en SOAP es WSDL (Web Service Definition Language). las tecnologías utilizadas son conocidas y la especificación SOAP se refiere más bien a la manera de usarlas. donde se definen métodos que permiten consultarlos para encontrar fácilmente aquel servicio que se necesite.Nota: Existen ampliaciones al protocolo SOAP base que definen protocolos y convenciones para tareas específicas como las mecionadas de seguridad. En . . Como vemos. los eventos y muchas otras cuestiones avanzadas. Windows Server 2003 incluye gratuitamente un servidor para implementar directorios UDDI en organizaciones.NET se implementan mediante los concidos Web Services Enhancements (WSE) actualmente por su versión 3. se podría utilizar SMTP (correo electrónico). Se trata de un formato estándar para describir las interfaces de los servicios web. Antes de usar un componente que actúa como servicio web se debe leer su archivo WSDL para averiguar cómo utilizarlo. la nueva plataforma de servicios de comunicaciones de Windows.. HTTP es el único protocolo definido en el estándar para SOAP pero éste es lo suficientemente abierto como para permitir que se empleen otros protocolos distintos para transmitir mensajes SOAP. Esta especificación permite la creación de directorios de servicios web. SOAP trata de sustituir a los diferentes formatos propietarios de empaquetamiento de datos que utilizan otras tecnologías (como DCOM o CORBA con NDR y CDR respectivamente).. enrutado de mensajes. WSDL describe qué métodos están disponibles a través de un servicio Web y cuáles son los parámetros y valores devueltos por éstos. y en un futuro inmediato con Windows Communication Foundation. y a la manera en que HTTP debe intercambiar estos mensajes. etc. así como los protocolos propietarios empleados para transmitir estos datos empaquetados.

Creación de un servicio Web En el módulo anterior se presentaron los servicios web: qué son. paso a paso. de dónde vienen y a dónde van. Proyectos de servicios Web Para crear un nuevo proyecto que albergue servicios Web sólo tenemos que utilizar el menú Archivo·Nuevo sitio Web y elegir el tipo "Servicio Web" en lugar del habitual "Sitio web ASP. un servicio web con Visual Studio 2005. Tras la teoría veremos una sencilla aplicación práctica construyendo. y comprobaremos lo extremadamente simple que es su creación con esta herramienta.NET" tal y como se muestra en la figura: . Nuestro primer ejemplo será un servicio web muy simple que se ocupará de devolver la fecha y la hora actuales del servidor en el que se ejecute.

Nuevo proyecto de servicios Web Nota: En realidad tampoco es necesario puesto que se pueden crear archivos de servicios web dentro de proyectos de aplicaciones Web "normales" usando el diálogo Agregar nuevo elemento. lo habitual es que se guarden en proyectos separados para facilitar su posterior gestión.Figura 6. Éstos constituyen el esqueleto de nuestro servicio.4. al igual que en ese caso. Sin embargo. La extensión asignada a los archivos que representan un servicio Web en ASP. En este caso y dado que el servicio Web no posee elementos de interfaz de usuario. Si hacemos doble-clic sobre Service.asmx es el que contiene la definición de nuestro servicio. Archivos del servicio Web Al aceptar se crean para nosotros diversos archivos en el nuevo proyecto..asmx se abre su definición en el editor de Visual Studio. del . define dónde se encuentra en código que dotará de funcionalidad al servicio Web. En esta figura el archivo Service. tal y como se observa en la figura del lateral. Lo único que contiene es la siguiente línea: Ésta se parece mucho a la directiva de las páginas ASPX y.asmx'.NET es '.

Éste contiene la definición de la clase indicada en el atributo Class. HTTP y demás tecnologías en las que se basan los servicios Web.vb.vb.único archivo que nos tenemos que preocupar es del que se indica en el atributo CodeBehind. La clase Service (podría llamarse de cualquier otro modo) está dentro del archivo Service. y que en nuestro ejemplo se llama Service. Sólo con hacer esto ya obtenemos la funcionalidad necesaria para gestionar el XML. veremos que por defecto contiene el siguiente código: Aparte de las preceptivas sentencias Imports. Los métodos que un servicio Web expone al exterior son métodos normales de una clase a los que se le ha añadido el atributo WebMethod. el cual se ubica dentro de la carpeta App_Code que como ya hemos estudiado asegura la compilación dinámica de los archivos de código que contiene. Por ejemplo. su gestión pasa inadvertida para nosotros. para que uno de nuestros métodos sea expuesto en un servicio Web y pueda ser utilizado remotamente desde cualquier otra plataforma o lenguaje basta con incluir el atributo WebMethod delante y que esté contenido dentro de una clase que hereda de WebService. Es decir. Si abrimos el archivo Service. Así de sencillo. tal y como se observa en el código anterior. vemos que la clase Service hereda de la clase WebService. elimine el método de ejemplo HelloWorld que introduce Visual Studio y escriba el siguiente código: .

Este ejemplo. hora. por ejemplo) el formato XML ovtenido es mucho más complejo y no se encuentra estandarizado. si bien al ser XML y disponer de su esquema es muy fácil utilizarlos desde cualquier lenguaje. En el caso de tipos básicos la cosa es fácil aunque se debe seguir una convención para hacerlo. como los de gestión. incluyendo cadenas. año. etc. pero hemos ganado mucho ya que éste se interpretará correctamente como una fecha en cualquier aplicación que consuma nuestro servicio. aunque trivial. quedando el código así: Lo único que hemos cambiado es el tipo a devolver. Tratar una fecha a partir de una cadena es un poco tedioso porque hay que analizarla para obtener sus diversas partes (día. fechas. Lo ideal sería obtener una representación única de una fecha sin preocuparnos de estos problemas. La especificación estándar de SOAP define representaciones en formato XML para todos los tipos de datos básicos que nos podemos encontrar en las aplicaciones. En el caso de otros objetos más complejos (como los dataSet. que no tiene porque ser el mismo que tienen los clientes. Al igual que hemos definido como tipo devuelto una cadena podemos definir perfectamente una fecha.Ahora disponemos de un método que devuelve la fecha y la hora actuales en el servidor en el que se ejecute nuestro servicio Web y que puede ser utilizado desde cualquier otra aplicación independientemente del lenguaje con el que esté construida y del sistema operativo en el que trabaje. en los que la sincronización horaria entre clientes y servidores es fundamental para asegurar la coherencia de facturaciones y otros datos económicos. Cualquier clase (o tipo) que se use como parámetro o como valor devuelto por un método que se expondrá en un servicio Web se serializa a XML antes de ser enviada a través de la red tanto en un sentido como en el otro (cliente-servidor y viceversa). . booleanos.. mes. minutos y segundos) y además su formato depende del idioma definido en el servidor.. Serializar a XML un objeto consiste en generar una representación de los datos de éste en formato XML de modo que posteriormente puedan ser deserializados en el otro extremo para obtener un objeto equivalente al original. Tipos de datos Vamos a mejorar un poco el ejemplo. Enseguida veremos cómo. puede resultar útil en entornos.

En una clase . Enseguida veremos cómo utilizarlo. incluso aunque el . Nota: Los objetos de la clase DataSet de ADO.Como resumen de este párrafo hay que quedarse con una idea: sólo se pueden emplear clases serializables como parámetros o valores devueltos por un método de un servicio Web. siendo el propio compilador el que llamará a la versión sobrecargada que convenga en cada caso. Parámetros opcionales y/o sobrecarga de métodos Web Imaginemos que tenemos que crear un servicio Web para una tarea determinada (para simplificar. Se trata de MessageName. de forma que podemos identificar de manera única a cada uno de ellos. En el caso de un obtener el mismo mismo nombre. Con ello dejamos nuestro método finalmente definido como: Con esto queda definido nuestro sencillo servicio web de ejemplo. De hecho es muy habitual que se utilicen como valores devueltos y como parámetros en métodos de servicios Web. y dicha tarea debe trabajar con diferentes tipos de datos o debe poder usarse de varias formas con parámetros diferentes. Además se usa para especificar ciertos comportamientos del método.NET podemos crear versiones sobrecargadas de un método cada una de las cuales tomará el tipo de datos pertinente. Con Description ofreceremos a los programadores que consuman nuestro servicio información sobre lo qué hace el método lo que puede ser de gran utilidad. A efectos de lo que nos interesa en este curso veremos sólo uno de los parámetros de este atributo: Description. realizar una suma).NET son objetos serializables que están adaptados a la perfección para su uso en un servicio Web. Descripción de métodos El atributo WebMethod no sólo se usa para especificar que un método determinado de la clase se expondrá para su consumo desde el exterior. Los DataSet tipados también se incluyen en esta categoría y de hecho pueden resultar incluso más sencillos de utilizar cuando el servicio se invoca desde entornos diferentes a . ya que no podemos exponer dos métodos Web con el Sin embargo existe otro parámetro del atributo WebMethod que un efecto similar.NET. permite conseguir servicio Web a priori puede parecer que no seremos capaces de efecto. digamos. MessageName se utiliza para asignar alias a los métodos Web que definamos.

si queremos exponer como servicio Web una clase que posee un método con varias sobrecargas sólo tenemos que emplear este atributo asignándole un identificador diferente a cada una. Cambiando el nombre del mensaje de una de ellas se pueden exponer sin problema ya que a la hora de consumirlas. Con esto conseguimos el efecto de métodos Web sobrecargados. Sin embargo si hubiésemos colocado simplemente la palabra WebMethod delante de ambas hubiésemos obtenido un error a la hora de compilar ya que no pueden exponerse dos métodos con el mismo nombre en un servicio Web. Por ejemplo: Las dos funciones con el mismo nombre y diferentes parámetros son perfectamente válidas en VB. De este modo. aunque tengan el mismo nombre. Ver vídeo de esta lección (Creación de un servicio Web de datos) .NET.nombre asignado a la función sea el mismo. se distinguen perfectamente por el nombre del mensaje empleado.

NET 2.NET o Consumiendo un servicio Web desde ASP.Consumo de un servicio web En esta lección vamos a estudiar el comportamiento del servicio Web que hemos creado y aprenderemos a consumirlo desde una página ASP.0 § Generación del proxy § cambio de ubicación del servicio § Credenciales de acceso . · Lección 3: Consumo de un servicio Web o Examinando manualmente un servicio Web creado con ASP.NET además de a examinarlos manualmente.

NET .NET es navegando con Internet Explorer a la URL del archivo asmx del servicio.Examinando manualmente un servicio Web creado con ASP. obtenemos una página como la de la figura: Figura 6..5. En nuestro ejemplo.Aspecto de la página generada automáticamente por ASP. si navegamos hacia el servicio horario anterior (basta con presionar F5 desde Visual Studio para conseguirlo).NET La manera más sencilla de examinar un servicio Web creado con ASP.

Tal y como comentamos en la primera lección. ASP. averiguará los métodos que éste ofrece y la forma de invocarlos. Si se intenta el acceso desde un equipo remoto no se tendrá acceso por cuestiones de seguridad. Este código XML es el que se utiliza para averiguar los métodos disponibles y como invocarlos. por ejemplo). El aspecto del WSDL es este (parcial): Figura 6. Para obtener el WSDL correspondiente a nuestro servicio basta con presionar sobre el enlace "descripción de servicios" que ofrece la página autogenerada. Nota: Esta página autogenerada sólo se muestra si se accede al servicio Web en modo local. Sin embargo el WSDL (ruta al servicio Web seguido de ?WSDL) sí es accesible siempre ya que es necesario que otras máquinas lo puedan leer para hacer uso del servicio. para que un cliente pueda consumir un servicio Web deberá primero leer el "contrato" de uso del servicio. es decir. aunque es posible habilitarlo en casos que se haga necesario (para depuración remota.NET simplemente lo procesa por nosotros y genera una bonita página Web para informarnos del contenido del servicio de una forma más agradable para los humanos. Como recordará este contrato está escrito con el lenguaje WSDL (Web Service Description Language). Si presionamos el método Hora obtendremos una página de pruebas que nos permitirá invocarlo.6.. Además dicha página nos ofrece ejemplos de mensajes SOAP de solicitud y respuesta para acceder al método: . Como es bastante tedioso leerlo.WSDL de nuestro servicio Web horario. Lo interesante de esta página es que nos permite probar manualmente los métodos del servicio Web siempre y cuando utilicen parámetros y valores devueltos sencillos.

Como vemos las llamadas a la función se realizan con XML. Obviamente también será XML.7. en el caso de . Ver vídeo de esta lección (Consumo de un servicio Web . en un objeto DateTime normal y corriente tras llamar a la función remota. como si enviásemos un formulario).Figura 6. se realiza mediante un POST HTTP 8es decir. Se ha resaltado una de las solicitudes de ejemplo facilitadas. tal y como define el estándar SOAP. El XML devuelto ofrece únicamente el resultado de invocar el método y al tratarse de una fecha viene codificada de manera independiente al idioma o al sistema operativo.Examinando manualmente un servicio web) . Si presionamos sobre el botón Invocar obtendremos el resultado en una ventana aparte: En este caso la invocación. ¿Y el resultado?. Cualquier cliente de SOAP sabe interpretar este valor como una fecha y por lo tanto acceder a sus elementos es una tarea muy sencilla pues se convierte.NET.Página de prueba delmétodo horario.. dado que la hacemos desde el navegador.

Consumo de servicios Web con ASP. Esto se consigue presionando con el botón secundario sobre el nodo del proyecto en el Explorador de soluciones y eligiendo la opción Agregar referencia Web: . Este etiqueta la usaremos para mostrar la hora en el servidor obtenida mediante el uso del servicio Web creado en el apartado anterior.NET. Para poder hacer uso del servicio Web debemos añadir una referencia al mismo desde nuestro proyecto. Crear un proxy para utilizar el servicio Cree un nuevo proyecto de aplicación Web y en la página Web por defecto agregue una etiqueta Label1.NET Si crear servicios web le ha parecido fácil enseguida comprobará que utilizarlos es incluso más fácil todavía con ASP.

.. .8.9.Buscar servicios web y agregarlos Podemos buscar servicios en la misma solución de Visual Studio. buscar todos los servicios que haya instalados en la máquina local o examinar directorios UDDI para conocer los servicios que contienen. Figura 6.Agregar referencia web Al hacer esto se abre un diálogo que nos permite escribir la dirección del WSDL de algún servicio Web concreto (si nos la sabemos) o buscar servicios Web en diversos lugares.Figura 6.

wsdl) que indica a ASP.NET cómo utilizarlo.Agregar el servicio Web de hora.discomap) que contienen información sobre cómo acceder al servicio Web y una copia del archivo de definición del servicio Web (. pero debemos utilizar algo más descriptivo. Figura 6.En nuestro caso agregaremos una referencia al servicio Web de hora que creamos en el apartado anterior escribiendo la URL en la línea de dirección URL. A partir de ahora disponemos de un nuevo espacio de nombres llamado como la referencia Web (en nuestro caso ServicioHora) que contiene una clase con el nombre de la clase que definimos al crear el servicio Web (Service en nuestro ejemplo). Dentro de esta carpeta hay dos archivos (. Por defecto el nombre que Visual Studio le otorga es localhost. De manera automática se añade una nueva carpeta llamada App_WebReferences y dentro de ella una carpeta por cada referencia a un servicio web que hayamos añadido. Por ejemplo. Así.10.. por ejemplo ServicioHora como se ha hecho en la figura.disco y . para mostrar la hora en el servidor en la etiqueta que hemos añadido a la página escribiríamos: . para utilizar cualquier método del servicio sólo debemos instanciar un objeto de esta clase y llamar al método que nos interese. Al seleccionarlo se muestran sus métodos y debemos asignarle un nombre con el que accederemos a su funcionalidad desde el código.

.serviciosweb.. etc. como por ejemplo ToLongDateString para obtener la expresión larga de la fecha. cuando la aplicación está terminada y usándose en el entorno real.ToString() Por supuesto el método Hora devuelve un objeto de la clase Date de VB. si bien éstos pueden estar ejecutándose en otro servidor e incluso en otro país a través de Internet. u operar con él para ver la diferencia con cualquier otra fecha.NET. .. A la clase auto-generada que representa en local a los objetos expuestos por el servicio web se la denomina proxy. Es decir.Url = "http://www.Hora().com/servicioHora.Service() sh.com escribiríamos: Dim sh As New ServicioHora. También podemos permitir que programadores de otras plataformas hagan uso de nuestro servicio. Debido a ello la referencia que hemos añadido al servicio Web no será válida al poner la aplicación en producción y deberemos hacer que apunte a la referencia web correcta.Dim sh As New ServicioHora. Nota: Hacer uso de este servicio Web desde una aplicación Windows es igual de fácil que desde una página ASP.NET y podemos utilizar cualquiera de sus métodos. Por ejemplo si a la hora de poner en producción la aplicación de ejemplo el servicio Web reside en un servidor cuya URL es www. Por supuesto lo habitual es almacenar esta dirección en el archivo web. Éste obviamente debe ser idéntico (su WSDL debe ser idéntica) al servicio web original que usamos en el desarrollo.Service() Label1.serviciosweb... La propiedad Url de la clase proxy que se crea para acceder al servicio web nos permite establecer en tiempo de ejecución la dirección en la que está ubicado el WSDL del servicio que realmente usaremos.asmx" . Incluso en caso de no ser así seguramente el servicio que usemos para desarrollo no sea el mismo que se utiliza luego en producción.config para recuperarla en tiempo de ejecución y poder variarla fácilmente sin tocar el código.Text = "Hora en el servidor: " + sh. si alguien añade la referencia Web por nosotros y no nos dice que estamos usando un servicio Web desde nuestro código no habrá diferencia a la hora de usar los objetos expuestos a través del servicio. Cambio de ubicación del servicio Lo más habitual es que cuando estamos desarrollando el servicio y el cliente se encuentren en la misma máquina.

. Windows Communication Foundation. Nota: Existen una serie de especificaciones adicionales para servicios Web denominadas Web Service Enhancenments (WSE) que añaden funciones especiales para autenticación. "clavesecreta") . que son un estándar de la W3C y la nuev aplataforma unificada de mensajería de Microsoft.Service() sh. privacidad.Service() sh.. Estos WSE siguen las especificaciones conocidas como WS-*.UseDefaultCredentials = True .Credentials = New System. El estudio de WSE se sale del ámbito de este curso.. Si deshabilitamos la autenticación anónima y marcamos la autenticación de Windows.Credenciales de acceso Podemos proteger el acceso a un servicio Web usando los métodos de autenticación u autorización proporcionados por Internet Information Server. también las implementa para sus servicios web.NetworkCredential("usuario". para poder acceder al servicio deberemos facilitar credenciales de acceso validas. cifrado. Con esto obtendremos una barrera de protección básica para nuestro servicio Web. Éstas se corresponden con el nombre de usuario y la contraseña de un usuario del sistema. enrutado. Se pueden usar las credenciales del usuario actualmente autenticado en la aplicación (sin tener que escribir nombre de usuario y contraseña alguno) usando la propiedad UseDefaultCredentials: Dim sh As New ServicioHora. Ver vídeo de esta lección (Consumo de un servicio Web .Net. El código necesario para hacerlo es el siguiente: Dim sh As New ServicioHora.... La propiedad Credentials se usa para enviar las credenciales de cualquier usuario al servidor.Orígenes de datos de objetos) .. y otras muchas tareas avanzadas.

Puede descargar el código fuente en su máquina y explorarlo o modificarlo para conocer de forma práctica cómo usar ASP. Si desea ejecutar la aplicación en su máquina necesitará SQL Server 2005 Express instalado. La aplicación que desarrollaremos en este tutorial es una versión reducida de MSDN Video donde podrá ver Visual Studio 2005 en acción en un escenario sencillo. Nota: MSDN Video utiliza una base de datos para almacenar su estado. Puede utilizarse para comprobar las mejores prácticas en la construcción aplicaciones distribuidas. escalables y con distintos tipos de clientes (Windows. Código fuente de MSDN Video Puede descargar el código fuente de MSDN Video y visionarlo o editarlo en su máquina.Aplicación de ejemplo MSDN Video A continuación vamos a desarrollar una aplicación que nos permita explorar las principales características de Visual Studio 2005. Web y móviles). También puede explorar los videos donde construimos esta aplicación paso a paso. La aplicación MSDN Video es una aplicación de ejemplo empresarial desarrollada en España por la comunidad de desarrollo y Microsoft.NET para desarrollar aplicaciones reales. .

Web y dispositivos móviles. Funcionalidad y Enlace de Datos de MSDN Video Web Video 5.html . Temas y Pieles y Conclusión de MSDN Video Web MSDN Video empresarial Puede descargar la versión empresarial de MSDN Video y ver cómo podemos convertir la aplicación que hemos desarrollado aquí en un sistema distribuido completo. Introducción MSDN Video Web y Modelo de Datos Video 2. El Esqueleto de Presentación MSDN Video Web Video 3. Seguridad en MSDN Video Web Video 6. Entidades de Negocio y Acceso a Datos de MSDN Video Web Video 4.com/msdn/Cursos/Curso_Desarrollo_web_con_Visual_Stud io_2005/index.Videos explicativos Si desea ver cómo se hizo esta aplicación puede visionar estos videos donde desarrollamos la aplicación paso a paso: · · · · · · Video 1. Web de MSDN Video Código fuente. Desarrolla con MSDN Puedes colaborar con MSDN Video. Transacciones. tutoriales y videos explicativos de la versión completa de MSDN Video. con acceso a través de servicios web desde clientes Windows. te proporcionamos materiales de formación.desarrollaconmsdn. Tomado de: http://www. videos y eventos para que aprendas las tecnologías utilizadas en la aplicación.

Sign up to vote on this title
UsefulNot useful