Documentos de Académico
Documentos de Profesional
Documentos de Cultura
Curso de Desarrollo Web Con Visual Studio 2005
Curso de Desarrollo Web Con Visual Studio 2005
En este curso se tratan todas las cuestiones fundamentales que le permitirn 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
caractersticas avanzadas.
Este curso le enseara entre otras cosas:
Contenido
Este mdulo presenta con carcter general la plataforma .NET y cmo sta se
diferencia de otros sistemas de desarrollo tradicionales, como ASP.
Al final, lo que se ejecuta es cdigo nativo que ofrece un elevado rendimiento. Esto es
cierto tambin para las aplicaciones Web escritas con ASP.NET y contrasta con las
aplicaciones basadas en ASP clsico que eran interpretadas, no compiladas, y que
jams podran llegar al nivel de desempeo que ofrece ASP.NET.
La siguiente figura muestra el aspecto que tiene el cdigo intermedio de una
aplicacin sencilla y se puede obtener usando el desemsamblador que viene con la
plataforma .NET.
As, por ejemplo, todo lo que tiene que ver con el manejo de estructuras de datos
XML en la plataforma .NET se encuentra bajo el espacio de nombres System.Xml. La
funcionalidad fundamental para crear aplicaciones Web est en el espacio de nombres
System.Web. ste a su vez contiene otros espacios de nombres ms especializados
como
System.Web.Caching
para
la
persistencia
temporal
de
datos,
System.Web.UI.WebControls, que contiene toda la funcionalidad de controles Web
para interfaz de usuario, etc...
Arquitectura de ADO.NET
El concepto ms importante que hay que tener claro sobre ADO.NET es su modo de
funcionar, que se revela claramente al analizar su arquitectura:
concreta de las clases conectadas abstractas que hemos visto, que hereda de stas y
que tiene en cuenta ya todas las particularidades del origen de datos en cuestin.
As, por ejemplo, las clases especficas para acceder a SQL Server se llaman
SqlConnection, SqlCommand, SqlDataReader y SqlDataAdapter y se
encuentran bajo el espacio de nombres System.Data.SqlClient. Es decir, al
contrario que en ADO clsico no hay una nica clase Connection o Command que se
use en cada caso, si no que existen clases especializadas para conectarse y recuperar
informacin de cada tipo de origen de datos.
Nota:
El hecho de utilizar clases concretas para acceso a las fuentes de datos
no significa que no sea posible escribir cdigo independiente del origen
de datos. Todo lo contrario. La plataforma .NET ofrece grandes
facilidades de escritura de cdigo genrico basadas en el uso de herencia
e implementacin de interfaces. De hecho la versin 2.0 de .NET ofrece
grandes novedades especficamente en este mbito.
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), y proveedores
"puente", que se utilizan para acceder a travs de ODBC u OLEDB cuando no existe
un proveedor nativo para un determinado origen de datos.
Nota:
Estos proveedores nativos, si bien muy tiles en determinadas
circunstancias, ofrecen un rendimiento menor debido a la capa
intermedia que estn utilizando (ODBC u OLEDB). Un programador novel
puede sentir la tentacin de utilizar siempre el proveedor puente para
OLEDB y as escribir cdigo compatible con diversos gestores de datos
de forma muy sencilla. Se trata de un error y siempre que sea posible es
mejor utilizar un proveedor nativo.
Capa desconectada
Una vez que ya se han recuperado los datos desde cualquier origen de datos que
requiera una conexin sta ya no es necesaria. Sin embargo sigue siendo necesario
trabajar con los datos obtenidos de una manera flexible. Es aqu cuando la capa de
datos desconectada entra en juego. Adems, 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 conexin. A veces nicamente necesitamos un almacn de datos
temporal pero que ofrezca caractersticas avanzadas de gestin y acceso a la
informacin.
Por otra parte las conexiones con las bases de datos son uno de los recursos ms
escasos con los que contamos al desarrollar. Su mala utilizacin es la causa ms
frecuente de cuellos de botella en las aplicaciones y de que stas no escalen como es
debido. Esta afirmacin es especialmente importante en las aplicaciones Web en las
que se pueden recibir muchas solicitudes simultneas de cualquier parte del mundo.
Finalmente otro motivo por el que es importante el uso de los datos desconectado de
su origen es la transferencia de informacin entre capas de una aplicacin. stas
pueden encontrarse distribuidas por diferentes equipos, e incluso en diferentes
lugares del mundo gracias a Internet. Por ello es necesario disponer de algn modo
genrico y eficiente de poder transportar los datos entre diferentes lugares, 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.
Todo esto y mucho ms es lo que nos otorga el uso de los objetos DataSet. Es obvio
que no se trata de tareas triviales, pero los objetos DataSet estn pensados y
diseados con estos objetivos en mente. Como podremos comprobar ms adelante en
este curso es bastante sencillo conseguir estas funcionalidades tan avanzadas y
algunas otras simplemente usando de manera adecuada este tipo de objetos.
Nota:
Otra interesante caracterstica de los DataSet es que permiten gestionar
simultneamente diversas tablas (relaciones) de datos, cada una de un
origen diferente si es necesario, teniendo en cuenta las restricciones y
las relaciones existentes entre ellas.
Los DataSet, como cualquier otra clase no sellada de .NET, se pueden extender
mediante herencia. Ello facilita una tcnica avanzada que consiste en crear tipos
nuevos de DataSet especializados en la gestin de una informacin concreta (por
ejemplo un conjunto de tablas relacionadas). Estas nuevas tipos clases se denominan
genricamente DataSet Tipados, y permiten el acceso mucho ms cmodo a los
datos que representan, verificando reglas de negocio, y validaciones de tipos de datos
ms estrictas.
Figura 1.5.- Cdigo autogenerado por Visual Studio para crear la interfaz de
la figura anterior.
Al contrario que en Visual Basic tradicional, en donde siempre existan instancias por
defecto de los formularios que podamos usar directamente, en .NET es necesario
crear un objeto antes de poder hacer uso de los formularios:
Dim frm As New MiFormulario
frm.Show()
Todos los controles heredan de una clase Control por lo que conservan una serie de
funcionalidades comunes muy interesantes, como la capacidad de gestionarlos en el
diseador (movindolos, alinendolos...), de definir mrgenes entre ellos o hacer que
se adapten al tamao de su contenedor.
Este tipo de aplicaciones se salen del mbito de este curso por lo que no se
profundizar ms en ellas.
Figura 1.6.- Cdigo ASP sencillo que genera una lista de seleccin y saluda al
presionar un botn.
Obviamente se podra haber simplificado sin enviar el formulario al servidor usando
JavaScript en el cliente para mostrar el saludo, pero la intencin es ilustrar la mezcla
de cdigo de cliente y de servidor que existe en este tipo de aplicaciones.
Las principales desventajas de este tipo de codificacin son las siguientes:
1. No existe separacin entre el diseo y la lgica de las aplicaciones. Si
queremos cambiar sustancialmente la apariencia de la aplicacin Web lo
tendremos bastante complicado puesto que el cdigo del servidor est
mezclado entre el HTML.
2. En ASP clsico no existe el concepto de control para la interfaz de usuario.
Lo nico que hay es HTML y JavaScript que se deben generar desde el servidor.
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), sino
que tenemos que crear un bucle que genere los elementos HTML necesarios
para generarla. Tampoco disponemos de un diseador visual que nos permita
gestionar los controles y elementos HTML existentes, y menos cuando stos se
encuentran mezclados con el cdigo del servidor.
Nota:
Para mayor simplicidad los videos de este mdulo estn realizados con aplicaciones de
consola. Si quiere reproducir los ejemplos mostrados en estos videos en una aplicacin web
puede modificar las instrucciones Console.WriteLine por Response.Write.
Contenido
Leccin 5: Atributos
o Atributos
Introduccin
En esta primera leccin veremos los tipos de datos que .NET Framework pone a
nuestra disposicin, as mismo veremos las diferencias con respecto a los tipos de
datos de VBScript/VB6 y las equivalencias entre los tipos de ambos entornos, de esta
forma nos resultar ms fcil familiarizarnos. Aunque no debemos olvidar que en .NET
los tipos de datos tienen un tratamiento, en algunos casos, especial que pueden
llevarnos a confusin, por tanto en los casos que pueda existir esa posibilidad de
funcionamiento diferente, veremos ejemplos de cmo los manejbamos en
VBScript/VB6 y cmo tendremos que usarlos desde Visual Basic .NET.
A continuacin daremos un repaso a conceptos bsicos o elementales sobre los tipos
de datos, que si bien nos sern familiares, es importante que lo veamos para poder
comprender mejor cmo estn definidos y organizados los tipos de datos en .NET y de
paso veremos las equivalencias con respecto a VBScript/VB6.
Tipos primitivos
o Sufijos o caracteres y smbolos 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 Ms opciones aplicables a los proyectos
Arrays (matrices)
o Declarar e inicializar un array
o Cambiar el tamao 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 .NET Framework y los
alias utilizados en Visual Basic 2005, as como el equivalente de VBScript/VB6.
.NET Framework
System.Boolean
System.Byte
System.Int16
System.Int32
System.Int64
System.Single
System.Double
System.Decimal
System.Char
System.String
System.Object
System.DateTime
VB.NET
Boolean
Byte
Short
Integer
Long
Single
Double
Decimal
Char
String
Object
Date
VBScript/VB6
Boolean *
Byte
Integer
Long
N.A.
Single
Double
Currency *
N.A. (ChrW)
String *
Variant / Object *
Date *
System.SByte
System.UInt16
System.UInt32
System.UInt64
SByte
UShort
UInteger
ULong
N.A.
N.A.
N.A.
N.A.
Smbolo
N.A.
%
&
!
#
Carcter
S
I
L
F
R
Decimal
UShort
UInteger
ULong
@
N.A.
N.A.
N.A.
D
US
UI
UL
Los tipos por valor son tipos de datos cuyo valor se almacena en la pila o en la
memoria "cercana", como los numricos que hemos visto. Podemos decir que el
acceso al valor contenido en uno de estos tipos es directo, es decir se almacena
directamente en la memoria reservada para ese tipo y cualquier cambio que hagamos
lo haremos directamente sobre dicho valor. De igual forma cuando copiamos valores
de un tipo por valor a otro, estaremos haciendo copias independientes.
Por otro lado, los tipos por referencia se almacenan en el "montculo" (heap) o
memoria "lejana". A diferencia de los tipos por valor, los tipos por referencia lo nico
que almacenan es una referencia (o puntero) al valor asignado. Si hacemos copias de
tipos por referencia, realmente lo que copiamos es la referencia propiamente dicha,
pero no el contenido.
Estos dos casos los veremos en breve con ms detalle.
Variables y constantes
Disponer de todos estos tipos de datos no tendra ningn sentido si no los pudiramos
usar de alguna otra forma que de forma literal. Y aqu es donde entran en juego las
variables y constantes.
Consejo para usar las constantes
Siempre que tengamos que indicar un valor constante, ya sea para indicar el mximo
o mnimo permitido en un rango de valores o para comprobar el trmino de un bucle,
deberamos usar una constante en lugar de un valor literal. De esta forma si ese valor
lo usamos en varias partes de nuestro cdigo, si en un futuro decidimos que dicho
valor debe ser diferente, nos resultar ms fcil realizar un solo cambio que cambiarlo
en todos los sitios en los que lo hemos usado. Adems 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 deberamos.
Pero esto no es algo nuevo, las constantes se definen de la misma forma que en
VBScript/VB6, salvo que ahora podemos obligarnos a indicar el tipo de datos que esa
constante va a contener. Esto lo veremos en la siguiente seccin.
Declarar variables
La declaracin de las variables en Visual Basic 2005 se hace de la misma forma que
en VBScript/VB6/VB6, o casi, las excepciones vienen dadas, como hemos comentado
antes, de la posibilidad de obligar a definir el tipo de cada variable y de cmo
podemos definir ms de una variable en una misma instruccin Dim.
A primera vista estamos declarando tres variables de tipo Integer, pero realmente
solo declara con el tipo indicado a la ltima variable, las otras dos, 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 clsico).
En Visual Basic 2005 al usar esa misma lnea de cdigo estamos declarando tres
variables de tipo Integer, esto es algo que debemos tener en cuenta, sobre todo si
nuestra intencin era hacer precisamente lo que VB6, haca, es decir, declarar dos
variables de tipo Variant y una de tipo Integer.
Declarar variables y asignar el valor inicial
En Visual Basic 2005 tambin podemos inicializar una variable con un valor distinto al
predeterminado, que en los tipos numricos es un cero, en las fechas es el 1 de enero
del ao 1 a las doce de la madrugada (#01/01/0001 12:00:00AM#) y en la
cadenas es un valor nulo (Nothing), para hacerlo, simplemente tenemos que indicar
ese valor, tal como veremos es muy parecido a como se declaran las constantes. Por
ejemplo:
Dim a As Integer = 10
En esa misma lnea podemos declarar y asignar ms variables, pero todas deben
estar indicadas con el tipo de datos:
Dim a As Integer = 10, b As Integer = 25
Por supuesto, el tipo de datos puede ser cualquiera de los tipos primitivos:
Dim a As Integer = 10, b As Integer = 25, s As String = "Hola"
Aunque para que el cdigo sea ms legible, y fcil de depurar, no deberamos mezclar
en una misma instruccin Dim ms de un tipo de datos.
Nota:
Es importante saber que en las cadenas de Visual Basic 2005 el valor de
En Visual Basic 2005 tambin podemos usar esas mismas funciones, aunque en el
caso de Chr, el valor que devuelve esta funcin es un valor de tipo Char, no de tipo
String como ocurre en VBScript/VB6, pero debido a que un valor de tipo Char se
puede convertir en una cadena, podemos hacer una asignacin como la mostrada en
el cdigo anterior sin ningn tipo de problemas.
Si nuestra intencin es asignar un valor Char a una variable, adems de la funcin
Chr, podemos hacerlo con un literal, ese valor literal estar encerrado entre comillas
dobles, (al igual que una cadena), aunque para que realmente sea un carcter
debemos agregarle una c justo despus del cierre de las comillas dobles:
Dim c As Char = "A"c
Tanto una como la otra tienen dos estados: conectado o desconectado dependiendo
de que agreguemos On u Off respectivamente.
Como recomendacin para buenas prcticas, debemos "conectar" siempre estas dos
opciones, si bien Option Explicit On ya viene como valor por defecto, cosa que no
ocurre con Option Strict, que por defecto est desconectado.
Nota:
La figura mostrada corresponde a la versin Visual Web Developer de
Visual Studio. El contenido de su pantalla variar dependiendo de la
versin de Visual Studio 2005 de la que disponga.
De la lista despegable Option Strict, seleccionamos On. Por defecto ya estarn
seleccionadas las opciones On de Option Explicit y Binary de Option Compare,
por tanto no es necesario realizar ningn cambio ms, para aceptar los cambios y
cerrar el cuadro de dilogo, presionamos el botn Aceptar.
Nota:
Aunque en esta captura muestre: C:\vbexpB1 en Default project
location, salvo que lo cambiemos, aparecer el path por defecto dentro
de Mis documentos.
Como podemos observar, aparecen pocas opciones, si bien podemos hacer que se
muestren todas las disponibles, para hacerlo, debemos marcar la casilla que est en
la parte inferior izquierda en la que podemos leer: Mostrar todas las
configuraciones, al seleccionar esa opcin nos mostrar un nmero mayor de
opciones, tal como podemos ver en la Figura 2.3:
Figura 2.4. Aviso de Option Strict al declarar una variable sin tipo
Nota:
Una de las ventajas del IDE (Integrated Development Environment,
entorno de desarrollo integrado) de Visual Studio 2005 es que nos avisa
al momento de cualquier fallo que cometamos al escribir el cdigo, este
"pequeo" detalle, aunque alguna veces puede llegar a parecer
fastidioso, nos facilita la escritura de cdigo, ya que no tenemos que
esperar a realizar la compilacin para que tengamos constancia de esos
fallos.
Ver
video
1
de
esta
leccin
(Declarar
Ver video 2 de esta leccin (Definir constantes)
variables)
Rojo
Verde
Azul
End Enum
En este segundo caso, el valor mximo que podemos asignar a los miembros de una
enumeracin ser el que pueda contener un tipo de datos Long.
3- Indicando el atributo FlagsAttibute, (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 enumeracin. Se usa tambin para indicar valores
que se pueden "sumar" o complementar entre s, pero sin perder el nombre, en breve
veremos qu significa esto de "no perder el nombre".
<Flags()> _
Enum Colores As Byte
Rojo = 1
Verde = 2
Azul = 4
End Enum
Nota:
Los atributos los veremos con ms detalle en otra leccin de este mismo
mdulo.
End Enum
Por tanto cabe pensar que podemos usar cualquier valor para asignar a una variable
declarada como una enumeracin, al menos si ese valor est dentro del rango
adecuado. Es decir, en el ejemplo de la figura usar un 1 en lugar de Colores.Rojo.
En Visual Basic 2005 esto no es posible, al menos si lo hacemos de forma "directa" y
con Option Strict conectado, ya que recibiremos un error indicndonos que no
podemos convertir, por ejemplo, un valor entero en un valor del tipo de la
enumeracin. En la Figura 2.8 podemos ver ese error al intentar asignar el valor 3 a
una variable del tipo Colores (definida con el tipo predeterminado Integer).
Figura 2.8. Error al asignar un valor "normal" a una variable del tipo Colores
El error nos indica que no podemos realizar esa asignacin, pero el entorno integrado
de Visual Studio 2005 tambin nos ofrece alternativas para que ese error no se
produzca, esa ayuda se obtiene presionando el signo de admiracin que tenemos
justo donde est el cursor del mouse, pero no solo nos dice cmo corregirlo, sino que
tambin nos da la posibilidad de que el propio IDE se encargue de hacerlo, tal como
podemos apreciar en la Figura 2.9.
CType es una de las formas que nos ofrece Visual Basic 2005 de hacer conversiones
entre diferentes tipos de datos, en este caso convertimos un valor entero en uno del
tipo enumerado Colores.
Si compilamos y ejecutamos la aplicacin, sta funcionar correctamente.
Es posible que usando CType no asignemos un valor dentro del rango permitido. En
este caso, el valor 3 podramos darlo por bueno, ya que es la suma de 1 y 2 (Rojo y
Verde), pero qu pasara si el valor asignado es, por ejemplo, 15? En teora no
deberamos permitirlo.
Estas validaciones podemos hacerlas de dos formas:
1- Con la clsica solucin de comprobar el valor indicado con todos los valores
posibles.
2- Usando funciones especficas del tipo Enum. Aunque en este ltimo caso, solo
podremos comprobar los valores definidos en la enumeracin.
En el siguiente ejemplo podemos hacer esa comprobacin.
Sub mostrarColor(ByVal c As Colores)
' comprobar si el valor indicado es correcto
' si no est definido, usar el valor Azul
If [Enum].IsDefined(GetType(Colores), c) = False Then
c = Colores.Azul
End If
Console.WriteLine("El color es {0}", c)
End Sub
Este cdigo lo que hace es comprobar si el tipo de datos Colores tiene definido el
valor contenido en la variable c, en caso de que no sea as, usamos un valor
predeterminado.
Nota:
La funcin IsDefined slo comprueba los valores que se han definido en
la enumeracin, no las posibles combinaciones que podemos conseguir
sumando cada uno de sus miembros, incluso aunque hayamos usado el
atributo FlagsAttribute.
Ver
Ver
Ver
Ver
video
video
video
video
1
2
3
4
de
de
de
de
esta
esta
esta
esta
leccin
leccin
leccin
leccin
(Enumeraciones
(Enumeraciones
(Enumeraciones
(Enumeraciones
1)
2)
3)
4)
Arrays (matrices)
Los arrays (o matrices) tambin es algo que podamos usar en VBScript/VB6, si bien
la forma en que se almacena en la memoria y la forma en que podemos usarlas en
Visual Basic 2005 ha cambiado.
En Visual Basic 2005 la declaracin de un array la haremos de la misma forma que en
VBScript/VB6, en el siguiente ejemplo declaramos un array de tipo String llamado
nombres:
Dim nombres() As String
Pero esta declaracin es ilegal en Visual Basic 2005, por el hecho de que los arrays
de .NET siempre deben tener el valor cero como ndice inferior.
Lo que si podemos hacer en Visual Basic 2005 es usar To para indicar el valor mximo
del ndice, aunque no tiene la misma "potencia" que en VBScript/VB6, al menos de
esta forma el cdigo resultar ms legible:
Dim nombres(0 To 10) As String
Con el cdigo anterior estamos creando un array de tipo String con tres valores cuyos
ndices van de cero a dos.
Si el array es bidimensional (o con ms dimensiones), tambin podemos inicializarlos
al declararlo, pero en este caso debemos usar doble juego de llaves:
Dim nombres(,) As String = {{"Juan", "Pepe"}, {"Ana", "Eva"}}
Juan
Pepe
Ana
Eva
Si bien tanto ReDim como ReDim Preserve se pueden usar en arrays de cualquier
nmero de dimensiones, en los arrays de ms de una dimensin solamente podemos
cambiar el tamao de la ltima dimensin.
Eliminar el contenido de un array
Una vez que hemos declarado un array y le hemos asignado valores, es posible que
nos interese eliminar esos valores de la memoria, para lograrlo, podemos hacerlo de
tres formas:
1. Redimensionando el array indicando que tiene cero elementos, aunque en el
mejor de los casos, si no estamos trabajando con arrays de ms de una
dimensin, tendramos un array de un elemento, ya que, como hemos
comentado anteriormente, los arrays de .NET el ndice inferior es cero.
2. Usar la instruccin Erase. Al igual que en VBScript/VB6, Erase elimina
totalmente el array de la memoria.
3. Asignar un valor Nothing al array. Esto funciona en Visual Basic 2005 pero no
en VBScript/VB6, debido a que en Visual Basic 2005 los arrays son tipos por
referencia
Los arrays son tipos por referencia
Como acabamos de ver, en Visual Basic 2005 los arrays son tipos por referencia, y tal
como comentamos anteriormente, los tipos por referencia realmente lo que contienen
son una referencia a los datos reales no los datos propiamente dichos.
Cual es el problema?
Vemoslo con un ejemplo y as lo tendremos ms claro.
Dim nombres() As String = {"Juan", "Pepe", "Ana", "Eva"}
otros = nombres
nombres(0) = "Antonio"
Qu ha ocurrido?
Que debido a que los arrays son tipos por referencia, 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.
Si realmente queremos tener copias independientes, debemos hacer una copia del
array nombres en el array otros, esto es fcil de hacer si usamos el mtodo CopyTo.
ste mtodo existe en todos los arrays y nos permite copiar un array en otro
empezando por el ndice que indiquemos. El nico requisito es que el array de
destino debe estar inicializado y tener espacio suficiente para contener los elementos
que queremos copiar.
En el siguiente cdigo de ejemplo hacemos una copia del contenido del array
nombres en el array otros, de esta forma, el cambio realizado en el elemento cero
de nombres no afecta al del array otros.
Dim nombres() As String = {"Juan", "Pepe", "Ana", "Eva"}
ReDim otros(nombres.Length)
nombres.CopyTo(otros, 0)
nombres(0) = "Antonio"
Adems del mtodo CopyTo, los arrays tienen otros miembros que nos pueden ser de
utilidad, como por ejemplo la propiedad Length usada en el ejemplo para saber
cuantos elementos tiene el array nombres.
Para averiguar el nmero de elementos de un array, tambin podemos usar la funcin
UBound, que es la que nos serva en VBScript/VB6 para saber esa informacin.
Sin embargo, el uso de la funcin LBound, (que sirve para averiguar el ndice inferior
de un array), no tiene ningn sentido en Visual Basic 2005, ya que todos los arrays
siempre tienen un valor cero como ndice inferior.
Para finalizar este tema, solo nos queda por decir, 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, aunque de esto hablaremos en la prxima
leccin, en la que tambin tendremos la oportunidad de profundizar un poco ms en
los tipos por referencia y en como podemos definir nuestros propios tipos de datos,
tanto por referencia como por valor.
Introduccin
En la leccin anterior vimos los tipos de datos predefinidos en .NET Framework, en
esta leccin veremos cmo podemos crear nuestros propios tipos de datos, tanto por
valor como por referencia.
Tambin tendremos ocasin de ver los distintos niveles de accesibilidad que podemos
aplicar a los tipos, as como a los distintos miembros de esos tipos de datos. De los
distintos miembros que podemos definir en nuestros tipos, nos centraremos en las
propiedades para ver en detalle los cambios que han sufrido con respecto a las clases
de VBScript/VB6. Tambin veremos temas relacionados con la programacin
orientada a objetos (POO) en general y de forma particular los que ataen a las
interfaces.
Clases y estructuras
Accesibilidad y mbito
o mbito
mbito de bloque
mbito de procedimiento
mbito de mdulo
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
Importacin 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 Implementacin de mltiples interfaces
o Mltiple implementacin de un mismo miembro
constructor
o
o
Esta caracterstica nos asegura que siempre podremos usar un objeto del tipo Object
para acceder a cualquier clase de .NET, de manera similar a como un variant serva
en VBScript/VB6 para tratar cualquier tipo de objeto.
De los miembros que tiene la clase Object debemos resaltar el mtodo ToString, el
cual ya lo vimos en la leccin anterior cuando queramos convertir un tipo primitivo en
una cadena. Este mtodo est pensado para devolver una representacin en formato
cadena de un objeto. El valor que obtengamos al usar este mtodo depender de
cmo est definido en cada clase y por defecto lo que devuelve es el nombre
completo de la clase. En la mayora de los casos, sin embargo, el valor obtenido al
usar este mtodo debera ser ms intuitivo: por ejemplo los tipos de datos primitivos
tienen definido este mtodo para devuelva el valor que contienen. De igual forma,
nuestras clases tambin deberan devolver un valor adecuado al contenido
almacenado. De cmo hacerlo, nos ocuparemos en breve.
Nota:
Todos los tipos de datos de .NET, ya sean por valor o por referencia
siempre estn derivados de la clase Object, por tanto podremos llamar a
cualquiera de los mtodos que estn definidos en esa clase.
Aunque en el caso de los tipos de datos por valor, cuando queremos
acceder a la clase Object que contienen, .NET Framework primero debe
convertirla en un objeto por referencia (operacin denominada boxing) y
cuando hemos dejado de usarla y queremos volver a asignar el dato a la
variable por valor, tiene que volver a hacer la conversin inversa
(unboxing).
Una vez definida la clase podemos agregar los elementos (o miembros) que creamos
conveniente. En el ejemplo, para simplificar, hemos agregado dos campos pblicos,
aunque tambin podramos haber definido cualquiera de los miembros permitidos en
las clases.
Enumeraciones
Campos
Mtodos (funciones o procedimientos)
Propiedades
Eventos
mbito
Es el alcance que la definicin de un miembro o tipo puede tener. Es decir, cmo
podemos acceder a ese elemento y desde dnde podemos accederlo.
El mbito de un elemento de cdigo est restringido por el "sitio" en el que lo hemos
declarado. Estos sitios pueden ser:
Accesibilidad
A los distintos elementos de nuestro cdigo (ya sean clases o miembros de las clases)
podemos darle diferentes tipos de accesibilidad. Estos tipos de "acceso" dependern
del mbito que queramos que tengan, es decir, desde dnde podremos accederlos.
Los modificadores de accesibilidad son:
Por ejemplo, podemos declarar miembros privados a una clase, en ese caso, dichos
miembros solamente los podremos acceder desde la propia clase, pero no desde fuera
de ella.
Nota:
Al igual que ocurre en VBScript/VB6, al declarar una variable con Dim,
por regla general, el mbito que le estamos aplicando es privado, pero
como veremos, en Visual Basic 2005, dependiendo del tipo en el que
declaremos esa variable, el mbito puede ser diferente a privado.
Miembros compartidos
Por otro lado, los miembros compartidos de una clase o tipo, son elementos que no
pertenecen a una instancia o copia en memoria particular, sino que pertenecen al
propio tipo y por tanto siempre estn accesibles o disponibles, dentro del nivel del
mbito y accesibilidad que les hayamos aplicado, y su tiempo de vida es el mismo que
el de la aplicacin.
Nota:
Lo ms parecido en VB6 a los miembros compartidos de Visual Basic
2005 son los mtodos y campos declarados en un mdulo .BAS.
Del mbito, la accesibilidad y los miembros compartidos nos ocuparemos con ms
detalle en una leccin posterior, donde veremos ciertas peculiaridades, como puede
ser la limitacin del mbito de un miembro que aparentemente tiene una accesibilidad
no restringida.
MsgBox(t)
Para usar este cdigo en Visual Basic 2005 tendremos que desactivar Option Strict y
cambiar el tipo Variant por Object, (cosa que el IDE har automticamente si
pegamos el cdigo), lo dems se puede quedar igual, incluso los tipos de datos,
aunque debemos recordar que un Long de VBScript/VB6 es un Integer de VB2005.
Como podemos comprobar las dos funciones tienen el mismo nombre, pero tanto una
como otra reciben parmetros de tipos diferentes.
Con Visual Basic 2005 podemos sobrecargar funciones, pero lo interesante no es que
podamos hacerlo, sino cmo podemos usar esas funciones. En el cdigo anterior
tenemos dos funciones llamadas Suma, la primera acepta dos parmetros de tipo
Integer y la segunda de tipo Double. Lo interesante es que cuando queramos usarlas,
no tenemos que preocuparnos de cual vamos a usar, ya que ser el compilador el que
decida la ms adecuada al cdigo que usemos, por ejemplo:
' En este caso, se usar la que recibe dos valores enteros
MsgBox( Suma(10, 22) )
El compilador de Visual Basic 2005 es el que decide que funcin usar, esa decisin la
toma a partir de los tipos de parmetros que hayamos indicado. En el segundo
ejemplo de uso, el que mejor coincide es el de los dos parmetros de tipo Double.
Tambin podemos tener sobrecarga usando una cantidad diferente de parmetros,
aunque stos sean del mismo tipo. Por ejemplo, podemos aadir esta declaracin al
cdigo anterior sin que exista ningn tipo de error, ya que esta nueva funcin recibe
tres parmetros en lugar de dos:
Function
Integer
Suma(n1
As
Integer,
n2
As
Integer,
n3
As
Integer)
As
Return n1 + n2 + n3
End Function
Por tanto, cuando el compilador se encuentre con una llamada a la funcin Suma en
la que se usen tres parmetros, intentar usar esta ltima.
Nota:
Para que exista sobrecarga, la diferencia debe estar en el nmero o en el
tipo de los parmetros, no en el tipo del valor devuelto.
Cuando, desde el IDE de Visual Studio 2005, queremos usar los mtodos
sobrecargados, nos mostrar una lista de opciones indicndonos las posibilidades de
sobrecarga que existen y entre las que podemos elegir, tal como vemos en la Figura
2.10:
Return n1 + n2
End Function
Con esta lnea de cdigo lo que estamos indicando al Visual Basic es que tenemos
intencin de usar una variable llamada c para acceder a una clase de tipo Cliente.
Esa variable, cuando llegue el momento de usarla, sabr todo lo que hay que saber
sobre una clase Cliente, pero hasta que no tenga una "referencia" a un objeto de ese
tipo no podremos usarla.
La asignacin 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
Nota:
En VBScript/VB6 esta forma de crear un nuevo objeto producira un
error, ya que para "asignar" a una variable un nuevo objeto tenemos
que usar la instruccin Set, en Visual Basic 2005 ya no es necesario el
uso de esa instruccin, de hecho si la usamos, recibiremos un error.
A partir de este momento, la variable c tiene acceso a un nuevo objeto del tipo
Cliente, por tanto podremos usarla para asignarle valores y usar cualquiera de los
miembros que ese tipo de datos contenga:
c.Nombre = "Antonio"
c.Apellidos = "Ruiz Rodrguez"
O tambin:
Dim c As Cliente = New Cliente
Las dos formas producen el mismo resultado, por tanto es recomendable usar la
primera.
En VBScript/VB6 este tipo de declaracin y asignacin no era recomendable, ya que
aade trabajo extra al compilador de VB. Ese trabajo extra consiste en comprobar si
el objeto al que queremos acceder ya est creado, en caso de que no sea as, primero
lo crea y despus lo usa, 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, el objeto se crea en la
memoria y se asigna a la variable, a partir de ese momento no se comprueba si ya
est creado o no, ya que se supone que s est creado.
Lo que debemos tener muy presente es que adems de la sobrecarga de trabajo que
aade VBScript/VB6 a este tipo de instanciacin, el comportamiento es muy diferente
al de Visual Basic 2005. Por ejemplo, si en VBScript/VB6 asignamos un valor nulo
(Nothing) a una variable declarada de esta forma y acto seguido usamos la variable,
el motor en tiempo de ejecucin (runtime) crea un nuevo objeto y asunto arreglado.
Pero en Visual Basic 2005, si asignamos un valor nulo a una variable, le estamos
diciendo al CLR (el runtime de .NET) que ya no queremos usar ms ese objeto, por
tanto lo elimina de la memoria; si despus queremos volver a usar la variable,
debemos crear otro objeto, (con New), de no hacerlo, se producir un error, ya que
en Visual Basic 2005 no existe la auto-instanciacin.
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. En VBScript/VB6 el constructor es el mtodo Class_Initialize. Sin embargo
en Visual Basic 2005 el constructor es un mtodo de tipo Sub llamado New.
En el constructor de una clase podemos incluir el cdigo que creamos conveniente,
pero realmente solamente deberamos incluir el que realice algn tipo de
inicializacin, en caso de que no necesitemos realizar ningn tipo de inicializacin, no
es necesario definir el constructor, ya que el propio compilador lo har por nosotros.
Esto es as porque todas las clases deben implementar un constructor, por tanto si
nosotros no lo definimos, lo har el compilador de Visual Basic 2005.
Si nuestra clase Cliente tiene un campo para almacenar la fecha de creacin 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.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 creacin del objeto.
En los constructores tambin podemos hacer las inicializaciones que, por ejemplo
permitan a la clase a conectarse con una base de datos, abrir un fichero o cargar una
imagen grfica, etc., aunque en algunos de estos casos nos facilitar la tarea una
nueva caracterstica que VBScript/VB6 no tiene.
Constructores parametrizados
De la misma forma que podemos tener mtodos y propiedades sobrecargadas,
tambin podemos tener constructores sobrecargados, ya que debemos recordar que
Teniendo esta declaracin de la clase Cliente, podemos crear nuevos clientes de dos
formas:
Dim c1 As New Cliente
Esta declaracin de la clase Cliente la podramos haber hecho de una forma diferente.
Por un lado tenemos un constructor por omisin (el que no recibe parmetros) en el
que asignamos la fecha de creacin y por otro el constructor que recibe los datos del
nombre y apellidos. En ese segundo constructor tambin asignamos la fecha de
creacin, ya que, se instancie como se instancie la clase, nos interesa saber siempre
la fecha de creacin. En este ejemplo, por su simpleza no es realmente un problema
repetir la asignacin de la fecha, pero si en lugar de una inicializacin necesitramos
hacer varias, la verdad es que nos encontraramos con mucha "duplicidad" de cdigo.
Por tanto, en lugar de asignar los datos en dos lugares diferentes, podemos hacer
esto otro:
Class Cliente
Public Nombre As String
Public Apellidos As String
Public FechaCreacion As Date
'
Public Sub New()
FechaCreacion = Date.Now
End Sub
'
Public Sub New(elNombre As String, losApellidos As String)
New()
Nombre = elNombre
Apellidos = losApellidos
End Sub
End Class
Nota:
El IDE de Visual Studio 2005 colorea las instrucciones y tipos propios del
lenguaje, tal y como lo hace el de VBScript/VB6, en el caso de Me,
VBScript/VB6 no la colorea, pero este no es el motivo de esta nota, lo
que no debe confundirnos es que cuando declaramos Sub New, tanto
Sub como New se muestran coloreadas, cuando solo se debera colorear
Sub; sin embargo cuando usamos Me.New, solo se colorea Me y no New
que es correcto, tal como vemos en la Figura 2.11, ya que en este caso
New es el nombre de un procedimiento y los procedimientos no son
parte de las instrucciones y tipos de .NET.
Structure Punto
Public X As Integer
Public Y As Integer
'
Sub New(ByVal x As Integer, ByVal y As Integer)
Me.X = x
Me.Y = y
End Sub
End Structure
Nota:
Tanto en las estructuras como en las clases podemos tener
constructores compartidos, en el caso de las estructuras, este tipo de
constructor es el nico que podemos declarar sin parmetros.
Campos
Como vimos, las variables declaradas a nivel del tipo, son los campos. La principal
diferencia con respecto a las clases, es que los campos de una estructura no pueden
inicialiarse en la declaracin y el valor que tendrn inicialmente es un valor "nulo",
que en el caso de los campos de tipo numricos es un cero.
Por tanto, si necesitamos que los campos tengan algn valor inicial antes de usarlos,
deberamos indicarlo a los usuarios de nuestra estructura y proveer un constructor
que realice las inicializaciones correspondientes, pero debemos recordar que ese
En este trozo de cdigo definimos e instanciamos una variable del tipo Punto, a
continuacin declaramos otra variable del mismo tipo y le asignamos la primera, si
estos tipos fuesen por referencia, tanto una como la otra estaran haciendo referencia
al mismo objeto en memoria, y cualquier cambio realizado a cualquiera de las dos
variables afectaran al mismo objeto, pero en el caso de las estructuras (y de los tipos
por valor), cada cambio que realicemos se har sobre un objeto diferente, por tanto la
asignacin del valor 200 al campo X de la variable p1 solo afecta a esa variable,
dejando intacto el valor original de la variable p.
Accesibilidad y mbito
Tal y como comentamos anteriormente, dependiendo de dnde y cmo estn
declarados los tipos de datos y los miembros definidos en ellos, tendremos o no
acceso a esos elementos.
Recordemos que el mbito es el alcance con el que podemos acceder a un elemento y
depende de dnde est declarado, por otro lado, la accesibilidad depende de cmo
declaremos cada uno de esos elementos.
mbito
Dependiendo de donde declaremos un miembro o un tipo, ste tendr mayor alcance
o cobertura, o lo que es lo mismo, dependiendo del mbito en el que usemos un
elemento, podremos acceder a l desde otros puntos de nuestro cdigo.
A continuacin veremos con detalle los mbitos en los que podemos declarar los
distintos elementos de Visual Basic 2005.
mbito de bloque
En los siguientes ejemplos veremos cmo podemos definir variables para usar
solamente en el bloque en el que estn definidas.
Los bloques de cdigo en los que podemos declarar variables son los bucles, (For, Do,
While), y los bloques condicionales, (If, Select).
Por ejemplo, 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
'...
End If
Next
'
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
mbito de procedimiento
Las variables declaradas en un procedimiento tendrn un mbito o cobertura que ser
el procedimiento en el que est declaradas, y como hemos visto, ese mbito incluye
tambin cualquier bloque de cdigo declarado dentro del procedimiento.
Estas variables ocultarn a las que se hayan declarado fuera del procedimiento, si
bien, dependiendo del tipo de mdulo, podremos acceder a esas variables "externas"
indicando el nombre completo del mdulo o bien usando la instruccin Me, tal como
vimos en el cdigo del constructor parametrizado de la estructura Punto.
Pero mejor vemoslo con un ejemplo. En el siguiente cdigo, definimos una clase en
la que tenemos un campo llamado Nombre, tambin definimos un mtodo en el que
internamente se utiliza una variable llamada nombre, para acceder a la variable
declarada en la clase, tendremos que usar la instruccin o palabra clave Me.
Public Class Cliente
Public Nombre As String = "Juan"
Function Mostrar() As String
Dim nombre As String = "Pepita"
Return "Externo= " & Me.Nombre & ", interno= " & nombre
End Function
End Class
En este ejemplo, el hecho de que una variable est declarada con la letra ene en
mayscula o en minscula no implica ninguna diferencia, ya que Visual Basic 2005 al
igual que VBScript/VB6 no hace distinciones de este tipo, si bien, en Visual Basic 2005
no se cambia automticamente las maysculas y minsculas de las variables, salvo
cuando estn en el mismo nivel de mbito; en cambio, si en VBScript/VB6 declaramos
una variable con el mismo nombre, aunque est en un mbito diferente, siempre se
usar el estado de maysculas/minsculas de la ltima definicin.
mbito de mdulo
Cuando hablamos de mdulos, nos estamos refiriendo a una clase, a una estructura o
a
cualquier
otro
tipo
de
datos
que
nos
permita
.NET.
En estos casos, las variables declaradas dentro de un tipo de datos sern visibles
desde cualquier parte de ese tipo, siempre teniendo en cuenta las restricciones
mencionadas en los casos anteriores.
El problema es que el compilador de Visual Basic 2005 nos indicar que el tipo Int32
no est definido, ya que intentar buscarlo dentro del mbito que actualmente tiene,
es decir, la declaracin que nosotros hemos hecho de System, por tanto para poder
acceder al tipo Int32 definido en el espacio de nombres "global" System de .NET
tendremos que usar la instruccin Global, por suerte el IDE de Visual Studio 2005
reconoce este tipo de error y nos ofrece ayuda para poder solventar el conflicto, tal
como vemos en la Figura 2.13:
Figura 2.13. 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, por la sencilla razn de que los espacios de nombres de .NET
Framework suelen estar definidos usando palabras en ingls.
Accesibilidad
La accesibilidad es la caracterstica que podemos aplicar a cualquiera de los elementos
que definamos en nuestro cdigo. Dependiendo de la accesibilidad declarada
tendremos distintos tipos de accesos a esos elementos.
Los modificadores de accesibilidad que podemos aplicar a los tipos y elementos
definidos en nuestro cdigo pueden ser cualquiera de los mostrados en la siguiente
lista:
del tipo
Class
Module
Structure
Enum
Friend
Friend
Friend
Public
Friend
Interface
Friend
de las variables de
los
declaradas
con procedimientos
Dim
Private
Friend
Private
Friend
Public
Public
N.A.
N.A.
(los
miembros
siempre
son
pblicos)
N.A.
Public
(no
se
pueden (no
se
declarar variables) indicarlo)
permite
Module
Structure
Enum
Interface
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.A.
N.A.
Siempre son pblicos
Anidado de tipos
Tal como hemos comentado en el prrafo anterior, podemos declarar tipos dentro de
otros tipos, por tanto el mbito y accesibilidad de esos tipos dependen del mbito y
accesibilidad del tipo que los contiene. Por ejemplo, si declaramos una clase con
acceso Friend, cualquier tipo que esta clase contenga siempre estar supeditado al
mbito de esa clase, por tanto si declaramos otro tipo interno, aunque lo declaremos
como Public, nunca estar ms accesible que la clase contenedora, aunque en estos
casos no habr ningn tipo de confusin, ya que para acceder a los tipos declarados
dentro de otros tipos siempre tendremos que indicar la clase que los contiene.
En el siguiente cdigo podemos ver cmo declarar dos clases "anidadas". Tal como
podemos comprobar, para acceder a la clase Salario debemos indicar la clase Cliente,
ya que la nica forma de acceder a una clase anidada es mediante la clase
contenedora.
Friend Class Cliente
Public Nombre As String
Namespace Dos
Public Class Clase2
Public Nombre As String
Sub Main()
Dim c1 As New Uno.Clase1
c1.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.
Nota:
En el mismo proyecto podemos tener ms de una declaracin de un
espacio de nombres con el mismo nombre, en estos casos el compilador
lo tomar como si todas las clases definidas estuvieran dentro del mismo
espacio de nombres, aunque estos estn definidos en ficheros diferentes.
De esta forma podemos usar el "alias" vb para acceder a las clases y dems tipos
definidos
en
ese
espacio
de
nombres.
En las figuras 1.14 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.
Propiedades
Las propiedades son los miembros de los tipos que nos permiten acceder a los datos
que dicho tipo manipula. Normalmente una propiedad est relacionada con un campo,
de forma que el campo sea el que realmente contenga el valor y la propiedad
simplemente sea una especie de mtodo a travs del cual podemos acceder a ese
valor.
Debido a que el uso de las propiedades realmente nos permite acceder a los valores
de una clase (o tipo), se suelen confundir los campos con las propiedades. De hecho
en VBScript/VB6 si definimos una variable pblica, sta se convierte en una propiedad
de la clase. En Visual Basic 2005 casi ocurre lo mismo, pero realmente un campo (o
variable) pblico no es una propiedad, al menos en el sentido de que el propio .NET
Framework no lo interpreta como tal, aunque en la prctica nos puede parecer que es
as, ya que se utilizan de la misma forma. Pero no debemos dejarnos llevar por la
comodidad y si no queremos perder funcionalidad, debemos diferenciar en nuestro
cdigo las propiedades de los campos.
Lo primero que debemos tener presente es que gracias a esta diferenciacin que hace
.NET Framework, (realmente VBScript/VB6 tambin la hace), podemos poner en
prctica una de las caractersticas de la programacin orientada a objetos: la
encapsulacin, de forma, que la manipulacin de los datos que una clase contiene
siempre se deben hacer de forma "interna" o privada a la clase, dejando a las
propiedades la posibilidad de que externamente se manipulen, de forma controlada,
esos datos. De esta forma tendremos mayor control sobre cmo se acceden o se
asignan los valores a esos datos, ya que al definir una propiedad, tal como hemos
comentado, realmente estamos definiendo un procedimiento con el cual podemos
controlar
cmo
se
acceden
a
esos
datos.
Este concepto no ha cambiado, al menos en el fondo, con respecto a como lo
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 cdigo, el bloque Get que es el
que se usa cuando queremos acceder al valor de la propiedad, por tanto devolvemos
el valor del campo privado usado para almacenar ese dato. El bloque Set es el usado
cuando asignamos un valor a la propiedad, este bloque tiene definido un parmetro
(value) que representa al valor que queremos asignar a 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, esta forma de definir las propiedades no se diferencia demasiado a como lo
hacemos en VBScript/VB6, y una vez que nos acostumbremos lo veremos como una
forma ms "compacta" de hacerlo.
Propiedades de solo lectura
En ciertas ocasiones nos puede resultar interesante que una propiedad sea de solo
lectura, de forma que el valor que representa no pueda ser cambiado.
En VBScript/VB6 para definir una propiedad de solo lectura bastaba con definir solo la
parte Get de la propiedad., En Visual Basic 2005 tambin se hace de esa forma, pero
debemos indicar expresamente que esa es nuestra intencin. Por tanto no solo
basta con definir solo el bloque Get, sino que debemos usar el modificador ReadOnly
para que el compilador de Visual Basic 2005 acepte la declaracin:
Public ReadOnly Property Hoy() As Date
Get
Return Date.Now
End Get
End Property
End Property
End Class
Para hacer que el bloque Set sea privado, lo indicamos con el modificador de
accesibilidad Private, al no indicar ningn modificador en el bloque Get, ste ser el
mismo que el de la propiedad.
En VBScript/VB6 podemos hacer esto mismo definiendo como pblico la declaracin
de Property Get y como privado la de la asignacin: Property Let.
Nota:
El nivel de accesibilidad de los bloques Get o Set debe ser igual o inferior
que el de la propiedad, por tanto si la propiedad la declaramos como
Private, no podemos definir como pblico los bloques Get o Set.
Propiedades predeterminadas
Una cosa que echamos en falta en Visual Basic 2005 son las propiedades
predeterminadas. Aunque existen no son exactamente igual que en VB6. En VB6
podemos definir como propiedad predeterminada cualquiera de las propiedades de la
clase, aunque la forma de hacerlo es bastante "rebuscada" y poco intuitiva. Al menos
podemos
definir
como
predeterminada
la
que
ms
nos
interese.
En Visual Basic 2005 no podemos definir como predeterminada cualquier propiedad,
ya que debido a como se realizan las asignaciones de objetos en .NET (sin necesidad
de usar Set), siempre debemos indicar la propiedad a la que queremos asignar el
valor, porque en caso de que no se indique ninguna, el compilador interpretar que lo
que queremos asignar es un objeto y no un valor a una propiedad.
Para evitar conflictos o tener que usar alguna instruccin "extra" para que se sepa si
lo que queremos asignar es un valor o un objeto, en Visual Basic 2005 las
propiedades predeterminadas siempre deben ser parametrizadas, es decir, tener
como
mnimo
un
parmetro.
Para indicar que una propiedad es la propiedad por defecto lo debemos hacer usando
la instruccin Default:
Default Public ReadOnly Property Item(ByVal index As Integer) As
Empleado
Get
' ...
End Get
End Property
Como vemos en este ejemplo, una propiedad por defecto puede ser de solo lectura y
tambin de solo escritura o de lectura/escritura.
Para usar esta propiedad, al ser la propiedad por defecto, no es necesario indicar el
nombre de la propiedad, aunque si as lo deseamos podemos indicarla, aunque en
este caso no tendra mucha utilidad el haberla definido como propiedad por defecto:
Dim e As New Empleado
Dim e1 As Empleado = e(2)
' Tambin podemos usarla indicando el nombre de la propiedad:
Dim e2 As Empleado = e.Item(2)
Incluso como vemos en este cdigo una de las sobrecargas puede ser de solo lectura
y la otra de lectura/escritura. Lo que realmente importa es que el nmero o tipo de
parmetros de cada sobrecarga sea diferente.
Las propiedades predeterminadas tienen sentido en Visual Basic 2005 cuando
queremos que su uso sea parecido al de un array. Por tanto es habitual que las clases
de tipo coleccin sean las ms indicadas para definir propiedades por defecto. Aunque
no siempre el valor devuelto debe ser un elemento de una coleccin o array, ya que
podemos usar las propiedades predeterminadas para acceder a los miembros de una
clase "normal", de forma que se devuelva un valor segn el parmetro indicado, esto
nos permitira, por ejemplo, acceder a los miembros de la clase desde un bucle For. Si
definimos una propiedad predeterminada como en el siguiente cdigo:
Public Class Articulo
Public Descripcin 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 Descripcin
Case 1
Return PrecioVenta.ToString
Case 2
Return Existencias.ToString
Case Else
Return ""
End Select
End Get
End Property
End Class
Console.WriteLine( art(i) )
Next
Resumiendo:
Las propiedades predeterminadas en Visual Basic 2005 siempre deben tener un
parmetro, para que su uso se asemeje a un array, es decir, se use como indizador
de la clase. Por convencin, cuando se usan como indizador, el nombre de la
propiedad predeterminada suele ser Item.
Interfaces
Las interfaces son un elemento bastante importante en .NET Framework, ya que de
hecho se utiliza con bastante frecuencia. En esta leccin veremos que son las
interfaces y como utilizarlas en nuestros proyectos. Tambin veremos que papel
juegan en .NET y cmo aplicar algunas de las definidas en la biblioteca base.
Qu es una interfaz?
Las interfaces son una forma especial de una clase, aunque la diferencia principal con
las clases es que las interfaces no contienen cdigo ejecutable, solo definen los
miembros.
Para entenderlo mejor, veamos las interfaces desde el punto de vista de Visual Basic
6.0.
En Visual Basic 6.0, cuando definimos una clase, realmente estamos haciendo dos
cosas:
1- Definiendo una interfaz con cada uno de los miembros que la clase contiene: mtodos,
propiedades, eventos, etc.
2- Definiendo el cdigo a utilizar por cada uno de esos miembros.
Desde ese punto de vista, podemos decir que una interfaz define cada uno de los
miembros de una clase, es decir, que tipo de mtodo es, si los mtodos tienen
parmetros, cuantos y de que tipos son, que propiedades o eventos define la clase,
etc.
Por tanto, podemos decir que la interfaz de una clase indica los miembros que dicha
clase expone, y como hemos indicado anteriormente, cuando en VB6 definimos una
clase, tambin estamos definiendo una interfaz, de hecho en Visual Basic 6.0 no hay
forma de definir interfaces como algo independiente de una clase; cuando queremos
definir una interfaz en VB6, lo ms que podemos hacer es definir una clase sin cdigo
ejecutable.
Pero Visual Basic 2005, va an ms lejos, ya que las interfaces las definimos de forma
independiente de las clases. Es ms, cuando definimos una clase NO estamos
definiendo una interfaz.
Para definir una interfaz en VB2005 tenemos que usar la instruccin Interface seguida
del nombre y terminar la declaracin con End Interface:
Public Interface IAnimal
'...
End Interface
Nota:
Segn las indicaciones de nomenclatura de .NET Framework, se
recomienda que todas las interfaces empiecen con una I mayscula
seguida del nombre al que hacer referencia la interfaz.
Y como comentbamos, cualquier clase que implemente una interfaz debe definir
cada uno de los miembros de esa interfaz, por eso es el propio Visual Basic el
encargado de crear automticamente los mtodos y propiedades que la interfaz
implementa, aunque solo inserta el "prototipo" de cada uno de esos miembros,
dejando para nosotros el trabajo de escribir el cdigo.
Usando la definicin de la interfaz IPrueba que vimos antes, el cdigo que aadir
VB ser el siguiente:
Public Class Prueba
Implements IPrueba
End Sub
End Get
Set(ByVal value As String)
End Set
End Property
End Function
End Class
End Sub
prueba1.Mostrar()
O bien de forma indirecta, por medio de una variable del mismo tipo que la interfaz:
Dim prueba1 As New Prueba
Dim interfaz1 As IPrueba
interfaz1 = prueba1
interfaz1.Mostrar()
Qu ha ocurre aqu?
Como ya comentamos anteriormente, cuando asignamos variables por referencia,
realmente lo que asignamos son referencias a los objetos creados en la memoria, por
tanto la variable interfaz1 est haciendo referencia al mismo objeto que prueba1,
aunque esa variable solo tendr acceso a los miembros de la clase Prueba que
conoce, es decir, los miembros definidos en IPrueba.
Si la clase define otros miembros que no estn en la interfaz, la variable interfaz1 no
podr acceder a ellos.
Saber si un objeto implementa una interfaz
Si las interfaces sirven para acceder de forma annima a los mtodos de un objeto, es
normal que en Visual Basic tengamos algn mecanismo para descubrir si un objeto
implementa una interfaz.
Para realizar esta comprobacin podemos usar en una expresin If/Then la instruccin
TypeOf... Is, de forma que si la variable indicada despus de TypeOf contiene el tipo
especificado despus de Is, la condicin se cumple:
If TypeOf prueba1 Is IPrueba Then
interfaz1 = prueba1
interfaz1.Mostrar()
End If
End Sub
Aunque si ambos mtodos hacen lo mismo, en este ejemplo mostrar algo, podramos
hacer que el mismo mtodo de la clase sirva para implementar el de las dos
interfaces:
Public Sub Mostrar() Implements IPrueba.Mostrar, IMostrar.Mostrar
End Sub
End Sub
End Get
Set(ByVal value As String)
End Set
End Property
End Function
End Class
Figura 2.02.16 IntelliSense solo muestra los mtodos que mejor se adecuan
a la declaracin
Un ejemplo prctico usando una interfaz de .NET
Tal como comentamos al principio, el propio .NET est "plagado" de interfaces, cada
una de ellas tiene un fin concreto, por ejemplo, si queremos definir una clase que
pueda ser clasificada por el propio .NET, esa clase debe implementar la interfaz
IComparable, ya que el mtodo Sort, (de la clase que contiene los elementos del tipo
definido por nosotros), que es el encargado de clasificar los elementos, har una
llamada al mtodo IComparable.CompareTo de cada uno de los objetos que queremos
clasificar, por tanto, si la clase no ha definido esa interfaz, no podremos clasificar los
elementos que contenga.
En el siguiente cdigo tenemos la definicin de una clase llamada Empleado que
implementa la interfaz IComparable y en el mtodo CompareTo hace la comprobacin
de que objeto es mayor o menor, si el de la propia clase o el indicado en el parmetro
de esa funcin:
Public Class Empleado
Implements IComparable
Console.WriteLine(e1.Nombre)
Next
Ver
video
1
de
esta
leccin
(Interfaces
Ver
video
2
de
esta
leccin
(Interfaces
Ver video 3 de esta leccin (Interfaces 3 y herencia)
1)
2)
Introduccin
Es indiscutible que por mucho que nos lo propongamos, nuestras aplicaciones no
estarn libres de errores, y no nos referimos a errores sintcticos, ya que,
afortunadamente, el IDE (Integrated Development Envirnment, entorno de desarrollo
integrado) de Visual Studio 2005 nos avisar de cualquier error sintctico e incluso de
cualquier asignacin no vlida (al menos si tenemos activado Option Strict On). Pero
de lo que no nos avisar, como es lgico, ser de los errores que se produzcan en
tiempo de ejecucin. Para estos casos, Visual Basic pone a nuestra disposicin el
manejo de excepciones. Veamos pues cmo utilizarlo, sobre todo el sistema de
excepciones estructuradas que es el recomendable para cualquier desarrollo con .NET
Framework.
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
Evaluacin condicional en un bloque Catch
Bloque Finally
o Captura de errores no controlados
Manejo de excepciones
En Visual Basic 2005 el tratamiento de errores (excepciones) ha cambiado con
respecto a como lo hacemos en VBScript/VB6, ahora podemos usar un tratamiento de
excepciones estructurado, de esta forma podemos detectar los errores que se
produzcan
en
nuestras
aplicaciones
de
una
forma
ms
"ordenada".
En VBScript/VB6 la nica forma de detectar errores es usando On Error. Esta forma
no estructurada de tratar los errores se sigue soportando en Visual Basic 2005, pero a
todas luces no es la forma recomendada. Debemos adaptar nuestra mente al formato
estructurado, ya que en un principio nos parecer que no es tan efectivo como On
Error.
En esta leccin veremos cmo tratar los errores de forma estructurada, ya que el
"viejo" On Error sigue funcionando de la misma forma que en VBScript/VB6.
Manejo de excepciones no estructuradas
Como hemos comentado, en Visual Basic 2005 tambin podemos usar el "viejo"
sistema de tratamientos de errores, es decir, el "clsico" On Error... que ahora se
llama tratamiento de errores no estructurado. La forma de utilizar On Error es la
misma que en VBScropt/VB6, por tanto no vamos a entrar en detalles de cmo usar
esta forma de interceptar errores, solo aclarar un par de cosas que debemos tener en
cuenta:
La primera es: intentar no usar esta forma de detectar errores, es preferible, aunque
al principio cueste adaptarse, utilizar los errores estructurados.
La segunda es que no podemos usar los dos sistemas al mismo tiempo, por lo menos
en un mismo mtodo o propiedad, o utilizamos On Error o utilizamos Try/Catch. De
todas formas, si utilizamos el IDE (entorno integrado) de Visual Basic, ser el propio
compilador el que nos avise cuando mezclemos las dos formas de detectar los
errores.
Manejo de excepciones estructuradas
Las excepciones en Visual Basic 2005 las podemos controlar usando las instrucciones
Try / Catch / Finally. Estas instrucciones realmente son bloques de instrucciones, al
estilo de If / Else.
Cuando queramos controlar una parte del cdigo que puede producir un error lo
incluimos dentro del bloque Try. Si se produce un error, ste lo podemos detectar en
el bloque Catch. Por ltimo, independientemente de que se produzca o no una
excepcin, podemos ejecutar el cdigo que incluyamos en el bloque Finally, para
indicar el final del bloque de control de excepciones lo haremos con End Try.
Cuando creamos una estructura de control de excepciones no estamos obligados a
usar los tres bloques, aunque el primero: Try s es necesario, ya que es el que le
indica al compilador que tenemos intencin de controlar los errores que se produzcan.
Por tanto podemos crear un "manejador" de excepciones usando los tres bloques,
usando Try y Catch o usando Try y Finally.
Veamos ahora con ms detalle cada uno de estos bloques y que es lo que podemos
hacer en cada uno de ellos.
Bloque Try
En este bloque incluiremos el cdigo en el que queremos comprobar los errores.
El cdigo a usar ser un cdigo normal, es decir, no tenemos que hacer nada en
especial, ya que en el momento que se produzca el error se usar (si hay) el cdigo
del bloque Catch.
Bloque Catch
Si se produce una excepcin, sta la capturamos en un bloque Catch.
En el bloque Catch podemos indicar que tipo de excepcin queremos capturar, para
ello usaremos una variable de tipo Exception, la cual pude ser del tipo de error
especfico
que
queremos
controlar
o
de
un
tipo
genrico.
Por ejemplo, si sabemos que nuestro cdigo puede producir un error al trabajar con
ficheros, podemos usar un cdigo como este:
Try
' cdigo para trabajar con ficheros, etc.
Catch ex As System.IO.IOException
' el cdigo a ejecutar cuando se produzca ese error
End Try
Aunque si no vamos usar la variable indicada en el bloque Catch, pero queremos que
no se detenga la aplicacin cuando se produzca un error, podemos hacerlo de esta
forma:
Try
' cdigo que queremos controlar
Catch
' el cdigo a ejecutar cuando se produzca cualquier error
End Try
= x \ y
Bloque Finally
En este bloque podemos indicar las instrucciones que queremos que se ejecuten, se
produzca o no una excepcin. De esta forma nos aseguramos de que siempre se
ejecutar un cdigo, por ejemplo para liberar recursos, se haya producido un error o
no.
Nota:
Hay que tener en cuenta de que incluso si usamos Exit Try para salir del
bloque de control de errores, se ejecutar el cdigo indicado en el
bloque Finally.
esto es algo que no deberamos consentir. Siempre deberamos detectar todos los
errores que se produzcan en nuestras aplicaciones, pero a pesar de que lo
intentemos,
es
muy
probable
que
no siempre
podamos
conseguirlo.
Por suerte, en Visual Basic 2005 tenemos dos formas de interceptar los errores no
controlados:
el
la
al
lo
Este evento se "dispara" cuando se produce un error que no hemos interceptado, por
tanto podramos usarlo para prevenir que nuestra aplicacin se detenga o bien para
guardar en un fichero .log la causa de dicho error para posteriormente actualizar el
cdigo y prevenirlo. Ya que cuando se produce el evento UnhandledException,
podemos averiguar el error que se ha producido e incluso evitar que la aplicacin
finalice. Esa informacin la obtenemos mediante propiedades expuestas por el
segundo parmetro del evento, 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 aplicacin.
Nota:
Cuando ejecutamos una aplicacin desde el IDE (entorno de desarrollo),
los errores no controlados siempre se producen, independientemente de
que tengamos o no definida la captura de errores desde el evento
UnhandledException. Ese evento solo se producir cuando ejecutemos la
aplicacin fuera del IDE de Visual Basic.
Introduccin
La forma que tienen nuestras clases y estructuras de comunicar que algo est
ocurriendo, es por medio de eventos. Los eventos no les son desconocidos a los
desarrolladores de VB6, ya que tambin existen y se pueden definir en ese lenguaje.
En Visual Basic 2005 se siguen usando de la misma forma que en VB6, aunque
seguramente siempre que hemos ledo sobre el tema aparece la palabra delegado. Y
es que, aunque VB2005 nos oculte (o facilite) el trabajo con los eventos, stos
siempre estn relacionados con los delegados. En esta leccin veremos que son los
delegados y que relacin tienen con los eventos, tambin veremos que podemos tener
mayor control sobre cmo se interceptan los eventos e incluso cmo y cuando se
asocian los eventos en la aplicacin cliente, aunque primero empezaremos viendo
cmo declarar y utilizar eventos en nuestros tipos de datos.
Eventos y delegados
Eventos
o Interceptar los eventos de los controles de un formulario
Interceptar eventos en Visual Basic 6.0
Interceptar eventos en Visual Basic 2005
o Asociar un evento con un control
o Formas de asociar los eventos con un control
1- Asociar el evento manualmente por medio de Handles
2- Asociar el evento desde la ventana de cdigo
3- Asociar el evento desde el diseador de formularios
o Asociar varios eventos a un mismo procedimiento
Delegados
o Qu ocurre cuando se asigna y se produce un evento?
o Qu papel juegan los delegados en todo este proceso?
o Definicin "formal" de delegado
o Utilizar un delegado para acceder a un mtodo
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
cmo "lanzarlos", ya que la forma de interceptarlos en una aplicacin ha cambiado un
poco, pero como veremos, incluso puede ser ms fcil definir los mtodos o
procedimientos que utilizamos para interceptarlos.
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 sera una referencia al
control Button1), y el segundo normalmente contiene informacin sobre el evento que
se produce. Si el evento en cuestin no proporciona informacin extra, como es el
caso del evento Click, ese parmetro ser del tipo EventArgs. Sin embargo en otros
eventos el segundo argumento tendr informacin 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.03
seleccionado
Ventana de
propiedades
con
los
eventos
del
control
Handles
End Sub
Nota:
Usar WithEvents y Handles es la forma ms 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.
En este caso, el uso de AddressOf es una forma "fcil" que tiene Visual Basic 2005 de
asociar un procedimiento de evento con el evento. Aunque por detrs, (y sin que nos
enteremos), realmente lo que estamos usando es un constructor a un delegado.
La ventaja de usar esta forma de asociar eventos con el procedimiento, es que
podemos hacerlo con variables que no estn declaradas con WithEvents, realmente
esta sera la nica forma de asociar un procedimiento de evento con una variable que
no hemos declarado con WithEvents.
Delegados
Como hemos comentado anteriormente los eventos son acciones que una clase puede
producir cuando ocurre algo. De esta forma podemos notificar a las aplicaciones que
hayan decidido interceptar esos mensajes para que tomen las acciones que crean
conveniente.
Visual Basic 2005 esconde al desarrollador prcticamente todo lo que ocurre cada vez
que decidimos interceptar un evento. Nosotros solo vemos una pequea parte de todo
el trabajo que en realidad se produce, y el que no lo veamos no quiere decir que no
est ocurriendo nada. Tambin es cierto que no debe preocuparnos demasiado si no
sabemos lo que est pasando, pero si tenemos conciencia de que es lo que ocurre,
puede que nos ayude a comprender mejor todo lo relacionado con los eventos.
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 mtodo que intercepta un evento y cmo hace el Visual Basic para comunicarse
con el receptor de dicho evento.
1. Cuando Visual Basic se encuentra con el cdigo que le indica que un mtodo
debe interceptar un evento, ya sea mediante AddHandler o mediante el uso de
Handles, lo que hace es aadir la direccin de memoria de ese mtodo a una
especie
de
array.
En la Figura 2.04.05 podemos ver un diagrama en el que un mismo evento lo
interceptan tres clientes, cuando decimos que un cliente intercepta un evento,
realmente nos referimos a que hay un mtodo que lo intercepta y el evento
realmente guarda la direccin de memoria de ese mtodo.
Es decir, el mtodo que intercepte este evento debe ser del tipo Sub y no recibir
ningn parmetro.
Si nuestro evento utiliza, por ejemplo, un parmetro de tipo String, la definicin del
delegado quedara de la siguiente forma:
Como podemos comprobar, 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.
Declaremos como declaremos los eventos, los podemos seguir usando de la misma
forma, tanto para producirlo mediante RaiseEvent como para definir el mtodo que
reciba ese evento.
Utilizar un delegado para acceder a un mtodo
Ahora veamos brevemente cmo usar los delegados, en este caso sin necesidad de
que defina un evento.
Como hemos comentado, un delegado realmente es una clase que puede contener
una referencia a un mtodo, adems define el prototipo del mtodo que podemos
usar como referencia. Sabiendo esto, podemos declarar una variable del tipo del
delegado y por medio de esa variable acceder al mtodo que indiquemos, siempre
que ese mtodo tenga la misma "firma" que el delegado. Parece complicado verdad?
Y no solo lo parece, es que realmente lo es. Comprobemos esta "complicacin" por
medio de un ejemplo. En este cdigo, que iremos mostrando poco a poco, vamos a
definir un delegado, un mtodo con la misma firma para que podamos usarlo desde
una variable definida con el mismo tipo del delegado.
Definimos un delegado de tipo Sub que recibe un valor de tipo cadena:
Delegate Sub Saludo(ByVal nombre As String)
ese
mtodo.
Pero esto no funciona, entre otras cosas, porque hemos comentado que un delegado
contiene (o puede contener) una referencia a un mtodo, y "Pepe" no es un mtodo
ni una referencia a un mtodo.
Segundo
intento:
Por lgica y, sobre todo, por sentido comn, mxime cuando hemos declarado un
mtodo con la misma "firma" que el delegado, deberamos pensar que lo que
debemos pasar a esa variable es el mtodo, ya que un delegado puede contener una
referencia a un mtodo.
saludando = New Saludo(mostrarSaludo)
Pues tampoco.
Para usar un delegado debemos indicarle la direccin de memoria de un mtodo, a
eso se refiere la definicin que vimos antes, una referencia a un mtodo no es ni ms
ni menos que la direccin de memoria de ese mtodo. Y en Visual Basic, desde la
versin 5.0, tenemos una instruccin para obtener la direccin de memoria de
cualquier mtodo: AddressOf.
Por tanto, para indicarle al delegado dnde est ese mtodo tendremos que usar
cualquiera de estas dos formas:
saludando = New Saludo(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 mtodo que tenga la misma firma
que la definicin del delegado, en nuestro caso, que sea de tipo Sub y reciba una
cadena.
Si queremos, tambin podemos declarar la variable y asignarle directamente el
mtodo al que har referencia:
Dim saludando As New Saludo(AddressOf mostrarSaludo)
End RaiseEvent
End Event
Como podemos apreciar, debemos definir un delegado con la "firma" del mtodo a
usar con el evento. Despus definimos el evento por medio de las instrucciones
Custom Event, utilizando el mismo formato que al definir un evento con un delegado.
Dentro de la definicin tenemos tres bloques, cada uno de los cuales realizar la
accin que ya hemos indicado en la lista numerada.
Nota:
Los eventos Custom Event solamente podemos definirlos e interceptarlos
en el mismo ensamblado.
Introduccin
Esta es la definicin que nos da la ayuda de Visual Basic sobre lo que es un atributo.
"Los atributos son etiquetas descriptivas que proporcionan informacin adicional
sobre elementos de programacin como tipos, campos, mtodos y propiedades.
Otras aplicaciones, como el compilador de Visual Basic, pueden hacer referencia
a la informacin adicional en atributos para determinar cmo pueden utilizarse
estos elementos."
En esta leccin veremos algunos ejemplos de cmo usarlos en nuestras propias
aplicaciones y, aunque sea de forma general, cmo usar y aplicar algunos de los
atributos definidos en el propio .NET Framework, al menos los que ms directamente
nos pueden interesar a los desarrolladores de Visual Basic.
Atributos
Atributos
o Tipos de atributos que podemos usar en una aplicacin
Atributos globales a la aplicacin
Atributos particulares a las clases o miembros de las clases
o Atributos personalizados
Acceder a los atributos personalizados en tiempo de ejecucin
o Atributos especficos de Visual Basic
o Marcar ciertos miembros de una clase como obsoletos
Atributos
Como hemos comentado en la introduccin, los atributos son etiquetas que podemos
aplicar a nuestro cdigo para que el compilador y, por extensin, el propio .NET
Framework los pueda usar para realizar ciertas tareas o para obtener informacin
extra sobre nuestro cdigo.
De hecho en cualquier aplicacin que creemos con Visual Basic 2005 estaremos
tratando con atributos, aunque nosotros no nos enteremos, ya que el propio
compilador los utiliza para generar los metadatos del ensamblado, es decir, la
informacin sobre todo lo que contiene el ejecutable o librera que hemos creado con
Visual Basic 2005.
Por otra parte, el uso de los atributos nos sirve para ofrecer cierta funcionalidad extra
a nuestro cdigo, por ejemplo, cuando creamos nuestros propios controles, mediante
atributos podemos indicarle al diseador de formularios si debe mostrar ciertos
miembros del control en la ventana de propiedades, etc.
Tipos de atributos que podemos usar en una aplicacin
Como hemos comentado, existen atributos que son globales a toda la aplicacin y
otros que podremos aplicar a elementos particulares, como una clase o un mtodo.
Nota:
La palabra o instruccin Assembly: lo que indica es que el atributo tiene
un mbito de ensamblado.
Estos los vamos a usar poco o nada en una aplicacin Web.
Atributos personalizados
Adems de los atributos que ya estn predefinidos en el propio .NET o Visual Basic,
podemos crear nuestros propios atributos, de forma que en tiempo de ejecucin
podamos acceder a ellos mediante las clases del espacio de nombres Reflection. Este
tema se sale un poco de la intencin de este curso, pero simplemente indicaremos
que los atributos personalizados son clases que se derivan de la clase
System.Attribute y que podemos definir las propiedades que creamos conveniente
utilizar en ese atributo para indicar cierta informacin a la que podemos acceder en
tiempo de ejecucin.
En el siguiente cdigo tenemos la declaracin de una clase que se utilizar como
atributo personalizado, notamos que, por definicin las clases para usarlas como
atributos deben terminar con la palabra Attribute despus del nombre "real" de la
clase, que como veremos en el cdigo que utiliza ese atributo, esa "extensin" al
nombre de la clase no se utiliza.
Veamos primero el cdigo del atributo personalizado:
<AttributeUsage(AttributeTargets.All)> _
Public Class AutorAttribute
Inherits System.Attribute
'
End Property
End Class
Nota:
Cuando utilizamos el atributo, en el constructor que de forma
predeterminada crea Visual Basic, los parmetros se indican por el orden
alfabtico de las propiedades, pero que nosotros podemos alterar
usando directamente los nombres de las propiedades, tal como podemos
ver en el cdigo de ejemplo anterior.
End Sub
COMClassAttribute
o Este atributo se utiliza para simplificar la creacin de componentes COM
desde Visual Basic.
VBFixedStringAttribute
o Este atributo se utiliza para crear cadenas de longitud fija en Visual Basic
2005. Habitualmente se aplica a campos o miembros de una estructura,
principalmente cuando queremos acceder al API de Windows o cuando
queremos usar esa estructura para guardar informacin en un fichero,
pero utilizando una cantidad fija de caracteres.
VBFixedArrayAttribute
o Este atributo, al igual que el anterior, lo podremos usar para declarar
arrays de tamao fijo, al menos si las declaramos en una estructura, ya
que por defecto, los arrays de Visual Basic son de tamao variable.
Contenido
En este mdulo aprenderemos todo lo fundamental acerca del desarrollo de
aplicaciones Web con ASP.NET 2.0, y en concreto mediante el uso de Visual Studio
2005.
Al terminar el mdulo estars preparado para trabajar en el entorno y crear
aplicaciones Web sin enlace a datos (esto se aprender ms adelante, en el mdulo
correspondiente).
Ms cdigo
Siguiendo con el ejemplo vamos a aadir un poco ms de cdigo para comprobar
hasta que punto son compatibles las pginas ASPX con el cdigo ASP.
Si lo modificamos para que tenga el siguiente aspecto:
rea de documentos
Figura 3.1.9.- Aspecto del ejemplo tras haber aadido los controles.
Nota:
Si no tiene claro cmo hacerlo vea el primer vdeo de esta leccin al pie
de este documento en donde se desarrolla el ejemplo completo.
Respondiendo al evento del botn
Para saludar al usuario con el nombre que introduzca en el campo de texto debemos
responder a la pulsacin del botn. En ASP clsico tendramos que enviar un
formulario a otra pgina (o a la misma) y ver qu valores no es estn pasando para
actuar en consecuencia. En ASP.NET esto no es necesario ya que trabajaremos segn
el clsico paradigma orientado eventos, respondiendo a las acciones del usuario.
En este caso debemos interceptar la pulsacin del botn por parte del usuario
verdad?. Pues lo nico que tendremos que hacer es escribir un manejador para el
evento Click del botn, algo que resultar familiar e intuitivo a los programadores de
VB6. Para ello haga doble-clic sobre el botn en el diseador. Esto har que se abra el
editor de cdigo y que automticamente aparezca un manejador de eventos para el
evento Click, que es el predeterminado de los botones:
Controles HTML
o Controles HTML
o Jerarqua de controles HTML
Controles Web
o Controles Web
o Adaptacin al navegador
o Jerarqua de controles Web
o Controles propios
Controles de validacin
o Controles Web de validacin
o Uso de los controles de validacin
o Validadores personalizados
o Colocar el foco en el error
un
mismo
calendario
en
un
Controles Web: son controles como los que hemos visto hasta ahora y
equiparables en todos sus aspectos a los controles nativos de ASP.NET 2.0.
Controles de usuario: permiten la reutilizacin de partes completas de la
interfaz de usuario y de la lgica asociada a sta, aunque el soporte para
configurarlos en tiempo de diseo es mucho ms reducido que en el caso de los
anteriores. Sin embargo son muy fciles de crear y ofrecen un mtodo sencillo
de encapsular funcionalidades que incluyan interfaz de usuario.
La creacin de controles Web (primer tipo) es una cuestin compleja que se sale del
mbito de este curso, por lo que no los estudiaremos. Sin embargo en la siguiente
leccin veremos la forma de crear nuestros propios controles de usuario.
Investigue por su cuenta la funcionalidad de algunos de los controles disponibles en
ASP.NET. Es la mejor forma de aprender. Descubrir que la mayora son muy fciles
de utilizar y sus propiedades y mtodos son de uso sencillo. Deje de momento los
enlazados a datos pues sern objeto de un mdulo posterior y suelen tener ms
complicacin.
Utilidad
Verifica que el control asociado no
se encuentra vaco.
RangeValidator
Genera un mensaje de error
cuando el contenido de su control
asociado est fuera de un rango
de valores dado. Permite validar
intervalos numricos (enteros o
decimales o monedas), fechas y
cadenas de texto.
RegularExpressionValidator Compara un texto introducido por
el usuario con una expresin
regular.
CompareValidator
Permite
comparar
el
valor
introducido por el usuario con una
constante o con el valor de la
propiedad de otro control.
CustomValidator
Se usa para implementar lgica
de validacin propia tanto en el
cliente como en el servidor.
Tabla 3.2.1.- Controles de validacin y su utilidad.
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.
No todos los controles se pueden validar con los controles de validacin. De hecho
slo un pequeo subconjunto de todos los controles Web son adecuados para un uso
conjunto. En cualquier caso los incluidos cubren la mayor parte de las necesidades
normales de introduccin de datos, y son los siguientes:
Control
Tipo
HtmlinputText Entrada de texto
HtmlTextArea Entrada de texto
TextBox
Entrada de texto
HtmlSelect
Lista de seleccin
ListBox
Lista de seleccin
DropDownList Lista de seleccin
RadioButtonList Botones de seleccin
HtmlInputFile Envo de archivos
Propiedad
Value
Value
Text
Value
SelectedItem.Value
SelectedItem.Value
SelectedItem.Value
Value
Sabiendo todo esto es fcil utilizar cualquiera de los controles de este tipo. Consulte el
vdeo de esta leccin para ver una prctica de uso.
Validadores personalizados
Tal vez el validador que necesite ms explicacin es el CustomValidator. Como su
propio nombre indica se usa para crear normas de validacin propias que no se
adapten a ninguna de las contempladas con los dems controles. Para conseguirlo se
definen funciones de validacin en el cliente y en el servidor.
Las funciones de validacin en el cliente se escriben en JavaScript o en VBScript y
se asocian con el control mediante la propiedad ClientValidationFunction. la
funcin definida puede tener cualquier nombre pero debe tomar dos argumentos, as:
function miValidador(origen, argumentos)
{
}
Controles de usuario
Como ya hemos adelantado en la leccin anterior, aparte de la compleja creacin de
controles Web personalizados del estilo de los que vienen con ASP.NET, existe una
forma rpida y sencilla de reutilizar partes completas de funcionalidad e interfaz de
usuario. Para ello no es necesario tener profundos conocimientos de la plataforma
.NET. Ni siquiera hacen falta conocimientos de HTML. Se trata de los controles de
usuario.
En esta leccin veremos qu son, cmo se crean y cmo se utilizan.
Controles de usuario
o Introduccin
o Definicin de la funcionalidad pblica
o Uso de los controles de usuario
o Carga dinmica de controles de usuario
Controles de usuario
Los controles de usuario son tan fciles de crear que, de hecho, ya conoce casi todo lo
que necesita para construirlos. Se crean exactamente igual que los formularios Web y
disponen de un diseador visual idntico que permite arrastrar otros controles sobre
su superficie. De hecho cualquier formulario Web (pgina ASPX) puede transformarse
directamente en un control reutilizable con slo unos pocos cambios de sintaxis.
Para aadir un nuevo control de usuario pulse con el botn secundario sobre el nodo
raz del proyecto en el explorador de soluciones y escoja la opcin "Agregar
elemento...". En el dilogo que aparece (ya sobradamente conocido) seleccione el
icono correspondiente a Control de usuario Web, como se ilustra en la siguiente
figura:
Por supuesto los controles que coloquemos en la superficie del control se vern
adecuadamente en la pgina que lo contenga y se comportarn del modo esperado,
esto es, recibiendo eventos, conservando su estado en el ViewState, etc...
Uso de los controles de usuario
Ahora que ya sabemos crear controles de usuario veamos la forma de usarlos desde
los formularios Web.
El modo ms sencillo de incluir un control de usuario en una pgina ASPX es
simplemente arrastrndolo desde el explorador de proyectos sobre su superficie de
diseo. Esto har que se visualice el control completo dentro de la pgina:
Las propiedades que hayamos definido para la clase Micontrol se pueden establecer
mediante atributos (al igual que ID en la lnea anterior, por ejemplo) siempre que se
trate de tipos simples.
Podemos modificar la directiva Register para incluir un prefijo que nos guste ms o
sea ms descriptivo que el que Visual Studio ha puesto por defecto.
Carga dinmica de controles de usuario
Otro modo de hacer uso de los controles de usuario es cargarlos dinmicamente
segn los necesitemos. El mtodo LoadControl de la clase Page o del formulario de
la pgina es el que nos va a ayudar a conseguirlo. Slo hay que pasarle como
argumento el nombre del archivo ASCX que contiene la definicin del control de
usuario, de modo similar a este:
Dim c As Control
c = Me.LoadControl("Micontrol.ascx")
Me.Form.Controls.Add(c)
En lugar de usar un tipo genrico (Control) como en este fragmento tambin podemos
usarlo como el verdadero tipo del control y as llamar a sus mtodos y propiedades
antes de aadirlo al formulario:
Dim c As Control
Dim miC As Micontrol
c = Me.LoadControl("Micontrol.ascx")
miC = CType(c, Micontrol)
miC.ValorInicial = "Bienvenido a esta pgina"
Me.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 pgina.
actual, debe solicitar una nueva. Esto provoca una nueva peticin de pgina desde el
navegador por lo que no es la forma de navegacin 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 pgina de un usuario o
para redirigir al final de un proceso ejecutado en el servidor.
Envo de datos entre pginas
Como hemos visto el comportamiento normal durante la pulsacin de un botn u otro
evento de controles servidor es el de realizar un post-back a la pgina actual. Sin
embargo puede haber ocasiones en las que, por el motivo que sea, se necesita
realizar ese envo de datos a otra pgina diferente, pero eso s, conservando el acceso
a todos los controles y datos de la pgina original (que como sabemos estn
contenidos en el ViewState).
ASP.NET 2.0 ha aadido una nueva funcionalidad denominada Cross Page Posting,
que permite precisamente esto. Para conseguirlo lo nico que hay que hacer es
ajustar la propiedad PostBackUrl del control cuyos eventos queremos gestionar
desde otra pgina asignndole la ruta virtual de sta ltima.
Los datos se reciben en la otra pgina pero todava tenemos acceso a los datos de la
pgina original a travs de la propiedad PreviousPage de la nueva. Se trata de un
objeto Page reconstruido a partir del ViewState recibido. Si la usamos as, de modo
genrico, tendremos que utilizar el mtodo FindControl de la clase Page para
localizar cualquier control que hubiese en la pgina original. Por supuesto si ambas
pginas pertenecen al mismo espacio de nombres (o lo hemos declarado) podemos
forzar el uso de la pgina como la clase original de sta usando CType y acceder
directamente a sus mtodos, propiedades y controles.
Tambin es posible determinar desde una pgina si los datos que est recibiendo son
de su propio Post-back o pertenece a otra pgina mediante la propiedad
IsCrossPagePostBack, que es muy similar a la propiedad IsPostBack que ya hemos
estudiado.
Esta tcnica es de un uso poco frecuente pero se trata de una novedad poco conocida
que me ha parecido interesante incluir aqu.
Transferir el control entre pginas
A veces puede ser til procesar el cdigo de una pgina y justo despus transferir el
control a otra pgina ejecutando tambin su cdigo. El mtodo Transfer de la clase
HttpServer ejecuta dinmicamente el cdigo de una pgina desde otra cualquiera.
La forma de hacerlo es la siguiente:
Server.Transfer("otrapagina.aspx")
Este mtodo es anlogo al del mismo nombre en ASP clsico, si bien en ASP.NET su
utilidad es menor puesto que, como veremos, existen maneras mucho mejores y ms
recomendables de reutilizar cdigo de uso comn en las pginas.
Reutilizacin de cdigo en una aplicacin
A menudo, al escribir una aplicacin, tenemos necesidades similares en diversas
partes de sta. Por ello sera absurdo escribir una y otra vez el mismo cdigo dentro
de los manejadores, al cargar una pgina y dems eventos. Lo mejor es encapsular el
cdigo en diversos mtodos y llamar a stos cuando sea necesario. Todo esto sonar
de perogrullo a cualquier programador experimentado.
En ASP clsico, por ejemplo, se solan agrupar las funciones de uso comn dentro de
archivos de inclusin que luego se utilizaban en las diferentes pginas gracias a una
directiva <!-- #include -->. Si bien esto constitua una manera bsica de reutilizar
cdigo no ofreca la flexibilidad de un lenguaje capaz de crear bibliotecas de objetos y
mtodos.
En .NET es posible crear nuevas clases que encapsulen funcionalidades comunes y
que sean reutilizables en cualquier punto de la aplicacin. En ASP.NET 2.0 existen una
serie de carpetas con nombres especiales que cuelgan de la carpeta principal de la
aplicacin y que llevan asociado un comportamiento especial. Una de estas carpetas
es 'App_Code'. Bsicamente, todo el cdigo que se coloque bajo esta carpeta
se compila de manera automtica.
Tal y como hemos estudiado anteriormente, cuando se solicita una pgina sta se
compila de manera automtica junto con su archivo de "code-beside" de forma que, a
medida que se accede a las diferentes partes de una aplicacin se va compilando por
completo. Dadas las caractersticas de Visual Studio, el cdigo residente en archivos
que no sean pginas o clases parciales de "code-beside" no se compila ya que jams
navegamos por l ni se referencia desde otras pginas. La excepcin a esta regla es el
cdigo que coloquemos en la carpeta App_Code que se compila automticamente al
comenzar la aplicacin.
Por ello, una buena forma de reutilizar cdigo entre pginas es agregar clases
especializadas a la carpeta App_Code. De hecho si presionamos con el botn
secundario sobre el proyecto en el explorador de soluciones y agregamos un nuevo
elemento de tipo Clase se nos mostrar una advertencia diciendo, grosso modo, que
debemos aadirla a App_Code si queremos que funcione. Incluso se crea
automticamente la carpeta si no lo hemos hecho ya con anterioridad:
por ejemplo) o DataSets. Estos ltimos son DataSets tipados que no dejan de ser
clases con un diseador asociado como veremos en el siguiente mdulo.
Una vez creadas nuevas clases en estas carpeta podemos aadirle mtodos,
propiedades y campos para dotarlas de la funcionalidad que requiramos. Por supuesto
son clases normales de .NET por lo que podremos derivarlas de otras clases para
obtener funcionalidad "gratis", hacer que implementen interfaces o incluirlas dentro
de mdulos o espacios de nombres para ordenarlas.
Si lo que desea es compartir cdigo entre distintas aplicaciones o encapsular
funcionalidad en una librera independiente, puede crear un proyecto de tipo librera
de clases. Este proyecto genera un archivo .DLL que puede compartir entre distintas
aplicaciones. Con esto podr reutilizar sus clases en tantos proyectos como quiera,
incluso en distintos tipos de proyectos como Aplicaciones Web y Aplicaciones
Windows.
Nota:
Si dispone de la versin Visual Web Developer no podr generar
bibliotecas DLL.
Contenido
Sin lugar a dudas uno de los mbitos ms importantes de un lenguaje o entorno de
programacin es su capacidad de acceso a datos. Prcticamente todas las aplicaciones
conllevan la realizacin de accesos a datos.
Le gustar saber que la plataforma .NET, y por lo tanto ASP.NET, ofrecen un potente
modelo de acceso a fuentes de datos. Se le conoce con el nombre genrico de
ADO.NET.
Nota:
No se deje engaar por el nombre: ADO.NET no casi nada que ver con el
anterior ADO utilizado en los tiempos de ActiveX y COM. S, dispone de
conexiones, comandos e incluso una clase que recuerda a los Recordset,
pero crame cuando le digo que es mejor que se olvide para siempre de
todos ellos. Tanto la filosofa de trabajo como la tecnologa son
diferentes por completo y es mejor que utilice una estrategia de "ojos
limpios" para acercarse correctamente a la nueva tecnologa.
Los conocimientos adquiridos en este mdulo le servirn para cualquier tipo de
desarrollo con .NET, no slo para aplicaciones Web. Los conceptos explicados son
vlidos tambin para cualquier versin de .NET no slo para la 2.0.
Introduccin a ADO.NET
Esta leccin presenta los fundamentos de ADO.NET, su arquitectura y sus principales
clases. Una vez que sepamos por donde pisamos pasaremos a estudiar ms a fondo
cada uno de los conceptos analizados aqu.
Introduccin a ADO.NET
Como cualquier otro modelo de acceso a datos, ADO.NET es un conjunto de clases
relacionadas entre s que estn especializadas en ofrecer toda la funcionalidad que un
programador necesita para realizar acceso a datos y manejarlos una vez los ha
obtenido.
Las clases genricas expuestas por ADO.NET se encuentran bajo el espacio de
nombres System.Data. Este espacio de nombres define clases genricas de acceso a
datos que posteriormente son extendidas para ofrecer caractersticas y funciones
especficas de cada proveedor.
El objeto ms importante a la hora de trabajar con el nuevo modelo de acceso a datos
es el DataSet. Sin exagerar demasiado podramos calificarlo casi como un motor de
datos relacionales en memoria. Aunque hay quien lo asimila a los clsicos Recordsets
su funcionalidad va mucho ms all como se ver en breve.
Arquitectura de ADO.NET
El concepto ms importante que hay que tener claro sobre ADO.NET es su modo de
funcionar, que se revela claramente al analizar su arquitectura:
La capa conectada
La capa conectada de ADO.NET contiene objetos especializados en la conexin con los
orgenes de datos. As, la clase genrica Connection se utiliza para establecer
conexiones a los orgenes de datos. La clase Command se encarga de enviar
comandos de toda ndole al origen de datos. Por fin la clase DataReader est
especializada en leer los resultados de los comandos.
La clase DataAdapter hace uso de las tres anteriores para actuar de puente entre la
capa conectada y la desconectada como veremos despus.
Estas clases son abstractas, es decir, no tienen una implementacin real de la que se
pueda hacer uso directamente. Es en este punto en donde entran en juego los
proveedores de datos. Cada origen de datos tiene un modo especial de
comunicarse con los programas que los utilizan, adems de otras particularidades que
se deben contemplar. Un proveedor de datos de ADO.NET es una implementacin
concreta de las clases conectadas abstractas que hemos visto, que hereda de stas y
que tiene en cuenta ya todas las particularidades del origen de datos en cuestin.
As, por ejemplo, las clases especficas para acceder a SQL Server se llaman
SqlConnection, SqlCommand, SqlDataReader y SqlDataAdapter y se
encuentran bajo el espacio de nombres System.Data.SqlClient. Es decir, al
contrario que en ADO clsico no hay una nica clase Connection o Command que se
use en cada caso, si no que existen clases especializadas para conectarse y recuperar
informacin de cada tipo de origen de datos.
Nota:
El hecho de utilizar clases concretas para acceso a las fuentes de datos
no significa que no sea posible escribir cdigo independiente del origen
de datos. Todo lo contrario. La plataforma .NET ofrece facilidades de
Descripcin
Permite conectar nuestras
aplicaciones a fuentes de
datos a travs de ODBC.
OLE
DB
.NET System.Data.OleDb
Realiza
la
conexin
Data Provider
utilizando un proveedor
OLEDB, al igual que el
ADO clsico.
Oracle
Client System.Data.OracleClient Proveedor de datos para
.NET
Data
acceder a Oracle.
Provider
SQL Server .NET System.Data.SqlClient
Permite
la
conexin
Data Provider
optimizada a SQL Server
7.0
o
posterior,
incluyenbdo
la
ltima
versin SQL Server 2005.
Los proveedores de acceso a datos que distribuye Microsoft en ADO.NET y algunos
desarrollados por otras empresas o terceros, contienen los mismos objetos, aunque
los nombres de stos, sus propiedades y mtodos, pueden ser diferentes.
Existen, por supuesto, proveedores para tipos de orgenes de datos de cualquier
gestor de datos existente en el mercado. stos los desarrolla normalmente la empresa
responsable del producto. Si bien stos optimizan el acceso a estos orgenes de datos
nosotros siempre podremos realizarlo mediante ODBC u OLEDB si tenemos necesidad.
En resumen: con la capa conectada de ADO.NET realizamos la conexin y
comunicacin con los orgenes de datos. Cada proveedor de datos implementa su
La capa desconectada
Una vez que ya se han recuperado los datos desde un origen de datos la conexin a
ste ya no es necesaria. Sin embargo sigue siendo necesario trabajar con los datos
obtenidos de una manera flexible. Es aqu cuando la capa de datos desconectada
entra en juego. Adems, 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
conexin. A veces nicamente necesitamos un almacn de datos temporal pero que
ofrezca caractersticas avanzadas de gestin y acceso a la informacin.
Por otra parte las conexiones con las bases de datos son uno de los recursos ms
escasos con los que contamos al desarrollar. Su mala utilizacin es la causa ms
frecuente de cuellos de botella en las aplicaciones y de que stas no escalen como es
debido. Esta afirmacin es especialmente importante en las aplicaciones Web en las
que se pueden recibir muchas solicitudes simultneas de cualquier parte del mundo.
Finalmente otro motivo por el que es importante el uso de los datos desconectado de
su origen es la transferencia de informacin entre capas de una aplicacin.
stas pueden encontrarse distribuidas por diferentes equipos, e incluso en diferentes
lugares del mundo gracias a Internet. Por ello es necesario disponer de algn modo
genrico y eficiente de poder transportar los datos entre diferentes lugares, 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. Todo esto y mucho
ms es lo que nos otorga el uso de los objetos DataSet, ncleo central de la capa
desconectada de ADO.NET.
Nota:
Otra interesante caractersticas de los DataSet es que permiten
gestionar simultneamente diversas tablas (relaciones) de datos, cada
para
lanzarla
(propiedad
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 clusula Finally nos aseguramos que siempre se va a cerrar la
conexin.
De todos modos escribir este cdigo es algo tedioso sobre todo si queremos que la
excepcin se replique y slo metemos la clusula Finally por el hecho de cerrar la
conexin.
Para facilitar el trabajo VB.NET en .NET 2.0 incluye una clusula especial denominada
Using que habilita la destruccin automtica de los objetos a los que se hace
referencia. As el cdigo anterior quedara simplemente:
Al terminar la clusula Using (aunque haya un error por medio) se llama de manera
automtica al mtodo Dispose del objeto utilizado (en este caso una conexin). Entre
otras cosas este mtodo 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 conexin a la base de datos pr el motivo que sea.
En principio en el caso de un cursor firehose tradicional obtendramos un error porque
se ha roto la conexin con el servidor. En el caso de un DataReader es posible que
sigamos ejecutando varias vueltas ms del bucle sin problemas. Esto se debe a que,
en realidad, el DataReader obtiene los registros en grupos a travs de la conexin 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 cdigo anterior, aunque sencillo, es un poco lioso y el uso de los DataReader est
algo limitado dada su idiosincrasia (de slo lectura y hacia adelante). Este cdigo es
adecuado si no necesitamos almacenar los resultados de la consulta en memoria ni
regresar sobre ellos una vez procesados una primjera vez. Tambin 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 cdigo muy poco til y complicado
de utilizar salvo para cosas muy sencillas. Adems slo hemos utilizado clases de la
capa conectada de ADO.NET. Todava debemos aprender a obtener los resultados
dentro de un DataSet para su explotacin de manera cmoda. Hay que tender un
puente entre ambos mundos (conectado y desconectado): el DataAdapter.
En un ejemplo sencillo como el anterior (y por otro lado uno de los ms comunes) se
crea una nica tabla en el DataSet de nombre "Table1" y posicin 0.
Las tablas contienen dos colecciones interesantes:
Con esta informacin resulta muy sencillo tratar los datos de una consulta. Podemos
acceder directamente a cualquier registro de la tabla usando su posicin en la
coleccin de filas. Por ejemplo para acceder al quinto registro de una tabla basta con
escribir:
Dim dr As DataRow
dr = ds.Tables(0).Rows(4)
que devolver un objeto del tipo adecuado para el campo que representa (una
cadena, un objeto de fecha, un booleano, etc...).
Nota:
Es muy sencillo definir objetos DataTable que dispongan de los campos
que deseemos sin depender de origen alguno de datos. Emplee el
mtodo Add de la coleccin Columns para crear nuevos campos, algunos
de los cuales pueden ser incluso derivados mediante una frmula de los
valores de otros. Esto permite definir estructuras de almacenamiento a
medida en memoria sin preocuparnos de usar una base de datos para
ello.
Ventajas del uso de objetos DataSet
Es posible cargar datos de varias tablas en un mismo DataSet, incluso aunque
procedan de bases de datos diferentes, y relacionarlas en memoria. Es posible
establecer relaciones entre ellas para mantener la consistencia, as como hacer un
mantenimiento en memoria de los datos (altas, bajas y modificaciones).
Posteriormente se puede sincronizar el DataSet con el servidor usando un
DataAdapter, realizando el proceso contrario al de obtencin de datos. Luego lo
veremos.
Consultas parametrizadas
Las consultas simples como la que acabamos de utilizar en los ejemplos anteriores
son muy raras. En la realidad las consultas son mucho ms complejas, suelen
intervenir varias tablas y dependen de diversos parmetros que le aaden
condiciones.
Por ejemplo, si en la base de datos Northwind queremos obtener slo aquellos
clientes de un pas determinado. Podramos escribir de nuevo la funcin DameClientes
para que se pareciese a la siguiente:
Los objetos de tipo Command disponen de una coleccin llamada Parameters que
sirve para asignar dichos parmetros. stos previamente se definen en la consulta
utilizando comodines que marquen su ubicacin.
Nota:
Cada proveedor de datos utiliza su propia convencin para indicar la
posicin de los parmetros en una consulta. En el caso de SQL Server se
indican con una arroba '@' seguida de un identificador. En otros
proveedores no se puede definir nombre para los parmetros, slo se
marca su posicin con un caracter especial.
La funcin anterior empleando parmetros sera la siguiente:
que es correcta. Ello elimina los problemas de los que hablbamos anteriormente y
permite optimizar el uso de consultas.
Es un cdigo muy similar al anterior que realizaba una seleccin de datos. En este
caso se ha definido una consulta de insercin con tres parmetros. En lugar de usar
ExecuteReader o un DataAdapter en este caso se utiliza el mtodo ExecuteNonQuery.
ste lanza la consulta (es decir, se inserta el nuevo registro) y devuelve el nmero de
registros afectados por la consulta (que en el caso de una insercin siempre es 1 si se
inserta correctamente o 0 si ha habido un error y lo captursemosr).
Las actualizaciones y eliminaciones de registros se podran conseguir de modo similar.
Trabajando desconectados
El cdigo anterior funciona perfectamente pero no es la forma ptima de trabajar
cuando tenemos que tratar con datos desconectados contenidos en objetos DataSet.
Los DataSet normalmente circulan, independientes de cualquier origen de datos,
entre las diferentes capas de una aplicacin e incluso se mueven entre contextos de
ejecucin y mquinas (por ejemplo a travs de un servicio Web como veremos).
Hemos dicho que son como pequeas bases de datos, por lo que la forma habitual de
trabajar con ellos es aadir, eliminar y modificar registros directamente sobre sus
tablas, sin pensar en la ubicacin real de estos datos.
Por fin, para eliminar un registro slo hay que usar su mtodo Delete, as:
Una vez especificados estos comandos slo resta llamar al mtodo Update del
DataAdapter para que se ocupe de sincronizar automticamente todos los cambios
que hayamos realizado en las tablas en memoria. Este mtodo acepta como
argumentos un DataSet completo, una DataTable o incluso un DataRow si slo
queremos actualizar un nico registro.
Definicin de los comandos
Los comandos de insercin, modificacin o borrado para el DataAdapter se definen del
mismo modo que en el cdigo de ejemplo al principio de este apartado, es decir, se
define la consulta apropieada y sus parmetros. En esta ocasin como los parmetros
sern rellenados automticamente por el DataAdapter hay qeu utilizar una sobrecarga
del mtodo Add de la coleccin de parmetros que incluye el nombre del campo
asociado con el parmetro, as:
Significado
Registros
que
no
estaban
originalmente.
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)
Controles de datos
Aparte de la escritura manual de cdigo y el uso
directo de objetos de ADO.NET, ASP.NET 2.0
proporciona un nuevo modelo de trabajo declarativo
para acceso a datos que nos permite realziar tareas
comunes de acceso a datos sin escribir cdigo alguno.
ASP.NET 2.0 presenta dos nuevos tipos de controles
Web que participan en este modelo declarativo de
enlace a datos. Estos controles nos abstraen por
completo de las complejidades de manejo de las
clases de ADO.NET por un lado, y de las dificultades
inherentes al modo de trabajo desconectado de las
pginas Web. Equiparan en muchos aspectos el
desarrollo web al tradicional desarrollo de aplicaciones
de escritorio.
Estos controles se encuentran agrupados en el cuadro de herramientas bajo el
nombre de "Datos", tal y como se ve en la figura.
Orgenes de datos
Estos controles de datos representan conexiones con diferentes tipos de orgenes de
informacin que van desde bases de datos a objetos de negocio. 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. Abstraen al
programador de las complejidades relacionadas con el manejo de los datos,
permitiendo de
paginarlos, etc..
manera
automtica
selecionarlos,
actualizarlos,
ordenarlos,
ASP.NET 2.0 ofrece los siguientes controles de origen de datos que se pueden ver en
la figura anterior:
Control
SqlDataSource
Descripcin
Enlaza con cualquier base de
datos para que exista un
proveedor de ADO.NET.
AccessdataSource Esta especializado en trabajar
con bases de datos Microsoft
Access.
ObjectDataSource Se enlaza con objetos de
negocio y capas personalizadas
de acceso a datos.
XmlDataSource
Trata datos contenidos en
documentos XML.
SiteMapDataSource Se enlaza con la jerarqua de
clases expuesta por el modelo
de navegacin de sitios de
ASP.NET 2.0.
ATENCIN!: El control SqlDataSource sirve para enlazar con
cualquier gestor de datos relacional para la que haya proveedor
ADO.NET disponible, no slo para enlazar con SQL Server. No se deje
despistar por su nombre.
Concurrencia optimista
Durante la configuracin de un origten de datos SQL (luego lo ver en el primer vdeo
de esta leccin) una de las opciones avanzadas que se presenta habla de la
Concurrencia optimista. La concurrencia optimista evita la actualizacin de
registros en el caso de que haya variado cualquiera de sus campos desde que se
obtuvieron de la fuente de datos. Este comportamiento puede ser bueno en ciertas
ocasiones, cuando queremos preservar los cambios realizados por cualquier usuario.
En otras sin embargo no resulta de utilidad y s aade una gran sobrecarga al acceso
a datos.
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. Al caso contrario a la concurrencia optimista se le denomina
concurrencia pesimista.
Nota:
En mi opinin debera llamarse "concurrencia realista" ya que, lo cierto
es que si se analiza con detenimiento la posibilidad de conflicto en un
sistema grande tiende a ser realmente pequea en la mayora de los
casos. Y de todos modos el sobreescribir cierta informacin no suele ser
Es decisin suya qu tipo de actualizacin utilizar pero en la mayor parte de los casos
usar seguramente la pesimista que, de hecho, es la que usted utiliza normalmente si
escribe las funciones a mano de manera independiente.
Controles enlazados a datos
Se trata de controles de interfaz de usuario que, haciendo uso de los anteriores,
muestran la informacin a travs de la pgina. Pueden sacar partido a todas las
propiedades de los orgenes de datos y por lo tanto habilitan de manera sencilla la
edicin, eliminacin, ordenacin, filtrado y paginacin de los datos entre otras cosas.
Para conectar un control enlazado a un DataSource slo hay que establecer su
propiedad DataSourceID indicando el nombre apropiado. As de facil.
Nota:
Si usted ya conoce los controles enlazados a datos de ASP.NET 1.x como
el DataGrid, el DataRepeater, etc... estos controles le resultarn ms
cmodos de utilizar pues al contrario que con aquellos no hay que
escribir cdigo alguno. Aunque estos controles "antiguos" no aparecen
en el cuadro de herramientas siguen estando soportados y los puede
seguir utilizando. Incluso si lo desea puede aadirlos al cuadro de
herramientas. De todos modos se recomienda utilizar el nuevo modelo
declarativo de acceso a datos.
DataSet tipados
La clase DataSet, como cualquier otra clase no sellada de .NET, puede ser extendida
mediante herencia para aadirle nuevas funcionalidades y aprovechar las ya
existentes. 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.
Por ejemplo, podemos crear un DataSet especial que tengan en cuenta las
particularidades de los datos que maneja para validarlos antes de permitir su
insercin, que verifique las relaciones con otros datos o que los transforme o controle
el acceso a los mismos. Nosotros slo tendramos 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 gestin de datos pura y dura.
Esta es, en esencia, la idea que subyace bajo los DataSet tipados de Visual Studio
2005. Se trata de clases especializadas derivadas de DataSet que ofrecen una forma
ms rpida y sencilla de acceder a los datos que albergan. Adems Visual Studio nos
permite crear este tipo de DataSet de forma visual y usando asistentes. En el vdeo se
ilustra la manera de conseguirlo.
Los DataSet tipados parten del conocimiento preciso de la estructura de una base de
datos para definir su funcionalidad. Esta es su principal diferencia con los DataSet
normales puesto que stos son genricos y no saben nada acerca de los datos que
albergan. Los tipados slo sirven para albergar una informacin muy concreta. Ganan
en especializacin y pierden en versatilidad.
Para agregar un DataSet tipado a nuestro proyecto slo hay que presionar con el
botn secundario sobre la carpeta App_Code y en el dilogo que aparece elegir el
icono de DataSet. La extensin del archivo generado es '.xsd' porque lo que en
realidad albergan es un esquema XML que define la estructura de los datos en los que
se van a especializar.
Una vez agregado el DataSet aparece una superficie de diseo y un asistente como el
de la figura.
que nos dara el nombre del primer cliente de la tabla de clientes en el DataSet 'ds'.
esta propiedad nombre adems ya sera un campo de tipo String que es el tipo
adecuado para la informacin albergada, por lo que se simplifica mucho su uso.
En un DataSet normal para obtener lo mismo tendramos que haber escrito:
ds..Tables(0).Rows(0)("Nombre").ToString()
Ntese que el mtodo Add del DataTable se ha sustituido por uno con nombre
especializado que nos ayuda a saber mejor por donde pisamos, pero su funcin es
idntica.
Para rellenar una tabla de un DataSet tipado se usa su correspondiente TableAdapter
as:
Dim clientes As New ClientesDS
Dim ta As New ClientesTableAdapters.ClientesTableAdapter()
ta.Fill(clientes.Clientes)
clientes.Clientes(0).Nombre = "Pepe"
....
o tambin usando el mtodo GetData para obtener la tabla directamente si slo nos
interesa esa parte concreta del DataSet (que puede constar de varias tablas):
Dim clientes As Clientes.ClientesDataTable
Dim ta As New ClientesTableAdapters.ClientesTableAdapter()
clientes = ta.GetData()
clientes(0).Nombre = "Pepe"
....
Contenido
En este mdulo vamos a aprender ciertas cuestiones avanzadas de ASP.NET 2.0 que
nos ayudarn a crear aplicaciones ms potentes y con menos esfuerzo que con
cualquier otra herramienta de desarrollo, incluyendo versiones anteriores de .NET.
Veremos como conseguir pginas con un aspecto y funcionalidad consistentes a lo
largo de toda la aplicacin Web. Tambin conoceremos los nuevos controles de
seguridad que vienen con ASP.NET 2.0, y estudiaremos la forma de mantener
informacin en memoria para agilizar las aplicaciones.
Rutas de imgenes
Leccin 3: Estado de las aplicaciones
o Mantenimiento de sesiones
Variables de sesin
Funcionamiento bsico de las sesiones
Sesiones sin cookies
Almacenamiento de sesiones
Tipos de objetos almacenables
o Informacin comn
Variables de aplicacin
Concurrencia en variables de aplicacin
Almacenamiento en cach
o Cach de salida
Directiva Outputcache
Atributos de OutputCache
Donde se hace la cach?
Almacenamiento en disco
Sustitucin post-cach
Leccin 4: Seguridad de las aplicaciones
o Autenticacin y autorizacin de usuarios
Autenticacin de IIS/Windows
Autenticacin Forms en ASP.NET
o Autorizacin de usuarios
Autorizacin de URLs
Autorizacin declarativa
Autorizacin imperativa
o La nueva API: Membership y Roles
Membership
Roles
Administracin 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
mantenimiento puesto que, para actualizar todas las pginas que lo utilizan, basta
con editar dicho archivo.
Una MP es en realidad como una pgina ASPX normal que contiene cdigo, elementos
HTML y controles Web de servidor. Sin embargo posee una extensin diferente
(.master) y utilizan una directiva <% @ master %> en lugar de una directiva <% @
page %>. Por lo dems se pueden considerar prcticamente equivalentes. Esto es
importante porque significa que ya sabemos todo lo necesario para crearlas.
Una pgina ASPX normal puede derivar su estructura a partir de una MP simplemente
aadiendo un atributo MasterPageFile a su directiva de pgina, as:
De este modo, cuando una pgina normal derive de una MP, slo se podr introducir
cdigo dentro de las zonas definidas por estos comodines de contenido.
Cuando aadimos una nueva pgina ASPX a nuestro proyecto y existe al menos una
Master Page, podemos marcar una opcin para que, antes de crearla, nos permita
seleccionar de qu MP derivar:
Una vez hecho esto podemos acceder a los elementos de la pgina de la que deriva la
actual a travs de su propiedad Master.
Por ejemplo, si nuestra Master Page tiene un elemento de imagen llamado 'Logo' y
queremos variarlo en cada pgina mediante cdigo slo habra que escribir:
Master.FindControl("Logo")
que nos aislar de lo que ocurra debajo para gestionar ese logo.
Temas y Skins
Gracias a las Master Pages podemos definir una estructura comn para las pginas de
nuestra aplicacin Web. Sin embargo an no hemos resuelto todas las cuestiones
sobre el mantenimiento de la interfaz que habamos planteado. Los controles que
aadamos a las zonas de contenido de nuestras pginas todava tendrn el aspecto
predeterminado. Podemos configurar su aspecto estableciendo las propiedades de
apariencia del control (como BackColor, Font, etc...). El problema que tiene este
mtodo es que, si deseamos cambiar por completo la apariencia de estos controles,
tendramos que tocar una por una todas las pginas. Esta no es una opcin admisible
en cuanto la aplicacin dispone de ms de unas pocas pginas.
Veamos las opciones que nos ofrece ASP.NET 2.0 para solventar esta otra parte de un
mismo problema.
Hojas de estilo
HTML ofrece una interesante opcin para independizar el aspecto de sus elementos
del contenido de las pginas a travs del uso de las hojas de estilo en cascada
(Cascading Style-Sheets o CSS). Las hojas CSS permiten definir el aspecto de
cualquier elemento HTML contenido en una pgina. Aunque se pueden definir dentro
de la propia pgina, hacerlo as les hace perder su verdadero sentido que no es otro
que el de separar la definicin del aspecto. As, es posible crear archivos con
extensin '.css' que se vinculan a las diferentes pginas de un sitio y definen el
aspecto de sus elementos.
Dentro de una hoja CSS se definen fundamentalmente dos tipos de estilos:
body {
background-color: #656565;
background-image: url(Images/background.gif);
background-repeat: repeat;
margin: 0;
padding: 0;
text-align: center;
font-family: Verdana, Arial, Helvetica, sans-serif;
font-size: 0.7em;
color: #FFFFFF;
En este fragmento, las etiquetas definen el aspecto que deben tomar los enlaces y el
cuerpo de la pgina.
Clases: definen aspectos que no estn 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;
color: #DBB94F;
}
.....
La gran ventaja de esta tcnica es que basta con tocar el archivo CSS para que todas
las pginas que lo utilizan vean su aspecto modificado de manera acorde a los
cambios. Da igual que sea slo una o haya miles. Al tener el aspecto centralizado en
una ubicacin nica el mantenimiento es muy sencillo.
Soporte de estilos en ASP.NET
Lo anterior es una caracterstica de HTML independiente de lenguajes de
programacin como ASP.NET. Por supuesto ASP.NET tiene en cuenta y soporta
perfectamente las hojas CSS.
Se puede aadir una etiqueta <LINK> a la cabecera de una pgina ASPX y los
elementos HTML que se generan a partir de los controles que contiene se mostrarn
siguiendo las indicaciones de la misma.
El entorno de desarrollo de Visual Studio permite definir los estilos de los controles
HTML de servidor de ASP.NET utilizando su propiedad Style, tanto en tiempo de
diseo como durante la ejecucin. El diseador de pginas ASPX incluso ofrece un
dilogo especializado para crear los estilos.
conseguiremos que las pginas que lo apliquen dispongan de controles TextBox con el
fondo gris claro y el borde punteado de 1 pixel de ancho. Las rejillas que se utilicen
automticamente tendrn el fondo blanco y las lneas pares azules.
Si nos fijamos, la nica diferencia entre un elemento del archivo de mscara y el
marcado de un control est en que los primeros carecen del atributo de identificacin
ID. Por lo dems son prcticamente idnticos.
TRUCO:
Dado que Visual Studio no proporciona asistencia para crear archivos de
mscara (es un simple editor de texto), una forma sencilla de definir sus
elementos es utilizar una pgina ASPX vaca para arrastrar y configurar
controles con los aspectos deseados. Luego slo hay que copiar su
definicin al archivo .skin eliminando todos los atributos ID.
Propiedades que se pueden personalizar
Aunque los archivos de mscara estn pensados para facilitar la aplicacin de
propiedades estticas de los controles, lo cierto es que se puede definir casi cualquier
otra propiedad de un control. Por ejemplo, si escribimos los siguiente en el archivo
.skin de un tema:
todos los controles de tipo TextBox de nuestra aplicacin mostrarn el texto "(valor)"
al cargar las pgina que usen este tema (ntese el atributo Text en la primera lnea).
En realidad cualquier propiedad de un control web puede personalizarse mediante un
archivo de mscara a menos que su creador haya indicado explcitamente lo
contrario. Esta particularidad puede resultar muy interesante en ciertos casos.
Nota:
Los creadores de controles pueden emplear el atributo
ThemeableAttribute para indicar que una propiedad no es
personalizable mediante una mscara.
Asignacin de temas
Ahora que ya conocemos la teora acerca de los temas y sabemos crear archivos de
mscara para los temas vamos a aprender a utilizarlos en la prctica.
Para que una pgina se adapte automticamente 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 pgina, as:
Al hacerlo todas las pginas de la aplicacin utilizarn el tema indicado sin necesidad
de establecerlo manualmente.
Si se define un tema especfico para una pgina, ste tendr precedencia sobre el
ajuste de Web.config. De hecho si deseamos que una pgina no utilice tema alguno
slo hay que establecer su atributo Theme a una cadena vaca ("").
Nota:
Dado que una aplicacin Web puede disponer de varios archivos de
configuracin (uno por cada carpeta) si queremos que la aplicacin
emplee un tema diferente en diferentes zonas slo tenemos que guardar
todas las pginas de cada zona en una carpeta diferente y crear archivos
web.config especficos para indicar el tema en cada una de ellas. Las
carpetas que no dispongan de su propio web.config heredarn el tema
principal del sitio.
Precedencia de propiedades
Cuando un elemento de una mscara define un atributo para un control, ste tiene
precedencia sobre el mismo atributo en caso de que se haya asignado tambin en la
pgina. Por ejemplo, si en una pgina tenemos un TextBox cuyo color de fondo lo
hemos establecido en amarillo, pero en el archivo .skin del tema que utiliza la pgina
este color indica que debe ser gris, al ejecutar la aplicaicn se ver de color gris.
Una forma alternativa de definir un tema para una pgina que cambia este orden de
precedencia es emplear el atributo StylesheetTheme en lugar del ms comn Theme
que hemos visto hasta ahora:
...
En este caso el valor establecido en la pgina para una propiedad tiene preferencia
sobre el valor del archivo de mscara en caso de haber coincidencia. Justo al contrario
que en el caso habitual.
Una posibilidad poco frecuente es utilizar ambos atributos (Theme y
StylesheetTheme) simultneamente. En este caso la precedencia lo que ocurre es lo
siguiente:
1. Se aplican los atributos del tema especificado en StylesheetTheme.
2. Se aplican los atributos definidos en la pgina que sobreescriben a los
del paso anterior en caso de coincidencia.
3. Se aplican los atributos del tema especificado en Theme que en caso de
coincidencia tienen por tanto preferencia sobre los anteriores.
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 pgina. La forma de conseguirlo es asignando su
propiedad EnableTheming a False.
Clases de un mismo tipo de control
El hecho de declarar un elemento genrico dentro de un archivo de mscara es til
pero no lo suficiente. Lo ms normal es que no todas las etiquetas o botones (por
poner un ejemplo) tengan exactamente el mismo aspecto sino ms bien que existan
varios tipos de etiquetas y botones que se empleen segn la ocasin.
Al igual que en el caso de las hojas de estilo en los temas se pueden definir distintas
clases de un mismo control, cada una con unos atributos especficos. La forma de
distinguir unos de otros es a travs del atributo SkinID. Considere el siguiente
ejemplo:
En este caso se han definido tres clases de controles TextBox. Los dos primeros
tienen asignado un SkinID y slo se aplicarn a aquellos controles TextBox cuya
propiedad SkinID coincida con el SkinID de la definicin. La ltima definicin 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 especficamente un SkinID.
Lo habitual es separar los distintos grupos de controles es varios archivos .skin dentro
de la carpeta de un tema. Se reconocern como si estuvieran todos en el mismo
archivo pero es ms ordenado gestionarlos por separado.
Inclusin automtica de hojas de estilo
Dentro de la carpeta de un tema tienen cabida tambin hojas de estilo como ya
hemos mencionado. Cuando se copia una o ms hojas de estilo enla carpeta, stas se
aaden de manera automtica a la cabecera de las pginas que utilizan el tema
mediante etiquetas <link>. La nica condicin para que esto funcione es que el
atributo <head> de lapgina (que representa la cabecera) tenga el atributo de
ejecucin en el servidor runat="server", cosa que todas las pginas cumplen de
manera predeterminada.
Rutas de imgenes
Por supuesto en las propiedades de los elementos de una mscara se pueden utilizar
imgenes como en este ejemplo:
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 algn modo un estado que les permita agrupar de
manera lgica las llamadas. Sin ello no habra forma, por ejemplo, de distinguir dos
llamadas a una misma pgina de dos usuarios diferentes. Para conseguir este artificio
sobre un protocolo sin estado ASP.NET proporciona las sesiones.
Nota:
Cabra pensar que una buena forma de distinguir unas llamadas de otras
en una aplicacin Web es a travs de la direccin IP del cliente. Nada
ms lejos de la realidad. Dos usuarios diferentes que accedan detrs de
un mismo router (por ejemplo, dos personas en una misma oficina)
tienen la misma IP exactamente. Adems, desde el punto de vista de la
seguridad es muy mala idea usar invariantes de este estilo pues son
fciles de falsear.
Variables de sesin
ASP.NET ofrece una coleccin llamada Session en el objeto Page que nos permite
almacenar parejas de claves y valores que estn disponibles desde todas las pginas
de una aplicacin y se distinguen automticamente 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 pginas sea el mismo. Por
convencin a las parejas de claves y valores almacenados en el objeto Session se les
denomina variables de sesin.
Por ejemplo, si quiero contar cuantas veces ha pasado un usuario por una pgina
'a.aspx' puedo escribir en su evento Load lo siguiente:
Session("Cuenta") += 1;
Esto hara que el valor asociado con la clave "Cuenta" se incrementara en uno cada
vez que se cargue la pgina. Es decir, en palabras llanas, incrementa en la unidad el
valor de la variable de sesin "Cuenta".
Si creamos una segunda pgina 'b.aspx' en la que mostramos el valor de la variables
de sesin mediante:
Response.Write(Session("Cuenta"))
ruta virtual aleatoria en todas las peticiones de modo que todas son distintas. Si la
llamada a una pgina se efectuaba en esta URL:
http://www.miservidor.com/miapp/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 pginas de ASP.NET es capaz de
distinguir que se trata de un identificador de sesin y actuar de manera transparente
para mantenerla y enviar las peticiones a las pginas correctas.
Este mtodo es menos propenso a fallos que el anterior pero tiene el inconveniente de
que se generan URLs mucho ms largas y menos atractivas. Las sesiones sin cookies
no existan en ASP 3.0.
Habilitar este tipo de sesiones es muy sencillo. Basta con abrir el archivo de
configuracin de la aplicacin (web.config) y aadir el siguiente ajuste dentro del
nodo <system.web>:
<sessionState cookieless="UseUri" />
Almacenamiento de sesiones
La informacin referente a los datos de sesin se almacena por defecto en la memoria
del servidor. Ello suscita un problema importante cuando la aplicacin debe ser muy
escalable y tener capacidad para gestionar miles de peticiones simultneas. En estos
casos es frecuente ubicarla en varios servidores balanceados. A medida que llegan
nuevas peticin a la granja de servidores, stas se reparten por las distintas
mquinas que la constituyen, bien aleatoriamente, bien siguiendo algn sistema de
cuotas o asignndolas por orden (round-robin).
Dado que cada mquina mantiene su propia copia de las sesiones, a menos que cada
usuario se redirija siempre al mismo servidor, no habr forma de mantener una
sesin coherente, pues no existe una ubicacin 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. An as
existen otros problemas con la sincronizacin de datos compartidos en
toda la aplciacin y adems el sistema reduce la escalabilidad.
ASP.NET 2.0 permite configurar el almacenamiento de sesiones para utilizar cualquier
proveedor de almacenamiento de sesin 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 sesin 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 travs del archivo web.config:
Tambin se puede asignar mediante cdigo usando la propiedad Timeout del objeto
Session.
Session.Timeout = 10
Informacin comn
Variables de aplicacin
Las variables de sesin permiten guardar informacin que concierne a un usuario
concreto y que no es accesible para los dems. Las variables de aplicacin por el
contrario estn pensadas para almacenar en memoria datos que estn accesibles para
todos los usuarios al mismo tiempo.
Las variables de aplicacin se gestionan exactamente de la misma manera que las de
sesin pero usando la propiedad Application de la pgina en lugar de Session.
Por ejemplo, implementar un contador de llamadas a pginas de una aplicacin es
muy sencillo si utilizamos el objeto Application, ya que slo tendramos que escribir en
la carga de cada pgina:
Application("Contador") += 1
Esta variable estar accesible desde cualquier otra pgina de cualquier sesin de
usuario.
Concurrencia en variables de aplicacin
El cdigo anterior presenta un problema poco evidente que tiene que ver con la
concurrencia de uso de las variables de aplicacin. En una aplicacin Web pueden
estar ejecutndose al mismo tiempo varias pginas. De hecho es bastante probable
que existan muchas coincidencias a la hora de escribir en la variable anterior si
metemos ese cdigo en todas las pginas de una aplicacin y hay bastantes usuarios.
De este modo se bloquea el acceso de las dems pginas a las variables de aplicacin
mientras no se llame al mtodo de desbloqueo y se evitan as los problemas de
concurrencia. Hay que tener cuidado sin embargo con el uso que se hace de esta
caracterstica pues puede afectar a la escalabilidad por bloqueos en las otras pginas.
Nota:
En ASP 3.0 esta era la nica manera de compartir memoria en el mbito
de aplicacin, pero no est exenta de problemas. En ASP.NET se soporta
un mtodo mucho mejor a travs de objetos de cach que ahora
veremos y se desaconseja el uso de las variables de aplicacin en la
medida de lo posible.
Almacenamiento en cach
ASP.NET ofrece un potente sistema de almacenamiento en cach que guarda los
objetos en memoria y es privado para cada aplicacin. De forma anloga a los dos
casos anteriores, existe un objeto Cache que proporciona una interfaz indexada que
permite establecer y recuperar pares de clave-valor. As podemos escribir:
Cache("MiClave") = miValor
....
Response.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, como por ejemplo un DataSet
resultante de una compleja consulta a una base de datos.
La ventaja fundamental de la cach de ASP.NET frente a las variables de aplicacin es
que es muy fcil conseguir la caducidad automtica de sus elementos.
Por ejemplo, imaginemos que llemos en la variable 'datos' el contenido de un archivo
XML y queremos guardarlo en memoria para uso comn y evitar as el contnuo
acceso a disco para leer el contenido. Si usamos una variable de aplicacin cmo nos
enteraremos de que el contenido del archivo ha cambiado y que, por lo tanto
debemos recargar los datos?
No hay forma de hacerlo. Podemos establecer un mecanismo propio que cada cierto
tiempo recargue la variable, pero la solucin dista mucho de ser ptima.
Conseguirlo con la cach de ASP.NET es muy sencillo, basta con escribir la siguiente
lnea:
Cache.Insert("MisDatos", datos,
New CacheDependency(Server.MapPath("misdatos.xml")))
datos,
Nothing,
DateTime.Now.AddHours(2),
Esta lnea agrega el elemento sin dependencia en objeto alguno y con una fecha de
caducidad para dentro de dos horas.
Cache.Insert("MisDatos",
TimeSpan.FromMinutes(30))
datos,
Nothing,
DateTime.MaxValue,
En este caso la caducidad es relativa e indica que el valor caducar en cuanto nadie
haga uso de el durante 30 minutos.
Se pueden agregar dependencias a archivos en disco y a claves en el registro y
tambin combinaciones de estas dependencias. La clase CacheDependency se
puede heredar para crear nuestros propios criterios de caducidad de cach. Incluso es
posible especificar un delegado a una funcin a la que queremos llamar
automticamente cuando el elemento expire y as recargarlo de inmediato.
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, de forma que cuando se modifiquen los datos de una base de
datos se reciba una notificacin automtica.
Este mecanismo es muy potente y conviene aprender a usarlo bien.
Cach de salida
La cach de salida de ASP.NET es un mecanismo que nos permite decidir qu partes
de una pgina deben generarse en cada solicitud y cules pueden ser aprovechadas
para posteriores peticiones. Su uso es extremadamente sencillo y pueden aumentar
de forma espectacular el rendimiento de cualquier aplicacin.
Si se defineuna directiva de cach para una pgina o un control de usuario, ASP.NET
no tiene que generarlos ni crear instancias de objetos, etc... tras la primera peticin,
por lo que se obtiene un rendimiento muy elevado ya que slo debe leer el resultado
de memoria y devolverlo.
Como se pueden aplicar las directivas de cach de salida a los controles de usuario, si
necesitamos hace cach slo de determinadas partes de una pgina y no de la pgina
entera, podemos convertir stas en controles de usuario y conseguir el efecto
buscado.
Directiva OutputCache
Para poder hacer cach del contenido de una pgina o un control de usuario hay que
indicar a ASP.NET de qu depende la caducidad de dicho contenido. Para ello se utiliza
la directiva OutpuCache.
La caducidad puede depender del tiempo, de algn parmetro, de una cabecera, etc...
Por ejemplo, la siguiente directiva:
VaryByParam: permite especificar que se haga una cach por cada valor
diferente que tome un parmetro que se le pasa a la pgina y que se indica en
este atributo. Por ejemplo, si tenemos una pgina a la que se le pasa un
parmetro "pais" y que devuelve un listado de clientes en dicho pas, al indicar
VarByparam="Pais" conseguiremos una cach de resultados diferente para cada
valor del parmetro. Cuando se le pasa un nuevo valor se ejecuta la pgina y se
almacena el resultado para las restantes veces que se solicite con el mismo
parmetro (durante el tiempo especificado). Si hay ms de un parmetro se
pueden especificar separndolos por punto y coma.
VaryByHeader: guarda una cach para cada valor de la cabecera HTTP
indicada. Por ejemplo si se indica varByHeader="User-Agent" conseguiremos
una versin en cach de la pgina por cada tipo de navegador utilizado para
acceder a la pgina. Se pueden especificar varias cabeceras separndolas por
punto y coma.
VaryByControl: en el caso de controles de usuario su cach se fragmentar
por cada valor de las propiedades del control indicadas en el atributo. No es
vlido en directivas de pgina, slo de controles de usuario y se debe
especificar siempre el VarByparam aunque sea con valor "None".
VaryByCustom: permite implementar nuestro propio criterio de cach. Se
debe implementar la funcin global GetVaryByCustomString (dentro de
Global.asax) a la cual se le pasa el valor del atributo para que pueda decidir
cmo actuar. No vamos a entrar en ms detalles en este curso.
Almacenamiento en disco
En ASP.NET 2.0 las versiones en cach de las pginas y controles se almacenan de
manera predeterminada tambin en disco, no slo en
memoria. Esto sirve para disponer de una cach aunque
haya poca memoria disponible y hace que sta sobreviva
incluso al reinicio del servidor. Se puede deshabilitar este almacenamiento a disco
estableciendo el atributo DiskCacheable a False en la directiva de cach de la pgina
o control.
Sustitucin post-cach
Esta es otra caracterstica de ASP.NET 2.0 que no estaba disponible en versiones
anteriores de la plataforma .NET.
En ASP.NET 1.x si hacamos cach de una pgina en la que todo permaneca
invariable excepto una pequea regin que mostraba, por ejemplo, la hora,
estbamos obligados a dividir la pgina en controles de usuario para evitar la cach
de esa pequea parte. ASP.NET 2.0 aade un nuevo tipo de control llamado
Substitution que permite hacer excepciones a la hora de almacenar en cach una
zona de una pgina. Este control est ubicado normalmente en la ltima posicin de
la lista de controles estndar en el cuadro de herramientas.
El control dispone de una propiedad MethodName que permite especificar el nombre
de un mtodo compartido (esttico) que devuelve una cadena con el texto o HTML a
mostrar en su lugar cuando se genere la pgina a partir de la cach. Este mtodo
toma como parmetro un objeto HttpContext que nos permite acceder al contexto
de la llamada.
Por ejemplo, definimos la siguiente funcin:
Por defecto la pgina a la que se redirige a los usuarios annimos para que se
autentiquen se llama "login.aspx" pero se puede especificar cualquier otra usando el
atributo loginUrl, por ejemplo:
<authentication mode="Forms">
<forms loginUrl="entrada.aspx"/>
</authentication>
Autorizacin de usuarios
Una vez que un usuario est autenticado, el proceso que regula a qu recursos tendr
acceso se denomina autorizacin.
Para realizar el control de acceso no slo llega con indicar qu mtodo de
autenticacin se usar (en este caso Forms) . Adems hay que especificar a qu
recursos se debe controlar el acceso y de qu manera. En ASP.NET existen diversos
modos de definir la autorizacin de acceso.
Autorizacin de URLs
Consiste en la autorizacin de acceso a determinados recursos de la aplicacin Web
(pginas ASPX, carpetas, archivos...) refrindose a ellos a travs de su ruta relativa
en el archivo de configuracin de la aplicacin.
Se especifica el nivel de acceso requerido mediante una o varias entradas en el nodo
raz de web.config (nodo <configuration>) que tienen un aspecto anlogo al
siguiente:
<location path=facturas.aspx>
<system.web>
<authorization>
<allow users=jose, hector, pablo>
<allow roles=clientes, administradores>
<deny users="?"/>
</authorization>
</system.web>
</location>
Pueden incluirse tantos nodos location como sea necesario dentro del archivo de
configuracin.
Lo habitual es incluir junto con el nodo de autenticacin un nodo de autorizacin
explcito que deniegue el acceso a todos los recursos a los usuarios annimos, as:
<authentication mode="Forms"/>
<authorization>
<deny users="?"/>
</authorization>
Dado que puede existir un archivo web.config por cada carpeta de la aplicacin se
pueden establecer distintos criterios de acceso a cada una, agrupando en ellas los
archivos con el mismo nivel de acceso.
Autorizacin declarativa
El sistema de autorizacin por URL es muy potente pues permite definir los permisos
de acceso de los usuarios a cualquier archivo controlado por ASP.NET y adems
hacerlo sin tocar el cdigo. Mediante la autorizacin declarativa de ASP.NET es
posible obtener un control mucho ms granular, llegando incluso a controlar accesos a
clases o mtodos concretos dentro de stas. Es decir, regula la autorizacin dentro
del cdigo de la aplicacin, definiendo a qu partes de ste se debe conceder el
acceso y cmo.
Existe tambin una clase MembershipUser que representa las propiedades de los
usuarios de la aplicacin.
Roles
Esta API complementa a la anterior para permitir la gestin de los roles de un usuario
y, al igual que sta, est basada en el mismo patrn de proveedores. No es necesario
utilizar el mismo proveedor para los roles que para los usuarios. Por ejemplo, se
pueden autenticar usuarios contra una base de datos SQL Server y obtener los roles
desde el Directorio Activo o las cuentas locales.
Al igual que en el caso anterior los mtodos de la clase Roles son todos estticos y
podemos usarlos sin instanciar nuevos objetos. Por ejemplo:
Roles.AdduserToRole("usuario", "administradores")
Este fragmento agrega un usuario al rol de administradores. Para obtener los roles a
los que pertenece un usuario podemos escribir:
Roles.getRolesforuser("usuario")
utilizar.
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. Cualquier clave que introduzca le devolver
el enigmtico mensaje "Introduzca otra contrasea" a menos que use
claves de al menos 7 caracteres de longitud e incluya en ellas un espacio
o un caracter no alfanumtico como un asterisco o un guin bajo. Este
ajuste se puede cambiar mediante configuracin.
El administrador de sitios Web utiliza las clases MemberShip y Roles para realizar su
trabajo.
Disponemos
de
su
cdigo
fuente
completo
en
la
carpeta
C:\WINDOWS\Microsoft.NET\Framework\v2.0.xxxxx\ASP.NETWebAdminFiles\
interesante examinarlo.
es
Contenido
Este mdulo presenta al alumno los fundamentos de los Servicios Web y las
Arquitecturas Orientadas a Servicios (SOA).
Tras una introduccin a los servicios Web y sus conceptos asociados se ve la forma de
crear y consumir servicios Web desde ASP.NET 2.0 usando Visual Studio 2005.
En este modelo toda la lgica de los datos, su validacin, los permisos, etc, residen en
un servidor intermedio y son utilizados por todos los clientes a travs de una red. En
este caso en el ordenador del usuario lo nico que hay es una capa de presentacin
que se ocupa bsicamente de recoger y recibir datos, es decir, acta de intermediario
entre el usuario y las reglas de negocio residentes en la capa intermedia. Este modelo
es ms eficiente y est muy evolucionado respecto al anterior pero an se puede ir
ms all.
La arquitectura de desarrollo en n-capas (n-tier que dicen los anglosajones) lleva el
concepto cliente-servidor un paso hacia adelante, dividiendo la capa intermedia en
muchas otras capas especializadas cada una de las cuales puede residir en un
servidor diferente:
SOAP
Las expectativas actuales respecto a los componentes han aumentado. Al igual que
podemos
usar
un
navegador
web para acceder
a cualquier
pgina
independientemente del sistema operativo del servidor en que resida, por qu no
podramos invocar mtodos de componentes a travs de la red independientemente
de dnde se encuentren, del lenguaje en el que estn escritos y de la plataforma de
computacin en la que se ejecuten?.
Esto es precisamente lo que ofrecen los Servicios Web. Gracias a ellos se derriban la
antiguas divisiones resultantes de los modelos de componentes descritos, y la
integracin de las aplicaciones, la ubicuidad de sus componentes y su reutilizacin a
travs de la red se convierten en una realidad.
La tecnologa que est detrs de todo ello se llama SOAP (jabn en ingls). Este
acrnimo (Simple Object Access Protocol) describe un concepto tecnolgico basado en
la sencillez y la flexibilidad que hace uso de tecnologas y estndares comunes
para conseguir las promesas de la ubicuidad de los servicios, la transparencia de los
datos y la independencia de la plataforma que segn hemos visto, se hacen
necesarios en las aplicaciones actuales.
Breve historia de SOAP
SOAP empez como un protocolo de invocacin remota basado en XML diseado por
Dave Winer de UserLand, llamado XML-RPC. A partir de ste se obtuvo en Septiembre
de 1999 la versin 1.0 de SOAP, en la que participo activamente Microsoft y el
archiconocido experto en programacin Don Box.
Esta primera versin fue ms o menos despreciada por los principales fabricantes de
software que en esa poca tenan en marcha un proyecto ms ambicioso llamado
Dado que los mensajes entre componentes y los datos de los parmetros para
llamadas a mtodos remotos se envan en formato XML basado en texto plano,
SOAP se puede utilizar para comunicarse con cualquier plataforma de
computacin, consiguiendo la ansiada ubicuidad de los componentes.
El uso de HTTP como protocolo principal de comunicacin hace que cualquier
servidor web del mercado pueda actuar como servidor SOAP, reduciendo la
cantidad de software a desarrollar y haciendo la tecnologa disponible
inmediatamente. Adems en la mayora de los casos se puede hacer uso de
SOAP a travs de los cortafuegos que defienden las redes, ya que no suelen
tener bloqueadas las peticiones a travs del puerto 80, el puerto por defecto de
HTTP (de ah la ubicuidad, aunque se pueden usar otros puertos distintos al 80,
por supuesto).
Nota:
Existen ampliaciones al protocolo SOAP base que definen protocolos y
convenciones para tareas especficas como las mecionadas de seguridad,
enrutado de mensajes, los eventos y muchas otras cuestiones
avanzadas. En .NET se implementan mediante los concidos Web Services
Enhancements (WSE) actualmente por su versin 3.0, y en un futuro
inmediato con Windows Communication Foundation, la nueva plataforma
de servicios de comunicaciones de Windows. El estudio de stos se sale
del mbito de este curso.
sta se parece mucho a la directiva de las pginas ASPX y, al igual que en ese caso,
define dnde se encuentra en cdigo que dotar de funcionalidad al servicio Web. En
este caso y dado que el servicio Web no posee elementos de interfaz de usuario, del
nico archivo que nos tenemos que preocupar es del que se indica en el atributo
CodeBehind. ste contiene la definicin de la clase indicada en el atributo Class, y que
en nuestro ejemplo se llama Service.
La clase Service (podra llamarse de cualquier otro modo) est dentro del archivo
Service.vb, el cual se ubica dentro de la carpeta App_Code que como ya hemos
estudiado asegura la compilacin dinmica de los archivos de cdigo que contiene.
Si abrimos el archivo Service.vb, veremos que por defecto contiene el siguiente
cdigo:
Aparte de las preceptivas sentencias Imports, vemos que la clase Service hereda de la
clase WebService. Slo con hacer esto ya obtenemos la funcionalidad necesaria para
gestionar el XML, HTTP y dems tecnologas en las que se basan los servicios Web. su
gestin pasa inadvertida para nosotros.
Los mtodos que un servicio Web expone al exterior son mtodos normales de una
clase a los que se le ha aadido el atributo WebMethod, tal y como se observa en el
cdigo anterior. Es decir, para que uno de nuestros mtodos 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. As de sencillo.
Por ejemplo, elimine el mtodo de ejemplo HelloWorld que introduce Visual Studio y
escriba el siguiente cdigo:
Lo nico que hemos cambiado es el tipo a devolver, pero hemos ganado mucho ya
que ste se interpretar correctamente como una fecha en cualquier aplicacin que
consuma nuestro servicio.
La especificacin estndar de SOAP define representaciones en formato XML para
todos los tipos de datos bsicos que nos podemos encontrar en las aplicaciones,
incluyendo cadenas, fechas, booleanos, etc... Cualquier clase (o tipo) que se use
como parmetro o como valor devuelto por un mtodo que se expondr en un
servicio Web se serializa a XML antes de ser enviada a travs de la red tanto en un
sentido como en el otro (cliente-servidor y viceversa).
Serializar a XML un objeto consiste en generar una representacin 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. En el caso de tipos
bsicos la cosa es fcil aunque se debe seguir una convencin para hacerlo. En el caso
de otros objetos ms complejos (como los dataSet, por ejemplo) el formato XML
ovtenido es mucho ms complejo y no se encuentra estandarizado, si bien al ser XML
y disponer de su esquema es muy fcil utilizarlos desde cualquier lenguaje.
Como resumen de este prrafo hay que quedarse con una idea: slo se pueden
emplear clases serializables como parmetros o valores devueltos por un mtodo
de un servicio Web.
Nota:
Los objetos de la clase DataSet de ADO.NET son objetos serializables
que estn adaptados a la perfeccin para su uso en un servicio Web. De
hecho es muy habitual que se utilicen como valores devueltos y como
parmetros en mtodos de servicios Web. Los DataSet tipados tambin
se incluyen en esta categora y de hecho pueden resultar incluso ms
sencillos de utilizar cuando el servicio se invoca desde entornos
diferentes a .NET.
Descripcin de mtodos
El atributo WebMethod no slo se usa para especificar que un mtodo determinado de
la clase se expondr para su consumo desde el exterior. Adems se usa para
especificar ciertos comportamientos del mtodo. A efectos de lo que nos interesa en
este curso veremos slo uno de los parmetros de este atributo: Description.
Con Description ofreceremos a los programadores que consuman nuestro servicio
informacin sobre lo qu hace el mtodo lo que puede ser de gran utilidad. Con ello
dejamos nuestro mtodo finalmente definido como:
Con esto queda definido nuestro sencillo servicio web de ejemplo. Enseguida veremos
cmo utilizarlo.
Parmetros opcionales y/o sobrecarga de mtodos Web
Imaginemos que tenemos que crear un servicio Web para una tarea determinada
(para simplificar, digamos, realizar una suma), y dicha tarea debe trabajar con
diferentes tipos de datos o debe poder usarse de varias formas con parmetros
diferentes.
En una clase .NET podemos crear versiones sobrecargadas de un mtodo cada una de
las cuales tomar el tipo de datos pertinente, siendo el propio compilador el que
llamar a la versin sobrecargada que convenga en cada caso.
En el caso de un
obtener el mismo
mismo nombre.
permite conseguir
MessageName se utiliza para asignar alias a los mtodos Web que definamos, de
forma que podemos identificar de manera nica a cada uno de ellos, incluso aunque el
Las dos funciones con el mismo nombre y diferentes parmetros son perfectamente
vlidas en VB.NET. Sin embargo si hubisemos colocado simplemente la palabra
WebMethod delante de ambas hubisemos obtenido un error a la hora de compilar ya
que no pueden exponerse dos mtodos con el mismo nombre en un servicio Web.
Cambiando el nombre del mensaje de una de ellas se pueden exponer sin problema
ya que a la hora de consumirlas, aunque tengan el mismo nombre, se distinguen
perfectamente por el nombre del mensaje empleado.
Con esto conseguimos el efecto de mtodos Web sobrecargados.
Tal y como comentamos en la primera leccin, para que un cliente pueda consumir un
servicio Web deber primero leer el "contrato" de uso del servicio, es decir,
averiguar los mtodos que ste ofrece y la forma de invocarlos. Como recordar este
contrato est escrito con el lenguaje WSDL (Web Service Description Language). Para
obtener el WSDL correspondiente a nuestro servicio basta con presionar sobre el
enlace "descripcin de servicios" que ofrece la pgina autogenerada. El aspecto del
WSDL es este (parcial):
En nuestro caso agregaremos una referencia al servicio Web de hora que creamos en
el apartado anterior escribiendo la URL en la lnea de direccin URL.
Credenciales de acceso
Podemos proteger el acceso a un servicio Web usando los mtodos de autenticacin u
autorizacin proporcionados por Internet Information Server. Si deshabilitamos la
autenticacin annima y marcamos la autenticacin de Windows, para poder acceder
al servicio deberemos facilitar credenciales de acceso validas. stas se corresponden
con el nombre de usuario y la contrasea de un usuario del sistema. El cdigo
necesario para hacerlo es el siguiente:
Dim sh As New ServicioHora.Service()
sh.Credentials = New System.Net.NetworkCredential("usuario",
"clavesecreta")
....
Con esto obtendremos una barrera de proteccin bsica para nuestro servicio Web.
Nota:
Existen una serie de especificaciones adicionales para servicios Web
denominadas Web Service Enhancenments (WSE) que aaden funciones
especiales para autenticacin, privacidad, cifrado, enrutado, y otras
muchas tareas avanzadas. Estos WSE siguen las especificaciones
conocidas como WS-*, que son un estndar de la W3C y la nuev
aplataforma unificada de mensajera de Microsoft, Windows
Communication Foundation, tambin las implementa para sus
servicios web. El estudio de WSE se sale del mbito de este curso.
La aplicacin
MSDN Video es una aplicacin
de
ejemplo
empresarial
desarrollada en Espaa por la
comunidad de desarrollo y
Microsoft. Puede utilizarse para
comprobar las mejores prcticas
en la construccin aplicaciones
distribuidas, escalables y con
distintos
tipos
de
clientes
(Windows, Web y mviles).
La aplicacin que desarrollaremos en este tutorial es una versin reducida de MSDN
Video donde podr ver Visual Studio 2005 en accin en un escenario sencillo.
Cdigo fuente de MSDN Video
Puede descargar el cdigo fuente de MSDN Video y visionarlo o editarlo en su mquina.
Nota:
MSDN Video utiliza una base de datos para almacenar su estado. Si
desea ejecutar la aplicacin en su mquina necesitar SQL Server 2005
Express instalado.
Videos explicativos
Si desea ver cmo se hizo esta aplicacin puede visionar estos videos donde
desarrollamos la aplicacin paso a paso:
Tomado de:
http://www.desarrollaconmsdn.com/msdn/Cursos/Curso_Desarrollo_web_con_Visual_Stud
io_2005/index.html