Además - Tecnología, Tips y Programación por Sergio Gonzalez

Transcripción

Además - Tecnología, Tips y Programación por Sergio Gonzalez
nº31 Noviembre 2006 • 6,50 € (España)
Visual Basic • C# • ASP.NET • ADO.NET • .NET Framework • Windows Server System
dotNetManía
www.dotnetmania.com
Dedicada a los profesionales de la plataforma .NET
TodotNet QA
Más allá del mito
Discusión sobre AJAX y ATLAS
Eventos
EuroDevCon 06 y EKON 10
Frankfurt, Alemania
Laboratorio
TestRunner for Visual Studio 2005
Fundamentos de AJAX. Cómo utilizarlo sin
ayudas externas• AJAX con
ASP.NET 2.0. Script callbacks•
AJAX, redefiniendo la
forma de ver la Web •
Microsoft AJAX
Library (Atlas). Cómo
extender ASP.NET con
lo más “cool” de la Web 2.0
Además
Relación entre delegados y eventos
El avisador que te avise, buen avisador será
Presentación de SharePoint
opinión
Orientación al producto versus orientación al procedimiento
dnm.editorial
dotNetManía
Dedicada a los profesionales de la plataforma .NET
Vol. III •Número 31 • Noviembre 2006
Precio: 6,50€
Eventos, eventos, eventos...
Editor
Paco Marín
([email protected])
Editor técnico
Octavio Hernández
([email protected])
Consejo de Redacción
Dino Esposito, Guillermo 'guille' Som, José
Manuel Alarcón, Lorenzo Ponte, Luis Miguel
Blanco y Miguel Katrib (Grupo Weboo).
Colaboradores habituales
Antonio Quirós, Braulio Díez, Carlos
Quintero, Eladio Rincón, Javier Aragonés,
Jorge Serrano, José Miguel Torres, Iván
González, Pepe Hevia, Salvador Ramos y
Sergio Vázquez
Además colaboran en este número
Gustavo Vélez, Hadi Hariri, Miguel Jiménez
y Román Fresneda
Atención al suscriptor
Pilar Pérez
([email protected])
Ilustraciones
Yamil Hernández
Edición, suscripciones y publicidad
.netalia
c/ Robledal, 135
28529 Rivas-Vaciamadrid (Madrid)
www.dotnetmania.com
Tf. (34) 91 666 74 77
Fax (34) 91 499 13 64
Imprime
GRUPO MARTE
ISSN
1698-5451
Depósito Legal
M-3.075-2004
>>
<<
Eventos, eventos, eventos... Para cuando tenga este ejemplar en sus manos ya se
habrá celebrado el CodeCamp en El
Escorial –les contaremos todo el mes que
viene–; a principios de noviembre tenemos el Tech–Ed Europe en Barcelona,
que este año se celebra conjuntamente con
el IT Forum; coincidiendo con éstos se
celebra en Madrid el SIMO, donde se presentará Windows Vista y 2007 Microsoft
Office System en su versión empresarial;
inmediatamente después, el 13 de noviembre nos visita David Chappell, que participará en la conferencia sobre SOA y
Business Process que ofrece gratuitamente Microsoft Ibérica; terminando
noviembre, se celebra expoQA, un evento
para profesionales de la ingeniería, la calidad y las pruebas de software; y también la
sexta edición de la feria MovilForum, donde los desarrolladores pueden entrar en contacto con los clientes de Movistar. ¡Qué hartazón de eventos, amigo!
Bienvenido al número 31, de noviembre de 2006, de dotNetManía.
Creo (aunque esté mal que yo lo
diga) que nos ha quedado un estupendo
especial sobre AJAX, tecnología imprescindible para el desarrollo de las aplicaciones Web de hoy y de mañana. Claro
que en realidad el mérito es de los autores. José Manuel Alarcón nos explica
los fundamentos de AJAX y los script callbacks, sin hacer referencia a implementación alguna; Miguel Katrib y Román
Fresneda usan la implementación
conocida como Ajax.NET (The Free
Library for .NET), de Michael Schwarz;
Miguel Jiménez presenta la implementación de Microsoft, Microsoft
AJAX Library (antes conocida como
Atlas), ahora ya en beta 1; y, por último,
Dino Esposito, con el espléndido título “Más allá del mito. Discusión sobre
AJAX y ATLAS”, ha agrupado preguntas relacionadas con el tema que nos ocupa. ¡Gracias a los cinco!
Si aún no sabe para qué sirve Sharepoint, le recomiendo que se lea el artículo de Gustavo Vélez, al que doy la bienvenida por su primera colaboración,
“Presentación de Sharepoint”.
Ajeno a la AJAXManía de este
número, El Guille continúa apuntalando los fundamentos de .NET, esta
vez con las relaciones entre delegados
y eventos, con su “Relación entre delegados y eventos. El avisador que te avise, buen avisador será”.
Hadi Hariri, fundador del grupo de
usuarios .NET de Málaga, se nos marchó
a Frankfurt al EuroDevCon 06 y EKON
10 –eventos para desarrolladores de
Borland– como ponente y también como
reportero de esta revista. Desde allí nos
mandó sus impresiones.
Por último, no quiero terminar sin
antes agradecer el esfuerzo extra realizado por Yamil Hernández, quien ha
ilustrado la portada y algunos artículos
interiores de este especial con su versión
de Ajax, el héroe griego.
Y esto es prácticamente todo por este
mes. Espero que le resulte útil.
Paco Marín
<<dotNetManía
Redactor Jefe
Marino Posadas
([email protected])
3
31
dnm.sumario
EuroDevCon 06 y EKON 10
08
Coincidiendo con el reciente lanzamiento de la línea de productos Turbo de Developer
Tools Group (una división de Borland), tuvo lugar en Frankfurt, Alemania, del 25
al 29 de septiembre, la décima edición de la Entwickler Konferenz (EKON), combinada
con la sexta Euro Developer Conference (antigua European BorCon).
Métricas para la evaluación de procesos de construcción de software
10-11
En la anterior entrega cogimos el metro para estimar la carga de trabajo necesaria a fin
de realizar un proyecto de construcción de software. Medimos, diseñamos, construimos y
ahora vuelve a tocar sacar el metro del bolsillo para comprobar si lo que hemos realizado
se corresponde con lo que planificamos, así como para verificar si el proceso de construcción
ha seguido las normas adecuadas y/o si tenemos evidencias de que no habrán demasiados
defectos que compliquen el mantenimiento futuro del mismo.
Fundamentos de AJAX. Cómo utilizarlo sin ayudas externas
13-19
Si hay una palabra de moda últimamente en el mundo del desarrollo Web, ésta es
sin duda AJAX. En este artículo vamos a aprender sus fundamentos, independientes
de la tecnología de servidor utilizada. Ello nos será útil para comprender mejor las
nuevas bibliotecas especializadas (como Atlas) y evitar posibles errores.
AJAX con ASP.NET 2.0. Script callbacks
20-24
dnm.sumario
La reciente versión 2.0 de ASP.NET ofrece una nueva técnica para implementar páginas
AJAX pero usando métodos nativos de servidor. Nos abstrae de la mayor parte de las
complejidades asociadas al código de script de cliente, limitándose nuestra aportación en
este sentido a procesar los resultados devueltos. En este artículo veremos cómo funcionan
los script callbacks.
AJAX, redefiniendo la forma de ver la Web
26-34
AJAX es el nombre con que se ha "popularizado" a un grupo de tecnologías que juntas
han cambiado la forma en que vemos la Web. AJAX abre la posibilidad de invocar
asíncronamente desde Javascript a código del lado del servidor en una aplicación Web,
usando XML como transporte (aunque se verá que esto último no es necesariamente así).
Microsoft AJAX Library (Atlas).
Cómo extender ASP.NET con lo más "cool" de la Web 2.0
35-40
La combinación tecnológica de XHTML, CSS, Javascript y XMLHttpRequest,
acuñada bajo el término AJAX desde 2005, representa la fórmula mágica de la
poción que está revolucionando el concepto de la Web. Los desarrolladores de ASP.NET
pueden unirse a la cruzada tecnológica gracias a Microsoft AJAX Library, una
extensión de ASP.NET que proporciona la funcionalidad deseada desde la comodidad
del .NET Framework 2.0 y Visual Studio 2005.
Presentación de SharePoint
41-44
SharePoint es el servidor con el crecimiento más acelerado de todos los productos de
Microsoft. Éste es un artículo introductorio sobre el producto, su arquitectura,
programabilidad y la nueva versión que aparecerá en corto plazo.
Relación entre delegados y eventos.
El avisador que te avise, buen avisador será
45-50
En el número anterior vimos con detalle casi todo lo concerniente a los delegados, y aunque
solo lo viésemos de pasada, comprobamos la relación entre los delegados y los eventos. En
este número nos centraremos en los eventos, pero antes comprobaremos que hay ciertas
características de los delegados que los hacen imprescindibles para usarlos con los eventos.
dnm.todotnet.qa
Más allá del mito. Discusión sobre AJAX y ATLAS
51-53
Las extensiones AJAX constituyen la siguiente gran novedad en el desarrollo de
ASP.NET, como puede ver el lector en este número de la revista. En esta columna
responderé algunas cuestiones que he recogido en las pasadas semanas, tratando de
hacer una introducción al mundo AJAX de forma suave y gradual.
dnm.laboratorio
TestRunner for Visual Studio 2005
dnm.biblioteca.net
54
55
Programación con ASP.NET 2.0. Jesse Liberty y Dan Hurwitz
Fundamentos de Bases de datos con Visual Basic 2005. Thearon Willis
dnm.desvan
58
6
noticias.noticias.noticias.noticias.noticias.noticias
<< dotNetManía
<< dnm.noticias
Feria movilforum 2006
Al día con versiones beta
La Feria movilforum es el gran evento movistar dedicado a
presentar los últimos desarrollos ligados con la movilidad y
enfocado a generar negocio poniendo en contacto a los
desarrolladores con los clientes de movistar.
Beta 1 del Developer Kit para .NET
Micro Framework
Más de 50
empresas,
entre expositores, colaboradores y patrocinadores
estarán presentes en esta edición,
una edición que contará con numerosas novedades y una fuerte presencia internacional.
Presentará un área de exposición
sectorizada en cinco grupos de actividad: Construcción, Industria y
Telecomunicaciones, Distribución,
Logística y Transporte; Medios de
Comunicación, Ocio y Turismo;
Sanidad y Administraciones Públicas; y Seguridad y Banca. Una oferta que se ampliará con los productos y promociones de las empresas
patrocinadoras y colaboradoras.
Otro aspecto destacable es el
hecho de que movilforum se extiende por América Latina como un
medio de apoyar a clientes movistar a través del foro que soporta tanto tecnológica como comercialmente a empresas desarrolladoras.
Una iniciativa que tendrá una
importante presencia en la feria de
este año gracias a la participación
como expositor de empresas pertenecientes a movilforum Latinoamérica y a través de diversas actividades, que en un futuro próximo
tendrán correspondencia como
oportunidades en los países del
entorno de Latinoamérica.
De la misma manera, a través de
los productos y desarrollos presentados por la empresa O2, que se
encontrará entre los colaboradores,
los visitantes podrán conocer en qué
estado se encuentra el mercado de
los aplicativos móviles en otros países europeos.
A través de la presencia de los
responsables de Telefónica Móviles
España en ponencias, foros sectoriales y mesas redondas temáticas,
podrán recoger de primera mano la
visión de la situación del mercado
de telefonía móvil y sus tendencias
de evolución futura.
Más información en www.feria.
movilforum.com.
CATÁLOGO MOVILFORUM
MovilForum presenta el nuevo
Catálogo de Soluciones Móviles, que
reúne más de 220 productos desarrollados por 70 empresas miembro. El
catálogo se ha dividido en una guía de
soluciones de movilidad y una colección de 9 catálogos sectoriales. El
Catálogo de Soluciones Móviles está
accesible para todos aquellos interesados en la movilidad a través de
www.movistar.es/empresas/servicios.
Presentación de Windows Vista y 2007
Microsoft Office System en SIMO 2006
La edición 2006 de la feria teccompañía en la feria, que este año
nológica SIMO ha sido el marco
ocupa el Pabellón 2 de IFEMA en
elegido por Microsoft para realizar
su totalidad. Para ello, Microsoft
el lanzamiento a empresas de dos de
contará con un auditorio en el que
los productos insignia de la comse realizarán presentaciones y sesiopañía: Windows Vista y 2007
nes demo, con capacidad para alberMicrosoft Office system.
gar a 1.500 personas.
El anuncio
oficial de estos PRESENTACIONES
Presentación para empresas: martes 7 a las 17.00 horas
productos
Presentación para profesionales TI: miércoles 8 a las 10.30 horas
tendrá lugar en
Presentación para desarrolladores: miércoles 8 a las 16.00 horas
el stand de la
Microsoft hizo este anuncio en el marco de la Embedded Systems Conference
en Boston.
El nuevo Micro Framework permite a los desarrolladores construir
aplicaciones para dispositivos muy
pequeños (limitados por el coste, la
memoria, el procesador y/o el consumo de energía) como sensores, monitores corporales para la atención
médica, automatización del hogar,
controles remotos, etc.
Puede ver más información en la crónica del MEDC de Niza, publicada en el
número 28, de julio-agosto, de dotNetManía y en http://www.aboutnetmf.com.
Visual Studio 2005 SP1 Beta
Microsoft ha anunciado la disponibilidad de la primera beta del service pack 1
para Visual Studio 2005. Una vez recibidos los comentarios de esta beta por los
usuarios, aproximadamente dentro de
unos 3 ó 4 meses estará lista la versión
definitiva.
Si quiere información técnica de esta
beta y descargas diríjase a http://connect.microsoft.com/VisualStudio.
ASP.NET AJAX Beta 1
Microsoft ha anunciado la Beta 1 de
ASP.NET AJAX v1.0 (antes ATLAS). La
idea es sacar una nueva beta en unas pocas
semanas, después una release candidate y
finalmente la versión final 1.0, que aún no
tiene fecha oficial. Más información y descargas en: http://ajax.asp.net. Presentación
de esta beta por Scott Guthrie en su blog:
http://weblogs.asp.net/scottgu/archive/2006/10/20/ASP.NET-AJAX-Beta-1Released.aspx.
Virtual PC 2007 Beta 1
Virtual PC 2007 Beta 1 está disponible para su descarga en: https://connect.
microsoft.com/programdetails.aspx?Program
DetailsID=874. Virtual PC 2007 está optimizado para trabajar correctamente con
Windows Vista.
dnm.noticias
Tercera edición de expo:QA, Jornadas de
Calidad y Testing de Software
expo:QA consolida su presencia en
el sector de la calidad y el testeo del software anunciando su 3ª edición los próximos 27, 28, 29 y 30 de noviembre en
el Hotel Meliá Barajas de Madrid.
expo:QA responde a la necesidad de
crear en España un espacio especializado, donde los profesionales de la ingeniería, la calidad y las pruebas de software puedan compartir conocimientos.
Es un lugar de encuentro para descubrir
las últimas soluciones, conocer prácticas
reales y compartir experiencias con
expertos en temas de automatización del
testeo, gestión de procesos de desarrollo, gestión de proyectos y testeo de software, entre otros temas.
Las jornadas están dirigidas a directores de desarrollo, responsables de proyectos, gerentes de calidad y profesionales de TI. En estas jornadas podrán
disfrutar de:
• Presentaciones y exposición de las
empresas más importantes de la indus-
tria: Borland, Compuware, TCP,
Telelogic, PRQA, Mercury, Gesein,
inQA.labs, Microsoft e IBM, siendo
estos dos últimos los patrocinadores
Premium del evento.
• Conferencias técnicas impartidas por
destacados profesionales del sector.
• Taller “Hands On” de soluciones de
calidad y testeo de software de la compañía Mercury.
• Cursos para los profesionales que quieran ampliar sus conocimientos en temas
de calidad y testeo de software, impartidos por especialistas que abordarán temas
actuales y prácticos.
inQA:labs, el equipo organizador de expo:QA
busca asociaciones, entidades, instituciones, universidades y medios de comunicación involucrados en el sector de las TIC e interesados en
fomentar la calidad del software en España para
apoyarle en la iniciativa de la expo:QA 2006. Si
está interesado o necesita más información no
dude en contactarnos en [email protected]
(www.expoqa.com) o al teléfono +34-932917632.
Tech-Ed 2006
Developers e IT Forum
Tech-Ed 2006 Developers se celebrará en Barcelona entre los días 7 al
10 de noviembre. Este evento es el más
importante que se realiza en la zona
EMEA para desarrolladores y arquitetos de software que usan tecnologías de
Microsoft.
Más información en: http://www.ms
eventseurope.com/TechEd/06/pre/defaultdev.aspx.
Tech-Ed 2006 IT Forum se celebrará también en Barcelona entre los días
14 y 17 de noviembre. Este evento está
diseñado para profesionales TI.
Más información en: http://www.ms
eventseurope.com/TechEd/06/pre/defaultitf.aspx.
Microsoft organiza la conferencia de SOA y Business Process con
la participación de David Chappell
Microsoft celebra el 13 de noviembre, en las instalaciones de
Microsoft en Pozuelo de Alarcón (Madrid), la conferencia de SOA y
Business Process Management (BPM) para proporcionar una mayor perspectiva sobre estas áreas y una visión general de las tecnologías de
Microsoft como WCF (Windows Communication Foundation), BizTalk
Server y Windows SharePoint Services.
La finalidad de este encuentro, dirigido a los responsables de la toma
de decisiones en TI, arquitectos, desarrolladores, administradores de
TI y otros interesados en ampliar sus conocimientos, es intercambiar
información y experiencias sobre estos productos de servidor para la
construcción de soluciones de proceso de negocios e integración. Para
ello, se contará con la participación especial de David Chappell, quien
analizará el mercado actual y examinará tanto los beneficios potenciales como la inversión requerida para lograr el éxito empresarial.
Los interesados en registrarse al evento pueden hacerlo directamente a través de la dirección Web http://www.microsoft.es/biztalk o en el teléfono 902 197 198.
David Chappell
David Chappell, Principal
de Chappell & Associates
(www.davidchappell.com) en San
Francisco, ha participado en
numerosos eventos y conferencias en Estados Unidos,
Europa, Asia y Latinoamérica,
y a sus seminarios han asistido
decenas de miles de desarrolladores, arquitectos, y responsables de la toma de decisiones de 40 países. Los libros de Chappell sobre software empresarial se han publicado en diez idiomas y se
han utilizado en ciertas carreras del MIT, la ETH de
Zurich y docenas de otras universidades. Y en sus prácticas de consultoría, ha ayudado a clientes de la talla de
Hewlett-Packard, IBM, Microsoft, Universidad de
Stanford y Target Corporation a adoptar nuevas tecnologías, comercializar nuevos productos, formar al personal de ventas y crear planes de negocio.
dnm.noticias
<< dotNetManía
David Chappell participará en este evento para facilitar una
amplia perspectiva de las tecnologías de Microsoft en SOA
y BPM, así como los beneficios que se obtienen al utilizar
Microsoft BizTalk Server
7
dnm.directo.eventos
Hadi Hariri
EuroDevCon 06 y EKON 10
Coincidiendo con el reciente lanzamiento de la línea de productos Turbo de Developer
Tools Group (una división de Borland), tuvo lugar en Frankfurt,Alemania, del 25 al 29
de septiembre, la décima edición de la Entwickler Konferenz (EKON), combinada con
la sexta Euro Developer Conference (antigua European BorCon).
<< Un cambio muy significativo fue la presencia de numero-
Hadi Hariri es
desarrollador y ponente
habitual en conferencias
internacionales sobre
.NET y otras
tecnologías.
Además es el fundador
del grupo de usuarios
.NET de Málaga y
actualmente trabaja en
Atozed Software
sas personalidades de la división de Developer Tools
Group (DTG) de Borland, incluyendo a David
Intersimone (evangelista por excelencia), Jason
Vokes, Jon Harrison, Gerard van der Pol de
EMEA y Nick Hodges, antiguo miembro de TeamB
y nuevo Product Manager de Delphi. Después de la
inauguración oficial de la conferencia por parte de
Massoud Kamali y Sebastian Meyen, de Software
& Support Verlag, organizadores del evento, se dio
paso al Delphi Product Address, donde Nick Hodges
deleitó al público con las novedades del compilador,
entre las cuales destacan las clases parciales y los tipos
parametrizados (genéricos). Aunque inicialmente
estas características serán solo para los compiladores
.NET, se mencionó que se estaba estudiando la posibilidad de portar la funcionalidad a Win32 y consecuentemente a los compiladores de 64 bits de Delphi
que verán la luz en 2008. Se recalcó que Highlander,
la próxima versión de Delphi, estará disponible para
el primer cuatrimestre de 2007 y un poco más adelante también verá la luz la VCL para Compact
Framework, lo cual supone todo un acontecimiento
para los desarrolladores de CF. También se anunció
que ECO (Enterprise Core Objects), la plataforma de
diseño y generación de código basada en UML de
Borland Developer Studio dará soporte para la
VCL.NET y no solo para Windows Forms y
ASP.NET como hace actualmente. Claramente, se
trata de una apuesta de DTG por la VCL.NET y por
proporcionar una ruta fácil de migración para sus
clientes de Win32 a .NET, sin problemas de compatibilidad.
La agenda tenía aproximadamente la mitad de las
charlas en inglés y la otra mitad en alemán. Estuvieron
presentes ponentes de reconocido prestigio como
David Intersimone junto a la tarta del EKON 10
Michael Li, Marco Cantú, Ray Kanopka, Bernd
Ua y Neal Ford. En la sección de fabricantes, no faltaron las empresas que asisten todos los años como
Atozed Software, Raize Software, IB Experts o
Advantage Database iAnywhere, entre otros. Y los
Delphi Code Camps fueron una ocasión perfecta para
que los asistentes y ponentes intercambiaran opiniones y discutieran cuestiones de actualidad.
Otro de los cambios importantes este año fue el
énfasis en DTG y no en Borland. La presencia exclusiva de desarrolladores y personas técnicas en el stand
de DTG, así como la ausencia de los productos englobados bajo lo que Borland denomina ALM, indicaba
claramente el compromiso de DTG de ser una empresa de productos para desarrolladores y cercana a ellos.
Al ser el décimo aniversario de EKON, se celebró la ocasión con una fiesta sorpresa, tanto para
Massoud Kamali como para los asistentes, con una
tarta enorme, así como con la presencia de bailes al
más puro estilo de los carnavales de Rio. Obviamente,
al haber tenido lugar el evento en Alemania, no faltó en ningún momento la cerveza.
dnm.opinion
Antonio Quirós
Métricas para la evaluación de procesos
de construcción de software
En la anterior entrega cogimos el metro para estimar la carga de trabajo necesaria a fin de realizar un proyecto de construcción de software. Medimos, diseñamos, construimos y ahora vuelve a tocar sacar el metro del bolsillo para comprobar si lo que hemos realizado se corresponde con lo que planificamos, así
como para verificar si el proceso de construcción ha seguido las normas adecuadas y/o si tenemos evidencias de que no habrán demasiados defectos que
compliquen el mantenimiento futuro del mismo.
<< El objetivo es que aprendamos de lo sucedido en los
Antonio Quirós
es colaborador habitual de
dotNetManía.
Co-fundador de las revistas
clippeRManía, FOXManía y
Algoritmo.Actualmente es
Director de Operaciones en
Alhambra-Eidos
proyectos para poder predecir en el futuro lo que
sucederá en los nuevos que abordemos. Imaginemos
el siguiente caso. Tenemos una compañía que sistemáticamente obtiene una media de defectos en el
software que construye que supone un 5% del tiempo total empleado en cada proyecto. Esto quiere
decir que cada 100 horas estimadas lo normal es
que el equipo necesite 105 para lograr la estabilización del software que ha construido. La estimación de las 100 horas la obtiene con técnicas de
medida estándar (puntos por función u otras similares), pero su repositorio histórico de proyectos le
indica que el 5% de los defectos es la media de
impacto sobre el software que construye. ¿Qué debe
hacer en sus siguientes estimaciones? Pues evidentemente, aprender de su historia e incrementar en
un 5% su estimación de carga de trabajo necesaria.
Si no lo hace así perderá dinero y creará incertidumbre en las expectativas que el cliente tiene en
el software que construye, ya que sistemáticamente el tiempo previsto se verá incumplido.
Lo que cada empresa o equipo de desarrollo puede medir para lograr este objetivo quizá sea diferente en función del tipo de proyectos que aborde y de
sus intereses particulares. En lo que a mí respecta, voy
a mencionar a continuación un conjunto de indicadores que usamos (entre otros) en mi compañía y que
nos ayudan en las reseñadas facetas de seguimiento y
predecibilidad.
El objetivo es que aprendamos de lo
sucedido en los proyectos para poder
predecir en el futuro lo que sucederá
en los nuevos que abordemos
Desviaciones en las fechas de entrega
Este indicador nos proporciona el porcentaje de
retraso en los procesos de análisis y construcción. La
fórmula que empleamos para el cálculo es:
% de retrasos = 100 * (días de retraso /
días de duración total)
Estabilidad de recursos humanos en
proyectos
Se trata de medir qué recursos se han mantenido
asignados al proyecto durante todo el tiempo inicialmente previsto. Evidentemente, la estabilidad de los
recursos y el hecho de que se cumpla que una tarea
planificada para un recurso es realizada por dicho
<< dnm.opinion
Promedio diario de
producción por proyecto
recurso, y no por otro, es una garantía de calidad. La
fórmula que empleamos para el cálculo es:
% recursos estables = 100 * (recursos estables /
recursos totales)
Al igual que el anterior,
éste no es un indicador de
calidad sino de eficiencia de
equipo. Lo que trata de
medir es el volumen económico medio que la compañía es capaz de facturar
cada día. Si el equipo de
trabajo es estable, una
mejora en este objetivo nos
indicaría que la productividad es mejor. Si el equipo crece o disminuye hay que
ponderar el indicador con estos cambios. La fórmula
que empleamos para el cálculo es:
promedio = € de proyectos /
días totales tardados en realizar dichos proyectos
Defectos en pruebas de aceptación
indice defectos = defectos reportados /
horas de la aplicación
Evidentemente, la aplicación de esta fórmula de
cálculo debe hacerse para una unidad de tiempo concreta que permita el seguimiento evolutivo, así tendremos en cuenta, por ejemplo, los proyectos cerrados en un mes, en un trimestre, etc.
Utilización de capacidad de desarrollo
Al igual que los dos anteriores, éste es un indicador de eficiencia. Trata de medir hasta qué punto tenemos empleados a los recursos de desarrollo de la compañía en proyectos facturables. La fórmula que empleamos para el cálculo es:
El empleo en el denominador de las horas que ha
costado construir la aplicación tiene como finalidad
la de trabajar con una unidad de medida fácil de calcular en cada momento, pero podría sustituirse por
los puntos por función totales de la aplicación o por
las líneas de código (LOC).
Siendo las horas teóricas aquellas que la suma de
los desarrolladores de la plantilla pueden realizar
excluidas vacaciones.
Eficiencia en proyectos de desarrollo
Defectos en garantía
La eficiencia no es, desde luego, un indicador
de calidad, pero sí nos indica hasta qué punto somos
productivos haciendo lo que hacemos, lo que, sin
duda, nos ayudará a hacer las cosas mejor en el futuro. Lo que realmente tratamos de medir aquí es la
diferencia que existe entre las horas que estimamos
que durará un proyecto y las que realmente nos lleva a hacerlo. Una cifra baja aquí no dirá nada acerca de si hacemos buen o mal software, pero probablemente nos lleve a la ruina. La fórmula que empleamos para el cálculo es:
Volvemos a los indicadores de calidad, aunque éste
(como en realidad todos) también tiene connotaciones económicas. Lo que mide es el impacto que tienen los reportes de errores de los clientes una vez que
la aplicación está terminada y aceptada. La fórmula
que empleamos para el cálculo es:
% eficiencia = 100 * (horas previstas / horas reales)
% utilización = 100 * (horas reales facturables /
horas teóricas)
índice defectos garantía =
horas dedicadas resolución defectos / 1000 LOC
En este caso se han empleado indicadores de medida como el tiempo y las LOC, pero igual que en casos
anteriores, éstos pueden ser sustituidos por otros cualesquiera que cumplan la misma función.
<<dotNetManía
Este indicador trata de medir el número de fallos
que los usuarios reportan en el proceso de realizar
las pruebas de aceptación de una aplicación, es decir,
en el último momento del ciclo de desarrollo de la
misma y donde el software ha debido pasar ya todos
los controles de calidad necesarios. Un número alto
en este dato hablaría bastante mal de nuestra capacidad de prueba. La fórmula que empleamos para el
cálculo es:
11
Suscríbase y llévese los
tres próximos libros gratis
además, el CD Vol. 2 con los números 12 al 22 en PDF
❑ Nº17 (6,50€)
❑ Nº18 (6,50€)
❑ Nº19 (6,50€)
❑ Nº20 (8,50€)
❑ Nº21 (6,50€)
❑ Nº22 (6,50€)
❑ Nº23 (6,50€)
❑ Nº24 (6,50€)
❑ Nº25 (6,50€)
❑ Nº26 (6,50€)
❑ Nº27 (6,50€)
❑ Nº28 (6,50€)
❑ Nº29 (6,50€)
❑ Nº30 (6,50€)
✃❑
❑
Oferta válida hasta el 30 de noviembre de 2006 o hasta agotar existencias
Deseo suscribirme a dotNetManía por un año (11 números) por un precio de 65,00€ IVA incluido y recibir gratuitamente los
tres próximos cuadernos técnicos que publique Netalia, y además el CD Volumen 2 con los ejemplares desde el 12 al 22 en formato PDF de alta calidad de forma gratuita. Si su dirección está fuera de España consulte los detalles en www.dotnetmania.com
Deseo que me envíen los números atrasados marcados según el precio de portada. Otros:
DATOS DE ENVÍO
CIF/NIF. . . . . . . . . . . . . . . . . . . . Empresa . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Nombre y apellidos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Dirección . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Población . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .Código Postal . . . . . . . . . . . . . . . . . . . Provincia . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Teléfono . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Fax . . . . . . . . . . . . . . . . . . . . . . . . . . . email . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
DATOS DE FACTURACIÓN (sólo si son distintos a los datos de envío)
CIF/NIF. . . . . . . . . . . . . . . . . . . . Empresa . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Nombre y apellidos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Dirección . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Población . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .Código Postal . . . . . . . . . . . . . . . . . . . Provincia . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Teléfono . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Fax . . . . . . . . . . . . . . . . . . . . . . . . . . . email . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
FORMA DE PAGO
❑ Talón nominativo a nombre NETALIA, S.L.
❑ Transferencia bancaria a nombre de NETALIA, S.L. a:
La Caixa - Número de cuenta 2100 4315 48 2200014696 (Indique su nombre en la transferencia)
❑ Domiciliación Bancaria (con renovación automática, previo aviso)
Indique su número de cuenta:
❑ Tarjeta de crédito
❑ VISA
❑ MASTERCARD
Número de su tarjeta:
Fecha de caducidad:
/
(imprescindible)
Firma y/o sello
a
de
Puede enviar sus datos por Fax al 91 499 13 64, o por teléfono al 91 666 74 77,
o por email a la dirección [email protected], o también puede
enviarlos por correo postal a la siguiente dirección:
de 2006
Usted autoriza a la mecanización
de estos datos. El responsable y
destinatario de éstos es Netalia,
S.L. Usted tiene derecho a acceder a sus datos, modificarlos y
cancelarlos cuando lo desee. Sus
datos no serán cedidos en ninguna de las formas posibles a terceras partes y no se utilizarán más
que para el buen funcionamiento de su suscripción a la revista
dotNetManía y para informarle de las actividades comerciales
que realice la editorial Netalia,
S.L. Si no desea recibir información comercial de dotNetManía
marque la casilla siguiente ❑
Netalia, S.L.
C/ Robledal, 135
28529- Rivas Vaciamadrid (Madrid)
dnm.asp.net
José M.Alarcón
Fundamentos de AJAX
Cómo utilizarlo sin ayudas externas
Si hay una palabra de moda últimamente en el mundo del desarrollo Web, ésta es sin
duda AJAX. En este artículo vamos a aprender sus fundamentos, independientes de la
tecnología de servidor utilizada. Ello nos será útil para comprender mejor las nuevas
bibliotecas especializadas (como Atlas) y evitar posibles errores.
José Manuel Alarcón Aguín
es redactor de dotNetManía.
Es ingeniero industrial y
especialista en consultoría de
empresa. Ha escrito varios libros,
y ha publicado más de
trescientos artículos sobre
informática e ingeniería en
revistas especializadas.
Es MVP de ASP.NET, MCTS,
MCPD, MCT y tutor de
campusMVP.
Visite su blog en www.jasoft.org
desde sus comienzos. Las limitaciones propias del
protocolo HTTP utilizado en las páginas Web han
impuesto el tradicional modelo de “petición-cargaprocesado de cliente” y vuelta a empezar. En una aplicación Web normal el usuario solicita una página, el
servidor devuelve el contenido HTML de ésta (normalmente generado a partir de alguna tecnología de
servidor como ASP.NET), el navegador lo procesa
y visualiza su contenido. Una vez que el usuario interactúa con el HTML, envía un formulario al servidor o pulsa un enlace, y se repite el ciclo: se solicita la página, se devuelve su contenido, se procesa y se visualiza.
Este proceso es el más natural para HTTP
(pensado desde luego de esta manera), pero
tiene el problema de que, a veces, para
obtener una página prácticamente igual
pero con pequeñas modificaciones es
necesario recargar la página completa.
Esto está especialmente vigente desde
que ASP.NET apareció en escena hace
unos años con su novedoso sistema de
postback, gracias al cual una aplicación
Web se programa prácticamente igual que
una de escritorio, respondiendo a eventos y
accediendo directamente a las propiedades de los
objetos. El problema de este sistema es que cada
uno de los postbacks al servidor hace que se recargue la página completa, lo cual es percibido de
manera evidente por los usuarios (es decir, “se
nota”) y crea una sensación poco amigable.
Si bien el concepto de postback es extre-
madamente útil, las actuales tendencias en el desarrollo Web hacen que éstas sean cada vez más parecidas a aplicaciones de escritorio (se han dado en
llamar aplicaciones Web 2.0). Esto implica que los
molestos y a la vez inevitables viajes al servidor no
deben ser percibidos por los usuarios. La sensación
para éstos debe ser la de que la aplicación está todo
el tiempo en su equipo, dejando de lado al servidor,
como en una aplicación de escritorio tradicional.
Cualquiera que haya usado GMail o Flickr sabe de
qué estoy hablando.
<<dotNetManía
<< Las aplicaciones Web llevan siendo más o menos iguales
13
<<dotNetManía
<< dnm.asp.net
14
Desde que el HTML Dinámico
(HTML + Javascript) y las hojas de estilo CSS hicieron su aparición, cada vez
más aplicaciones hacen uso de las posibilidades de modificación “al vuelo” de
contenidos que estas tecnologías brindan. Hoy en día todos los navegadores
soportan DHTML, por lo que escribir
complejos programas que interactúen
con los contenidos de la página no implica, como antes, tener que dejar fuera a
parte de tus posibles usuarios. Desde hace
ya bastantes años existen aplicaciones que
haciendo uso de DHMTL crean espectaculares efectos en las páginas y modifican dinámicamente contenidos.
Lo que ya no es tan habitual es que
estos contenidos dinámicos vengan
determinados por programas que están
en el servidor. La idea es hacer las peticiones al servidor (donde está la lógica
de nuestro programa escrita en
ASP.NET, PHP, JSP o el lenguaje que
sea), pero de forma que este hecho sea
transparente para los usuarios. Este es
el objetivo perseguido por AJAX.
Este simpático acrónimo hasta hace
poco asociado con el apasionante mundo de la limpieza, viene del inglés
Asynchronous Javascript And XML. Se
basa en el uso de un objeto llamado
XMLHttpRequest, presente en los navegadores modernos, que como es de
imaginar sirve para hacer peticiones de
documentos XML a través del protocolo HTTP, y que apareció por primera vez en las bibliotecas XML de
Microsoft (MSXML). Con este objeto
se piden documentos XML que luego
es posible manipular mediante código
Javascript desde dentro de una página
y mostrar resultados dentro de elementos de la misma. Esta es la idea
básica, aunque como veremos da
mucho más de sí.
Aunque ahora parece que los chicos
de Google han inventado la pólvora con
GMail, lo cierto es que el concepto original de esta tecnología fue creado por
Microsoft (se llamaba Remote Scripting).
El primer navegador en soportarlo fue
Internet Explorer y la primera aplicación
de este tipo fue Outlook Web Access, para
acceder a buzones Exchange.
Como veremos enseguida, aparte de
que su nombre original haya perdurado
por ser simpático, la realidad es que AJAX
no siempre es asíncrono ni siempre usa
XML. Lo que de verdad importa es el
objeto XMLHttpRequest; lo demás son
opciones. Este artículo presenta los fundamentos de la tecnología para que usted
no dependa de biblioteca alguna a la hora
de implementar estas características, y
sobre todo –seamos realistas– para que
cuando utilice una de dichas bibliotecas
(en este número de dotNetManía se
habla de las más importantes) comprenda lo que hay debajo y pueda determinar
posibles problemas.
•
•
•
El objeto XMLHttpRequest
Para sacar partido a AJAX, aparte de
saber HTML y Javascript, el primer
objeto que debemos conocer a fondo es
XMLHttpRequest.
Se trata de una clase disponible en
todos los navegadores modernos que permite lanzar desde Javascript peticiones de
recursos GET y POST a través de HTTP.
En lenguaje llano, esta clase nos permite
simular desde el código de nuestras páginas llamadas a Internet como si fueran
hechas por los usuarios. Si ha utilizado
alguna vez las bibliotecas MSXML con
Visual Basic 6.0 o ASP 3.0, es probable
que ya lo conozca. Aunque en el caso de
Internet Explorer se sigue exponiendo su
funcionalidad como un objeto ActiveX,
en el resto de los navegadores (Firefox,
Opera, Safari...) ya forma parte de sus clases nativas.
Los métodos y propiedades básicos
de esta clase que debemos conocer son
los siguientes (los corchetes indican
parámetros opcionales):
• open(metodo, URL, [asincrono],
[usuario], [clave]): sirve para abrir
una conexión al servidor. No envía
ni obtiene información, sólo se
conecta. El tercer parámetro es booleano y sirve para indicar si la conexión se realizará de forma asíncrona
(por defecto) o no. Los dos últimos
parámetros sirven para especificar
un nombre de usuario y una contraseña de acceso para recursos protegidos por autenticación básica, si
bien esto es bastante absurdo pues
estarán escritos en claro en el
Javascript.
• send(contenido): envía una petición.
Si el método es POST, se pueden
•
•
•
•
incluir los datos a enviar en el parámetro; en caso contrario, se usa un
nulo.
abort(): cancela un envío/petición.
onreadystatechange: se le asigna un
método que será llamado automáticamente cuando se descargue del
todo el recurso apuntado por la
URL remota (cuando se llama asíncronamente).
readyState: informa del estado de la
petición:
- 0 = no iniciada
- 1 = cargando
- 2 = terminada pero sin procesar
- 4 = completada
status : código de estado HTTP
resultado de la petición: por ejemplo 200 (éxito), 404 (no encontrado), etc.
statusText: mensaje de información
del estado anterior.
responseXML: documento DOM que
representa el XML devuelto por la
petición (se espera XML, claro).
responseText: el contenido puramente textual del recurso remoto.
Útil si no nos devuelve XML, como
es muy habitual.
Aunque la clase dispone de algunos
métodos y propiedades más, con éstas
tendremos suficiente para el 99% de los
casos que nos vamos a encontrar.
Menos teoría, vamos a la
práctica
Veamos cómo se usa la clase
XMLHttpRequest con un ejemplo sencillo.
Consideremos algo simple como el ejemplo de la figura 1. Hay una lista desplegable que contiene una serie de categorías.
Al elegir una de éstas, en la lista de al lado
deberá aparecer una lista de elementos
asociados, obtenidos dinámicamente
mediante una llamada al servidor. Este
ejemplo es muy sencillo, pero nos ayuda
a centrarnos sólo en la parte que nos interesa ahora, que es la de cliente.
Es obvio que lo que debemos hacer
para que esto funcione es responder a
los eventos de cambio de selección de
la primera lista, lanzando por detrás una
petición a una página del servidor que
nos devolverá los elementos de la lista
secundaria.
<< dnm.asp.net
Lo primero que debemos hacer para lanzar una
llamada al servidor desde nuestro código Javascript
es obtener una referencia a un objeto de la clase
XMLHttpRequest que utilizaremos. Dado que Internet
Explorer es diferente a los demás navegadores en este
aspecto, debemos distinguir con quién estamos trabajando para poder instanciarlo. Podemos encapsular esta
funcionalidad en el código del fuente 1.
function getHttpRequest()
{
var httpReq;
//Si es Mozilla, Opera, etc...
if (window.XMLHttpRequest)
{
httpReq = new XMLHttpRequest();
}
//Internet Explorer lo expone como control ActiveX
else
{
httpReq = new ActiveXObject(“Microsoft.XMLHTTP”);
}
}
Fuente 1
Una vez que tenemos una referencia al objeto,
usaremos sus métodos y propiedades para lanzar una
petición a la página de servidor que nos interese, por
ejemplo así:
http = getHttpRequest();
http.onreadystatechange = finCarga;
http.open("GET",
"http://www.miserv.com/misdatos.aspx",true)
http.send(null);
En la segunda línea establecemos la función que
se llamará automáticamente cuando cambie el estado
de la petición que vamos a hacer. Ello no implica que
dicha petición
tenga éxito o que sea llamada sólo
cuando termine, como veremos enseguida.
function finCarga()
{
if (http.readyState == 4) //4: completado
{
if (http.status == 200) //200: OK
{
res = http.responseXML;
Procesarespuesta();
}
else //Se produjo un error
{
alert(“No se pudo recuperar la información: “+
http.statusText);
}
}
}
Fuente 2
<<dotNetManía
Figura 1
La tercera línea abre el conducto de petición que
en este caso usará el método GET para cargar una
determinada URL de modo asíncrono (true en el tercer parámetro).
Por fin, debemos hacer la llamada (open no la hace,
sólo la prepara), usando para ello el método send. Se
le pasa un valor nulo porque no enviamos ninguna
información extra (es una petición GET). El hecho
de que sea una llamada asíncrona hará que se devuelva el control inmediatamente a Javascript al pasar por
esta línea, por lo que podríamos seguir haciendo otros
procesos sin que se viera interrumpida la interacción
con el usuario. Podríamos usar llamadas síncronas (false en el tercer parámetro) para lanzar varias llamadas
seguidas con la certeza de que se ejecutarán en un
determinado orden. Es decir, AJAX en realidad no
siempre debe ser asíncrono.
Obviaremos de momento el código de la página del
servidor, que podría ser cualquiera (acceder a una base
de datos para obtener los elementos, leer un archivo o la
memoria, etc.). Lo único verdaderamente importante es
ponernos de acuerdo en cómo se van a devolver los resultados a través de la petición. Podemos complicarlo todo
lo que queramos usando XML o cualquier otra notación
que consideremos oportuna. Más tarde retomaremos
este tema. De momento, para acabar con el ejemplo
vamos a suponer simplemente que el servidor nos devuelve una lista de elementos separados por comas que se
desean mostrar en el control secundario.
Como hemos visto, se define una función llamada
finCarga que es llamada de manera automática al ir cambiando el estado de la petición. Podemos ver su aspecto
en el fuente 2. Lo único que hacemos es detectar cuando se ha terminado la petición (readyState será igual a
4) y que ésta haya sido una petición exitosa (el código de
estado HTTP debe ser 200). Si el código HTTP es 404
(no encontrado), 500 (error en el servidor) u otro cualquiera se advierte con un mensaje al usuario. En caso de
resultado positivo, lo único que hacemos es anotar la res-
15
<< dnm.asp.net
puesta del servidor en una variable global
de la página (res en este caso) y procesar
el resultado adecuadamente. En este caso
se separan los elementos con las comas y
se carga la lista secundaria. Dado que es
un código Javascript trivial y no aporta
nada al tema que nos ocupa no lo he
incluido aquí, pero se puede descargar desde la Web de la revista.
Lo único que se usa normalmente al
mostrar los resultados son los conocidos métodos getElementsByTagName y
getElementByID de HTML dinámico y
del DOM. Estudie el ejemplo incluido
en el ZIP (www.dotnetmania.com) para
ver exactamente cómo se ha hecho.
Posibles problemas que
debemos tener en cuenta al
usar AJAX
Ahora que ya conocemos los rudimentos de AJAX “a pelo”,
vamos a ver cuáles son
los principales problemas que podremos
encontrar al usar estas
técnicas. Probablemente, serán los mismos que nos encontraremos si utilizamos
alguno de los paquetes específicos para
AJAX de ASP.NET,
por lo que debemos ser conscientes de
ellos.
Los más importantes son los
siguientes:
1. Llamadas fuera del dominio.
2. Llamadas que producen errores o
que no vuelven jamás.
3. Envío de datos al servidor.
4. Contenidos no actualizados debido
a caché.
muy fácil procesar lo que devuelven con las
técnicas descritas para, por ejemplo, realizar búsquedas en Google o Amazon con
sus API respectivas, enviar posts a nuestro
blog, consumir fuentes RSS, etc.
Todo esto parece estupendo, pero tiene un gravísimo inconveniente: los navegadores, por cuestiones de seguridad,
bloquean todas las peticiones realizadas
mediante XmlHttpRequest a dominios que
no sean el que aloja la página desde la
que se está usando. En realidad se trata
de una restricción bastante lógica y que
aparece en otras partes del navegador,
como las cookies, el acceso a variables de
Javascript entre marcos, los objetos Flash
o los applets de Java. Pero esto, claro está,
supone una limitación importante para
ciertos tipos de aplicaciones AJAX que
podríamos desarrollar, como las de los
ejemplos comentados.
zar la llamada a otros dominios devolviendo el resultado a nuestro Javascript
(directamente o preprocesándolo de
algún modo). En .NET esto implica normalmente crear un manejador de peticiones con extensión .ashx que se encargue de realizar por nosotros las peticiones que nos interesen.
Pero ¡mucho ojo con esto! Normalmente este tipo de servicios –al igual que
los que se encargan de leer archivos de
disco de manera genérica y otros similares– son un verdadero peligro de seguridad si no los programamos bien. Si
optamos por esta solución, lo mejor es
tomar varias precauciones de cara a la
seguridad: tener muy acotados los servicios o las URL a las que se puede llamar
desde el proxy. Lo mejor es identificarlos a cada uno con un número o código
decidiendo a cuál se llama desde una cláusula switch (o Select
Case en VB.NET),
nunca poniendo la
URL directamente
en la llamada desde
Javascript. Otra opción es tratar de identificar al script llamante de alguna manera: mediante una
cabecera que te debe
enviar, comprobando
el dominio del referer
y cosas similares. Está
claro que un cracker
experimentado se puede saltar esto, pero
le costará bastante trabajo; y así eliminamos de un plumazo a los aficionados que
quieran hacer uso ilícito de tu servicio.
Si es posible, limite el número máximo
de llamadas seguidas que se permite hacer
desde una determinada IP o, mejor, en
una determinada sesión de servidor. Toda
precaución es poca. Atlas (más adelante
en este mismo número), ofrece la posibilidad de crear este tipo de proxies de
manera sencilla.
Otra opción más simple aunque un
poco “chapucera” (y también más tediosa y propensa a errores) consiste en usar
un marco interno (IFRAME) oculto. En él
se carga la URL que deseamos llamar
usando su propiedad src. Al ser un marco interno, tenemos acceso a todas las
propiedades de su objeto document; es
decir, que podemos detectar cuándo ha
AJAX se basa en el uso de un objeto llamado
XMLHttpRequest, presente en todos los
navegadores modernos
<<dotNetManía
Llamadas fuera de dominio
16
Una vez que uno empieza a juguetear
con las posibilidades de AJAX enseguida se
nos ocurren ideas geniales para sacarle partido. La más obvia, claro está, es la de utilizar las técnicas para acceder desde el cliente a ciertos servicios Web ajenos de utilidad ubicados en Internet. Así, dado que los
servicios Web están basados en XML, es
La pregunta ahora es: ¿cómo solucionamos este problema? En Internet
Explorer basta con bajar el nivel de
seguridad para que ya funcione correctamente, pero no es una buena solución
(no le puedes pedir esto a tus usuarios).
En Firefox, Opera y Safari no hay forma de saltarse esta restricción. Existe
una salvedad en Firefox que consiste en
firmar digitalmente el Javascript que
usas, pero tampoco vale de mucho pues
sólo funcionaría en este navegador.
La única forma de resolver el problema de manera independiente al navegador es, aunque sea de Perogrullo, hacer
que no dependa de éste; es decir, llevarnos el problema al servidor. Para ello lo
que debemos hacer es construir un servicio proxy que esté en nuestro servidor
(al que sí podremos llamar con AJAX) y
que sea éste el que se encargue de reali-
<< dnm.asp.net
Gestión de errores y llamadas que no vuelven
No podemos asumir que las llamadas que hagamos
al servidor van a funcionar siempre. Puede haber un error
en el código del servidor, puede haber cambiado la URL
y no aparecer la página que llamamos, haber errores de
permisos, etc. Lo que pase en el servidor está fuera de
nuestro control. Ante eso hay que estar preparado. La
forma de controlar estas situaciones es, como en cualquier componente de comunicaciones por HTTP, a
través del código de estado que devuelva el servidor. Todo
esto ya se había apuntado antes y se había tenido en cuenta en el código del fuente 2. Podríamos afinar más en el
tratamiento de errores y devolver un mensaje diferente
según el código de estado.
Hay, sin embargo, una situación menos frecuente
pero más peligrosa que se puede producir: que la llamada asíncrona al servidor no vuelva o no lo haga en
un tiempo razonable (timeout). ¿Qué hacemos en ese
caso? No podemos contar con la notificación de final
de carga puesto que, al no regresar la llamada, no saltará, así que el código del fuente 2 no nos sirve.
Lo que se hace en estos casos es establecer un temporizador con el tiempo máximo que deseemos esperar,
para que al cabo de ese intervalo la petición sea anulada
directamente, sin esperar más por la respuesta. Podemos
ver un ejemplo en el fuente 3. En él se ha modificado el
código de llamada anterior para añadir la creación de un
temporizador que se encarga de anular la petición al pasar
un tiempo determinado (en este caso de 20 segundos,
pero puede ajustarse a cualquier otro valor). Observe
también cómo en el evento de fin de carga se elimina el
temporizador cuando la petición termina de procesarse
en caso de que regrese.
Envío de datos al servidor
Normalmente cuando pensamos en AJAX, es decir,
en llamadas asíncronas a servicios, lo hacemos desde el
punto de vista de obtener información: llamo a una página que me devuelve unos valores y los muestro en la interfaz de usuario. Aunque éste es el uso más común de AJAX,
lo cierto es que también es muy útil usarlo en el sentido
inverso, para enviar datos al servidor. Las utilidades y
necesidades que puede cubrir este caso son múltiples, y
de hecho hay muchos sistemas que le sacan partido.
La forma más sencilla y directa de enviar datos
simples al servidor es incluirlos en la URL a la que
llamamos como parámetros GET:
urldestino.aspx?Parametro1=1234&Parametro2=5
Aunque esto puede servirnos para cosas muy sencillas,
no es lo que necesitaremos en la mayor parte de los casos.
http = getHttpRequest()
http.onreadystatechange = finCarga;
http.open(“GET”,
“http://www.miserv.com/misdatos.aspx”, true)
//20 segundos
var tmrAnular=setTimeout(“AnularPeticion()”, 20000);
http.send(null);
function AnularPeticion()
{
http.abort();
}
function finCarga()
{
if (http.readyState == 4) //4: completado
{
clearTimeOut(tmrAnular);
if (http.status == 200) //200: OK
{
res = http.responseXML;
ProcesaRespuesta();
}
else //Se produjo un error
{
alert(“No se pudo recuperar la información: “+
http.statusText);
}
}
}
Fuente 3
Lo habitual es que la información haya que enviarla con el método POST. La principal diferencia entre
GET y POST estriba en que el método GET hace
una sola llamada al servidor, solicitando una página y
enviando algunos parámetros de datos en la propia
petición. POST, por el contrario, realiza dos conexiones al servidor. En la primera solicita una URL y
en la segunda envía los datos. Mediante GET lo máximo que se puede enviar son 2 Kb de información,
mientras que POST no tiene esta limitación.
Para enviar datos al servidor mediante POST,
nuestro código AJAX sería similar al siguiente:
http = getHttpRequest()
http.onreadystatechange = finCarga;
http.open("POST",
"http://www.miserv.com/misdatos.aspx", true)
http.send('Parametro1=1234&Parametro2=5');
Con esto no hemos ganado demasiado. Ahora se
envían los datos con POST (sólo cambia el primer parámetro de open) pero los hemos tenido que introducir en
el método send en lugar de en la propia URL. Esto sólo
simularía el envío de parámetros mediante POST desde un formulario HTML (que, por otro lado, en ocasiones puede ser lo que queramos).
<<dotNetManía
terminado de cargar y leer sus contenidos, procesándolos también mediante DOM.
17
<< dnm.asp.net
Lo habitual es que, en lugar de enviar
parámetros, queramos enviar información
pura y dura del tamaño que sea preciso,
que es para lo que suele usarse POST. Esto
se puede conseguir modificando ligeramente el código anterior para incluir una
cabecera que indique al servidor que lo
que le llega son, precisamente, datos (línea
3 del fragmento del fuente 4).
Con esto nuestro problema queda
resuelto.
Si queremos asegurarnos de que la
petición va a llegar a su destino podemos hacer fundamentalmente dos cosas:
1. Agregar una cabecera que indique
que se debe obtener el contenido
siempre que éste sea posterior a una
fecha, por ejemplo así:
http.setRequestHeader(
'If-Modified-Since',
'Wed, 1 Jan 2003 00:00:00 GMT');
http = getHttpRequest()
http.onreadystatechange = finCarga;
http.setRequestHeader('content-type', 'application/x-www-form-urlencoded');
http.open("POST", "http://www.miserv.com/misdatos.aspx", true)
http.send('Aquí ahora mando la información que quiera al servidor');
Fuente 4
Contenidos no actualizados
debido a caché
Cuando se envía
una petición HTTP
es posible que, si la
caché del lado servidor no está correctamente configurada, el
navegador realice su
propia caché y por lo
tanto la llamada no
llegue al servidor
jamás. O puede que
exista un proxy-caché
por medio (Telefónica, por ejemplo, los utiliza) que almacene peticiones anteriores y por lo tanto
obtengamos únicamente una copia, sin
realizar la llamada al servidor real. Eso
puede ser estupendo (muchas veces es lo
que querremos para ahorrar procesamiento), pero otras veces puede ser una
maldición, ya que no obtendremos los
datos actualizados.
A la hora de enviar datos por POST
no hay problemas, porque con este
método no actúa nunca la caché. El problema, si se da, está en las peticiones
GET, por otro lado las más habituales.
Si el servidor tiene bien configurada
la caché (es decir, indica cuándo caducan
los contenidos o marcamos en IIS que
éstos caduquen inmediatamente), no
deberíamos experimentar fallos, a excepción de lo comentado respecto a los
proxy-caché de algunos proveedores.
Indicaremos siempre una fecha anterior a la actual (como la del ejemplo), y
se den dos peticiones idénticas incluso a
través de un proxy-caché. Obviamente, ese
parámetro adicional de nombre inventado no debería afectar en absoluto a la llamada puesto que no está siendo tenido en
cuenta por la aplicación. Esta segunda técnica es la más fiable, aunque un poco más
tediosa de implementar.
Los datos de retorno: JSON
En el ejemplo anterior hemos hecho
que la página del servidor devuelva ciertos valores separados por comas. Si bien
esto puede ser suficiente en los casos
más sencillos, en otras ocasiones necesitaremos manejar estructuras de datos
más complejas.
El recurso al que llamemos en el
servidor debe devolver siempre texto.
Éste puede ser cualquier cosa: texto
plano, XML, código
Javascript o incluso
HTML. En este último caso, podemos
obtener desde el servidor un contenido
HTML completo
que se debe escribir
en una zona de la
página (por ejemplo
un <DIV> o un <SPAN>).
Sin embargo, la
mayor parte de las
veces lo que tendremos que procesar es
alguna estructura de datos.
La “X” de AJAX significa XML, ya
que el origen de esta técnica deriva inicialmente del uso del objeto
XMLHttpRequest, pensado para obtener este
tipo de información. Como hemos
demostrado en el ejemplo, esto no es necesariamente así. De hecho, hoy en día el
XML se usa muy poco a la hora de representar los datos textuales devueltos desde
el servidor en páginas AJAX.
El motivo de esto es principalmente
que los datos representados con XML, si
bien son ricos en estructura, hacen que el
resultado devuelto ocupe mucho debido
a las etiquetas de apertura y cierre de los
diferentes nodos. Gracias al DOM es fácil
procesar la información jerárquica que se
representa mediante XML; aún así,
debería existir algún método más directo
y que ocupe menos ancho de banda.
<<dotNetManía
Como alternativa a XML ha surgido un nuevo
estándar llamado JSON que lo sustituye con
muchas ventajas añadidas
18
así siempre se pedirá la última versión
al servidor.
2.- Añadir un número aleatorio (o cadena) a la URL de cada petición. En
este caso suele funcionar muy bien
el agregarle una marca temporal, de
modo que cada una de las peticiones que se hagan sea diferente y por
lo tanto los caché que existan por
medio tengan que repetir siempre la
petición. Por ejemplo:
http.open("POST",
"http://www.miserv.com/misdatos.aspx?
pasacache=" +
new Date().getTime(), true);
Aquí se añade a la URL un parámetro que lleva como valor la fecha y hora
en formato numérico (es decir, un número muy largo y que varía varias veces cada
milisegundo), por lo que es muy difícil que
<< dnm.asp.net
var cliente = eval(res);
JSON permite representar objetos en
forma de código JavaScript que luego
podremos evaluar
Siendo res el nombre de la variable que contiene el JSON obtenido del servidor. Es decir, lo único que hacemos es procesar la expresión JSON. Al
hacerlo obtenemos en la variable cliente un objeto cuyas propiedades son los datos que queremos
manejar. De este modo, lo único que tenemos que
hacer para leerlos es escribir directamente expresiones como ésta:
Como alternativa a XML ha surgido un nuevo
estándar llamado JSON, que lo reemplaza con mucha
ventaja en la mayor parte de los casos. JSON es el
acrónimo de Javascript Object Notation, y como su propio nombre indica permite representar objetos (en
realidad estructuras complejas) en forma de código
Javascript que luego podemos evaluar. JSON tiene
varias ventajas sobre XML, a saber:
1. Ocupa mucho menos al transmitirlo por la Red.
2. El acceso a los elementos de datos representados es directo y sin necesidad de procesamiento farragoso usando el DOM o expresiones regulares.
3. Los datos pueden ir colocados en cualquier
posición.
alert("El nombre de la empresa es " + cliente.empresa);
Consideremos el siguiente código XML que representa los datos de un cliente:
<cliente>
<nombre>José Manuel</nombre>
<apellidos>Alarcón Aguín</apellidos>
<empresa>Krasis</empresa>
<telefono>902 876 475</telefono>
<edad>34</edad>
</persona>
Ahora consideremos la misma representación en
JSON:
{
"nombre" : "José Manuel",
"apellidos" : "Alarcón Aguín",
"empresa" : "Krasis",
"telefono" : "902 876 475",
"edad" : 34
Más fácil imposible. Nada de recorrer una jerarquía XML con el DOM o ir buscando nodo a nodo
en el contenido. Se convierte en Javascript puro y utilizable nada más llegar desde el servidor.
El uso de JSON como formato de intercambio
sólo tiene dos problemas aparentes. El primero de
ellos es el más obvio: generar XML con C# o VB.NET
es muy fácil pero generar JSON requiere un cierto
trabajo por nuestra parte. Para evitárnoslo existe una
biblioteca llamada Jayrock (http://jayrock.berlios.de)
que permite convertir objetos .NET directamente a
su representación JSON.
El otro problema es tal vez menos evidente pero
más importante: la seguridad. Dado que se usa una
expresión eval para convertir el texto en objetos
Javascript, podría utilizarse de manera malintencionada para inyectar código peligroso en la página al efectuar la evaluación. Para evitarnos este peligro, en JSON.org tenemos un script (http://www.json.
org/json.js) que extiende las cadenas de Javascript
para convertirlas a JSON verificando la sintaxis y
evitando lo que no sean datos. Si incluimos este
script en nuestra página, en lugar de utilizar eval
podemos escribir:
var cliente = res.parseJSON();
para obtener el mismo resultado.
El script nos ofrece además la funcionalidad inversa de la siguiente manera:
var miCadena = cliente.toJSONString();
}
Esto nos puede servir para enviar datos JSON al
servidor, para almacenar un objeto en una cookie, etc.
En resumen
En este artículo hemos aprendido los fundamentos
de AJAX, así como los principales problemas que nos
podemos encontrar al utilizarlo. La comprensión de todo
ello nos va a resultar útil, aún cuando no utilicemos las
técnicas más rudimentarias sino que recurramos a un kit
especializado como Atlas o AJAX.NET.
<<dotNetManía
Crear esta representación es muy fácil pues es sintaxis Javascript normal (en www.json.org es posible
encontrar una explicación completa). Como se puede
comprobar, ocupa menos espacio, es igual de fácil de
leer y permite usar datos nativos y no sólo cadenas.
En estructuras más complejas todavía se puede apreciar más el ahorro de datos que implica.
En cualquier caso, lo más espectacular de JSON
es lo fácil que resulta utilizarlo. Basta con escribir lo
siguiente:
19
dnm.asp.net
José M.Alarcón
AJAX con ASP.NET 2.0
Script callbacks
La reciente versión 2.0 de ASP.NET ofrece una nueva técnica para implementar páginas AJAX pero usando métodos nativos de servidor. Nos abstrae de la mayor parte
de las complejidades asociadas al código de script de cliente,limitándose nuestra aportación en este sentido a procesar los resultados devueltos. En este artículo veremos
cómo funcionan los script callbacks.
<< La filosofía de los script callbacks de ASP.NET 2.0 es la
José Manuel Alarcón Aguín
es redactor de dotNetManía.
Es ingeniero industrial y
especialista en consultoría de
empresa. Ha escrito varios libros,
y ha publicado más de
trescientos artículos sobre
informática e ingeniería en
revistas especializadas.
Es MVP de ASP.NET, MCTS,
MCPD, MCT y tutor de
campusMVP.
Visite su blog en www.jasoft.org
misma que la de AJAX. Es decir, desde el cliente se
provoca una llamada en segundo plano al servidor, el
cual procesa la petición y devuelve al cliente un resultado textual que es procesado por un método Javascript
construido a tal efecto. De hecho, por debajo lo que
se hace es utilizar un objeto XMLHttpRequest, tal y como
hemos visto en el anterior artículo de fundamentos
de AJAX.
La diferencia principal entre la técnica de script
callbacks que ofrece ASP.NET 2.0 y lo que hemos estudiado hasta ahora es que nos podemos despreocupar
totalmente de la complejidad inherente al manejo de
XMLHTTPRequest, y de la gestión de la mayor parte de
los errores, pues de ello se encarga por nosotros la
infraestructura de .NET de manera transparente.
Además –y esto es importante– en lugar de llamar a
otra página del servidor llamaremos a la misma página (como si fuera un postback), o incluso solo a determinadas partes de ésta si implementamos la técnica
en un control en lugar de en la página entera.
Esta técnica se ha incluido en ASP.NET 2.0 específicamente para realizar postbacks al servidor en segundo plano, y así seguir sacando partido al poderoso modelo de eventos de servidor de .NET sin que el usuario
aprecie los “viajes” de ida y vuelta realizados.
Cómo usar los script callbacks
El uso de los script callbacks es sencillo, pero hasta
que se ve un ejemplo completo cuesta un poco entender su funcionamiento. En los próximos apartados
desgranaré poco a poco sus elementos y pido al lector un poco de perseverancia hasta llegar a la parte
final, en la que todo “encaja”.
Lo primero que debemos saber es que para sacar
partido a esta nueva técnica, el control o la página a
la que queramos dotar de funcionalidad AJAX deberá implementar la interfaz ICallbackEventHandler.
Para ello podemos incluir una etiqueta:
<%@ Implements interface=
"System.Web.UI.ICallbackEventHandler" %>
en el código HTML de la misma, o mejor todavía,
hacer que la clase code-beside (la clase parcial incluida
en el archivo .cs o .vb relacionado) implemente explícitamente dicha interfaz, tal y como se muestra en la
figura 1. Como se puede apreciar, al escribir el nombre de la interfaz tras la definición de la clase veremos
que en la etiqueta inteligente (smart tag) asociada se
ofrece la posibilidad de generar de manera automática las definiciones de los miembros de la misma, para
que podamos implementarlos tanto implícita como
explícitamente.
Antes de pasar a ver con detalle esta interfaz, es
preciso señalar que no solo podremos implementarla en una página que contenga controles cuyo uso provocará llamadas asíncronas al servidor. Podemos crear también nuestros propios controles de usuario o
controles Web que implementen dicha interfaz y que,
al ser colocados sobre una página, provocarán la ejecución en el servidor de sus propias llamadas, lo cual
nos permite un gran nivel de encapsulado.
Figura 1
<< dnm.asp.net
La interfaz que debemos implementar es muy sencilla, pues solo consta de dos miembros:
• Método RaiseCallbackEvent: se llama de manera
automática al producirse un callback (o llamada en
segundo plano) al servidor mediante código de
script. Recibe como parámetro una cadena que se
genera en el lado de cliente (en el navegador) antes
del envío. Enseguida veremos la manera de hacerlo y qué información le pasaremos. Lo importante es saber que dentro de este método haremos
todo el procesamiento que sea necesario como
resultado de la llamada. Por ejemplo, recibimos
un identificador y vamos a una base de datos para
obtener los datos de detalle de una entidad asociada. Su firma es la siguiente:
void ICallbackEventHandler.RaiseCallbackEvent(
string eventArgument)
• Método GetCallbackResult: este método se llama
automáticamente en el servidor a la hora de devolver los resultados del procesamiento al cliente.
Dichos resultados se devuelven en forma de cadena de texto y se reciben en el navegador en una
función Javascript (¿se aprecia la similitud con lo
visto en el artículo anterior?). En esta cadena de
resultados podemos meter cualquier información
en el formato que deseemos, tal y como ya hemos
analizado: valores separados por comas, XML,
JSON, etc. La firma de este método es ésta:
string ICallbackEventHandler.GetCallbackResult()
Generar la llamada desde el cliente
Ahora que ya conocemos la teoría sobre cómo proceder en el servidor, estudiaremos cómo se provoca la
llamada desde el navegador. Para ello hay que usar
obviamente Javascript, solo que en esta ocasión no
tendremos que encargarnos nosotros de ello, sino que
ASP.NET proporciona todo lo necesario de manera
automática.
Para provocar la llamada al servidor se utiliza una
función Javascript llamada WebForm_DoCallback que
acepta unos determinados parámetros. Ésta se encuentra definida en uno de los manejadores .AXD que
ASP.NET incluye de manera automática por nosotros en las páginas asíncronas. Eso sí, no debemos
hacer uso de ella directamente. El hecho de que sepamos cómo se llama e incluso podamos averiguar para
qué se usa cada uno de sus parámetros no es motivo
para que la usemos de modo directo. En versiones o
revisiones posteriores de ASP.NET podría cambiar
de nombre o de parámetros. Por eso, para evitarnos
este problema, dentro de la clase ClientScript de
ASP.NET hay un método llamado GetCallback
EventReference que sirve precisamente para generar
una llamada Javascript con el nombre y parámetros
adecuados a esta función, obteniendo algo análogo a
este código:
WebForm_DoCallback('__Page',document.getElementById(
'ddlCategorias').value,ActualizaVista,null,
MuestraError,false)
GetCallbackEventReference tiene tres versiones
sobrecargadas que se pueden llamar. A la más común
se le pasan los siguientes parámetros:
• Control: una referencia al control ASP.NET que
implementa la interfaz ICallbackEventHandler,
y que obviamente puede ser la propia página
actual (que hereda de la clase Control).
• Argumento Javascript: la expresión
Javascript que se evaluará en el navegador
antes de enviar al servidor la petición, y
cuyo resultado es precisamente lo que
recibiremos en el método RaiseCall
BackEvent visto antes. Puede ser una simple cadena o número, siendo con más frecuencia una expresión Javascript completa que devuelve algún resultado obtenido
de los controles de la página.
• Nombre de función Javascript de retorno: el
nombre de una función Javascript que se
llamará en el cliente cuando se devuelva
la llamada del servidor. A ésta se le pasará el resultado devuelto por el miembro
GetCallbackResult (una cadena), así como
una variable de cadena para marcar el contexto de la llamada (información auxiliar
opcional para saber desde dónde se llama,
[ ]
NOTA IMPORTANTE
En la mayor parte de los artículos que se pueden
encontrar en Internet sobre los script callbacks, viene
documentado el trabajo con esta característica tal y
como estaba definida en las primeras betas de ASP.NET.
Casi no hay información actualizada, y todo aquello no
funciona con la versión definitiva de .NET 2.0. Por
ejemplo, antes la interfaz solo disponía de un método.
Ahora son dos, por lo que nos vemos obligados a usar
una variable de clase, común a ambas, para devolver el
resultado al cliente. Como ventaja tenemos que se separa el procesamiento de la llamada de su resultado, de
modo que, aunque se produzca un error en el evento,
se sigue llamando igualmente a GetCallbackResult para
devolver el resultado, y podemos jugar con eso. Existen
muchas otras diferencias entre esas primeras versiones
y la definitiva, así que no se puede fiar uno de lo que
lea por ahí sobre este tema.
<<dotNetManía
La interfaz ICallbackEventHandler en
detalle
21
<< dnm.asp.net
como se explica en el siguiente parámetro).
• Contexto: se trata de un identificador
de contexto (puede ser una cadena
cualquiera o un número, etc.) que
servirá para identificar el contexto
de la llamada. De este modo podemos reutilizar la misma función de
cliente o de servidor (se recibe en
ambas) pero tratarla de forma diferente según el contexto. Este parámetro cobra importancia cuando
desde una misma página se reciben
llamadas asíncronas diferentes provocadas por distintos controles en el
navegador, ya que todas se procesan
con el método RaiseCallBackEvent
y hay que distinguir unas de otras.
¿JAX? ¡esto es SÍNCRONO
por defecto!
<<dotNetManía
Un momento, ¿la “A” de “AJAX” no
es por “Asíncrono”? Sí. Sin embargo, por
defecto, con los parámetros pasados en el
método anterior, la función de script generada (WebForm_DoCallback) hace una llamada síncrona al servidor. No pasa nada, normalmente no notaremos diferencia, pero
claro, en caso de tener una conexión lenta (o fallar ésta) podríamos notar una cierta paralización de la interfaz del navegador. Por ello es recomendable utilizar una
forma sobrecargada del método que nos
permite especificar que las llamadas sean
asíncronas, y que añade dos parámetros
más a los cuatro que acabamos de ver:
• Función Javascript para errores: el nombre de una función Javascript que se
llamará de forma automática en caso
de producirse cualquier error en la llamada al servidor. Toma los mismos
parámetros que en el caso de la función Javascript de retorno.
• ¿La llamada es asíncrona?: si ponemos
true en este último parámetro la llamada será asíncrona, y si ponemos false (valor por defecto) será síncrona.
22
¿Para qué puede ser útil hacer llamadas síncronas? Pues como ya hemos
visto en el artículo anterior, para asegurarnos de que se van a ser efectuadas en
un determinado orden, o cuando existen dependencias entre unas y otras para
evitarnos complejos códigos de sincronización.
Recapitulemos antes de continuar
Lo que hemos visto hasta ahora puede resultar en primera instancia un poco
lioso. Sin embargo, si lo repasamos
poniéndolo todo junto paso a paso se
entenderá mejor:
1. Definimos un atributo para un control que, respondiendo a un evento
de HTML, hará una llamada en
segundo plano al servidor que será
la que nos devuelva los resultados.
Puede ser un clic, un cambio de
selección, etc. Para saber qué código Javascript debemos usar para
generar la llamada utilizamos el
método GetCallbackEventReference.
2. En el servidor, en uno de nuestros
controles o en la propia página, implementamos la interfaz ICallbackEvent
Handler, cuyos métodos serán ejecutados automáticamente cuando se realice la llamada en segundo plano desde el navegador.
3. Definimos en el código HTML de
nuestra página una función Javascript
que toma como parámetros una cadena con los resultados de la llamada que
hemos realizado al servidor, y una
variable de contexto para distinguirla
de otras en caso de que todas se gestionen con esta misma función.
Hagamos un par de puntualizaciones más:
• Esta técnica funciona con cualquier
navegador moderno como FireFox,
Safari u Opera, y no solo con
Internet Explorer, como afirman
algunos artículos por ahí.
• Al llamar en segundo plano a la página también se lanzan los eventos de
ésta, como en una llamada normal.
Para distinguir –por ejemplo desde
Page_Load u otro evento– si una llamada al servidor se corresponde con
una llamada asíncrona de tipo script
callback, la clase Page define una propiedad llamada IsCallback que permite distinguir éstas y funciona del
mismo modo que la propiedad
IsPostBack sobradamente conocida.
De este modo, podremos distinguir
este tipo de llamadas y gestionar el
código de la página de forma diferente al de una llamada común.
Figura 2
Un ejemplo completo
Para entender mejor todo lo visto
hasta ahora vamos a realizar un ejemplo completo. El código fuente está disponible para su descarga desde la página Web de dotNetManía.
Nuestro ejemplo será muy sencillo
pero suficiente para comprender todo lo
explicado hasta ahora. Por esta razón,
obviaremos cualquier otro código que nos
pueda descentrar de nuestro objetivo, que
es entender los script callbacks . Crearemos
una página con una lista de categorías y
un botón que, al ser pulsado, mostrará
debajo (sin hacer postback) los contenidos
de dicha categoría. La figura 2 muestra el
ejemplo en funcionamiento.
Para empezar, vamos a crear un
nuevo proyecto de Visual Web
Developer. Sobre la página por defecto ( Default.aspx ) arrastraremos un
control DropDownList de nombre
ddlCategorías. Le asignaremos una lista
de elementos (“Empresas”, “Libros”,
“Blogs”, “Revistas”...). Es importante no
marcar su opción de “AutoPostback”.
Ahora añadimos un botón. Pero
atención, muy importante: no nos sirve
un botón de ASP.NET (control Web)
ya que este tipo de control siempre se
genera como un botón de envío de formulario (submit) y es precisamente eso
lo que queremos evitar. Debemos utilizar un botón de HTML (o sea, un INPUT
de toda la vida) arrastrándolo desde la
categoría HTML de los controles de
ASP.NET. Una vez en el formulario,
pulsaremos sobre él con el botón derecho y escogeremos la opción de ejecutarlo en el servidor (realmente solo se
le añade un atributo runat="server" en
su definición). Le llamaremos cmdVer.
Para finalizar, añadimos debajo y desde el mismo grupo de controles HTML
una capa (DIV) con el nombre
divResultados, asignándole manualmente un estilo que permita que crezca adap-
<< dnm.asp.net
AJAX de forma sencilla en el control GridView
El control GridView que viene con ASP.NET 2.0 es un estupendo control que nos permite
dotar de funcionalidades de paginación y ordenación de datos a un origen de datos sin necesidad
de escribir código alguno.Lo que mucha gente desconoce es que,además,en la mayoría de los casos
se puede conseguir esta funcionalidad sin tener que refrescar la página completa, al más puro estilo AJAX. Mediante esta vía, al pulsar sobre la cabecera de la rejilla o cambiar de página se recargan
exclusivamente los contenidos de ésta,pero sin realizar un postback al servidor que fuerza el refresco de la página completa.
Para conseguirlo solo es necesario establecer a true la propiedad
EnableSortingAndPagingCallbacks del control,como ilustra la
figura adjunta.
Para dotar a la rejilla de esta útil característica los programadores de ASP.NET han utilizado script callbacks.El control GridView implementa la interfaz ICallBackEventHandler. No mostraremos el
código aquí por falta de espacio, pero es interesante estudiarlo con
cualquier decompilador como .NET Reflector.Lo dejamos como ejercicio.
Aunque la propiedad es ciertamente útil y funciona muy bien en la mayor parte de los casos,
hay un par de detalles que se deben tener en cuenta:
1. La técnica no funcionará si alguna columna de la rejilla es de tipo plantilla, es decir, no es un
control BoundField o derivado (que son los que añade automáticamente el GridView). Si convertimos alguna columna en plantilla, la próxima vez que ejecutemos la página que contiene
la rejilla se producirá una excepción que nos avisará de la incompatibilidad.
2. Si no hemos usado como origen de datos un control DataSource (SqlDataSource,
ObjectDataSource,etc.),no funcionarán la ordenación ni la paginación estilo AJAX.Ello es debido a que el código llama al método DataBind al final y por lo tanto debe haber algún control enlazado permanentemente a la rejilla.
tándose a su contenido (style="overflow:
visible; width: 90%").
Con todo ello el código de la página quedará como el del fuente 1.
Ya tenemos la base necesaria para
crear el ejemplo. Ahora vamos a ver lo
importante.
Fuente 1
Figura 3
la lista), el nombre de la función a llamar tras terminar la petición al servidor
(ActualizaVista), el dato de contexto
(en este caso un nulo), el nombre de la
función Javascript que se llamará si hay
un error en la comunicación, y un booleano que indica si queremos que la llamada sea asíncrona o no.
Por fin, se asigna ese código Javascript al evento onClick del botón (que
no deja de ser más que un atributo del
mismo). Al ejecutar la página obtendremos el HTML para el botón:
<input name="cmdVer" type="button"
id="cmdVer" value="Ver fuente"
onClick="Javascript:WebForm_DoCallback(
'__Page',document.getElementById(
'ddlCategorias').value,
ActualizaVista,null,MuestraError,
false)" />
<<dotNetManía
nos ocurra. Es
obvio que tendremos que
escribir un
manejador
para el evento
onClick del
botón que
provocará la
1.- Realizar las peticiones al servidor
llamada en
Lo primero en el orden lógico es pensegundo plasar cómo vamos a enviar las peticiones al
no. El código
servidor. En nuestro ejemplo lo haremos
que debemos incluir para conseguirlo nos
cuando se pulse el botón, aunque podría
lo da el método GetCallbackEvent
Reference estudiado antes. Por lo tanto,
ser al cambiar la selección de la lista o con
cualquier otro evento de Javascript que se
lo único que debemos hacer es asociarlo
al botón, lo que
<body>
haremos durante la
<form id=”form1” runat=”server”>
carga de la página.
<div>
Para ello necesitare<asp:DropDownList ID=”ddlCategorias” runat=”server”>
mos decidir qué
<asp:ListItem>Revistas</asp:ListItem>
<asp:ListItem>Blogs</asp:ListItem>
valor se pasará al ser<asp:ListItem>Empresas</asp:ListItem>
vidor durante la lla<asp:ListItem>Libros</asp:ListItem>
mada, qué función
<asp:ListItem>Provoca error</asp:ListItem>
de Javascript se va a
</asp:DropDownList>
<input id=”cmdVer” runat=”server” type=”button”
llamar como resvalue=”Ver fuente”/>
puesta final al call<br /><br />
<div id=”divResultados” style=”overflow: visible; width: 90%”> back, un dato de contexto (no lo usare</div>
</div>
mos en nuestro
</form>
ejemplo) y el nom</body>
bre de la función
Javascript que se llamará en caso de producirse un error. Teniendo todo eso en
cuenta, el código resultante se presenta en
la figura 3.
Lo que se hace es obtener el identificador para la lista desplegable que
se usará en el HTML resultante (no tiene por qué coincidir en general con el
que le hemos dado en la página ASPX;
depende de donde esté colocado) y con
eso construimos una cadena Javascript
que simplemente sirve para obtener el
valor del elemento que esté seleccionado en ésta (este código Javascript lo
almacenamos en la variable jsItem).
A continuación, generamos el código Javascript que va a provocar la llamada al servidor con el método
GetCallbackEventReference . Como
parámetros se le pasan el control que
gestionará el callback (la propia página,
es decir, this en C# o Me en VB), el código Javascript que nos da el valor a enviar
al servidor (el elemento seleccionado en
23
<< dnm.asp.net
#region Miembros de ICallbackEventHandler
private string resCallBack = “”;
string ICallbackEventHandler.GetCallbackResult()
{
return resCallBack;
}
void ICallbackEventHandler.RaiseCallbackEvent(string eventArgument)
{
//Se recibe como argumento el nombre seleccionado en la lista
switch (eventArgument)
{
case “Revistas”:
resCallBack = “DotNetMania,MSDN Magazine,The Code Project”;
break;
case “Blogs”:
resCallBack = “www.jasoft.org,www.geeks.ms,weblogs.asp.net”;
break;
case “Empresas”:
resCallBack = “Krasis [www.krasis.com],Microsoft [www.microsoft.com],
Plain Concepts[www.plainconcepts.com]”;
break;
case “Libros”:
resCallBack = “Crimen y castigo,Cien años de soledad,El Quijote”;
break;
default:
Response.StatusCode = 500;
Response.End();
break;
}
}
#endregion
Fuente 2
<script>
<!—
//Nombre del control DIV asignado por ASP.NET en el cliente
var NombreDiv = “divResultados”;
//Escribe dentro del DIV el HTML que se le pase
function EscribeTexto(txt)
{
document.getElementById(NombreDiv).innerHTML = txt;
}
//Procesa los resultados del servidor
function ActualizaVista(res, context)
{
EscribeTexto(res.replace(/,/g, “<BR/>”));
}
//Muestra un mensaje de error en el DIV
function MuestraError(txtError, context)
{
EscribeTexto(“Error: “ + txtError);
}
Fuente 3
2.- Definir la interfaz ICallbackEventHandler
<<dotNetManía
3.- Implementar las funciones de recepción de resultados en el cliente
Solo nos resta una cosa y es decidir qué hacemos con
los resultados una vez que se termine la llamada. En nuestro caso haremos algo muy sencillo: al igual que en el
ejemplo anterior, separaremos los elementos recibidos
como resultado sustituyendo las comas por retornos de
carro (<BR/> en HTML) y esta cadena resultante la introduciremos directamente en el <DIV> de resultados que
hemos incluido. El código Javascript es muy sencillo y
se muestra en el fuente 3.
Fijémonos en las funciones. La primera de ellas es
general y se usa desde las otras dos simplemente para
introducir el HTML que queramos dentro del DIV. Las
otras dos funciones son la implementación de los métodos de resultado y de error, respectivamente. Deben tener
los mismos nombres que escogimos en el paso 1, al generar la llamada al servidor. En el primer caso se sustituyen
las comas por un retorno de carro, y en el caso del error
se muestra el mensaje de error en el DIV en lugar de los
resultados. Así de sencillo. En ejemplos reales podríamos
hacer cosas mucho más complejas con HTML dinámico, todo dependerá de nuestro dominio de Javascript.
En el código del fuente 2, para simular un error y
facilitar la prueba del método correspondiente, hemos
incluido un elemento en la lista (el último) que provoca al ser elegido un código de estado HTTP 500
(código estándar para indicar que se han producido
errores en el servidor). De esta manera, al escoger la
última opción de la lista en el navegador se interpreta como si fuese un error en nuestra página ASPX y
se fuerza así la llamada a la función de error.
Conclusiones
//—>
</script>
24
ICallbackEventHandler. En nuestro ejemplo, el código sería el del fuente 2.
Si nos fijamos, el código es muy sencillo. Hemos eliminado acceso a datos y otras cuestiones para centrarnos en lo que nos ocupa. Así que según el valor que se
le pase al método (la selección de la lista desplegable)
anotamos una u otra lista de elementos separados por
comas en una variable. El contenido de ésta es lo que se
devuelve en el método GetCallbackResult, y por lo tanto lo que se le pasa al cliente como resultado. Con esto
hemos finalizado la implementación de la interfaz.
Ahora que ya estamos provocando las peticiones
al servidor vamos a definir los métodos que se ejecutarán en éste como resultado de la llamada y que son
los que obtienen el resultado a devolver. Como hemos
visto, para ello es necesario implementar la interfaz
La técnica de script callbacks tiene muchas aplicaciones, aunque la verdad es que queda un poco deslucida
si la comparamos con las posibilidades que nos da Atlas
para ASP.NET (tecnología que se describe en este mismo número). Ahora bien, para muchos casos sencillos
en los que no queramos (o no podamos) instalar Atlas
o que no se justifique la carga adicional asociada a éste,
resultará una opción simple y segura para conseguir
efectos AJAX.
dnm.asp.net
Román Fresneda
Miguel Katrib
AJAX, redefiniendo la forma de ver la Web
AJAX es el nombre con que se ha “popularizado” a un grupo de tecnologías que
juntas han cambiado la forma en que vemos la Web. AJAX abre la posibilidad de
invocar asíncronamente desde Javascript a código del lado del servidor en una aplicación Web, usando XML como transporte (aunque se verá que esto último no es
necesariamente así).
<< Los que estábamos habituados al desarrollo de aplicacio-
Miguel Katrib
Miguel Katrib es Dr.en
Computación y Catedrático del
Dpto.de Ciencia de la
Computación de la Universidad
de La Habana.Dirige el Grupo
WEBOO dedicado a la enseñanza
y desarrollo de la Orientación a
Objetos y la Programación en la
Web.Miguel es redactor de
dotNetmanía y asesor de
programación y tecnología .NET
para CARE Technologies SA.
Román Fresneda Quiroga es
instructor de programación en
C# del Dpto. de Ciencia de la
Computación de la Universidad
de La Habana. Román es desarrollador y webmaster del grupo
WEBOO y entusiasta de ASP
.NET y de la tecnología .NET.
nes de escritorio, cuando comenzamos a desarrollar
aplicaciones Web en ASP.NET no nos acostumbrábamos al navegador “colgado” esperando por la respuesta del servidor Web.
Aunque por el momento ya existían medios
(entre los que se encuentra el muy popular
Javascript) para superar este aparente escollo
de los escenarios Web, todavía no se hablaba
conscientemente de una solución eficaz a tal
problema. Pero fueron llegando después aplicaciones como Gmail (http://www.gmail.com),
Google Maps (http://maps.google.com) y Flickr
(http://www.flickr.com), que nos hicieron ver que
las aplicaciones Web podían acercarse al tiempo de
respuesta de las aplicaciones de sobremesa.
Por lo general, la interacción con una aplicación Web tradicional sigue un patrón común:
- Inicialmente, el usuario accede e interactúa con
un formulario, provocando una petición al servidor Web. Esto desencadena toda la lógica de la
aplicación en el servidor, quien puede a su vez
interactuar con bases de datos u otras aplicaciones no visibles directamente por el usuario.
- El servidor responde a la aplicación cliente (en su
mayoría navegadores) en forma de HTML
(XML). La aplicación cliente interpreta ese
HTML y muestra un nuevo “formulario” al usuario (figura 1).
cia de las aplicaciones Web. Con independencia de su
ancho de banda, mientras el servidor procesa la petición el usuario espera… y desespera.
El propósito de AJAX es atenuar este efecto, al darle más responsabilidad al navegador en tareas que antes
podrían haber requerido una petición al servidor, enviando menos datos hacia éste o haciendo
peticiones al servidor en el
trasfondo, es decir, sin
esperar por una interacción explícita del
usuario (como la pulsación de un botón
de envío).
Entre las principales ventajas técnicas de este enfoque está la independencia de la plataforma cliente,
pero puede llegar a ser no completamente agradable
a los usuarios finales fundamentalmente por la latenEn este artículo se usa una implementación de AJAX para .NET conocida como Ajax.NET (de Michael Schwarz [1]) ya popular en Internet.Para ilustrar
cómo usar esta biblioteca y algunos de sus pros y contras se desarrolla como ejemplo una aplicación para ofrecer un álbum de fotos vía Web.
<< dnm.asp.net
Figura 1. El modelo clásico
de aplicación Web.
Una aplicación AJAX es diferente en
el sentido de que se sustituye el patrón
típico de interacción por la utilización de
un intermediario, el mecanismo AJAX
(figura 2), entre el cliente y el servidor,
haciendo que la aplicación ofrezca una
mejor respuesta. En vez de cargar una
página Web completa al principio de la
sesión, el navegador carga el motor
AJAX, que está escrito en Javascript. Este
motor es el responsable de dibujar la
interfaz de usuario y de comunicarse con
el servidor. El primer subproducto de la
introducción de esta capa extra es permitir que la comunicación con el servidor sea ahora asíncrona; de este modo
disminuye en el usuario la sensación de
ver el navegador “colgado”. Cada acción
del usuario que normalmente generaría
una petición al servidor toma la forma
de una llamada Javascript al motor AJAX.
El mecanismo AJAX maneja aquellas respuestas que no requieran un viaje al servidor (figuras 3 y 4).
Figura 2. El modelo de
aplicaciones Web AJAX.
Figura 4. El patrón de interacción
asíncrono de una aplicación Web AJAX.
Algunos de los conceptos AJAX que
se pueden encontrar en el trabajo
“Patrones AJAX” (ver [7]) reflejan lo
dicho anteriormente:
- Sensación de continuidad.
- Actualizaciones en tiempo real.
- Interacción gráfica más rica.
Estos conceptos implican a su vez la
adopción de ciertos “patrones” de
implementación para su realización en
cualquier aplicación. Ejemplos de estos
patrones son:
• Clientes más gruesos: las aplicaciones
AJAX deben ser lo suficientemente
ricas para evitar llamadas innecesarias al servidor. Sólo se harán llamadas al servidor si no se puede lograr
el mismo efecto directamente en el
navegador cliente.
• Descarga predictiva: en ciertos casos,
las aplicaciones deben anticiparse a
las acciones del cliente y descargar
datos que éste probablemente vaya
a usar luego.
• Refrescamiento periódico: El navegador
refresca la información volátil, encuestando al servidor periódicamente de
un modo transparente al usuario.
• Validaciones del lado del cliente: Se
harán todas las validaciones posibles
del lado del cliente para evitar envíos hacia el servidor.
Para la implementación de estos
patrones, la mayoría de los frameworks
Las figuras 3 y 4 (ver [2]) muestran
el patrón de interacción de un cliente
con una aplicación Web tradicional y
una aplicación Web AJAX.
En este artículo se muestra como
ejemplo de aplicación AJAX la implementación de un álbum de fotos para colocar
y compartir fotos en la Web, pero evitando el tedio y la lentitud que algunas de
estas aplicaciones presentan. El objetivo
principal del ejemplo se centra en mostrar cómo se puede hacer una aplicación
Web donde no hay que refrescar toda la
interfaz que se le muestra al usuario para
poder visualizar cambios en ésta.
Se ha utilizado como plataforma de
desarrollo a ASP.NET 2.0 y Visual
Studio .NET 2005, aunque la solución
puede ser portada con mínimo esfuerzo al .NET Framework 1.1. Además, se
hace uso de Javascript y DHTML para
las tareas del lado del cliente.
Figura 5. Creación del proyecto Web con VS.NET
2005 en el sistema de archivos.
Para que nuestro álbum de fotos pueda ser reutilizado en diferentes aplicaciones Web, será implementado como un
control de usuario Web. Para ello se crea
un nuevo proyecto Web llamado
PhotoGallery (figura 5).
<<dotNetManía
Figura 3. El patrón de interacción síncrono
de una aplicación Web tradicional
AJAX usan una combinación de las
siguientes tecnologías:
• DHTML/CSS y DOM, para lograr
una presentación dinámica.
• XML y XSLT, para el intercambio
y manipulación de los datos.
• XmlHttpRequest o iframes para la
transmisión asíncrona de los datos.
• Javascript como lenguaje para lograr
los tres propósitos anteriores.
27
<< dnm.asp.net
Incluso es posible escribir conversiones especializadas de
objetos .NET en objetos Javascript y viceversa, permitiendo
con ello desarrollar aplicaciones más personalizadas
Figura 6. Creación del control de usuario.
Después de creado el proyecto Web,
se le agrega el control de usuario, al que
llamaremos AlbumFotos.ascx (figura 6).
VS .NET crea entonces una clase
que representa a este control de usuario y despliega el diseñador para que
indiquemos cómo se quiere visualizar
este control. Gracias a las clases parciales de VS 2005, la clase del control queda “limpia” del código necesario para
el trabajo del diseñador (que mayoritariamente se esconde en el método
InitializeComponent). Consideremos
que después de trabajar con el diseñador el control para el albúm de fotos
ha alcanzado el estado que se muestra
en la figura 7.
dro de texto a su lado; uno para mostrar
una “presentación” del álbum completo, una etiqueta para mostrar el nombre de la foto, una para mostrar el orden
dentro del álbum y otra para mostrar la
descripción dada por el dueño; una imagen (<IMG> de HTML) para mostrar la
imagen actual, y tres botones con fines
“administrativos” (borrar, adicionar y
renombrar), que sólo serán visibles para
el dueño del sitio donde se encuentre el
álbum en cuestión. Estos privilegios
podrían ser implementados con la API
de Membresía que ofrece ASP.NET 2.0;
sin embargo, por sencillez nos limitaremos a dar una implementación ingenua.
Por otra parte, los datos y comentarios
relacionados con una foto en cuestión
podrían ser guardados en una base de
datos; aquí igualmente para mantener
la sencillez se mantendrá un documento de texto para cada foto, en el que se
guardará la descripción dada por su
autor, el nombre de la imagen y los
comentarios hechos por los demás
usuarios.
Registro de AJAX.NET en la
aplicación
<<dotNetManía
Figura 7 El álbum de fotos en vista Diseño
28
Al control se le han incluido los cuatro botones clásicos para indicar la navegación (primera, anterior, siguiente y
última), un botón para comentar una
foto, uno para ir a una foto específica,
en base a un número indicado en el cua-
A diferencia de cualquier control de
usuario común en ASP.NET 1.x/2.0,
con AJAX gran parte del código para
manejar los eventos que provocan los
botones en la interfaz de usuario no van
a ser manejados del lado del servidor,
sino que van a tener una fuerte carga de
código del lado del cliente. El código
en el cliente es en este caso Javascript,
el lenguaje de script por excelencia en la
mayoría de los navegadores. Hay plataformas AJAX (como [4] y [5]) que
ocultan todo el código Javascript. Sin
embargo, en este trabajo se ha escogido AJAX.NET porque es una imple-
mentación que posibilita al programador tener control sobre todo el proceso; es decir, desde el código Javascript
del lado del cliente hasta el código del
lado del servidor. Incluso es posible
escribir conversiones especializadas de
objetos .NET en objetos Javascript y
viceversa, permitiendo con ello desarrollar aplicaciones más personalizadas.
Lo primero que hay que hacer para
poder usar esta biblioteca es agregar una
referencia a AJAX.NET en la carpeta
bin. En [1] hay dos versiones, una para
la versión 1.1 y otra para la versión 2.0
de .NET Framework. Se ha utilizado
en este ejemplo la versión para .NET
Framework 2.0.
No basta con agregar la referencia,
también se debe registrar un manejador
de petición (HTTP handler) que usa
AJAX.NET. Este manejador convierte
las llamadas del código cliente en llamadas a métodos del lado del servidor
de un modo transparente y genera el
Javascript apropiado en el código cliente. Más adelante veremos que el tipo
donde se encuentran los métodos que
se deseen invocar debe ser “registrado
para AJAX”, de tal manera que el
HttpHandler (para un buen artículo sobre
HTTP handlers, vea [6]) sepa a qué
método de qué tipo debe llamar al hacer
la citada conversión.
Hay que generar ahora el archivo
web.config y añadir en la sección <system.web> las siguientes líneas:
<httpHandlers>
<add path=”ajaxpro/*.ashx”
verb=”POST,GET”
type=”AjaxPro.AjaxHandlerFactory,
AjaxPro2”/>
</httpHandlers>
Con esto se le dice a ASP.NET que
toda petición que venga a la carpeta vir-
<< dnm.asp.net
El código del lado del servidor, los métodos AJAX
Casi todas las implementaciones de los conceptos
de AJAX utilizan el objeto XmlHttpRequest (algunas
usan iframes) para despachar las peticiones desde el
cliente y procesar las respuestas del servidor en el código Javascript. En particular, AJAX.NET genera, para
cada tipo registrado por el usuario, un proxy Javascript
que se encargará, mediante el objeto XmlHttpRequest,
de enviar asíncronamente las llamadas a métodos del
lado del servidor y recibir la respuesta de éstos (incluida alguna posible excepción).
Se ha usado mucho XML para el intercambio
de datos entre el cliente y el servidor, por el soporte de API que dan muchos navegadores para el trabajo con documentos XML. Sin embargo, las últimas tendencias (como las que se muestran en [7])
indican que XML se ha ido sustituyendo por JSON
[8], el formato nativo en Javascript para representar objetos; JSON es, en la mayoría de los casos,
menos engorroso que XML para representar la misma información. Esto ayuda a disminuir el tráfico
cliente-servidor y hacer más fácil la conversión de
la información textual que envía el servidor en objetos Javascript.
Lo que se pretende es enviar
hacia el servidor solo los datos
necesarios para poder refrescar
una parte de la interfaz
Las llamadas que se producen desde Javascript
usando el proxy van a ser interceptadas por el manejador HTTP y transformadas en llamadas a métodos
AJAX mediante reflexión. Para redondear la ilusión
del programador cliente de AJAX.NET, el proxy
Javascript sigue una sintaxis casi idéntica a aquélla del
lado del servidor. Esto se verá en el ejemplo que se
muestra más adelante.
Para que el control pueda usar AJAX.NET debe
ser registrado. Esto se hace en el evento Load del con-
trol llamando al método RegisterTypeForAjax de la clase Utility de la biblioteca AJAX.NET:
protected void Page_Load(object sender, EventArgs e)
{
Utility.RegisterTypeForAjax(type of(AlbumFotos));
...
}
El método RegisterTypeForAjax también puede ser
utilizado para generar tipos Javascript a partir de tipos
.NET, de manera que en tiempo de ejecución los conversores AJAX transformen “automáticamente” objetos .NET en objetos Javascript y viceversa. Lo único
que se requiere es que el tipo .NET esté marcado con
el atributo Serializable.
La invocación a este método emite algunas referencias en la página HTML que se genera hacia el
cliente:
<script type=”text/javascript”
src=”/PhotoGallery/ajaxpro/prototype.ashx”>
</script>
<script type=”text/javascript”
src=”/PhotoGallery/ajaxpro/core.ashx”>
</script>
<script type=”text/javascript”
src=”/PhotoGallery/ajaxpro/converter.ashx”>
</script>
<script type=”text/javascript”
src=”/PhotoGallery/ajaxpro/AlbumFotos,
App_Web_albumfotos.ascx.cdcab7d2.4deryp-x.ashx”>
</script>
Las tres primeras son referencias al núcleo Javascript
de AJAX.NET, generado por el HTTP handler mencionado anteriormente; la cuarta es una referencia al archivo que contendrá al tipo Javascript que servirá de proxy
a nuestro control de usuario.
Recordemos que la tarea fundamental de este ejemplo es ganar tiempo evitando refrescar la interfaz completa del cliente. Lo que se pretende es enviar hacia
el servidor solo los datos necesarios para poder refrescar una parte de la interfaz de acuerdo con la acción
realizada por el usuario. El soporte que nos brinda
public interface IAlbumFotos
{
//borra una foto del álbum
void Borrar(string dirBase,string caminoFoto);
//agrega una foto al álbum
void Adicionar(string dirBase, string caminoFoto);
//renombra una foto del álbum
void Renombrar(string dirBase, string caminoFoto, string nuevoNombre);
//comenta una foto específica
void Comentar(string dirBase, string caminoFoto, string comentario);
//devuelve la ruta de una foto dado su índice
InformacionFoto IrAFoto(string dirBase int cual);
//devuelve el total de fotos del álbum
int TotalDeFotos(string directorioBase);
}
Fuente 1 La interfaz funcional del álbum
<<dotNetManía
tual /ajaxpro con extensión .ashx será procesada por una
instancia del manejador AjaxPro.AjaxHandlerFactory.
Ahora bien, nosotros no hemos creado ninguna carpeta
virtual con ese nombre; es AJAX.NET quien usa esta
carpeta virtual para fines internos.
29
<< dnm.asp.net
AJAX.NET para lograr este cometido son los métodos AJAX. AJAX.NET interpretará como tales a
aquellos métodos que se hayan marcados con el atributo AjaxMethod (el tipo AjaxMethodAttribute forma
parte de la biblioteca AJAX.NET).
La funcionalidad del álbum de fotos se resume en
el fuente 1.
El control Web de usuario deberá entonces implementar esta interfaz IAlbumFotos. Para que nuestros
métodos puedan ser “invocados” desde el lado del
cliente, es necesario marcarlos con el atributo
AjaxMethod. En caso de que un método necesite hacer
uso de la sesión, entonces hay que indicarle al constructor del atributo un parámetro del tipo enumerado HttpSessionStateRequirement. Este tipo enumerado ofrece tres posibilidades: lectura, escritura y lectura/escritura.
Por ejemplo, el método TotalDeFotos va a necesitar escribir y leer:
protected void Page_Load(object sender, EventArgs e)
{
Utility.RegisterTypeForAjax(typeof(AlbumFotos));
Utility.RegisterTypeForAjax(typeof(InformacionFoto));
if (!Page.ClientScript.IsClientScriptBlockRegistered(“miScript”))
{
Page.ClientScript.RegisterClientScriptBlock(
typeof(AlbumFotos), “miScript”,
string.Format(
“ var directorioBase
= \”{0}\”;\n” +
“ var contadorID
= \”{1}\”;\n” +
“ var descripcionID
= \”{2}\”;\n” +
“ var imagenID
= \”{3}\”;\n” +
“ var nombreFotoID
= \”{4}\”;\n” +
“
“
“
“
<<dotNetManía
btnPrimera
btnAnterior
btnProxima
btnUltima
=
=
=
=
“ var panelComentariosID
“ var numeroFotosTbxID
“ var nombreFotoBaseID
Una propiedad fundamental de nuestro álbum, y
que pudiera mostrarse en la interfaz de usuario con
fines administrativos, es el directorio base de donde
se van a obtener las imágenes. Esta propiedad va a
ser usada solamente para poder configurar el directorio desde el diseñador de la página.
primeraImgBtn.ClientID,
anteriorImgBtn.ClientID,
proximaImgBtn.ClientID,
ultimaImgBtn.ClientID,
Implementación del control
borrarImgBtn.ClientID,
adicionarImgBtn.ClientID,
renombrarImgBtn.ClientID,
comentarImgBtn.ClientID,
Quizás una limitación de AJAX.NET es que no
soporta la propiedad ViewState (lo que se manifiesta en que al invocar esta propiedad se devuelve null). Como es sabido, esta característica es útil
para almacenar la información relacionada con un
control y que no trasciende la página donde éste
se encuentra. La razón que alega el autor es que
esto aumenta el tráfico desde y hasta el servidor y
limita la velocidad de ejecución de la aplicación.
Sin embargo, a nuestro juicio la incomodidad por
la falta de ViewState no se ve compensada por la
supuesta ganancia en el rendimiento por prescindir de ésta.
Es por este motivo de ausencia de ViewState
que los métodos del fuente 1 reciben cómo parámetro la ruta del directorio donde se encuentran
las fotos. Más adelante en el artículo se dará una
explicación más detallada de cómo se hará para que
el valor de esta propiedad viaje del cliente al servidor y viceversa.
\”{5}\”;\n”
\”{6}\”;\n”
\”{7}\”;\n”
\”{8}\”;\n”
+
+
+
+
= \”{9}\”;\n” +
= \”{10}\”;\n” +
= \”{11}\”;\n” +
“ var btnBorrar
= \”{12}\”;\n” +
“ var btnAdicionar
= \”{13}\”;\n” +
“ var btnRenombrar
= \”{14}\”;\n” +
“ var btnComentar
= \”{15}\”;\n” +
“ var btnPresentacion
= \”{16}\”;\n” +
“ var btnIrFoto
= \”{17}\”;\n” +
“ var imageBase
= \”{18}\”;\n” +
“ var operationsPanelID
= \”{19}\”;\n”,
this.Attributes[“DirectorioBase”],
contadorLabel.ClientID,
descripcionFotoLabel.ClientID,
fotoActualImage.ClientID,
nombreFotoLbl.ClientID,
[AjaxMethod(HttpSessionStateRequirement.ReadWrite)]
public int TotalDeFotos(string directorioBase)
{
List<InformacionFoto> dirInfo =
ActualizaCache(directorioBase);
return dirInfo.Count;
}
30
var
var
var
var
panelComentarios.ClientID,
numeroFotoTbx.ClientID,
nombreFotoBase.ClientID,
presentacionImgBtn.ClientID,
irFotoImgBtn.ClientID,
imageBase.ClientID,
operationsBasePanel.ClientID
),
true
);
}
//eventos Javascript
//navegación
primeraImgBtn.Attributes[“onclick”]
anteriorImgBtn.Attributes[“onclick”]
proximaImgBtn.Attributes[“onclick”]
ultimaImgBtn.Attributes[“onclick”]
irFotoImgBtn.Attributes[“onclick”]
//administración
borrarImgBtn.Attributes[“onclick”]
renombrarImgBtn.Attributes[“onclick”]
comentarImgBtn.Attributes[“onclick”]
adicionarImgBtn.Attributes[“onclick”]
presentacionImgBtn.Attributes[“onclick”]
=
=
=
=
=
“IrPrimera();”;
“IrAnterior();”;
“IrProxima();”;
“IrUltima();”;
“IrAFoto()”;
=
=
=
=
=
“Borrar();”;
“PreparaRenombrado();”;
“PreparaComentario();”;
“PreparaAdicion();”;
“PrepararPresentacion();”;
}
Fuente 2 El método Page_Load del control AlbumFotos
<< dnm.asp.net
El método Page_Load
Para poder acceder a los controles desde el código Javascript es necesario que el código del control
emita hacia el código del cliente para cada control
una variable Javascript que contenga el nombre real
del control del lado del cliente. La razón detrás de
esto es que en el HTML que se emite hacia el cliente ASP.NET renombra a cada control de la interfaz
de forma jerárquica, de manera que, al ocurrir un
postback, la jerarquía de controles impuesta por nosotros en el diseñador (o mediante código en el caso
de los controles personalizados) pueda ser recompuesta (para más detalles ver otro trabajo publicado en dotNetManía [3]).
Note en el fuente 2 que al principio del método
se registran dos tipos: AlbumFotos, que representa al
álbum de fotos e InformacionFoto, que nos va a servir
para contener diferentes datos relacionados con una
foto específica. Ambos tipos tuvieron que ser marcados con el atributo Serializable.
Debemos generar además algunas variables “de estado” hacia el código Javascript del lado del cliente. En
este caso, una variable para el directorio base de modo
de poder pasarlo como parámetro a cada uno de los
métodos AJAX (marcados con el atributo AjaxMethod)
que son llamados desde el cliente hacia el servidor. El
valor de esta variable se extrae directamente del atributo DirectorioBase del control, que debe ser especificado en la página que use el control en cuestión, como se
muestra en el fuente 3.
<<dotNetManía
<%@ Page Language=”C#” AutoEventWireup=”true”
CodeFile=”SamplePage.aspx.cs” Inherits=”SamplePage”
EnableEventValidation=”false” %>
%>
<%@ Register Src=”AlbumFotos.ascx” TagName=”AlbumFotos”
TagPrefix=”weboo” %>
%>
<!DOCTYPE html PUBLIC
“-//W3C//DTD XHTML 1.0 Transitional//EN”
“http://www.w3.org/TR/xhtml1/DTD/xhtml1transitional.dtd”>
32
<html xmlns=”http://www.w3.org/1999/xhtml” >
<head runat=”server”>
<title>Untitled Page</title>
</head>
<body>
<form id=”form1” runat=”server”>
<table>
<tr>
<td>
<weboo:AlbumFotos
ID=”AlbumFotos1”
runat=”server”
DirectorioBase=”MisImagenes”/>
</td>
</tr>
</table>
</div>
</form>
</body>
</html>
Fuente 3
Note que es importante haber registrado el control al inicio de la página mediante:
<%@ Register Src=”AlbumFotos.ascx”
TagName=”AlbumFotos”
TagPrefix=”weboo” %>
Observe también que al final del fuente 2 se
incluye código para enlazar el evento onclick de
cada uno de los controles de navegación y administración del álbum con las funciones Javascript
adecuadas. Éstas serán las que finalmente invocarán a los métodos AJAX, como veremos en la próxima sección.
Llamada a un método AJAX desde el cliente
Para ilustrar, se describe a continuación el código del método Comentar que forma parte de la funcionalidad de nuestro álbum. Del lado del servidor, el
código queda como se muestra en el fuente 4.
[AjaxMethod]
public void Comentar(string directorioBase,
string caminoFoto,
string comentario)
{
caminoFoto = CreaCamino(directorioBase, caminoFoto);
string caminoMetadata = CreaCamino(
directorioBase,
Path.GetFileNameWithoutExtension(caminoFoto)+
“.cmt”);
FileStream fStream=new FileStream( caminoMetadata,
FileMode.Append);
using (StreamWriter writer=new StreamWriter(fStream)){
if (fStream.Length == 0)
{
writer.WriteLine(“#descripcion”);
writer.WriteLine();
writer.WriteLine(“#comentarios”);
}
writer.WriteLine(comentario);
}
}
Fuente 4. El código del método Comentar.
Los comentarios a cada unas de las fotos podrían ser guardados en alguna base de datos o usando algún otro mecanismo sofisticado. Por simplicidad, en este ejemplo nos limitamos a usar archivos de texto adicionales ubicados en la misma carpeta de la foto y con el mismo nombre pero extensión .cmt. Estos archivos podrán contener la descripción dada originalmente por el propietario del
álbum más todos los comentarios hechos por los
usuarios con acceso al álbum.
El método Comentar anterior va a ser invocado
asíncronamente a través del código Javascript, como
se muestra en el fuente 5.
<< dnm.asp.net
[Serializable]
public class InformacionFoto {
private string nombreArchivo;
private string descripcion;
private string[] comentarios;
public InformacionFoto(string nombreArchivo, string[] comentarios) {
this.nombreArchivo = nombreArchivo;
CreaComentarios(comentarios);
descripcion = comentarios.Length > 0 ? comentarios[0] : null;
}
AlbumFotos.Comentar( directorioBase,fotoActual,
text,rComentar);
}
private void CreaComentarios(string[] comentarios) {
if (comentarios.Length > 1)
{
this.comentarios = new string[comentarios.Length - 1];
Array.Copy( comentarios, 1, this.comentarios, 0,
this.comentarios.Length);
}
}
public string[] Comentarios {
get { return comentarios; }
}
Fuente 5. La función Comentar en Javascript.
Note que el método Comentar del lado del servidor (fuente 4) tiene sólo 3 parámetros y sin embargo
la invocación que se hace desde Javascript (fuente 5)
tiene 4 parámetros. Los tres primeros parámetros son
variables de estado Javascript para controlar el funcionamiento de la interfaz del lado del cliente, y cuyos
valores son transformados automáticamente por el
HTTP handler de AJAX.NET a los valores .NET del
método Comentar del fuente 4. El cuarto es una referencia a un callback Javascript que va a ser invocado al
término de la llamada asíncrona al servidor, forma
muy parecida a la usada en el patrón asíncrono de la
propia plataforma .NET.
El código de este método rComentar que hace de
callback es el siguiente:
function rComentar(response){
alert('Su comentario ha sido agregado');}
El parámetro response contiene información acerca de la respuesta del servidor. De particular interés
son las siguientes propiedades de response:
value: contendrá el valor devuelto por el método
asíncrono invocado del lado del servidor, en
caso de que éste devuelva alguno.
error: en el caso que el método del servidor provoque una excepción, ésta viajará hacia el
cliente en esta propiedad. Se puede conocer el mensaje de la excepción usando la
expresión response.error.Message.
Por ejemplo, el método IrAFoto que se utiliza
en el fuente 7 devuelve un valor del lado del servidor, con información acerca de la foto a la cual se
quiera navegar. Esta información va a estar encapsulada en un objeto de tipo InformacionFoto, cuya
definición se muestra en el fuente 6. El código
Javascript que invoca al método IrAFoto se muestra en el fuente 7.
Observe en el uso de las propiedades Descripcion,
Comentarios y NombreArchivo la manera en que
AJAX.NET mimetiza el tipo .NET en el proxy
Javascript generado. En este caso el valor de res-
public string Descripcion {
get { return descripcion; }
}
public string NombreArchivo {
get { return nombreArchivo; }
}
}
Fuente 6. La clase InformacionFoto.
function ActualizaFoto(indiceFoto, enableCtrls) {
...
AlbumFotos.IrAFoto(directorioBase,indiceFoto,rActualizaFoto);
...
}
function rActualizaFoto(response) {
var info = response.value;
var src = directorioBase + “/” + info.NombreArchivo;
document.getElementById(imagenID).src = src;
document.getElementById(nombreFotoID).innerHTML =
fotoActual = info.NombreArchivo;
document.getElementById(contadorID).innerHTML =
“” + (indiceActual+1) + “ de “ + total;
document.getElementById(descripcionID).innerHTML =
info.Descripcion == null
? “<i>Sin Descripción</i>” : info.Descripcion;
var comentarios = info.Comentarios;
var panelComentarios = document.getElementById(panelComentariosID);
if(comentarios != null)
{
panelComentarios.innerHTML = “”;
for(i = 0 ; i < comentarios.length; i++)
{
panelComentarios.innerHTML += comentarios[i] + “</br>”;
}
}
else
{
panelComentarios.innerHTML = “<i>Sin comentarios </i>”;
}
}
Fuente 7. Usando el proxy Javascript generado para InformacionFoto.
<<dotNetManía
function Comentar()
{
text = EliminaControlesComentario();
var panelComentarios =
document.getElementById(panelComentariosID);
panelComentarios.innerHTML =
panelComentariosPrevText.startsWith(“<I>”)
? text : panelComentariosPrevText+”<br/>”+text;
panelComentariosPrevText = “”;
33
<< dnm.asp.net
ASP.NET reconstruye la jerarquía de controles a partir del
HTML que se envía al servidor en postback. Este mecanismo tiene fuertes
controles de seguridad para evitar ataques maliciosos por inyección de
código script dentro del HTML que se envía
ponse.value es de un tipo Javascript generado al vue-
lo por el manejador HTTP de AJAX.NET y que sirve de proxy al tipo .NET mostrado en el fuente 6.
AJAX y la seguridad
Un último detalle importante: ASP.NET reconstruye la jerarquía de controles a partir del HTML
que se envía al servidor en postback. Este mecanismo
tiene fuertes controles de seguridad para evitar ataques maliciosos por inyección de código script dentro del HTML que se envía. Como ahora aquí con
AJAX.NET se ha modificado dinámicamente el
HTML, es necesario validar todo lo que viaja hacia
el servidor. Por defecto, ASP.NET lanzaría una
excepción al tratar de validar el HTML enviado
originalmente hacia el cliente contra el enviado por
el cliente hacia el servidor, especialmente en los
datos que forman parte de los controles del formulario. Una alternativa para evitar este comportamiento de ASP.NET es especificar que no se va a
validar automáticamente la información que venga desde el cliente. Esto se logra usando el atributo EnableEventValidation de la directiva <%@Page> de
la página que use nuestro control de usuario:
<%@ Page Language=”C#” ...
EnableEventValidation=”false”%>
En un ejemplo sencillo como el presentado en
este artículo, esto sería suficiente para poder combinar el comportamiento usual de algunos controles en
ASP.NET, que es producir postbacks, con el control
que se está definiendo y que depende en su mayoría
de callbacks Javascript. Sin embargo, de modo general la solución no puede ser renunciar a la seguridad;
en un escenario más complejo y realista habría que
validar en el código Javascript los datos enviados hacia
el servidor. Por razones obvias de simplicidad esto no
se ha incluido aquí.
<<dotNetManía
Conclusiones
34
En este artículo se ha mostrado con un pequeño
ejemplo cómo usar la biblioteca AJAX.NET para
implementar conceptos AJAX en aplicaciones Web
ASP.NET. Hay otras alternativas interesantes, como
[4] y [5], pero se ha escogido la biblioteca AJAX.NET
por su popularidad y por la granularidad que permite. Otros temas más avanzados, como son los convertidores AJAX de dicha biblioteca, podrían servir como
tema para futuros artículos.
El código fuente completo del ejemplo está disponible a los lectores en el sitio Web de
dotNetManía, http://www.dotnetmania.com.
La primera respuesta de Microsoft a este “nuevo” estilo de programación de aplicaciones Web
ha sido incluir los script callbacks en ASP.NET 2.0
(ver en este mismo número el artículo “Ajax con
ASP.NET 2.0. Script callbacks”). Sin embargo, la
simpleza de éstos (ya que solo permiten el intercambio entre el código script de cliente y el código de servidor mediante cadenas de caracteres) hizo
que la compañía lanzara la propuesta de ATLAS,
que promete ser una de las mejores plataformas
AJAX para el desarrollo de aplicaciones Web. Ud.
puede tener ya un primer encuentro con ATLAS a
través del artículo de Miguel Jiménez “Microsoft
AJAX Library (Atlas). Cómo extender ASP.NET
con lo más ‘cool’ de la Web 2.0” que también está
en este número de dotNetManía.
Referencias
[1]
Michael Schwarz, Ajax.NET- The Free Library for NET,
http://www.schwarz-interactive.de.
[2]
Jesse James Garrett, Ajax, A New Approach to Web
Applications, http://adaptivepath.com/publications/
essays/archives/000385.php
[3]
Luis Miguel Blanco, Emitir código JavaScript desde WebForms
y controles Web personalizados, dotNetManía Nº 15.
[4]
Anthem.NET, http://anthem-dot-net.sourceforge.net
[5]
MagicAjax, http://www.magicajax.net
[6]
Michael Flanakin, Implementing HTTP Handlers in
ASP.NET, http://www.developerfusion.co.uk/show/4643
[7]
Ajax Patterns, http://ajaxpatterns.org
[8]
JSON, JavaScript Object Notation, www.json.org
dnm.asp.net
Miguel Jiménez
Microsoft AJAX Library (Atlas)
Cómo extender ASP.NET con lo más “cool” de la Web 2.0
La combinación tecnológica de XHTML, CSS, Javascript y XMLHttpRequest, acuñada bajo el término AJAX desde 2005, representa la fórmula mágica de la poción
que está revolucionando el concepto de la Web. Los desarrolladores de ASP.NET
pueden unirse a la cruzada tecnológica gracias a Microsoft AJAX Library, una extensión de ASP.NET que proporciona la funcionalidad deseada desde la comodidad del
.NET Framework 2.0 y Visual Studio 2005.
<< Hace algún tiempo que se habla de la revolución de la Web La base de Atlas: callbacks vs. postbacks
Miguel Jiménez
es Software Development
Engineer y Responsable de
Formación en ilitia Technologies.
MVP de Visual C# desde 2005,es
líder de INETA en España y
coordinador del Madrid .NET
User Group.Colabora
frecuentemente con MSDN y
otros grupos de usuarios.
2.0 y de las virtudes de AJAX (acrónimo en inglés para
Asynchronous Javascript And XML) para crear aplicaciones Web más ligeras, ricas, interactivas y usables. El tipo
de desarrollo que propone esta combinación de tecnologías se basa en el uso del objeto XMLHttpRequest desde
Javascript para hacer llamadas al servidor que no son
percibidas por el usuario.
El problema que AJAX intenta solventar está generado por el propio protocolo HTTP, el estándar usado
por los navegadores para comunicarse con servidores
Web y enviar de vuelta la información. HTTP es un
protocolo sin estado, es decir, que para preservar los datos
del usuario entre las distintas peticiones hay que escribir código en el servidor que se encargue de ello. La
experiencia típica del usuario Web dicta que la página
completa se envía al servidor para realizar la persistencia de datos; el servidor devuelve la página actualizada y
durante el proceso el usuario percibe un refresco en su
navegador, siendo totalmente incapaz de realizar ninguna operación en la aplicación Web mientras se produce la actualización del contenido.
Hay muchos avances en esta dirección desde los tiempos “ancestrales” de ASP. Por ejemplo, con la introducción de ASP.NET y el
viewstate se eliminó por completo todo el trabajo de gestionar manualmente la persistencia de estado a través de los objetos Request
y Response de las aplicaciones Web. Tras la
experiencia con los postbacks en las versiones
1.0 y 1.1 del Framework, se intenta mejorar la
experiencia del usuario introduciendo el concepto
de ASP.NET 2.0 callbacks en el desarrollo Web.
El concepto de postback es bien conocido por los desarrolladores de ASP.NET. Es el proceso de enviar la información de un formulario Web desde el navegador del
cliente al servidor a través del método POST del protocolo HTTP. Esto sucede cada vez
que un control, método o servicio
se ha de ejecutar en el servidor o
requiere de una actualización. Es
tan frecuente en las aplicaciones desarrolladas con
ASP.NET que puede
llegar a ser extremadamente frustrante.
Con ASP.NET 2.0 se
introducen los callbacks. Un
callback es similar a un postback en que actualiza infor-
<< dnm.asp.net
¿Qué es Atlas?
Atlas [1] se ha construido sobre .NET Framework
2.0 y extiende el soporte de scripts de cliente en los controles de servidor. Se basa en los principios de encapsulación, abstracción y orientación a objetos de
ASP.NET 2.0, puesto que no se trata de otra librería
que encapsula de forma sencilla las llamadas al objeto
XMLHttpRequest, sino de un completo modelo de desarrollo cliente-servidor basado en AJAX y .NET
Framework.
Atlas proporciona funcionalidad en el cliente y en
el servidor. Incluye un conjunto de extensiones de servidor y una librería de scripts de cliente, cuya interacción proporciona un conjunto de tecnologías que da
como resultado aplicaciones Web más ricas a la vez
que ligeras. Atlas es, por tanto, una librería de desarrollo Web compuesta por controles, scripts, servicios
y extensiones de servidor.
Scott Guthrie [2] anunció recientemente en su
blog la disponibilidad y el nombre definitivo para Atlas,
que proporciona además una clara idea de su objetivo
y arquitectura:
• La librería de scripts de cliente se llamará
Microsoft AJAX Library, funcionará con cualquier navegador y con cualquier servidor de backend (PHP, Cold Fusion).
• Las extensiones de servidor se llamarán
ASP.NET 2.0 AJAX Extensions, y como parte del cambio se modificará el prefijo de las etiquetas de <atlas:> a <asp:>.
• El set “Atlas Control Toolkit” se llamará
ASP.NET AJAX Control Toolkit e incluirá
una extensión de controles para maximizar el
valor proporcionado por Atlas.
Por último, Scott hizo público que la versión 1.0
de Atlas estará disponible antes de final de año y no
junto con el lanzamiento de Orcas en 2007, como estaba previsto inicialmente.
Tras esta información, se despejan varias dudas con
respecto a Atlas: no es una simple librería para gestionar callbacks y actualizar porciones de páginas Web de
manera asíncrona; no es una librería de uso exclusivo
para entornos de desarrollo Microsoft; y finalmente,
es una librería totalmente extensible y compatible con
los estándares actuales.
Los escenarios soportados por Atlas no se limitan
a actualizar información en el servidor o actualizar porciones de páginas Web con llamadas asíncronas. Atlas
permite el desarrollo de interfaces de usuario más ricas,
que serían poco prácticas sin este tipo de librería. Por
ejemplo, imaginemos una aplicación Web de recetas
donde el usuario busca en función de diferentes parámetros: tipo, dificultad, calorías, ingredientes. Se puede escribir el código para realizar una búsqueda basada en estos criterios, pero sería poco usable presentar
un DropDownList donde haya cientos de opciones para
cada uno de esos parámetros. En este caso, Atlas nos
permite utilizar un TextBox donde al escribir las primeras letras de un ingrediente, por ejemplo, se realiza una consulta al servidor que presenta una lista mucho
más amigable que coincide con el filtro que se está
introduciendo. Este comportamiento se mejora si se
realizan sucesivas búsquedas conforme se va completando el ingrediente deseado, añadiendo lo que se
conoce como AutoComplete a un TextBox. Es una forma
de sugerir el contenido que se puede incluir en un campo determinado sin utilizar el control estándar para
esta acción (DropDownList) pero limitando el conjunto
de opciones que se pueden introducir.
Figura 1
La arquitectura de Atlas
En el diagrama de arquitectura mostrado en la figura 1 se observa que la funcionalidad de servidor de Atlas
(en la parte derecha) se ha construido extendiendo la
funcionalidad de servidor proporcionada por ASP.NET
2.0 y que se engloba dentro de las ASP.NET AJAX
Extensions. Incluye un conjunto de controles y puentes de servicios en el lado del servidor.
<<dotNetManía
mación en el servidor, pero no lanza el proceso para la
totalidad de la página, sino que utiliza el objeto
XMLHttpRequest para realizar la operación entre bastidores. En el servidor, el proceso tampoco lanza el ciclo de
vida completo de un formulario Web, siendo por tanto
mucho más ligero de ejecutar.
En septiembre de 2005, y como extensión del
modelo de callbacks introducido en ASP.NET 2.0, el
equipo de desarrollo de ASP.NET lanzó públicamente la primera CTP (Community Technology Preview) de
Atlas, una extensión para ASP.NET 2.0 que permitiría
crear aplicaciones Web más ricas y ligeras basadas en
los principios de AJAX.
37
<<dotNetManía
<< dnm.asp.net
38
La capa de cliente presentada en el diagrama (en
la parte izquierda), “Microsoft AJAX Library”, ofrece una serie de scripts que se encargan de garantizar
la compatibilidad entre navegadores, un conjunto de
tipos y todo el modelo de controles, componentes y
servicios. Tal y como se extrae del anuncio de Scott
Guthrie, esta librería de scripts no está atada al lado
servidor y se puede utilizar para crear aplicaciones
basadas en Javascript sin intervención de un servidor
ASP.NET o que utilicen cualquier otro servidor como
backend. Sin embargo, el nuevo conjunto de controles de servidor desarrollados para ASP.NET 2.0 con
Atlas hace un uso extensivo de esta librería de cliente. La utiliza para comunicar todos los cambios, peticiones y eventos de manera asíncrona al código del
servidor.
El nuevo modelo de interacción entre cliente y
servidor difiere un poco del modelo tradicional presentado por el protocolo HTTP. Gracias al uso de
la abstracción del objeto XMLHttpRequest, se pueden
actualizar porciones de la página sin provocar un
refresco, en lugar de actualizar la página completa
en cada petición. El usuario puede seguir trabajando con la aplicación Web e incluso sin percibir que
se ha realizado una llamada al código de servidor. El
objeto XMLHttpRequest debe su versatilidad a que
puede devolver texto plano, XML o notación JSON
en una llamada a servidor y posteriormente interpretarlo en el cliente.
Para conocer más detalles sobre ambos modelos
de interacción entre cliente y servidor, consulte el artículo de Román Fresneda y Miguel Katrib [3] en
este mismo número de dotNetManía.
El modelo de desarrollo en Atlas es muy práctico, ya
que permite desarrollar la misma funcionalidad de varias
formas: a través de los controles de servidor de Atlas,
programáticamente en el cliente usando las librerías de
scripts o usando el nuevo lenguaje declarativo XML Script.
Todas las opciones proporcionan la misma funcionalidad y potencia, pero a través de un modelo de desarrollo distinto que ha sido pensado con diferentes perfiles
en mente (desarrolladores de controles, diseñadores gráficos y programadores Web).
Las extensiones y librerías de Atlas se pueden descargar de http://atlas.asp.net y se instalan localmente en
el equipo del desarrollador. Añaden a la herramienta
Microsoft Visual Web Developer una plantilla adicional de sitios Web para C# y Visual Basic que aparece
cuando seleccionamos la opción “File” > “New” >“Web
Site”, tal y como se muestra en la figura 2.
El modelo de despliegue de Atlas no implica ninguna instalación en el servidor que aloje las Webs desarrolladas con él. La principal referencia de una aplicación Atlas es la librería Microsoft.Web.Atlas.dll; ésta
se copia localmente al directorio bin y actualiza el
fichero web.config de la aplicación; las librerías de
scripts de cliente se copian igualmente de manera local
Figura 2
a la aplicación. Por tanto, las aplicaciones Web desarrolladas con Atlas se pueden desplegar de manera
sencilla, sin requisitos de instalación y proporcionando un sistema más flexible de cara a la actualización e
instalación side-by-side de diferentes aplicaciones con
diferentes versiones del motor de Atlas.
Microsoft AJAX Library
La librería de cliente es la responsable de generar
el modelo de clases y tipos en Javascript que permite
utilizar un entorno más familiar para desarrollar aplicaciones AJAX. Esta librería se presenta en diferentes piezas, siendo la base de ellas la capa de Browser
Compatibility.
Uno de los puntos fuertes de Atlas es el hecho de
que sea multiplataforma, es decir, que funcione en la
mayor cantidad de navegadores posibles. Esta capa
garantiza el funcionamiento de los scripts de cliente
en cualquier navegador (Internet Explorer, Firefox,
Safari y Opera) y se encarga de realizar la abstracción
de las diferentes peculiaridades de Javascript en cada
navegador de forma que no afecten al resto de la
librería. Se incluyen distintas librerías de Javascript
en función del navegador que realiza la petición, por
lo que el proceso es totalmente transparente para el
desarrollador y para el usuario.
Por encima de la compatibilidad de navegadores
se encuentra el Type System, una aproximación del
sistema de tipos de .NET Framework a Javascript.
Permite implementar espacios de nombres, clases y
simular herencia haciendo más similares el desarrollo de scripts al de código de servidor y acercando la
orientación a objetos a Javascript.
La Base Class Library, al igual que su homóloga en .NET Framework, se apoya en el sistema de
tipos. Incluye tipos familiares como StringBuilder,
Debug, Event e IDisposable, y además contiene: la encapsulación y abstracción del objeto XMLHttpRequest a
través de WebRequest, WebResponse y WebMethods; los
métodos de serialización con JSON (Javascript Object
Notation [4]); y las API de Membership, como Profile
y Authentication.
<< dnm.asp.net
El conjunto de controles que se incluirán en Atlas
promete ser bastante extenso (casi todos los controles
básicos de ASP.NET serán migrados)
scripts, aísla la capa gráfica de la de comportamiento, y finalmente se centra en
el comportamiento de los objetos y no
en cómo implementar dicho comportamiento. Nikhil Khotari [6], desarrollador del equipo de Atlas, expone
en su blog más detalles sobre las ventajas y motivos que impulsaron a desarrollar Atlas XML Script en la capa de
presentación.
Es en el UI Framework donde se
agrupan las diferentes tareas asociadas
a los controles y sus actividades o comportamientos. Existen actions (acciones),
<input type=”text” id=”searchText” />
<input type=”button” id=”searchButton” />
<script type=”text/xml-script”>
<page xmlns=”http://schemas.microsoft.com/xml-script/2005”>
<references>
<add src=”ScriptLibrary/Atlas/AtlasUI.js” />
<add src=”ScriptLibrary/Atlas/AtlasControls.js” />
</references>
<components>
<textbox id=”searchText” />
<button id=”searchButton”>
<bindings>
<binding property=”enabled”
dataContext=”searchText” dataPath=”text.length”
transform=”NumberToBoolean” />
</bindings>
<click>
<!— Call the invoke method of ServiceMethod when the button is clicked —>
<invokeMethod target=”searchMethod” method=”invoke” />
</click>
</button>
<serviceMethod id=”searchMethod”>
<bindings>
<!— Bind the query field of the parameters property of the
ServiceMethod to the text property of searchText
(and keep them in sync) —>
<binding property=”parameters” propertyKey=”query”
dataContext=”searchText” dataPath=”text” />
</bindings>
</serviceMethod>
</components>
</page>
</script>
Fuente 1
que representan acciones que llaman a
componentes o servicios en un control,
behaviors (comportamientos) como el
drag and drop y validators (validadores),
similares a los comportamientos, pero
dedicados a validar controles. Y por
supuesto, un completo modelo de binding que permite enlazar diferentes propiedades de los controles con otros controles, objetos, componentes o servicios.
El conjunto de controles que se
incluirán en Atlas promete ser bastante
extenso (casi todos los controles básicos
de ASP.NET serán migrados), entre
ellos, por ejemplo, temporizadores, contadores, vistas de lista y un divertido control de mapas basado en VirtualEarth.
Como el modelo es 100% extensible, se
ha creado un proyecto open source donde
desarrollar aquellos controles que sean
interesantes para la comunidad de programadores, que se ha denominado Atlas
Control Toolkit [7] y se puede encontrar en Codeplex [8].
ASP.NET 2.0 AJAX
Extensions
Finalmente, llegamos a la parte de servidor. Se distribuirá con nombre y funcionalidad muy distinta a la librería de
cliente. Es la encargada de instrumentar
ASP.NET 2.0 con operaciones AJAX
basándose en la Microsoft AJAX Library.
Por un lado, como se apreciaba en
la figura 1, tenemos la nueva rama de
controles de servidor, Atlas Server
Controls. Son similares en nombre y
funcionalidad a los actuales controles
Web, pero incluyen nuevos métodos y
propiedades para gestionar eventos y
scripts de cliente orientados a crear aplicaciones AJAX.
Dentro de este conjunto de controles
hay dos especialmente importantes, que
<<dotNetManía
Desarrollar una capa de controles
y componentes es una tarea mucho más
sencilla una vez se dispone de una sólida base de desarrollo con orientación
a objetos, tipos y un lenguaje más familiar. Estas capas se sitúan sobre las tres
anteriores y se denominan: Controls
and Components y Component
Model and UI Framework.
La capa de controles y componentes no es de uso obligatorio. Se puede
desarrollar una aplicación AJAX usando únicamente el núcleo de Atlas, pero
no tendremos acceso a los controles de
servidor y otras funcionalidades altamente recomendables. Esta capa de
componentes incorpora un nuevo lenguaje de persistencia que, sin escribir
una línea de Javascript, permite definir el comportamiento de un control.
Este lenguaje se denomina Atlas XML
Script, y es un lenguaje declarativo
basado en XML que, tal y como se puede observar en el fuente 1, aporta varias
ventajas: simplifica la lectura del código, elimina la necesidad de escribir
39
<<dotNetManía
<< dnm.asp.net
40
usados conjuntamente minimizan los postbacks de cualquier aplicación Web. Por un
lado, el control ScriptManager, que se
encarga de modificar el modelo postback
desde cliente, y en segundo lugar el control UpdatePanel, que controla el ciclo de
vida de la página en el servidor para conseguir actualizar solo porciones en el cliente. El control ScriptManager se ha de
incluir en todas las páginas que utilicen
funcionalidad de Atlas y se encarga de
manejar el código HTML, Javascript,
XML Script y datos del viewstate en las
llamadas de callback al servidor. Este control se guía por el UpdatePanel para determinar qué regiones ha de gestionar y
actualizar. Pueden existir tantos
UpdatePanel como se desee, de forma que
diferentes regiones de la página se actualicen de forma independiente.
Además, Atlas incluye dos bridges
(puentes) a servicios. Un bridge es un enlace que permite comunicar la capa de cliente con servicios remotos o locales. Sirven
de punto de entrada o conexión a la capa
cliente con una determinada funcionalidad en el servidor. En primer lugar, disponemos del App Services Bridge que
enlaza con los servicios de aplicación de
ASP.NET 2.0 como Membership, Roles
y Authentication. Está directamente
representado en el especio de nombres
Sys.Services.Authentication de la librería
de cliente y permite acceder desde
Javascript a toda la funcionalidad proporcionada por ASP.NET 2.0.
En segundo lugar, tenemos el Web
Services Bridge, que como su nombre
indica enlaza con servicios Web locales
o remotos para que puedan ser llamados directamente desde la capa de cliente. Los servicios accesibles incluyen
aquellos desarrollados con ASP.NET
(.asmx), los desarrollados con Windows
Communications Foundation (.svc) y
aquellos métodos marcados como
[WebMethod] en las páginas Web. Son
directamente accesibles desde el código cliente a través de un proxy que se
genera en Javascript. La creación de este
proxy es posible gracias a un HttpHandler
introducido por Atlas que gestiona el
código generado para un WSDL en
Javascript (utilizando la librería de cliente de Microsoft AJAX Library). En el
fuente 2 se puede observar el código
Javascript generado como proxy de un
var SearchAutoComplete=new function() {
this.path = “http://localhost/TestAtlas/SearchAutoComplete.asmx”;
this.appPath = “http://localhost/TestAtlas/”;
var cm = Sys.Net.ServiceMethod.createProxyMethod;
cm(this,”GetCompletionList”,”prefixText”,”count”);
}
Fuente 2
<script type=”text/javascript” language=”JavaScript”>
function CallWebService()
{
requestSimpleService = SearchAutoComplete.GetCompletionList(
5,
// Parametros
OnComplete,
// Evento OnComplete
OnTimeout
// Evento TimeOut
);
return false;
}
function OnComplete(result)
{
alert(result);
}
function OnTimeout(result)
{
alert(“Timed out”);
}
</script>
Fuente 3
servicio Web local con un único métorio. Microsoft AJAX Library y Microsoft
do, y en el fuente 3 como utilizarlo desASP.NET 2.0 AJAX Extensions proporde cliente con Atlas.
cionan las herramientas que simplifican
Los servicios han de ser generalel desarrollo de Webs más ligeras y ricas.
mente locales, puesto que hay que utiPuede que la próxima killer app esté desalizar el HttpHandler que genera el proxy
rrollada con Atlas, no podría garantizarlo… pero sí puedo garantizar que pronto
y por tanto, para enlazar con un servitendremos mucho más contenido relacio remoto (proporcionado por otro
proveedor) es necesario crear un Service
cionado con Atlas y la creación de aplicaBridge local que se enlazará desde la capa
ciones Web 2.0.
de cliente. Esto representa
todo un avance en el desa- Referencias
rrollo de aplicaciones Web
MashUp [9] con Atlas, que [1] Microsoft Atlas, http://atlas.asp.net.
hasta ahora no presentaba [2] Scott Guthrie, http://weblogs.asp.net/scottgu
una alternativa muy alentaRomán Fresneda y Miguel Katrib, AJAX: Redefiniendo la
dora para reutilizar servicios [3]
forma de ver la Web, dotNetManía Nº 31 (este ejemplar).
desarrollados por terceros.
[4] Javascript Object Notation (JSON), http://www.json.org
Conclusiones
Las aplicaciones Web del
futuro son una realidad hoy
en día. Utilizan servicios
Web, carga asíncrona de
datos e interfaces de usuario
que tienen poco que envidiar
a las aplicaciones de escrito-
[5]
Historia de XMLHttpRequest, http://en.wikipedia.org/wiki/XMLHTTP
[6]
[7]
[8]
Nikhil Kothari, http://www.nikhilk.net
[9]
MashUp, http://en.wikipedia.org/wiki/Mashup_(web_
application_hybrid)
Atlas Control Tookit, http://atlas.asp.net/atlastoolkit
Codeplex, http://www.codeplex.com
dnm.sharepoint
Gustavo Vélez
Presentación de SharePoint
SharePoint es el servidor con el crecimiento más acelerado de todos los productos de Microsoft. Éste es un artículo introductorio sobre el producto, su arquitectura, programabilidad y la nueva versión que aparecerá en corto plazo.
<< Qué es SharePoint
Figura 1. Página principal del portal SharePoint 2003
Arquitectura
Windows SharePoint está basado en Microsoft
SQL Server (o MSDE) como repositorio de configuración e información y ASP.NET como framework. Un concepto básico del diseño de SharePoint
es que todos los documentos, datos de listas y la
información sobre configuración y contenido en
general son guardados en las bases de datos y no
en archivos físicos en los servidores. WSS utiliza
dos bases de datos, una para configuración del sistema y otra para contenido; SPS agrega otras dos
bases de datos, una para guardar datos sobre los
usuarios que permite personalizar individuamente el sistema, y otra para el funcionamiento de la
máquina de búsqueda.
<<dotNetManía
Gustavo Vélez es Ingeniero
Mecánico y Electrónico,
especializado en el diseño,
desarrollo e implementación de
software (MCSD) basado en
tecnologías de Microsoft,
especialmente SharePoint. Es
creador y webmaster de
http://www.gavd.net/servers, y
trabaja com Senior Developer en
Winvision (http://www.winvision.nl)
Microsoft SharePoint es la familia de servidores creados por Microsoft con el propósito de servir como herramientas de colaboración y comunicación, y diseñados para conectar personas, información, procesos y sistemas dentro y fuera de una
organización. SharePoint 2003 está constituido por
dos componentes:
Windows SharePoint Services (WSS) es un
integrante de Windows 2003 y Windows 2003 R2
que permite compartir datos y documentos, cooperar en tareas compartidas e intercambiar mensajes
sin abandonar las aplicaciones de Microsoft Office,
y que además ofrece la infraestructura para crear sitios
Web que pueden servir como sitios de reunión e intercambio, configurar su seguridad y los permisos necesarios para los usuarios. Los servicios por defecto de
WSS incluyen la máquina de búsqueda dentro del
contexto de cada sitio, sistemas de alertas y flujo de
trabajo para aprobación de documentos.
Windows SharePoint Server (SPS) está construido sobre la base de WSS y amplía sus posibilidades de colaboración ofreciendo un portal que permite organizar la información en una forma estructurada; provee una máquina de búsqueda más poderosa que permite indexar información no solo dentro del contexto de diferentes sitios, sino también en
sistemas externos a SharePoint (otros servidores
Web, Exchange), provee un “Mi Sitio” (portal personal para cada usuario), audiencias para dirigir información a grupos de usuarios específicos y “SingleSign-On” para conectar a otras aplicaciones utilizando las credenciales del usuario sin necesidad de
volverse a identificar.
41
<< dnm.sharepoint
Funcionalmente hablando, SharePoint utiliza
una serie de plantillas que sirven como base para el
diseño y formación gráfica de cada página en cada
sitio. Las plantillas proveen el código HTML estático básico para crear cada página. Detrás de cada
plantilla existe un archivo dinámico, programado
en Collaborative Application Markup Language
(CAML), que contiene grupos de definiciones para
ampliar y generar el código HTML específico de
cada página dentro del sitio. Las plantillas son cargadas en memoria interna en el servidor al inicio
de su funcionamiento, y cuando un usuario solicita una página, SharePoint busca la información
necesaria (basada en los derechos del usuario) en la
base de datos, la integra en la plantilla respectiva y
envía el código HTML resultante de regreso. Este
diseño garantiza que los tiempos de respuesta sean
lo más cortos posibles: el “esqueleto” de cada página está siempre disponible, y solamente es necesario recuperar la información delta específica desde
la base de datos, mezclar ambos y generar el
código HTML.
SharePoint utiliza
servidores virtuales para
facilitar la creación de
servidores aislados en un
solo sistema. Por defecto, después de una instalación estándar, solamente se crea un servidor virtual que sirve como sitio
de administración, pero
el administrador del sistema puede crear hasta
99 servidores virtuales
por instalación física de
SharePoint. En SPS, cada portal es de hecho un servidor virtual. Todos los servidores virtuales utilizan el
mismo conjunto de plantillas, por lo que los cambios
realizados en ellas afectarán a todos los sitios y portales creados.
Internet Information Server (IIS) es el servidor dentro de Windows encargado de manejar las solicitudes
HTTP, pero SharePoint 2003 modifica su comportamiento por medio de un filtro ISAPI para controlar rutas
administradas o inclusiones y exclusiones. El filtro ISAPI se encarga de determinar si una solicitud debe ser procesada dentro del contexto de SharePoint, o si se trata
de un proceso separado, ejecutado por otra aplicación o
por el servidor Web. En SharePoint 2007 el filtro ISAPI ya no es necesario, pues SharePoint se comporta como
una aplicación ASP.NET manejada dentro del contexto normal de IIS.
IIS además controla toda la autenticación primaria de usuarios (anónima, básica o integrada de
Windows) para cada servidor virtual, y administra la
forma de habilitar solicitudes anónimas, si es necesario. Después de que un usuario ha sido autenticado
por IIS y Windows, y ha sido aceptado por el sistema, SharePoint se encarga del proceso de autorización, basado en los permisos definidos dentro de
WSS/SPS para cada usuario. El Directorio Activo de
Windows puede ser utilizado como sistema de autenticación, y SharePoint se encarga de definir los derechos que cada usuario tiene en cada página, e inclusive dentro de los diferentes componentes de una misma página.
Administración y escalabilidad
SharePoint está diseñado para poder responder
rápidamente con cargas muy altas de usuarios. El sistema de mezcla de plantillas en memoria y contenido delta desde la base de datos garantiza que la respuesta del sistema no se degrada con el aumento de
usuarios. Cuando las cargas empiezan a ser demasiado altas, la arquitectura
del sistema permite crecer horizontalmente, es
decir, con agregar nuevos servidores físicos al
lado de los existentes, e
implementando un sistema de balanceo de cargas, el aumento de usuarios se puede absorber de
una forma sencilla.
Según las especificaciones, una instalación
de SharePoint puede
contener hasta 2 millones de documentos por
cada librería (cada
documento con un máximo de 2 GB), 2.000 librerías por sitio Web y 250.000 sitios por cada servidor virtual. En cuanto a usuarios, si son registrados individualmente (no en grupos de AD), el sistema puede manejar un máximo de 2 millones. La
cantidad de documentos está más limitada por la
capacidad máxima de SQL Server que por
SharePoint, y la cantidad de servidores en una configuración de granja depende de la versión y configuración de Windows, no de SharePoint.
La configuración y administración de SharePoint se realiza desde una aplicación Web, e incluye la distribución de la topología del sistema (cuáles servidores realizan qué tipo de tarea), configuración de bases de datos y sistemas auxiliares, importación de datos de usuarios desde el Directorio
Activo, configuración de grupos de usuarios y sus
derechos y creación (y eventual eliminación) de servidores virtuales. Los usuarios con suficientes derechos pueden crear sitios Web y determinar qué
<<dotNetManía
SharePoint está aquí para quedarse y su
importancia aumenta cada día más
42
usuarios pueden trabajar dentro de ellos, el administrador del sistema solamente necesita darles
derechos locales de administrador a los usuarios
encargados de la creación de sitios. SharePoint viene por defecto con herramientas especializadas para
darle respaldo al sistema, que junto con las herramientas de respaldo de SQL forman la estrategia
indicada para recuperación de desastres.
Figura 2.Administración central de SharePoint 2003
Programabilidad
SharePoint 2003 está basado en el ASP.NET
Framework 1.1 de Microsoft, aunque WSS y algunas partes de SPS son compatibles con el Framework
2.0. Por lo tanto, Visual Studio 2003 es la herramienta de programación, y CSharp y Visual Basic
.NET son los lenguajes recomendados. SharePoint
presenta una extensa API que cubre todos los aspectos de WSS/SPS y permite interactuar programáticamente con el sistema.
La API de WSS 2003 contiene 13 namespaces
con aproximadamente 170 clases, y SPS añade
otros 16 namespaces con 310 clases. Además, existen otros 20 namespaces no documentados por
Microsoft, dedicados al funcionamiento interno de
SharePoint. El modelo de objetos tiene tres objetos principales de alto nivel: SPSite, que representa una colección de sitios Web, SPWeb, que representa un sitio Web individual, y SPGlobalAdmin, utilizado para la administración y configuración global. Cada elemento funcional de WSS y SPS puede ser programado, incluyendo añadir, editar,
borrar y devolver datos de listas y librerías, crear
nuevas listas con sus metadatos (campos personalizados), trabajar con documentos de librerías (proteger, desproteger, aprobar, rechazar, crear, modificar, eliminar), y todas las tareas administrativas
como crear, eliminar y modificar sitios Web, añadir usuarios y modificar sus derechos.
Una característica especial de SharePoint son
sus WebParts. Windows SharePoint Services 2001 fue
el primer servidor de Microsoft que introdujo el
concepto de WebPart, un elemento programáticamente aislado del centro funcional de SharePoint,
pero que se puede instalar en una página para realizar una función específica. Las WebParts son controles Web que residen en un contenedor (zona de
WebParts) dentro de cada página Web. El
Framework 2.0 de Windows adaptó y generalizó
el sistema de WebParts, haciéndolo utilizable para
cualquier aplicación Web, pero SharePoint 2003
no puede utilizar WebParts programadas para el
Framework 2.0.
Las WebParts representan la forma más fácil y
rápida para extender la funcionalidad de SharePoint,
y, probablemente, es la labor de programación que
más se realiza dentro de WSS/SPS. Una vez creada,
una WebPart consta principalmente de un archivo
.dll con el código compilado, y un archivo .dwp
(XML) con su definición; otros archivos pueden formar parte de una WebPart (recursos, configuración,
localización), y SharePoint ofrece la posibilidad de
crear un archivo .cab comprimido que contiene todos
los archivos necesarios y que se puede instalar en los
servidores utilizando la herramienta de administración de SharePoint.
Un sistema completo de SOAP WebServices es instalado por defecto con SharePoint. WSS 2003 proporciona 16 WebServices que permiten realizar las
tareas básicas del sistema, y SPS agrega otros 3 para
trabajar específicamente con el portal. Aunque no tan
extendido y poderoso como el modelo de objetos de
la API, los WebServices proporcionan la posibilidad
de poder interactuar con WSS y SPS remotamente
y desde otros sistemas que no necesariamente sean
basados en tecnologías Windows. Cuando los
WebServices estándar no son suficientes, la API permite programar WebServices personalizados que realicen tareas específicas, y que funcionen dentro de su
contexto.
Para modificar el layout y capa de presentación
de SharePoint se pueden crear nuevas plantillas, y
se pueden utilizar hojas de estilo (CSS) personalizadas. Otras plantillas permiten crear páginas Web
especializadas en donde aparezca la funcionalidad
necesaria para un trabajo específico. Para la programación de plantillas es necesario tener conocimientos de CAML, que en cuanto a estructura y
sintaxis difiere bastante de C# y Visual Basic. En
cuanto a las hojas de estilo, cada sitio Web utiliza
algunos archivos .css predefinidos, pero es posible
configurar el sistema para que utilice una hoja de
estilo personalizada. Todos los elementos gráficos
en cada página están definidos por una clase de
estilo, así que es posible cambiar visualmente las
páginas de una forma radical.
<<dotNetManía
<< dnm.sharepoint
43
<< dnm.sharepoint
Cambios esperados en la versión 2007
SharePoint forma parte de la división Office de
Microsoft, y como tal, en el año 2007 aparecerá la
nueva versión. La familia de servidores, que en la versión 2003 consta de WSS y SPS, será ampliada, incluyendo diferentes versiones de SPS, una de las cuales
reemplazará al actual Content Management Server
(CMS) de Microsoft como servidor para extranet.
Además, incluirá dos servidores auxiliares, uno para
Excel (cálculo y contención de hojas de cálculo en un
servidor centralizado) y otro para InfoPath (presentación de formularios InfoPath como páginas Web, e
interacción con ellos sin necesidad de tener InfoPath
instalado localmente).
<<dotNetManía
Figura 3. SharePoint 2007 como Content Management System
44
Arquitectónicamente, el diseño básico se mantendrá intacto. SharePoint podrá utilizar SQL 2000 o
SQL 2005 como base de datos, pero con SQL 2005
se beneficiará de una mejor y más rápida respuesta
debido a la mayor optimización de éste. El sistema de
plantillas combinadas con información delta de la base
de datos para generar HTML es también igual, aunque en la nueva versión se utiliza la tecnología de
Páginas Maestras introducida por el Framework 2.0.
En cuanto a programación, todo el código está basado en el Framework 2.0 de .NET, siendo ahora Visual
Studio 2005 la herramienta a utilizar. Las WebParts
podrán utilizar las clases originales de SharePoint 2003
(por compatibilidad), las clases definidas por el
Framework 2.0, o las clases definidas por SharePoint
2007 mismo (que contienen algunas mejoras especialmente pensadas para WSS). La API ha sido radicalmente ampliada, incluyendo todos los namespaces y clases necesarias para funcionar como sistema de manejo
de contenido (CMS), aunque la compatibilidad con la
API de 2003 ha sido garantizada.
Funcionalmente han sido introducidos numerosos cambios, como la integración con el Workflow
Figura 4. Página principal del portal SharePoint 2007
Foundation para poder utilizar flujos de trabajo especialmente programados (con Visual Studio o con el
SharePoint Designer, anteriormente conocido como
FrontPage). La infraestructura de permisos ha sido
ampliada, cubriendo autorización a nivel de documentos, y no solamente a nivel de librerías, como ocurre
en la versión 2003. Nueva es también la posibilidad
de crear blogs y páginas Wiki (páginas Web colaborativas), y la mejora de la máquina de búsqueda y la forma de presentación de datos encontrados.
SharePoint proporcionará herramientas de migración, tanto para migrar sistemas de CMS hacia la nueva versión, como para migrar instalaciones de WSS y
SPS. Las herramientas incluyen no solamente la
migración propiamente dicha, sino también herramientas de análisis para poder predeterminar los posibles problemas. Microsoft ha definido tres estrategias
de migración, que cubren toda la gama de sistemas
empleados: migración “En sitio” (actualización del
sistema) para sistemas pequeños, “Gradual” (las dos
versiones instaladas paralelamente) para sistemas
medianos, y “Migración de Bases de Datos” para sistemas con grandes cantidades de contenido.
Conclusiones
SharePoint es el servidor que Microsoft ha escogido como centro para su estrategia de intercambio
de información. Como tal, el producto esta aquí para
quedarse, y su importancia y aceptación aumentan
cada día. El servidor ha llegado también a un punto
de madurez tecnológica que lo hace muy estable, fácilmente escalable y flexible por las posibilidades que
ofrece como plataforma de desarrollo. La versión 2007
continúa el camino señalado, aumentando la funcionalidad por defecto, e integrando extranet e intranet
en un solo servidor.
Referencias
http://www.microsoft.com/spain/servidores/sharepoint
http://www.gavd.net/servers
dnm.inicio.fundamentos
dnm.incio.fundamentos
Guillermo “Guille” Som
Relación entre delegados y eventos
El avisador que te avise, buen avisador será
En el número anterior vimos con detalle casi todo lo concerniente a los delegados, y
aunque solo lo viésemos de pasada, comprobamos la relación entre los delegados y
los eventos. En este número nos centraremos en los eventos, pero antes comprobaremos que hay ciertas características de los delegados que los hacen imprescindibles
para usarlos con los eventos.
<< Delegados
Delegados multidifusión: unión de varios delegados
[ ]
NOTA
Guillermo “Guille” Som
es Microsoft MVP de Visual Basic
desde 1997. Es redactor de
dotNetManía, miembro de Ineta
Speakers Bureau Latin America,
mentor de Solid Quality
Iberoamericana y autor del libro
Manual Imprescindible de
Visual Basic .NET.
http://www.elguille.info
A lo largo de este artículo, usaré delegate
con la primera letra en minúscula para referirme a la instrucción que tanto C# como Visual
Basic utilizan para definir delegados. Pero cuando quiera hacer referencia a la clase System.
Delegate, usaré la primera letra en mayúscula;
así los programadores de C# no se confundirán
con los cambios de mayúsculas y minúsculas
que tanto les afecta, porque en ese lenguaje, el
tamaño (de las letras) sí que importa.
Como ya comenté en el artículo anterior, los delegados multidifusión son los que en realidad nos permiten que los eventos tengan el comportamiento que
tienen y nos permitan utilizarlos de forma muy flexible. En un momento veremos por qué.
Al usar la instrucción delegate, creamos en realidad un objeto de tipo MulticastDelegate. Veamos
que nos dice la documentación de Visual Studio 2005
sobre esta clase:
Representa un delegado multidifusión; es decir, un
delegado que puede tener más de un elemento en su lista
de invocación.
Está claro, en este caso no hay dudas sobre el significado. Y debido a que éste es el tipo de delegado
que siempre usaremos (o al menos el que usaremos
en un gran porcentaje de las ocasiones), en adelante al indicar que usamos un delegado será para referirnos a este tipo de delegado que permite tener más
de un elemento asociado, ya que, como acabamos de
comprobar, los delegados que podemos crear por
medio de la instrucción delegate son de este tipo de
delegados “compuestos”.
Ahora que sabemos qué es un delegado multidifusión, veamos cómo podemos unir varios delegados en uno solo.
Agregar delegados a la lista de un delegado multidifusión
En C# los operadores += y -= están sobrecargados para poder utilizarlos con este tipo de delegados, de forma que si queremos añadir más de un dele-
<<dotNetManía
Cuando definimos un delegado tanto en C# como
en Visual Basic usamos la instrucción delegate. Esa instrucción en realidad lo que hace es definir un tipo de
datos especial. Y la primera impresión es que en realidad esa instrucción utiliza el tipo definido en la propia
librería de clases de .NET que tiene el mismo nombre:
System.Delegate. Pero no es así: en realidad el tipo de
datos que obtenemos con una declaración por medio
de la palabra clave delegate es System.Multicast
Delegate, que está basada en la clase Delegate.
En esta primera parte del artículo nos centraremos en la clase MulticastDelegate y en cómo se pueden agrupar varios métodos delegados en un mismo
objeto delegado, además de ver cómo podemos invocar a todos esos métodos con una sola llamada.
45
<< dnm.inicio.fundamentos
gado a la lista de delegados lo haremos usando precisamente el operador de asignación e incremento (+=).
Veamos un ejemplo de cómo agrupar varios delegados y cómo invocarlos, y cuando veamos lo que ocurre, lo tendremos todo más claro.
En el fuente 1 tenemos una definición de un delegado, el cual es una plantilla para un método de tipo
void (no devuelve nada) y que recibe como parámetro una cadena. En ese mismo código fuente, tenemos tres métodos que podemos usar con una variable definida mediante ese delegado; cada uno de los
métodos muestra la cadena pasada como argumento
en la consola, pero de forma diferente, con la idea de
que podamos ver que es lo que en realidad está ocurriendo.
Pero lo que aquí tenemos que “demostrar” es cómo
agregar más de un método a una misma variable, y tal
como vimos al principio de esta sección, debemos
hacerlo mediante el operador +=, por tanto, si usamos
el código mostrado en el fuente 3, conseguiremos lo
que estamos buscando.
// La definición del delegado
delegate void MostrarCadenaCallback(string str);
Como vemos en dicho código fuente, la forma de
asociar varios delegados es la misma que cuando asignamos solo uno, con la única diferencia del operador
usado para dicha asignación. Y con el operador de
asignación y suma también podemos usar las dos formas de asignar el método al que se llamará desde el
delegado.
Lo más interesante de todo esto está en la última
línea. Cuando invocamos al delegado pasándole el parámetro que espera (en este caso una cadena), éste se encargará de llamar secuencialmente a todos y cada uno de
los métodos delegados que hayamos añadido a la variable que hace referencia al delegado multidifusión.
El orden de llamada a cada uno de los métodos
que tenemos en la lista del delegado es el mismo en
el que hemos añadido esos métodos; por tanto, el código del fuente 3 producirá la siguiente salida:
// Varias definiciones del método con la firma adecuada
// para el delegado MostrarCadenaCallback
// Muestra la cadena sin alterar
static void mostrarStr(string str){
Console.WriteLine(str);
}
// Muestra la cadena en mayúsculas
static void mostrarUpper(string str){
Console.WriteLine(str.ToUpper());
}
// Muestra la cadena en minúsculas
static void mostrarLower(string str){
Console.WriteLine(str.ToLower());
}
Fuente 1. Definición de un delegado y tres métodos que
tienen la misma firma
Para usar ese delegado y asociarlo a cualquiera de los
métodos lo haríamos tal como vemos en el fuente 2. En
este caso solo usamos uno de los tres métodos que hemos
definido, en particular el método mostrarUpper.
MostrarCadenaCallback delegado1;
//delegado1 = new MostrarCadenaCallback(mostrarUpper);
delegado1 = mostrarUpper;
delegado1(“Hola delegado”);
<<dotNetManía
Fuente 2. La forma habitual de usar un delegado e invocarlo
46
Al ejecutar el código del fuente 2, comprobaremos que el mensaje indicado se muestra completamente en mayúsculas, que en realidad es lo que esperamos que ocurra, y tal como vimos en el artículo anterior tenemos dos formas de asignar a la variable delegado1 el método que vamos a usar; la asignación que
está comentada es la que tendríamos que usar en las
versiones anteriores a Visual C# 2005.
MostrarCadenaCallback delegado2;
delegado2 = new MostrarCadenaCallback(mostrarStr);
delegado2 += new MostrarCadenaCallback(mostrarLower);
delegado2 += mostrarUpper;
delegado2(“¡Hola Delegado!”);
Fuente 3.Asociar varios métodos con una misma variable de
tipo delegado
¡Hola Delegado!
¡hola delegado!
¡HOLA DELEGADO!
De la misma forma que podemos añadir nuevos
métodos a un delegado, podemos quitar métodos que
previamente hayamos añadido. Para ello usaremos el
operador -=, el cual se usa exactamente como el que
acabamos de ver, pero su función es eliminar delegados de la lista. Si queremos quitar un delegado que
no está previamente añadido no se produce ninguna
excepción; simplemente la petición se ignora.
Si al código del fuente 3 le agregamos la siguiente línea antes de llamar al delegado, lo que conseguiremos es que solo haya dos métodos en la lista del
delegado:
delegado2 -= mostrarLower;
Nuevamente comprobamos que también podemos usar la forma “abreviada” para quitar métodos de
la lista de delegados.
<< dnm.inicio.fundamentos
NOTA
Definir eventos
En Visual Basic no hay forma de añadir y quitar métodos de
la lista de un delegado multidifusión,al menos de la forma como
se hace con C#. La única forma de hacerlo es por medio de los
métodos compartidos Combine y Remove de la clase Delegate o
del delegado que definamos, aunque el valor devuelto siempre
es del tipo Delegate. Para llamar al delegado podemos usar el
método Invoke de la clase Delegate o bien usar la llamada directa, en cuyo caso el objeto debe ser del tipo del delegado que
estamos combinando. En el código de ejemplo que acompaña
al artículo hay varios métodos con distintas formas de usar el
método Combine y Remove.
Todo esto es así de complicado si trabajamos directamente con delegados que no están relacionados con eventos,ya que
si trabajamos con eventos, podemos usar las instrucciones
AddHandler y RemoveHandler para conseguir la misma funcionalidad de los operadores += y -= respectivamente.
Como ya vimos en el artículo anterior, la definición de un evento está estrechamente ligada con los
delegados, particularmente en el caso de C#, ya que
en Visual Basic podemos definir eventos sin que tengamos que asociarlos con delegados, al menos desde
el punto de vista del programador; el compilador de
Visual Basic se encarga de la relación entre la definición del evento y el delegado que debe tener asociado el evento que definamos.
El hecho de que cada evento esté relacionado con
un delegado es porque la forma de lanzar ese evento
(o lo que es lo mismo, la forma de notificar que ese
evento ha ocurrido) es llamando al delegado con los
parámetros que hayamos definido.
Por ejemplo, si queremos tener un evento en una
clase para que nos notifique cada vez que se modifica
el contenido de una propiedad, tendremos que definir un delegado que indique la “firma” que debe tener
el método que vaya a recibir dicha notificación.
Además, debemos definir el evento propiamente dicho,
el cual será una variable especial del tipo del delegado. Lo de “variable especial” es porque en realidad se
define como cualquier otra variable (solo que con un
tipo delegado como tipo de datos), pero añadiéndole
la instrucción event. En el fuente 4 vemos la definición del delegado y el evento.
Nomenclatura en las definiciones de los delegados
Para finalizar el tema de los delegados, una nota
sobre la nomenclatura recomendada.
En la definición de los delegados se recomienda
el sufijo EventHandler para los nombres de delegados
que se utilizan en eventos y el sufijo Callback para los
nombres de delegados que no sean manejadores de
eventos.
En caso de que definamos una clase para usar como
parámetro de un delegado relacionado con un evento, debemos añadirle el sufijo EventArgs si dicha clase se deriva de System.EventArgs.
Una vez hechas estas aclaraciones, pasemos a ver
qué son y cómo definir y usar los eventos.
public delegate void NombreCambiadoEventHandler(
string nuevo, string anterior);
public event NombreCambiadoEventHandler NombreCambiado;
Fuente 4. Definición de un evento y el delegado asociado
¿Qué es un evento?
En este ejemplo, definimos un delegado que recibe dos parámetros; el primero es el nuevo valor que
hemos asignado a la propiedad y el segundo el que
tenía antes de asignar ese nuevo valor.
A continuación definimos el evento, que es del tipo
del delegado. Como vemos, en realidad la definición
del evento no se diferencia mucho de cómo definiríamos una variable que quisiéramos tener relacionada
con un evento, salvo porque utilizamos la instrucción
event para definirla. Esa instrucción hace que exista
“automáticamente” una relación entre el delegado y
el evento, de forma que no tengamos que instanciar
expresamente el delegado para poder usarlo.
Usar los eventos de una clase
Una vez que tenemos definido el evento en una
clase, podemos recibir notificaciones cada vez que ese
evento se produzca. Por supuesto, la clase que define
el evento es la que se encargará de producir el evento para informar a los objetos que deseen recibir dicha
notificación.
<<dotNetManía
Un evento es un mensaje (o notificación) que lanza un objeto de una clase determinada cuando algo ha
ocurrido. El ejemplo más clásico y fácil de entender
es cuando el usuario pulsa con el ratón en un botón
de un formulario. Esa acción produce, entre otros, el
evento Click del botón en el que se ha pulsado. De
esa forma, el botón notifica que esa acción ha ocurrido, y ya es cuestión nuestra que hagamos algo cuando eso ocurra. Si estamos interesados en interceptar
ese evento tendremos que comunicárselo a la clase que
define el botón; si no lo estamos, simplemente no es
necesario que indiquemos nada.
Como es de suponer, los eventos se pueden definir en cualquier clase, y no solo en clases que tengan algún tipo de interacción con el usuario, aunque lo más habitual es que precisamente se usen con
clases que forman parte de la interfaz gráfica que
se le presenta al usuario de una aplicación. De esa
forma podremos saber que algo está ocurriendo y
en qué control, de forma que sepamos en todo
momento lo que el usuario quiere hacer o lo que
está haciendo.
47
<< dnm.inicio.fundamentos
Para recibir el mensaje del evento, debemos
crear un método que tenga la misma firma que el
delegado que hemos asociado a dicho evento.
Usando el evento definido en el fuente 4, la asociación deberíamos hacerla tal como vemos en el
código del fuente 5.
Cliente cli = new Cliente();
cli.NombreCambiado += new
Cliente.NombreCambiadoEventHandler(
cli_NombreCambiado);
Figura 1. Creación automática del delegado adecuado desde
el editor de Visual C# 2005
Figura 2. Creación automática de un método con la firma del
delegado asociado con el evento
Fuente 5.Asociación de un evento con un método
[ ]
NOTA
El método indicado en el constructor del delegado debemos definirlo con la firma determinada por
el propio delegado, quedando la definición tal como
vemos en el fuente 6.
void cli_NombreCambiado(string nuevo, string anterior)
{
label2.Text = “Se ha cambiado el nombre:\n” +
“Nuevo valor:
“ + nuevo + “\n” +
“Valor anterior: “ + anterior;
}
Debido a que los eventos, de forma predeterminada, son miembros de instancia (están
asociados con cada instancia de la clase que los
define), si creamos un nuevo objeto de esa clase debemos volver a asociar el método que recibirá la notificación del evento.
Esto no es necesario si esa clase solo la instanciamos una vez y usamos siempre la misma
instancia.
Fuente 6. Definición del método que recibirá la notificación
cuando se produzca el evento.
<<dotNetManía
Producir un evento
48
Como podemos apreciar, la forma de asociar el
evento con el método que recibirá la notificación cada
vez que éste se produzca es usando el operador +=,
que como vimos es la forma que tienen los delegados multidifusión de añadir los métodos que recibirán el aviso cada vez que dicho delegado sea llamado; en el caso de los eventos, ese aviso se iniciará cuando lancemos el evento desde la clase que lo define
(en un momento veremos cómo).
Una pega que podemos encontrarnos es con la
definición del método que recibe el evento. En realidad no es un problema, ya que si sabemos que definición tiene el delegado sabremos cuál debe ser la
definición de dicho gestor de evento. Pero para que
nos resulte más cómodo, el editor de Visual C# 2005
nos facilita dicha creación; incluso nos permite saber
cuál es el delegado asociado con el evento que queremos interceptar.
En las figuras 1 y 2 vemos cómo el IDE de Visual
Studio 2005 nos permite tanto usar el delegado
correcto (figura 1) como la creación del método con
la firma adecuada (figura 2).
De esta forma, no tendremos que buscar la definición del delegado para crear de forma fácil el método que debemos usar.
Una vez que tenemos la definición del delegado
y el evento en nuestra clase, tenemos la posibilidad
de lanzar o producir dicho evento. Cuándo y dónde
lanzar el evento depende de nuestro código. En el
ejemplo de la clase Cliente que produce un evento
cada vez que se modifica la propiedad Nombre, lo haremos de la forma que mostramos en el fuente 7.
private string m_Nombre;
public string Nombre
{
get { return m_Nombre; }
set{
if( NombreCambiado != null )
{
NombreCambiado(value, m_Nombre);
}
m_Nombre = value;
}
}
Fuente 7. La forma de producir un evento en C#
En el bloque set es donde lanzamos el evento.
En este ejemplo lo lanzamos se modifique o no el
contenido de la propiedad, pero ese detalle no es lo
<< dnm.inicio.fundamentos
[ ]
NOTA
Veremos cómo definir, interceptar y lanzar los eventos en
Visual Basic en un próximo artículo dedicado exclusivamente a
los eventos desde el punto de vista de ese lenguaje, en el que también veremos cómo usar la nueva instrucción Custom Event ,
exclusiva de Visual Basic 2005.
Interceptar el mismo evento más de
una vez
Como podemos comprobar en el
código mostrado en las secciones anteriores, la asociación entre un evento y
el método que recibirá la notificación
de que dicho evento produce lo hacemos mediante el operador +=. Si esa asociación la hacemos con varios métodos,
todos y cada uno de esos métodos recibirán la notificación de que el evento se
ha producido. Esto es posible porque en
el fondo la instrucción event en realidad está definiendo un objeto del tipo
MulticastDelegate , y como vimos al
principio de este artículo por medio
Un evento es un mensaje (o notificación) que lanza un objeto
de una clase determinada cuando algo ha ocurrido
de ese tipo de delegado podemos “asociar” varios métodos con un mismo
delegado.
Por tanto, todos los métodos que
agreguemos por medio del operador +=
estarán listos para recibir el mismo mensaje que lancemos (ver fuente 7). Y tal
como vimos en el código del fuente 3,
el orden en el que se notificarán será el
mismo en el que hayamos añadido esos
métodos a la lista de métodos que quieren recibir el evento.
Esa asociación la podemos realizar tanto usando un nuevo método
como usando un método ya existente. En este último caso, ese método
se ejecutará tantas veces como veces
esté en la lista de delegados que recibirán la notificación, algo que seguramente no será de mucha utilidad,
pero que es posible. Y debido a que
podemos hacerlo, debemos tenerlo en
cuenta, para que no ocurra esa múltiple notificación. Por ejemplo, si la
clase que produce eventos solo la instanciamos una vez, y utilizamos el
siguiente código para “ligar” el método con el evento:
cli.NombreCambiado += new
Cliente.NombreCambiadoEventHandler(
cli_NombreCambiado);
Cada vez que ejecutemos esa línea se
añadirá el método cli_NombreCambiado a
la lista de métodos que recibirán la notificación, y cuando el evento se produzca,
se llamará esa misma cantidad de veces,
consiguiendo algo que seguramente no
era lo que queríamos.
Un mismo método que recibe eventos
de clases diferentes
En el mismo ejemplo que estamos
usando, podemos asociar un mismo
método para que reciba notificaciones
de objetos diferentes, ya que si la firma del método coincide con la del
delegado del evento, ese método lo
podremos usar sin ningún tipo de problema. Esto es aplicable no solo al
objeto “cli” que hemos definido en el
ejemplo, sino a cualquier otra instancia que creemos del tipo Cliente (o
cualquier otra clase que queramos
usar, siempre que el método tenga la
misma firma que el delegado correspondiente); de esa forma podremos
ahorrarnos algo de código.
Debido a que el ejemplo de la clase
Cliente puede que no nos aclare mucho,
veamos esto último usando controles y
eventos definidos en los controles de
Windows.Forms. Por ejemplo, si tenemos
varios controles de tipo TextBox en un
formulario y queremos seleccionar todo
el texto que tenga ese control al recibir
el foco (cuando el control es el control
activo), podemos hacer una múltiple
asociación con un mismo método, tal
como vemos en el fuente 8.
Ni qué decir tiene que todos los
eventos (como es este caso), deben
tener la misma firma, lo cual no implica que deban ser del mismo tipo, ya
que lo único que en realidad importa
es que el delegado asociado con el
evento tenga la misma definición que
el método que recibirá la notificación
del evento. En el caso de los contro-
this.textBox1.Enter += new System.EventHandler(this.textBox_Enter);
this.textBox2.Enter += new System.EventHandler(this.textBox_Enter);
this.textBox3.Enter += new System.EventHandler(this.textBox_Enter);
Fuente 8.Asociación de eventos de clases diferentes con un mismo método
<<dotNetManía
importante; en lo que de verdad debemos fijarnos es en la comprobación de
si el evento no es nulo, ya que debemos
hacer esa comprobación, con idea de
lanzar el evento solo si alguien lo está
interceptando; en caso contrario no
debemos llamar al delegado multidifusión, que es en realidad el que se encarga de “propagar” el mensaje a todos los
métodos que hayamos definido para
recibir el mensaje.
Si alguien está esperando la notificación del evento, usamos el mismo
nombre del evento (que en realidad es
un MulticastDelegate) para lanzar el
evento, indicando los parámetros adecuados (en nuestro ejemplo, el nuevo
valor de la propiedad y el valor que tenía
antes). Y una vez que hemos producido
el evento es que asignamos el nuevo
valor al campo que mantiene el contenido de esa propiedad.
49
<< dnm.inicio.fundamentos
les de Windows.Forms, ese mismo método lo podríamos asociar a un botón:
this.button1.Enter +=new
EventHandler(this.textBox_Enter);
Lo que sí debemos tener en cuenta es que el código que usemos en ese método esté preparado para que
los controles puedan ser de tipos diferentes, tal como
vemos en el código del fuente 9.
private void textBox_Enter(object sender, EventArgs e)
{
labelInfo.Text = “El foco lo tiene “+
((Control)sender).Name;
if( sender is TextBox )
{
((TextBox)sender).SelectAll();
}
}
Fuente 9. Si un mismo método se producirá desde clases
diferentes debemos tenerlo en cuenta en el código.
<<dotNetManía
Añadir “manejadores” de evento
50
Cuando estamos trabajando con formularios y controles, la asociación entre un evento y el método que usaremos para interceptarlo lo podemos hacer de varias formas. Una de ellas es de forma totalmente manual, que es
la que hemos visto anteriormente; pero para ser sinceros, esa no será la forma habitual de asociar un evento
con un método, ya que el diseñador de formularios de
Visual Studio 2005 nos ofrece una forma más sencilla.
Para “ligar” un evento con un método (y crearlo si
no existe), debemos seleccionar el control que define el
evento que queremos usar y en la ventana de propiedades seleccionar “Eventos” (el botón con la imagen de un
rayo amarillo). De esa forma tendremos una lista de los
eventos definidos por ese control (o al menos de los eventos que el creador del control haya decidido que se muestren en esa ventana de propiedades). En la figura 3 podemos ver algunos de los eventos de un formulario.
Como vemos en la figura 3, si el evento está asociado a un método, se muestra el nombre del mismo;
si no hay ninguna asociación, el campo se muestra en
blanco. Para crear un nuevo método y asociarlo al evento, simplemente tendremos que hacer una doble pulsación en la caja de textos en blanco. Pero si lo que queremos es usar uno de los métodos existentes, podemos
seleccionar el método de la lista desplegable; en esa lista solo se mostrarán los métodos que tengan la misma
firma del delegado asociado con ese evento, tal como
podemos ver en la figura 4, donde el delegado del evento Click tiene la misma firma que los mostrados en
dicha lista, lo que nos permite usar cualquiera de los
existentes o bien crear uno nuevo.
Figura 3. Desde la
ventana de
propiedades podemos
seleccionar el evento
que queremos
interceptar
Figura 4. Podemos
asociar un evento a un
método existente, el
cual seleccionamos de
una lista desplegable
Lo único que no nos permite el diseñador de formularios es asociar varios métodos de eventos a un
mismo evento. En ese caso, tendremos que hacer
manualmente esa asociación. La pregunta puede ser
¿dónde hacer esa asociación? La respuesta es: donde
queramos, pero siempre que ese código no se repita
más de una vez, con idea de no agregar más veces de
las necesarias el método que intercepta el evento. Por
tanto, lo más recomendable es que escribamos ese
código en el constructor del formulario, pero justo
después de la llamada al método InitializeComponent.
Esto también es válido para cuando decidamos asociar manualmente los eventos con los métodos que
recibirán la notificación.
Conclusiones
En este artículo hemos visto cómo trabajar con los
eventos en C#: desde cómo definirlos hasta cómo interceptarlos y cómo están relacionados los eventos con los
delegados, principalmente con los delegados multidifusión, gracias a los cuales podemos asociar un mismo
evento con varios métodos. Si a lo comentado en este
artículo le añadimos todo lo dicho en el artículo anterior, dedicado casi exclusivamente a los delegados, tenemos todo lo necesario para entender cómo trabajan los
eventos y los delegados. Pero no todo está dicho: aún
hay ciertas cosas que necesitamos saber para sacarle
todo el rendimiento a los eventos y delegados, principalmente a los que definamos en nuestras propias clases. Pero eso lo dejaremos para otro artículo en el que
también trataremos estos conceptos desde el punto de
vista del programador de Visual Basic.
Como siempre, el código de los ejemplos usados en el artículo está disponible (tanto para C#
como para Visual Basic) desde el sitio Web de
dotNetManía.
dnm.todotnet.qa
Dino Esposito
Más allá del mito
Discusión sobre AJAX y ATLAS
<< Alguien en Redmond debe haber sido mordido por el gusa-
Dino Esposito
es mentor de Solid Quality
Learning y autor de “Programming
Microsoft ASP.NET 2.0 Core
Reference” y “Programming
ASP.NET 2.0 Applications Advanced
Topics”, ambos de Microsoft
Press.Afincado en Italia, Dino es
un ponente habitual en los
eventos de la industria a nivel
mundial.Visite su blog en:
http://weblogs.asp.net/despos.
Puede enviarle sus consultas a
[email protected]
nillo de la mitología griega, últimamente. Sólo así se
entiende la repetida mención de nombres como Ajax
–el popular héroe de la guerra de Troya– y Atlas, uno
de los Titanes primordiales, condenado a soportar sobre
sus hombros el peso de la Tierra. Ciertamente, AJAX
no es una marca registrada por Microsoft, sino un término acuñado para identificar un montón de tecnologías Web, utilizadas por Google (y otros) para construir
buenas aplicaciones. Como mi hijo de 8 años ya sabe,
AJAX significa Asynchronous Javascript And XML. Atlas
es simplemente el nombre en código de la plataforma
Microsoft basada en AJAX para ASP.NET. Hacia el final
del verano de 2006, se cambió el nombre de AJAX por
el de ASP.NET 2.0 AJAX Extensions, así que el pobre
titán puede descansar en paz.
Hola Dino, gracias por tus artículos y tu labor de
escritura. Tengo un problema del que estoy casi seguro que habrás escrito algún artículo o que tendrás una
respuesta rápida. Estoy tratando de ejecutar Javascript
en el cliente en el evento de postback. Más concretamente, intento mostrar un GIF animado del tipo “Por favor,
espere” mientras se prepara el servidor. Pero no se produce animación, supongo que porque la página está
siendo reprocesada.
¿Quieres primero una respuesta del tipo sí o no? De
acuerdo, tu suposición es totalmente correcta y puedes
olvidarte de mostrar un GIF animado en una actualización clásica tipo postback en la página activa. Esto es
por diseño, y tiene más que ver con el navegador que
con ASP.NET. Un GIF animado es sencillamente una
colección de sub-imágenes o marcos que la aplicación
manejadora muestra periódicamente en una hebra de
background. La hebra está activa dependiendo del estado de la página que lo contiene. Cuando haces un post-
back, el navegador congela la página y destruye la hebra.
Cualquier interacción entre el navegador y cualquier
elemento de la página se detiene, y consecuentemente,
cesa la animación.
Dispones de dos opciones “conservadoras”, y otra
algo más intrusiva. La más sencilla es usar un fichero GIF estático o un mensaje. ¿No te gusta, no? La
segunda opción supone el uso de una página intermedia o quizás un marco para mostrar el mensaje con
soporte completo de animación. Harías el reenvío de
la página que muestra el feedback del usuario y cargarías la página de destino en el evento onLoad de la etiqueta <body>; de esta forma, la página de transición
se mantiene hasta que se carga la otra. Sin embargo,
algunos amigos me han comentado que siguen teniendo dificultades asociadas con esta técnica en lo referente a los GIF animados.
¿Qué es lo que falta? Una aproximación tipo AJAX,
o similar. Es una buena solución utilizar las extensiones
de AJAX, aunque esto supone añadir algún fichero binario a la aplicación instalada. Si AJAX no es una opción,
puedes convertir el control en un botón de cliente y
enlazarlo a una rutina script callback. Las rutinas de callback en ASP.NET son una característica nativa de
ASP.NET 2.0 y no requieren vínculos externos. El API
es un tanto extraño, pero funciona bien. El problema,
en este caso, es cómo actualizar la página después del
postback. El script callback termina por llamar a un método servidor en la página y devuelve al cliente una cadena. La actualización de la interfaz de usuario del cliente para reflejar esta situación es algo enteramente opcional. Y podría no ser divertido.
En resumen, lo más sencillo que podrías hacer para
mantener el GIF animado mientras se procesa la página es usar un poco de las extensiones de AJAX. Tienes
<<dotNetManía
Las extensiones AJAX constituyen la siguiente gran novedad en el desarrollo de
ASP.NET,como puede ver el lector en este número de la revista.En esta columna responderé algunas cuestiones que he recogido en las pasadas semanas, tratando de
hacer una introducción al mundo AJAX de forma suave y gradual.
51
<< dnm.todotnet.qa
que encapsular el botón y la porción de
interfaz de usuario afectada por el clic en
un control UpdatePanel.
<atlas:ScriptManager runat=server
ID=ScriptManager1/>
<atlas:UpdatePanel …>
<contenttemplate>
<%— Tu viejo código ASP.NET —%>
<contenttemplate>
</atlas:UpdatePanel>
De esta forma, cualquier postback
causado por el código incluido en el
panel es transformado en un postback
de AJAX, sin refresco de la página
completa. Si muestras un GIF animado durante el refresco de la página, la
animación continuará hasta que la
página esté lista. Y existe otro control
tipo AJAX que todavía facilita más las
labores de este tipo: el control Update
Progress. A continuación incluyo un
fragmento de código real que recorre
las páginas de un DataGrid, utilizando
un GIF animado por cada página
(fuente 1).
El control UpdateProgress se enlaza a
cualquier control UpdatePanel de la página y se muestra siempre que se refresca
uno de los paneles. No hay que preocuparse por mostrar o esconder el panel de
progreso, lo hará ASP.NET. La figura 1
da una idea de lo que puede esperarse ver.
Figura 1. Controles UpdatePanel y
UpdateProgress mostrando un GIF
animado mientras la página se recarga y se
refrescan los datos.
<atlas:ScriptManager ID=”scriptManager”
EnablePartialRendering=”true”
runat=”server” />
<<dotNetManía
<atlas:UpdatePanel ID=”UpdatePanel1” runat=”server”>
<ContentTemplate>
<asp:GridView ID=”GridView1” runat=”server”
DataSourceID=”ObjectDataSource1”
AllowPaging=”True”
AutoGenerateColumns=”False”>
<Columns>
<asp:BoundField DataField=”ID” HeaderText=”ID” />
<asp:BoundField DataField=”CompanyName” H
eaderText=”Company”/>
<asp:BoundField DataField=”Country”
HeaderText=”Country”/>
</Columns>
</asp:GridView>
<asp:ObjectDataSource ID=”ObjectDataSource1”
runat=”server”
TypeName=”IntroAtlas.CustomerManager”
SelectMethod=”LoadByInitial” />
</ContentTemplate>
</atlas:UpdatePanel>
52
<atlas:UpdateProgress runat=”server”
ID=”UpdateProgress1”>
<ProgressTemplate>
<div>
<img alt=”” src=”/Images/indicator.gif”/>
<span id=”Msg”>Please, wait ... </span>
<input id=”abortButton” type=”button”
runat=”server” value=”Cancel”/>
</div>
</ProgressTemplate>
</atlas:UpdateProgress>
Fuente 1
Existen un par de puntos
a tener en cuenta. Estoy asumiendo que la operación del
lado del servidor lleva un cierto tiempo en completarse:
suficiente como para justificar la barra de progreso. Esto
no es muy probable en un
DataGrid sencillo. Sin embargo, puede aplicarse la combinación de controles usada más
arriba siempre que exista un
refresco de página que lleve
tiempo suficiente.
Internamente, el control
UpdatePanel ejecuta una petición colateral que simula el
clásico postback, excepto que
está limitado a los controles
del panel. No hay necesidad
de cambiar el estilo de programación para poder apreciar
los beneficios de AJAX.
El segundo punto a considerar tiene que ver con el
botón “Cancel” de la figura 1.
¡Exactamente! Puedes abortar la operación e interrumpir
el proceso de refresco de la
página. Más concretamente,
puedes cortar solo la conexión entre navegador y servidor y cerrar el socket relacionado. Si el servidor ha comenzado una
operación crítica (tal como vaciar todas
las tablas de una base de datos), no hay
mucho que puedas hacer para detenerlo.
Simplemente, te ahorrarías un mensaje
del tipo “misión completada”.
Como en el fragmento de código
anterior, el botón de abortar es simplemente un botón <input> nombrado como
AbortButton y marcado con el atributo
runat=”server”.
Atlas me interesó mucho al principio porque prometía ejecutar la mayor
parte de mi código desde el cliente: en
particular el enlace a datos. Me encantaría poder pulsar un botón y descargar
un DataSet en el cliente que llenara una
tabla de forma incremental. ¿Recuerda
cómo funcionaban los ficheros GIF en
Netscape hace unos años? ¿Cree que
Atlas me ofrece un modo de ver cómo
se llena un DataGrid a medida que van
descargándose las filas en el navegador
del cliente?
No estoy seguro de cómo te vas a
tomar mi ambigua respuesta. La respuesta es “más o menos”. De otra forma, es
como preguntar cómo ves un vaso: ¿medio
lleno o medio vacío? Metáforas aparte, el
enlace a datos del lado del cliente te suministra la posibilidad de descargar un
DataSet y utilizarlo para rellenar elementos HTML enlazados. Pero, deberíamos
de ponernos de acuerdo en el significado
exacto de “incremental”.
No sé realmente cómo Netscape
interpretaba gráficamente los ficheros GIF
y soy totalmente lego en lo que se refiere
a la estructura interna de estos ficheros.
Lo que sé de los navegadores se limita al
hecho de que establecen una nueva petición por cada imagen enlazada, y solicitan la imagen completa. Es posible que la
estructura interna de los ficheros GIF haga
posible que los navegadores muestren porciones de la imagen a medida que se descargan. Pero las cosas son diferentes en el
enlace a datos para Atlas. El enlace a datos
es una operación en dos pasos: primero,
obtienes los datos; después los enlazas a
un control, y el control los utiliza para
rellenar su estructura.
En otras palabras, la interpretación
gráfica (rendering) sucede incrementalmente; no así la descarga de los datos. El
<< dnm.todotnet.qa
<div id=”tableResults”></div>
<div style=”display: none;”>
<div id=”table_layoutTemplate”>
<table cellpadding=”2”>
<thead class=”tableHeader”>
<tr>
<td><b>Book</b></td>
<td><b>Info</b></td>
</tr>
</thead>
<tbody
id=”tableResults_itemTemplateParent”
class=”tableContent”>
<tr id=”table_itemTemplate” >
<td>
<img id=”table_Cover” src=””
alt=””/>
</td>
<td>
<span id=”table_ISBN”></span><br/>
<span id=”table_Title”></span><br/>
<span id=”table_Publisher”></span>
<br/>
</td>
</tr>
</tbody>
</table>
</div>
</div>
Fuente 2
Como puedes ver, la plantilla consta de dos partes. El bloque vacío llamado tableResults es, simplemente, el
punto de inserción del resultado final.
El bloque oculto no es interpretado gráficamente por el navegador; en su lugar
es interpretado por el control ListView
para generar el código de marcado final
que será inyectado en el bloque previo.
La correspondencia entre los elementos HTML de la plantilla y los datos,
así como el rol de cada fragmento
HTML se define en una rutina de XML
Script (fuente 3).
<listView id=”tableResults”
itemTemplateParentElementId=
”table_itemTemplateParent”>
<layoutTemplate>
<template layoutElement=”table_layoutTemplate”/>
</layoutTemplate>
<itemTemplate>
<template layoutElement=”table_itemTemplate”>
<label id=”tableResults_ISBN”>
<bindings>
<binding dataPath=”ISBN” property=”text”/>
</bindings>
</label>
<label id=”tableResults_Title”>
<bindings>
<binding dataPath=”Title” property=”text”/>
</bindings>
</label>
<label id=”tableResults_Publisher”>
<bindings>
<binding dataPath=”Publisher” property=”text”/>
</bindings>
</label>
<image id=”tableResults_Cover”>
<bindings>
<binding dataPath=”CoverPicture”
property=”imageURL” />
</bindings>
</image>
</template>
</itemTemplate>
</listView>
Fuente 3
El control ListView contiene dos
bloques de etiquetas fundamentales:
layoutTemplate e itemTemplate. El nodo
<layoutTemplate> señala el ID del elemento HTML que representa la raíz del
ListView. El nodo <itemTemplate> indica
el bloque de HTML que hay que repetir
por cada ítem de datos enlazado. Los
nodos <binding> definen enlaces entre
propiedades de los datos y elementos del
árbol HTML.
El control ListView implementa la
interpretación gráfica incremental,
esto es, muestra código de marcado de
forma automática para cada subconjunto de filas que se procesa: 5 a la vez.
Sin embargo, cuando empieza el proceso de interpretación los datos ya se
han descargado en su totalidad en el
cliente.
Puedes asociar datos a un control
ListView de dos formas: por programa, o
de manera declarativa. Si optas por la
opción de programa, añadirías algún código Javascript del tipo:
var tableResults = $(“tableResults”);
tableResults.control.set_data(results);
La función $ es un atajo o
alias de document.getElement
ById. El argumento results indica el valor de retorno del método de un servicio Web, tal como
un ADO.NET DataTable o una
colección de datos .NET. No
hay que decir que la variable
results es un objeto Javascript
que simula una colección o un
objeto DataTable.
El enlace declarativo se realiza a través de un componente
DataSource de cliente, como se
muestra en el fuente 4.
El nodo <binding> indica
que el ListView está enlazado
al origen de datos específico.
En particular, la propiedad de
datos del control ListView se
rellena con los contenidos de
la propiedad de datos del origen de datos. Los contenidos
del origen de datos se suministran a través de un servicio Web especial: una clase
que hereda de la clase base
DataService y adorna sus
<dataSource id=”dataSource1”
serviceURL=”MyDataSource.asmx”/>
<listView id=”tableResults”
itemTemplateParentElementId=
”table_itemTemplateParent”>
<bindings>
<binding dataContext=”dataSource1”
dataPath=”data”
property=”data” />
</bindings>
</listView>
Fuente 4
métodos con atributos que permiten
especificar los métodos Select, Update,
Insert y Delete.
Me doy cuenta que esta es muy
poca información, pero las restricciones de espacio no me permiten explayarme más. Para información más detallada y código fuente, podrías consultar la obra editada por Microsoft Press
titulada “Introducing ASP.NET 2.0
AJAX Extensions”, que será publicada en
el mes de noviembre de este año.
Traducción por Marino Posadas
<<dotNetManía
enlace a datos requiere la acción combinada de dos componentes: un control de
origen de datos y un control de enlace a
datos. Atlas dispone de dos controles de
cliente enlazados a datos: ListView e
ItemView. El primero suministra una vista de datos tipo listado; el segundo provee de una vista de datos para un único
registro. Ambos están basados en plantillas y no disponen de mecanismo de interpretación visual incrustado . Pero requieren de una plantilla HTML para definir
su interfaz de usuario. A continuación
mostramos una plantilla que genera una
tabla HTML con una fila de cabecera y
dos columnas:
53
dnm.laboratorio.net
Lorenzo Ponte
TestRunner for Visual Studio 2005
Todo lo que no se gestiona no se puede mejorar. La calidad es uno de los aspectos básicos a la hora de desarrollar una aplicación. En el laboratorio de este
número analizamos una herramienta especialmente indicada para gestionar la
calidad del software; basada en la realización de pruebas unitarias, nos permitirá cuantificar la calidad de las aplicaciones.
<< ¿Qué son las pruebas unitarias? Las pruebas unitarias
son una aproximación dinámica a la verificación de un
programa. Estas pruebas consisten en ejecutar un programa de testing contra el código de la aplicación que
estemos desarrollando. Mediante las baterías de pruebas que genera el programa, podremos determinar tanto los errores como la calidad en el rendimiento de la
aplicación.
TestRunner es uno de esos programas diseñados
para realizar pruebas unitarias contra aplicaciones diseñadas en Visual Studio .NET. Integrado en el IDE de
Visual Studio (existen versiones tanto para VS 2003 como
para 2005), es capaz mediante un solo clic de lanzar aproximadamente 1400 pruebas en 5 segundos.
Mediante una interfaz muy
intuitiva, la herramienta nos
permite planificar diferentes
tipos de tests, que incluso se
Características principales de TestRunner
• Integración en el IDE de Visual Studio
• Ejecución a través del menú contextual
• Resultados de las ejecuciones en formato gráfico
• No bloquea la correcta ejecución de Visual Studio
bas, se pueden ver los posibles errores, así como el
tiempo que tardan en ejecutarse las distintas pruebas
unitarias. Los resultados se almacenan en un fichero
de registro con el fin de poder estimar la mejora en
el rendimiento de la aplicación una vez se hayan subsanado o corregido las partes del código que
TestRunner nos ha indicado. La herramienta también
permite ir directamente a la línea de código responsable de un error desde su interfaz.
TestRunner se ejecuta en hilos diferentes a los que
utiliza Visual Studio. Esto garantiza que no interfiera en
la correcta ejecución y compilación de los programas.
Conclusiones
Lorenzo Ponte es redactor de
dotNetManía. Es Arquitecto de
Sistemas y Aplicaciones .NET.
Experto en Datawarehousing y
Business Intelligence, Marketing
Intelligence, CRM analítico.
Actualmente es consultor de la
empresa Matchmind y
Webmaster de clikear.com
pueden ir modificando a medida que TestRunner se ejecuta.
Una de las principales características a destacar de
TestRunner es la
forma de mostrar los
resultados que se van
obteniendo de la ejecución. Según van
avanzando las prue-
Cuantificar la calidad del software es uno de los puntos pendientes todavía en muchos desarrollos. Desde el
laboratorio de dotNetManía recomendamos la utilización de este tipo de herramientas, con los que podemos
llegar a una aproximación bastante fiable con el fin de
obtener una mayor calidad en nuestros proyectos.
Ficha técnica
Nombre
TestRunner
Versión
2.2.2005.0615
Fabricante
Mailframe
Web
www.mailframe.net/Products/TestRunner
Categoría
Calidad del Software
Precio
Sin especificar
Valoración
<< dnm.biblioteca.net
dnm.biblioteca.net
Por Marino Posadas
Programación con ASP.NET 2.0
Jesse Liberty y Dan Hurwitz
Editorial: Anaya Multimedia & O’Reilly
ISBN: 8441520526
Páginas: 1.056
Primera edición: 2006
Idioma: Castellano
Como el lector podrá adivinar por su extensión, se trata de una auténtica enciclopedia
del desarrollo de ASP.NET 2.0, abarcando todos los problemas comunes (y otros que
no lo son tanto), con un espíritu didáctico y abundantes ejemplos de código sin dejar
atrás ningún tema importante.
Fundamentos de Bases de datos con Visual Basic 2005
Thearon Willis
Editorial: Anaya Multimedia & Wrox
ISBN: 8441520534
Páginas: 736
Primera edición: 2006
Idioma: Castellano
Otra muestra del anterior acuerdo de colaboración de Anaya con editoriales extranjeras es esta interesante obra de Thearon Willis, centrada en el tratamiento de datos con
Visual Basic 2005. Bien escrita y abundantemente decorada con ejemplos de todas clases, queremos destacar el énfasis que se hace en las operaciones críticas de mantenimiento de datos: selección, inserción, borrado y modificación. Se dedican a cada uno de esos
apartados muchas páginas, explicando los problemas que pueden aparecer y sugiriendo
un sinfín de soluciones a cuestiones del día a día.
También se incluyen comparativas de utilización (SQL Server/Oracle), un par de útiles
capítulos para el tratamiento de datos desde Access (que todavía sigue usándose en un
porcentaje significativo de entornos), un adecuado tratamiento del acceso a datos desde ASP.NET y un análisis del uso de servicios Web que devuelven datos. Una obra muy
completa.
<<dotNetManía
<<
Poco después de valorar una de las obras de Jesse Liberty, nos llega otra novedad –publicada junto a Dan Hurwitz– fruto de la colaboración de Anaya Multimedia con la editorial
O’Reilly, que amplia así la oferta de obras de autores extranjeros. Bien traducida, no queremos dejar de mencionar entre sus valores –que son muchos–, los aspectos colaterales propios del desarrollo Web, a veces obviados por otros autores y que aquí tienen tanta importancia como el resto (configuraciones, memoria caché y rendimiento, funcionamiento del
servidor IIS, instalaciones, creación de controles personalizados, etc.).
55
[ ]
dnm.club >>> dnm.club >>> dnm.club >>> dnm.club >>>
dnm.club >>> dnm.club >>> dnm.club >>> dnm.club >>> dnm.club >
<< dnm.desvan
Marino Posadas
noticias.noticias
Vista está en RTM (Ready to Manufacture) desde el 20 de
Octubre,pero el SP3 de XP se retrasa
Microsoft presenta el futuro de
las videoconferencias con
RoundTable
Los datos son ya oficiales. Para cuando estas líneas vean la
luz, Vista habrá sido presentado oficialmente en SIMO de
Madrid y Tech-Ed’06 de Barcelona, pero el producto está en
plena fase de distribución final, para hacerle disponible al público en Enero/07 como estaba previsto. No obstante, el siguiente service pack de Windows XP (SP3) ha sufrido un retraso desde finales de 2007 hasta la primera mitad de 2008, en lo que
parece la adición de un conjunto funcional de cierta envergadura. No hay que olvidar, además, que .NET Framework 3.0
promete estar plenamente operativo tanto para XP como para
Windows Server 2003.
Documentos en la Red
Tour Visual sobre la nueva interfaz de usuario de Windows Vista.
Un recorrido por las nuevas características visuales de Vista, que estará a punto de salir cuando el lector lea estas líneas. Publicado
por ComputerWorld en http://www.computerworld.com/
action/article.do?command=viewArticleBasic&articleId=9003926.
Y no es el único documento sobre el tema. Cabe destacar
igualmente el publicado por CNET News, que hace un
compendio (“Piecing together Vista”) de todas las novedades surgidas en torno a Vista desde primeros de año hasta
el último momento (http://news.com.com/2009-1016_36050105.html?part=rss&tag=6050105&subj=news)
El nuevo producto presentado oficialmente en la página de
Microsoft con un artículo explicativo (http://www.microsoft.com/
presspass/features/2006/oct06/1020officeroundtable.mspx) está previsto que aparezca oficialmente
para mediados de 2007. Combina las características de unos
auriculares con micrófono, con las ofrecidas por el nuevo dispositivo, que la compañía espera comercializar a un precio aproximado de 3.000$. En la página antes citada, Gurdeep Singh
Pall, vicepresidente del Grupo de Comunicaciones en Microsoft,
explica con más detalle las capacidades de RoundTable.
Utilidades del mes
Media Coder: Simplemente, baste la
siguiente lista de formatos soportados:
MP3, Ogg Vorbis, AAC, AAC+, AAC+V2, MusePack, WMA,
RealAudio FLAC, WavPack, Monkey's Audio, OptimFrog, AAC
Lossless, WMA Lossless, WAV H.264, Xvid, DivX, MPEG
1/2/4, H.263, Flash Video, 3ivx*, RealVideo*, Windows Media
AVI, MPEG/VOB, Matroska, MP4, RealMedia*, ASF/WMV,
Quicktime*, OGM* CD, VCD, DVD, CUE Sheet. Con todos
ellos es capaz de trabajar esta herramienta gratuita de conversión, disponible en http://www.rarewares.org/mediacoder.
Blogs del mes
<<dotNetManía
El almacenamiento del mañana. Documento publicado
58
Blog de Internet Explorer. Es un blog más
por Jack Germain en CIO Today, y disponible en
http://www.cio-today.com/story.xhtml?story_title=
Data_Storage_of_Tomorrow&story_id=1110078RANZX. Hace
un recorrido por el camino previsible de las mejoras en
el almacenamiento del software, coincidiendo en casi
todo con lo que ya apuntara Jim Gray a esta revista, hace
más de un año.
o menos oficial, mantenido por ocho de
los desarrolladores de IE7. Podemos
encontrar desde soluciones a problemas de
instalación, hasta trucos, atajos, mejoras
funcionales, consejos, etc. Disponible en
http://blogs.msdn.com/ie.
LifeHacker: Recursos de enseñan-
Blog de Robert Hurlbut.
za gratuitos, que alguien se ha
tomado la molestia de recopilar y
publicar en http://lifehacker.com/software/education/technophilia-get-a-free-college-education-online-201979.php.
Muy completo blog sobre
noticias del desarrollo en .NET, conferencias, eventos y actividades en la red. Contiene un montón de artículos desde su puesta en marcha en 2003, y dispone de un listado de blogs recomendadas sobre seguridad que es una auténtica referencia del tema.

Documentos relacionados