Seguridad en los servicios SOA con WCF

Anuncio
www.dotnetmania.com
nº 38 junio 2007 6,50 €
Visual Basic • C# • ASP.NET • ADO.NET • SQL Server • Windows System
dotNetManía
dedicada a los profesionales de la plataforma .NET
Seguridad en los servicios SOA con WCF
autenticación y autorización
Paso de páginas en 3D con WPF • Arquitecturas
distribuidas con Service Broker • Serialización XML.
El serializador que lo serialice... debe saber XML
eventos
MIX 2007
Burning, burning…
I feel the silverlight rising!!!
Laboratorio
Nevron .NET Vision
TodotNet@QA
Páginas Web, indexadores y DHTML
Opinión
Seguimiento y control de los proyectos
entrevista
Scott Guthrie
General Manager
División de desarrollo de Microsoft
editorial
dotNetManía
Dedicada a los profesionales de la plataforma .NET
Vol. III •Número 38 • Junio 2007
Precio: 6,50€
Difícil originalidad
Editor
Paco Marín
(paco.marin@netalia.es)
Redactor jefe
Marino Posadas
(marino.posadas@netalia.es)
Editor técnico
Octavio Hernández
(octavio.hernandez@netalia.es)
Redacción
Dino Esposito, Guillermo 'Guille' Som, José
Manuel Alarcón y Miguel Katrib (Grupo
Weboo)
Empresas Colaboradoras
Alhambra-Eidos
Plain Concepts
Raona
Solid Quality Learning
Además colaboran en este número
Antonio Quirós, César de la Torre, Iskander
Sierra, Iván González, Mario del Valle, Miguel
Egea, Miguel Jiménez y Yamil Hernández.
Corresponsal para América Latina
Pablo Tilotta
Ilustraciones
Mascota: Yamil Hernández
Portada: Javier Roldán
Atención al suscriptor
Pilar Pérez
(pilar.perez@netalia.es)
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
Gráficas MARTE
Bienvenido al número 38, de junio de
2007, de dotNetManía.
Somos diferentes, somos originales. El
artículo de portada de este mes es “Seguridad en los servicios SOA con WCF:
autenticación y autorización” de César de
la Torre, de la división de plataforma y
desarrollo de Microsoft Ibérica. El mundo no habla de otra cosa que de diseño y
de experiencia de usuario y César se marca este pedazo artículo de autenticación y
autorización con WCF.
En realidad, no somos tan diferentes
ni tan originales. No hemos podido dejar
de publicar la crónica que desde Las Vegas
nos ha preparado Iván González, donde
Microsoft ha presentado una buena cantidad de novedades relacionadas con las
herramientas enfocadas a mejorar la experiencia de usuario.
Aún a riesgo de no ser tan originales,
no hemos podido resistir la tentación —ya
que estábamos en Las Vegas— de completar esta información con una entrevista,
nada más y nada menos, que a Scott
Guthrie, que es director general en la
división de desarrollo y que coordina los
equipos de ASP.NET, CLR, WPF, Silverlight, Windows Forms, IIS 7.0, Commerce Server, .NET Compact Framework y Visual Studio Web. No se pierda bajo ningún concepto esta fenomenal
entrevista de Miguel Jiménez.
Dejándonos arrastrar, ya casi sin posibilidad de ser originales, por esta fiebre por el
diseño, ¡cómo no seguir publicando los artículos sobre WPF del Grupo Weboo de la
Universidad de La Habana! Su trabajo “Paso
de páginas en 3D con WPF” define un visualizador de páginas que permite hojear un
documento con un efecto similar al de hojear un libro o una revista de papel. Quién sabe
si no acabaremos utilizándolo para una futura versión online de dotNetManía.
Y mire usted, ya de perdidos al río. Está
bien, somos como todos, nos dejamos llevar
por la actualidad, y para rematar, este número lleva en el centro un pequeño póster de
la arquitectura de Silverlight que espero le
sea útil. Cuélguelo cerca de su puesto de trabajo aun a riesgo de no ser muy original.
Junto al artículo de portada, Miguel
Egea con su trabajo “Arquitecturas distribuidas con Service Broker”, en el que se describe de manera práctica la utilización de la
tecnología Service Broker de SQL Server
2005, y el Guille con el suyo para la sección
de iniciación “Serialización XML. El serializador que lo serialice... debe saber XML”,
consiguen dar una cierta heterogeneidad al
contenido de este ejemplar.
Es posible que no hayamos sido muy
originales, pero, aunque esté mal decirlo, creo que nos ha quedado un buen
número. Espero que también lo vea así y
sea de su agrado.
ISSN
1698-5451
Depósito Legal
M-3.075-2004
<< dotNetManía
Paco Marín
3
sumario 38
Seguimiento y control de los proyectos
8-9
Hace unos pocos números hablábamos de las ventajas y virtudes de la planificación. ¿Cómo
abordar un proyecto si no nos hemos detenido antes a planificar de forma adecuada y rigurosa
las distintas tareas del mismo, los recursos que las realizarán, los costes asociados, la mecánica
de control de calidad, la gestión de riesgos, etc.? Sin embargo, con esto no basta.
Entrevista a Scott Guthrie
10-12
Es, sin duda alguna, una de las personas más relevantes en Microsoft, y desde su posición de
General Manager en la división de desarrollo coordina los equipos de ASP.NET, CLR, WPF,
Silverlight, Windows Forms, IIS 7.0, Commerce Server, .NET Compact Framework y
Visual Studio Web.
MIX '07: Burning, burning…I feel the silverlight rising!!!
14-16
Crónica desde Las Vegas del MIX 07, celebrado durante los días 30 de abril, 1 y 2 de mayo,
donde la cantidad de innovaciones que Microsoft ha presentado ha sido realmente espectacular.
También en esta sección contamos con la crónica del TechNet & MSDN Day en el Cono Sur
celebrado en el marco de la Semana de la Seguridad.
Seguridad en los servicios SOA con WCF: autenticación y autorización
18-30
En este artículo se presentan los conceptos generales relacionados con la seguridad desde el punto
de vista de Windows Communication Foundation (WCF), para luego presentar en detalle dos
de sus características fundamentales: la autenticación y la autorización.
Paso de páginas en 3D con WPF
32-38
En un artículo anterior, los autores nos adentraron en el mundo de los efectos 3D en WPF,
mostrándonos cómo lograr un objeto 3D muy utilizado, una esfera. En esta entrega nos
definen un “visualizador de páginas” que permite “hojear” un documento con un efecto
similar al de hojear un libro o una revista de papel.
Arquitecturas distribuidas con Service Broker
39-42
En este artículo se describe de manera práctica la utilización de la tecnología Service Broker de
SQL Server 2005 para implementar arquitecturas distribuidas.
Serialización XML. El serializador que lo serialice... debe saber XML
43-48
En el artículo anterior vimos cómo “persistir” los objetos usando las clases que utilizan
IFormatter. En aquella ocasión tuvimos la oportunidad de ver cómo definir los tipos que
queríamos serializar por medio del atributo Serializable y la interfaz ISerializable. En este
artículo veremos otra forma de serializar nuestros objetos, que utiliza XML puro como
formato.
dnm.todotnet.qa
Páginas Web, indexadores y DHTML
49-51
Las aplicaciones Web están basadas en URL, y este hecho es clave para que los buscadores Web puedan
indexarlos y buscarlos apropiadamente. Este mes hablamos sobre HTML dinámico (DHTML), y en
particular sobre la propiedad innerHTML.
dnm.laboratorio.net
Nevron .NET Vision
52-55
Este mes presentamos .NET Vision, una suite de componentes para la capa de presentación que
le permitirá dotar a sus aplicaciones de posibilidades de visualización de información que
realzarán en buena medida sus interfaces de usuario.
dnm.biblioteca.net
57
Pro C# with .NET 3.0, Special Edition
Expert .NET 2.0 IL Assembler
dnm.desvan
58
<<dotNetManía
noticias noticias noticias noticias
noticias
6
Microsoft anuncia novedades en WinHEC
Novedades sobre acceso a datos
Los pasados 15 al 17 de
mayo se celebró en Los
Ángeles una nueva edición de
WinHEC (Windows Hardware Engineering Conference).
En su keynote de apertura, Bill
Gates resaltó el alto ritmo de
ventas de Windows Vista y la
reacción positiva ante él de
clientes y partners, transcurridos 100
días desde su salida al mercado. Gates
resaltó la importante ola de innovación
y nuevas tecnologías que con la salida
al mercado de Vista están disponibles
ahora a los consumidores en general.
Asimismo, desveló el nombre del próximo sistema operativo de servidor de
Microsoft, que hasta ahora se conocía
por el sobrenombre Longhorn: Windows Server 2008. Y en otro orden
de cosas, anunció que nuevos fabricantes de hardware y software han decidido unirse al proyecto asociado a la
creación del futuro Windows Home
Server.
Entity Framework no estará inicialmente en Orcas
Una plataforma de servidor de
nueva generación
Bill Gates subrayó que Windows
Server 2008 es un componente clave
para la siguiente ola de innovación en
el hardware, que incluye soporte para
virtualización, procesadores de múltiples núcleos y aplicaciones de 64 bits.
Windows Server 2008 lleva a un nivel
aún más alto las reconocidas fiabilidad, seguridad y facilidad de mantenimiento de Windows Server 2003
R2 para ayudar a aliviar la presión
sobre los administradores de sistemas,
incluyendo mejoras que permiten
automatizar aún más las tareas de gestión diaria, incrementar la seguridad,
ofrecer una plataforma más extensible
para el alojamiento de aplicaciones
Web, mejorar la eficiencia y aumentar la disponibilidad.
Nuevos partners para Windows
Home Server
Durante la conferencia, se anunció que tres nuevos fabricantes de hardware (Gateway, LaCie y Medion) han
decidido unirse a HP para desarrollar
equipos para Windows Home Server,
la nueva solución de Microsoft para
ayudar a las familias que disponen de
múltiples PC centralizar, compartir y
proteger sus activos digitales (imágenes, música y vídeos). Varios fabricantes de software, incluyendo Diskeeper, Embedded Automation, Iron
Mountain y SageTV, entre otros,
anunciaron también su disposición a
desarrollar productos especializados
para esa futura plataforma.
Para más información sobre lo
acontecido en WINHEC, visite
http://www.microsoft.com/whdc/winhec.
ASP.NET Futures de mayo 2007
ASP.NET Futures contiene una
visión preliminar de características
en versiones experimentales, aún en
desarrollo, que se están considerando para incluir en futuras versiones
de ASP.NET y .NET Framework.
Las características de esta versión
incluyen: controles de servidor de
Silverlight para audio y vídeo, y para
XAML; controles de datos dinámicos, con los que obtener información
del esquema de la base de datos en
tiempo de ejecución; soporte para
gestionar el historial del explorador
(botón “Atrás”); servicios de aplicación, que le permitirán añadir capacidades de búsqueda a sus aplicaciones Web usando la API del motor de
búsqueda que prefiera; y soporte para
lenguajes dinámicos, como IronPython o Javascript, usando el futuro
DLR (Dynamic Language Runtime)
Más información y descargas:
http://ajax.asp.net.
Recientemente se ha confirmado que ADO.NET
Entity Framework, tecnología incorporada en la
recientemente liberada beta 1 (aunque sin algunos elementos esenciales para hacerla funcional), no formará
parte inicialmente de la próxima versión de Visual Studio. Consecuentemente, tampoco estará LINQ to
Entities, la extensión de LINQ para operar sobre Entity
Framework. Según informa Mike Pizzo, arquitecto
del equipo de Programación de Datos, estos productos aparecerán posteriormente (se espera que durante
la primera mitad de 2008) como una extensión independiente a .NET Framework y Visual Studio Orcas.
Entity Framework es una tecnología de acceso a
datos construida sobre ADO.NET 2.0 que ofrece
un Modelo de Datos de Entidad (Entity Data Model)
para permitir la creación de modelos conceptuales
de los datos antes de mapearlos a esquemas relacionales. Esto permitirá a los desarrolladores trabajar
contra un modelo conceptual de los datos en vez de
hacerlo directamente contra la capa de acceso a bases
de datos relacionales.
Más información en: http://www.microsoft.com/spanish/msdn/articulos/archivo/041206/voices/Next-Generation.mspx.
Proyectos Jasper y Astoria
En el marco del MIX de Las Vegas se anunciaron
dos nuevos proyectos relacionados con el acceso programático a datos que llevan los nombres provisionales Jasper y Astoria. De ambos productos ya se dispone de una CTP para su evaluación temprana.
El proyecto Jasper se orienta al desarrollo ágil e iterativo. Construido encima de ADO.NET Entity Framework, permitirá comenzar a interactuar con los datos
de una base de datos sin necesidad de definir clases o
realizar mapeados, y crear interfaces de usuario para
interactuar con los datos sin preocuparse por la “fontanería” subyacente. Jasper, no obstante, es extensible
y permite definir un modelo de clases y lógica de negocio propios.
Por otra parte, el objetivo del proyecto Astoria es
hacer posible que las aplicaciones expongan datos como
servicios de datos que puedan ser utilizados por clientes Web situados dentro o fuera de la red corporativa.
Estos servicios de datos podrán ser consumidos mediante peticiones HTTP tradicionales y utilizando formatos abiertos como XML “plano” y JSON, lo que hace
a Astoria un endpoint ideal, entre otras, para las aplicaciones basadas en AJAX.
Más información y descargas en: http://msdn2.microsoft.com/en-us/data/bb419139.aspx.
opinión
Antonio Quirós
Seguimiento y control de los proyectos
Hace unos pocos
números hablábamos de
las ventajas y virtudes
de la planificación.
¿Cómo abordar un
proyecto si no nos
hemos detenido antes a
planificar de forma
adecuada y rigurosa las
distintas tareas del
mismo, los recursos que
las realizarán, los costes
asociados, la mecánica
de control de calidad, la
gestión de riesgos, etc.?
Sin embargo, con esto
no basta.
Antonio Quirós es
colaborador habitual
de dotNetManía. Cofundador de las revistas clippeRManía, FOXManía y Algoritmo.
Actualmente es director de operaciones en
Alhambra-Eidos.
<< Vivimos una época en la que se enarca, de manera sustantiva,
la función de la planificación y, sin embargo, nos olvidamos de forma permanente de la no menos importante función del seguimiento
y control que de los proyectos debemos realizar, mientras se encuentran en su proceso de realización. Está muy bien que seamos capaces de anticiparnos a la acción y que, por tanto, realicemos los planes acerca de cómo las cosas han de acontecer; pero, desde luego,
es imprescindible que luego apliquemos procedimientos que nos
posibiliten seguir el cumplimiento de los planes y garantizar que se
tomarán las medidas correctoras necesarias para garantizar que éstos
se cumplan.
Así las cosas, nos encontramos muchas veces con perfiles profesionales de laboratorio que son capaces de definir hasta sus más
mínimos detalles complicados planes de actuación, pero que luego son incapaces de salir al frente de batalla y tomar las decisiones
oportunas a fin de llevar a buen puerto aquello que fue tan bonito
dibujar cuando aún no nos estábamos enfrentando a los problemas
reales del día a día. Por ello, un grupo de desarrollo necesita tener
perfiles híbridos para este doble abordaje de las cosas, o al menos
garantizar que tiene cabezas que sean capaces de diseñar planes y
cabezas que sean capaces de ejecutarlos, aunque dichas funciones
estén separadas en personas distintas.
Si tuviera que definirme acerca de qué considero más importante a la hora de garantizar el éxito de un proyecto, tendría claro que
una mala planificación se puede superar con unos buenos mecanismos de control y seguimiento, pero lo contrario es imposible. Hemos
también de tener en cuenta que ambos mundos están fuertemente
acoplados. La planificación de un proyecto de desarrollo de software ha de prever que se producirá un mecanismo posterior de seguimiento; habrá también de anticipar los hitos de dicho proceso y habilitar los buffers a través de los que podamos medir el impacto de las
desviaciones que la planificación inicial vaya sufriendo.
Aunque esto es aplicable a cualquier tipo de proyecto, los proyectos de desarrollo de software tienen algunas peculiaridades que
<< dnm.opinión
…una mala planificación se puede superar con unos
buenos mecanismos de control y seguimiento, pero
lo contrario es imposible
de nuestros clientes es básico para no naufragar en este proceloso océano.
Esto nos conduce a un contexto en
que es imprescindible reglamentar con
nuestro cliente el método de seguimiento y control que usaremos para garantizar que lo planificado en el proyecto se
cumpla. Lo normal es que comencemos
dicho proceso por una función claramente educativa, que consista en contar a nuestro cliente todo lo necesario para que
entienda realmente cómo se produce el
proceso de desarrollo de software y porqué son tan importantes las labores de
seguimiento, replanteamiento de alcances en función de cambios, re-planificaciones, etc. Es frecuente que se tienda a
pensar que hacer software es como hacer
puentes, y no se entienda, por tanto, el
impacto que los cambios permanentes tienen en el mismo. Por eso, además de educar a nuestro cliente, hemos de construir
con él el modelo de colaboración bajo el
que controlaremos el proyecto. Solo un
proceso común y aceptado, con un modelo de colaboración claro entre cliente y
proveedor, y quizá un SLA claro que
garantice los intereses del cliente, son la
garantía de que podemos lograr el éxito.
Y esto, desde luego, no se logra sólo con
nuestra implicación y con un cliente alejado y que aparece sólo el día en que el
software realizado ha de ser usado. Sé que
no es fácil, pero tenemos que convencer
a nuestros clientes de que han de involucrarse en este proceso, que tienen que estar
a nuestro lado en el día a día, que tienen
que conocer la problemática con la que
nos enfrentamos y compartir la toma de
decisiones con nosotros. Para afrontar
esto, lo mejor es que exista al menos una
persona con una posición jerárquica
importante en la compañía para la que
hacemos el proyecto que sea la responsa-
ble del mismo y que nos ayude a remover
cuantas piedras aparezcan en el camino,
vinculadas a procesos de coordinación con
el cliente y no a elementos tecnológicos.
Además de esta persona, es bastante
importante que exista una comisión de
alto nivel, con participación de la Dirección General y, si no es posible, al menos
de la Financiera (si las empresas tienen
Dirección de Sistemas de Información, lo
normal es que ésta sea la idónea), donde
con un ritmo pautado de reuniones de
seguimiento se vaya informando acerca
de todo lo que va aconteciendo, se vaya
supervisando el cumplimiento de la planificación realizada y siguiendo la evolución de los distintos riesgos que nuestro
proyecto ha decidido controlar.
Y ante todo esto, hemos de matizar
también que estamos ante un sector donde la prisa está mucho más a la orden del
día que en otros. Cuando una empresa
decide montar alguna nueva pieza en su
sistema de información, está dejando en
manos del equipo que debe desarrollar
dicha pieza una responsabilidad crucial en
su negocio. La rotura de una planificación
implicará probablemente pérdidas relevantes para nuestro cliente y, por tanto,
las decisiones correctoras han de tomarse de forma rápida. Seguir un proyecto
debe tener un componente fundamental
y es que en cuanto conozcamos la posibilidad de un problema lo afrontemos inmediatamente. El síndrome del estudiante
(empezar a estudiar siempre pocas horas
antes del examen) es una de las enfermedades letales que más pueden dañar a los
proyectos de software. El seguimiento
para anticiparnos a los problemas es la
receta adecuada para curar dicha enfermedad y uno de los más importantes signos que demuestran la madurez de una
compañía que desarrolla software.
<<dotNetManía
los hacen más sensibles a que el binomio
planificación-seguimiento deba ser
correctamente abordado. Uno de los más
importantes es el que se refiere a la diferencia de peso en cuanto a la dificultad
que las distintas fases de un proyecto presentan. Tradicionalmente tendemos a
concentrar el interés fundamental en la
fase de construcción, pensando que las
labores tecnológicas que se plantean en
aquella son las más importantes, las más
complejas de realizarse y, por tanto, las
más susceptibles de retrasarse por el
impacto de los problemas. Sin embargo,
el estudio histórico comparado de los
proyectos de software nos desvela que el
cumplimiento de plazos en esta fase suele estar bastante garantizado, ya que los
distintos retos técnicos a los que debemos enfrentarnos, siempre que tengamos a profesionales cualificados, suelen
ser temas bien tratados. Sin embargo, las
fases de análisis e implantación llevan
aparejado un fenómeno mucho más
impactante en el cumplimiento de plazos: se trata de la coordinación de procesos con nuestro cliente y sus usuarios.
Esto suele ser bastante más complicado,
y en ello se mezclan elementos de negocio, psicológicos, organizacionales, etc.
que impactan de forma mucho más fuerte que los tecnológicos en las planificaciones que hayamos realizado. Esta situación suele redundar en que los planificadores suelen colocar muchos más buffers
de protección ante las dificultades técnicas que ante estas otras, que suelen considerar rutinarias, estando ahí una de las
principales causas de roturas de planificación en los proyectos.
Otro asunto relevante es el entorno
de cambio permanente en que suele vivir
un proyecto de software mientras se está
realizando. En otras actividades industriales, los cambios de especificaciones
son poco o nada frecuentes; sin embargo, en nuestro mundo están a la orden
del día. Si esto no se ha tenido en cuenta en la planificación y luego no se sigue
adecuadamente, tendremos ahí una de las
principales causas de fracaso en nuestro
sector. Tener un entorno listo que nos
permita gestionar el cambio en el alcance del proyecto, re-planificar de forma
permanente y contar con la supervisión
9
entrevista
Miguel Jiménez
Es,sin duda alguna,una de
las personas más relevantes en Microsoft, y desde
su posición de General
Manager en la división de
desarrollo coordina los
equipos de ASP.NET,CLR,
WPF,Silverlight,Windows
Forms, IIS 7.0, Commerce Server,.NET Compact
Framework y Visual Studio Web. ¡Casi nada!
Miguel Jiménez
es Software
Development
Engineer y
responsable de
formación para ilitia
Technologies.
Coordina el Madrid
.NET User Group,
es MVP de Visual
C#, líder de INETA
en España y
colabora
frecuentemente con
MSDN y otros
grupos de usuarios.
Contacta con él en
miguel@ilitia.com
Blogs:
http://blogs.clearscreen
.com/migs
Fotografías del
evento por José
Carlos Palencia
Durante el pasado MIX’07
en Las Vegas aprovechamos la ocasión para charlar un rato sobre Silverlight,AJAX y la inminente fusión de los desarrolladores Web con los
diseñadores gráficos para
crear la tan famosa versión 2.0 de nuestra querida Internet.
entrevista a
Scott Guthrie
Hola Scott, es realmente impresionante la cantidad de equipos que coordinas. Con tanto trabajo
de gestión y tantísimas personas en esos equipos,
¿podrías indicarnos qué tareas se incluyen en tu rol?
Coordino todos esos equipos, pero de manera muy
sencilla porque todos estos equipos simplemente me
reportan a mí. Puede parecer demasiado trabajo, pero
tenemos muy buenos líderes en cada uno de esos equipos que favorecen que este proceso sea muy transparente. Mi trabajo se basa principalmente en tres pilares: tener
a la gente adecuada, asegurar que tenemos una estrate-
gia técnica y, finalmente, verificar que mantenemos la
estrategia cuando construimos nuestros productos.
¿Cuánto tiempo llevas trabajando en Microsoft?
Ahora ya son 10 años.
Y ¿cuál ha sido el reto más extraño o excitante al que te has enfrentado hasta el momento trabajando para Microsoft?
Bueno, seriamente no he trabajado en nada realmente extraño, pero lo más excitante durante todos
estos años ha sido el lanzamiento de .NET 1.0, y durante esta semana, la presentación de Silverlight.
Hablando de Silverlight, parece ser
el nuevo buque insignia de la compañía en términos de desarrollo y
expansión en la Web. ¿Esperáis una
rápida adopción de la tecnología?
Estamos a esperando a lanzar la versión 1.0 en torno al verano. Esta versión
soportará escenarios donde el contenido
multimedia es la clave: audio, vídeo y streaming. Y después, para desarrolladores,
probablemente con la versión 1.1, sobre
finales de año, dispondremos de la primera entrega importante donde poder
desarrollar todo el potencial de Silverlight integrado con .NET Framework.
¿Entonces deberíamos esperar a
la versión 1.1 para comenzar a distribuir y crear aplicaciones basadas
en Silverlight en lugar de apresurarnos con la 1.0?
No. No creo que haga falta esperar a
la versión 1.1 para integrar multimedia,
audio y streaming con gráficos interactivos y soporte para AJAX. Por ejemplo, si
estás desarrollando un sitio con soporte
para webcasts o videocasts, o donde deseas
importar vídeo, toda la funcionalidad que
necesitas estará a tu alcance con la versión 1.0 en verano.
La mayoría de los desarrolladores
siguen actualmente formándose e
investigando sobre AJAX, puede que
incluso no lo hayan aplicado aún en
ningún proyecto. Ahora tenemos a Silverlight también en escena, ¿no es un
paso demasiado grande?
Para desarrolladores de .NET, Silverlight proporcionará una manera más
sencilla de crear contenido más rico.
Como para los desarrolladores de Windows Forms que están migrando actualmente a WPF, encuentro la migración a
Silverlight muy natural porque tienes control total sobre el modelo de objetos, el
modelo de encapsulación, puedes responder a eventos y ese tipo de cosas que
no harán el desarrollo de aplicaciones tan
duro. Actualmente tenemos mucha potencia gráfica y de procesado, potencia para
crear experiencias realmente diferenciadoras, así que tenemos que exprimirnos
al máximo como desarrolladores para usar
toda esta potencia creando interfaces de
usuario atractivas.
¿Desarrolladores creando interfaces de usuario atractivas? Con toda la
nueva gama de productos como AJAX,
Silverlight y Expression, parece que
se crea una nueva especie en el ecosistema del desarrollo de software: los
devsigners, una evolución de desarrolladores a diseñadores, ¿o más bien al
contrario?
Creo que en el futuro veremos a
muchas personas desenvolviéndose en este
nuevo rol entre diseñadores y desarrolladores. Pero de todas formas, lo que pretendemos con Silverlight es hacerlo extremadamente sencillo para que desarrolladores y diseñadores trabajen juntos. A partir de ahora veremos cómo más y más compañías contratan diseñadores para integrarlos en pequeños equipos de desarrollo, y lo más interesante es que estos diseñadores podrán participar en el proyecto de
manera más transparente; olvidémonos ya
de diseñadores entregando una imagen a
los desarrolladores para que capten la idea
e intenten reflejarla en el software.
Si los diseñadores pasan a formar
parte del ciclo de vida del desarrollo
de software, ¿existe soporte para integrar Expression dentro del proceso de
desarrollo y Team Foundation Server?
Queremos dar soporte a Team Foundation Server y Visual Studio Team System con Expression. La primera versión,
que sale en estas semanas, no soporta
TFS, pero puedes utilizar las herramientas externas para proteger y desproteger
ficheros en el repositorio de código. Esperamos, de todas formas, más avances en
la integración de las herramientas de
diseño con TFS y Visual Studio.
Y con tanta revolución tecnológica en el campo de la experiencia de
usuario en la Web, ¿cuáles son los planes de futuros de Silverlight con respecto a AJAX?
Estamos invirtiendo mucho en AJAX
actualmente. Si nos centramos en Visual
Studio Orcas tenemos Intellisense para
Javascript, soporte nativo de depuración
de Javascript, opciones más avanzadas
para la edición y gestión de CSS, muchas
mejoras en el diseñador de HTML y
finalmente, actualización de controles
para soportar AJAX directamente. Creo
que el punto es más bien decidir si tu aplicación se va a centrar en el lado del servidor o en el lado del cliente. En este punto, podemos ver cómo AJAX se integra
perfectamente con el servidor, con
ASP.NET, y cómo nuestra lógica de
negocio se encuentra allí y nos resulta
realmente sencillo desarrollar nuestra
aplicación con AJAX. Y por otro lado,
cuando queremos apoyarnos en el motor
gráfico o realizar tareas más intensas en
el lado del cliente, integrar vídeo o media,
es cuando Silverlight entra en juego.
Los diseñadores están totalmente
acostumbrados a Flash y su plug-in
está ampliamente distribuido y soportado en multitud de plataformas. ¿Crees que se producirá una migración
hacia Silverlight desde Flash?
Depende, porque Flash se usa para
muchas cosas diferentes. Depende de tu
escenario concreto; por ejemplo, Silverlight puede aportar avances más significativos para desarrolladores y para vídeo.
No esperamos que aquellos que hacen
animaciones o clips de Flash migren a Sil-
<<dotNetManía
<< dnm.directo.entrevista
11
<< dnm.directo.entrevista
verlight, pero sí disponemos de hueco
para la integración con desarrolladores.
Los últimos movimientos en las
herramientas para desarrolladores nos
guían hacia la interfaz de usuario, experiencias interactivas y usables de la tan
aclamada Web 2.0, y a nosotros nos
gustaría saber qué es la Web 2.0 para
ti. Una definición por Scott Guthrie.
Esta es una difícil. Yo creo que la Web
no es ni 1.0 ni 2.0, es más bien una simple etiqueta. Creo que la nueva Web va
de cómo permitimos a la gente crear
experiencias de usuario más atractivas,
con más enganche. No es acerca de construir, es crear una conexión emocional
con el cliente y esto se consigue con los
desarrolladores que aportan funcionalidad, los diseñadores creando la imagen y
una última parte con aspectos de red
social; esto hace que te enganches, que te
apasione y te sientas bien.
Estamos mirando actualmente cómo
podemos añadir soporte de manera sencilla a la indexación por parte de los motores de búsqueda. Al fin y al cabo, en la base
no es más que un fichero XAML y los bots
deberían ser capaces de indexarlo. Esta
semana, como parte del lanzamiento de
la siguiente versión de ASP.NET Futures, hemos presentado controles que permiten controlar la navegación y estado en
páginas con AJAX y Silverlight; esto nos
permite investigar sobre el tema de la indexación y búsquedas.
Qué piensas sobre los desarrolladores actualmente, ¿crees que están
preparados comenzar a “ajaxificar” sus
aplicaciones?
Creo que sí. Lo están. Una de la cosas
en las que más empeño hemos puesto con
Microsoft AJAX es en hacerlo realmente
sencillo. Creo que lo que hemos hecho con
el UpdatePanel y el Control Toolkit es,
<<dotNetManía
Creo que la nueva Web va
de cómo permitimos a la
gente crear experiencias
de usuario más atractivas,
con más enganche
12
Entonces tan solo es necesario
tener una pequeña idea, aderezada con
una experiencia de usuario impresionante, un poquito de red social y ¿ya
tenemos nuestro producto Web 2.0?
Creo que la gente es mucho más
importante que aderezarlo con el toque
de red social. La clave es crear ese vínculo emocional con ellos; Silverlight y AJAX
nos ayudan precisamente a eso.
Y en este mundo tan conectado,
¿dispone Silverlight de soporte para
indexación en motores de búsqueda?
1
desde una perspectiva empresarial, muy
sencillo de usar, mantener y evita que la
gente escriba grandes cantidades de Javascript, con todo el coste de mantenimiento que ello conlleva. Por ejemplo, una de
las cosas interesantes de Silverlight en este
contexto es que permitirá crear aplicaciones AJAX de manera mucho más sencilla;
simplemente porque no tenemos que limitarnos a Javascript y escribir código para
diferentes navegadores, sino a usar los lenguajes de .NET junto a LINQ. Esto nos
ayuda a crear mejores aplicaciones.
Últimamente da la sensación de
que el mundo del desarrollo por parte de Microsoft avanza demasiado
rápido. Es muy difícil, incluso en
roles más técnicos de evangelistas,
mantenerse actualizado en este mercado. La mayoría de las empresas
comienzan a trabajar ahora con Framework 2.0 cuando ya tienen disponible la 3.0 y la 3.5 a la vuelta de
la esquina. ¿Es alguien realmente
capaz de avanzar a una velocidad tan
vertiginosa?
Bueno, creo que el desarrollo en la
calle se está moviendo bastante rápido
en cuanto a nuevas tecnologías. La Web
nos permite actualmente buscar y encontrar información de manera muy sencilla, rápida y somos capaces de aprender
mucho más rápido. Esto representa un
reto para nosotros. Si no continuamos
añadiendo funcionalidad y evolucionando nuestras herramientas para mejorarlas, es sencillo, nos quedaremos atrás. Ese
es el motivo por el que lanzamos tantas
versiones de nuestros productos; como
media, planeamos lanzar una versión de
Visual Studio cada 2 años. Por este motivo, Visual Studio Orcas soporta multitargeting y nos permite utilizar los últimos avances en el IDE de desarrollo a la
vez que podemos seleccionar el Framework de .NET para el que desarrollamos
nuestras aplicaciones. Además, en cada
versión mantenemos completamente la
compatibilidad de API entre las diferentes versiones del Framework, de forma
que se pueda utilizar esta ventaja para
realizar transiciones más suaves.
Muchas personas leen tu blog1, se
te conoce como uno de los miembros
más activos técnicamente en las comunidades Microsoft. Pero ¿de dónde
sacas tiempo para realizar tu trabajo y
tener un blog tan sumamente técnico?
Bueno, je je, suelo escribir por la
noche, más bien tarde. Me gusta tener el
blog, es probable que la mayoría de la gente lo encuentre útil, pero a mí me da una
oportunidad única de probar nuestros
productos, las nuevas funcionalidades y
jugar con nuestras cosas.
Como Scott sabe, un grupo de sevillanos traducen su blog diariamente al castellano: http://thinkingindotnet.wordpress.com
eventos
eventos
Burning, burning…
I feel the silverlight rising!!!
<<
Si a usted, lector asiduo de dotNetManía, le hablaran de Silverlight, Astoria, Jasper… ¿qué respondería? Posiblemente que la cantidad de innovaciones que Microsoft ha presentado durante el
Silverlight
Pero la estrella de esta edición fue, por supuesto,
Silverlight. Esta tecnología está llamada a revolucionar la Web y a poner contra las cuerdas a Adobe Flash, hasta ahora sin competencia. Podemos encontrar el sitio oficial, con ejemplos de los resultados que
se pueden obtener y todo lo que necesitamos para empezar a trabajar con Silverlight, en http://www.silverlight.net. A
día de hoy, disponemos de dos versiones
de Silverlight, la 1.0 y la 1.1. La principal
diferencia entre ambas está en el modelo
de desarrollo. Mientras que en Silverlight
1.0 el único lenguaje de que disponemos
es Javascript, en 1.1 tendremos opción de
usar también C# o Python gracias a la
inclusión de .NET Framework para Silverlight con su propia BCL. Algunas de
las diferencias entre una y otra versión se
presentan en la figura 1.
Scott Guthrie, nuestro entrevistado de este mes
Es increíble ver cómo Microsoft ha
MIX 07, celebrado en Las Vegas los días 30 de abril,
conseguido introducir en 4MB todo lo necesario
1 y 2 de mayo ha sido realmente espectacular. Al
para que Silverlight 1.1 funcione, incluyendo un
nivel de los mejores PDC (Professional Developers
Conference), donde Microsoft suele aprovechar para
presentar novedades revolucionarias a su audiencia de desarrolladores.
El MIX es un evento diferente a otros grandes
eventos como el Tech-Ed o el IT-Forum. Es un
evento enfocado a la experiencia de usuario, tanto
en entornos Web como en entornos de escritorio,
en el que la audiencia, aparte de desarrolladores,
está formada también en gran parte por diseñadores y personas con un perfil más de negocio.
Dentro del mundo de la Web, se trataron muchos
temas relacionados con la Web 2.0, mash-ups, estándares como XHTML y CSS, usabilidad, accesibilidad, etc. En esta área hubo ponentes espectaculares,
en muchos casos externos a Microsoft e independientes, de la talla de Tantek Çelik, Molly HolzschFigura 1. Diferencias entre versiones 1.0 y 1.1 de Silverlight
lag, Kelly Goto y un largo etcétera.
<< dnm.directo.eventos
Expression Studio
A la par, las herramientas de desarrollo se actualizan para dar soporte a este nuevo miembro de la
familia. Durante la keynote central se anunció además
el lanzamiento de la versión RTM de Expression
Studio, que engloba a Expression Web, Expression
Blend, Expression Design y Expression Media. De
Expression Blend, además de la nueva versión, se
presentó la CTP de mayo de la versión 2.0, que
incluye un nuevo tipo de proyecto para desarrollar
aplicaciones Silverlight tanto en Javascript como en
.NET.
Expression Media Encoder es la herramienta para
la edición de vídeo. Su objetivo es poder preparar los
vídeos en diferentes formatos, comprimiéndolos en VC1 para su publicación en la Web y su visionado con Silverlight. En la página de Microsoft Expression está disponible para descarga una versión de prueba de 180
días de este producto. Los vídeos generados con esta
herramienta podemos publicarlos en nuestros propios
servidores o hacer uso del servicio gratuito de Silverlight Streaming para publicar hasta 4 Gb de vídeos.
Para más información sobre este servicio y darse de alta
en el mismo, visite http://silverlight.live.com.
ASP.NET
ASP.NET también se actualiza con dos nuevos controles de servidor que nos permiten incluir de forma sencilla en una página o bien una aplicación Silverlight o bien una fuente de audio o vídeo. Además,
hay novedades en ASP.NET AJAX Extensions: la
inclusión de los controles de datos dinámicos y el
soporte para lenguajes dinámicos sobre el DLR
(Dynamic Language Runtime) como IronPython o
Javascript manejado. Todo esto lo podemos encontrar en un paquete denominado ASP.NET Futures
(May 2007).
Windows Media
Center
Windows Media Center se
ha ido posicionando poco a
poco no solo como el centro de entretenimiento del
hogar, sino también como
plataforma de desarrollo.
Desde hace unos meses ya
están disponibles las versiones 5.0 y más recientemente 5.1 del Windows Media
Center SDK. Durante el
MIX se presentaron algunos ejemplos de integración
de Silverlight y WPF con
Windows Media Center,
demostrando las posibilidades de la plataforma para
dar lugar a una nueva generación en lo relativo a los
anuncios y la publicidad.
Visual Studio “Orcas”
La base de la plataforma para el desarrollador sobre
la que se asientan muchas de las novedades antes mencionadas es .NET Framework 3.5 y Visual Studio
“Orcas”, omnipresentes en muchas de las presentaciones, sobre todo las orientadas a los desarrolladores. Durante el MIX se hizo especial hincapié en las
capacidades de “Orcas” respecto al desarrollo Web,
como el nuevo diseñador con soporte mejorado para
CSS, vista partida código/diseño o las mejoras en el
desarrollo de aplicaciones AJAX gracias a una nueva
CTP de ASP.NET AJAX, la inclusión de Intellisense
en Javascript y mejoras en la depuración de código
escrito en este lenguaje.
Las Vegas
Tema aparte es la ciudad que Microsoft ha escogido
para celebrar el MIX, que merece también una mención especial. Pero hasta aquí podemos contar. La
representación española en Las Vegas decidió que lo
que sucede en Las Vegas, se queda en Las Vegas. El
próximo año tendrán que ir ustedes mismos, invertir
unos dólares, tirar de la palanca y esperar que la suerte les acompañe.
Texto: Iván Gonzalez
<<dotNetManía
CLR reducido. Y más increíble incluso verlo funcionar, por ejemplo, en Safari bajo MacOS. Sí, ha leído
bien: porque Silverlight es multiplataforma, y los desarrollos realizados en Silverlight podremos verlos en
Windows usando Internet Explorer o Firefox, al igual
que en MacOS X usando Safari o Firefox. Además,
Miguel de Icaza y el equipo de Mono anunciaron
durante el evento que darán soporte para Silverlight
en Linux con el proyecto Moonlight.
15
<< dnm.directo.eventos
TechNet & MSDN Day
en el Cono Sur
El 26 de abril, en Buenos Aires,
Argentina, en el marco de la Semana de la Seguridad, Microsoft Cono
Sur ha dedicado sus tradicionales y
multitudinarios TechNet & MSDN
Days a presentar una gama de productos y nuevas tecnologías orientadas a la seguridad.
El día estuvo dividido en dos grandes eventos: para los profesionales TI
con el TechNet Day y para los desarrolladores con el MSDN Day.
TechNet Day
Se presentaron soluciones realmente maravillosas y completas como
System Center, ForeFront y Virtual Machine System.
System Center no es otra cosa que
un conjunto de soluciones de monitorización de Infraestructura IT (aplicaciones, seguridad y hardware).
Después fue el turno de Virtual
Machine System, producto con el cual
Microsoft se sumerge en el mundo de
los servidores virtuales.
Por último, fue el turno de ForeFront, poderoso centro de seguridad
(antiphishing, antivirus, antispyware,
etc.), el cual permite desde una consola centralizada poder controlar la
seguridad de todo el parque de equipos de la compañía.
<<dotNetManía
MSDN Day
16
Durante el MSDN Day pudimos
conocer sobre la potencia y posibilidades de Visual Studio Team
Foundation Server. Éste permite
la perfecta integración de varios
desarrolladores para una misma aplicación o desarrollo mediante el control de versionado, y la posibilidad
de crear builds solo desde los cambios que cada desarrollador desee
pasar a testing.
Desde este Visual Studio es
posible añadir contadores de estado los cuales pueden ser monitorizados por la gente de IT mediante MOM (Microsoft Operations
Manager) o desde el nuevo System
Center. De esta manera, la difícil
integración entre el área de tecnología y los desarrolladores es
posible.
El manejo de versionado y la
perfecta documentación de cada
build permite actuar ante fallos,
recuperando versiones anteriores a
nuestro desarrollo y, de esta forma,
solucionar en breves minutos una
caída importante del sistema.
Siguiendo con la política de virtualización, nuestras aplicaciones o
desarrollos ahora podrán contar
con el Isolated Storage, que no es
otra cosa que la posibilidad de grabar información en discos virtuales, ya que precisamente en aplicaciones distribuidas nos es imposible determinar si el cliente tiene la
unidad D: o la carpeta Mis Documentos. Todo esto gracias al novedoso Windows Communication
Foundation.
En cuanto a aspectos de seguridad (motivo principal del evento), tomamos contacto con el código firmado mediante distintas técnicas como el uso de tokens otorgados por servicios de confianza.
También se logra la seguridad
mediante certificados digitales y
las cardspaces.
Finalizados ambos eventos,
como broche final, Microsoft presentó su nueva línea de productos
Expression.
Puede ver un reportaje en vídeo
del evento en http://www.vb-mundo.com/tv.asp.
Texto: Pablo Tilotta
Agenda
SQLU SUMMIT Madrid 2007
18 al 22 de Junio — Madrid
Organiza: Solid Quality Learning
El mayor evento dedicado a la plataforma de
datos de Microsoft que se celebra en España,
donde se darán cita ponentes de primer nivel
tanto nacional como internacional. Cinco
días con tres tracks: SQL Server 2005, Business Intelligence y Desarrollo.
http://learning.solidq.com/ib
We Love… Web!
28 de Junio de 2007 — 09:00h a 18:00h
Organiza: ilitia Technologies
Con tracks sobre Microsoft Office Sharepoint 2007 y Microsoft AJAX Extensions
1.0 para ASP.NET 2.0 y con una propuesta participativa: “Trae tu portátil y aprende con nosotros”.
formacion@ilitia.com
¿Tu escritorio todavía no es web?
6 de Junio Madrid y 7 de Junio Barcelona
No al Anti-Aging
13 de Junio Madrid y 14 de Junio Barcelona
NET 2.0–3.0 Evolution in Financial IT
20 de Junio Madrid y 21 de Junio Barcelona
Organiza: Raona
www.raona.com/formacion/seminarios
Kill The Experts… with AJAX
14 de junio de 2007 — 19:00h a 21:00h
Organiza: Madrid .NET User Group
http://www.madriddotnet.com
El estado del arte con BI con SQL Server 2005 & Desarrollo con LINQ
14 de Junio de 2007
Organiza: CatDotNet
http://www.catdotnet.org
Potenciando la productividad con
EntLib 3.1
21 de junio de 2007 — 18:00h a 20:00h
Organiza: BcN DEV .NET User Group
http://www.bcndev.net
eventos
plataforma.net
César de la Torre
Seguridad en los servicios SOA con WCF:
autenticación y autorización
En este artículo se presentan los conceptos generales relacionados con
la seguridad desde el punto de vista de Windows Communication Foundation (WCF), para luego presentar en detalle dos de sus características
fundamentales: la autenticación y la autorización.
César de la Torre trabaja
actualmente en Microsoft
como MBS-ISV Development Advisor, dentro de
la División de Desarrolladores y Plataforma de
Microsoft.
Su background es fundamentalmente la arquitectura y desarrollo de aplicaciones distribuidas, con
tecnología Microsoft,
durante más de 11 años.
Blog: http://blogs.
msdn.com/cesardelatorre
Windows Communication Foundation (en lo sucesivo, WCF) es, en definitiva, una nueva tecnología
para desarrollar servicios (y fijaros en que digo
“servicios”, no “servicios Web”; supongo que
intuiréis el porqué…). Esto está más o menos claro para todo el que haya oído algo sobre .NET
3.0 (WinFX en nombre beta) y sus pilares tecnológicos (WCF, WF, WPF y WCS).
Hasta ahora, para desarrollar servicios Web XML
nos basábamos en ASMX (ASP.NET). Sin embargo, ¿necesitamos algo más que simplemente los servicios Web básicos? ¿Qué razones podríamos tener
para “dar el salto” y cambiar en nuestras implementaciones de aplicaciones SOA, dejando de desarrollar servicios Web XML básicos y empezando a utilizar una nueva tecnología como WCF?
Bueno, las razones son precisamente los requerimientos avanzados de las aplicaciones empresariales, que necesitan más cosas que simplemente una
comunicación entre cliente y servicio (como hacen
los servicios Web básicos). Yo veo los siguientes puntos/necesidades por los que “dar el salto”:
• Seguridad avanzada orientada a mensajes en
las comunicaciones con los servicios, incluyendo diferentes tipos de autenticación, autorización, cifrado, no tampering, firma, etc.
• Mensajería estable y confiable.
• Soporte de transacciones distribuidas entre
diferentes servicios.
• Mecanismos de direccionamiento y enrutado.
• Metadatos para definir requerimientos como
políticas.
• Soporte para adjuntar grandes cantidades
de datos binarios en llamadas/respuestas a
servicios (imágenes y/o adjuntos de cualquier tipo).
Los estándares WS-* son los que definen precisamente dichos nuevos requerimientos y aspectos avanzados de los servicios. WS-* es realmente “un mundo nuevo”: abarcan muchísimas cosas,
y comparar WS-* con los servicios Web básicos
(WS-I o basic profile) es como comparar un camión
con una carretilla…
En definitiva, cualquiera de los anteriores
requerimientos puede justificar la utilización de
WCF como tecnología de nuestros servicios-SOA.
Sin embargo, probablemente una de las principales razones por las que utilizar WCF sea concretamente la seguridad, tanto por su importancia en
el mundo de las comunicaciones remotas como
por sus amplias posibilidades en WCF (es probablemente uno de los aspectos con más variantes
de WCF).
En el mundo de las comunicaciones, “no debemos fiarnos de nadie”; cada extremo de las comunicaciones debe poder identificarse con el otro
extremo, y debemos poder establecer límites de
qué es lo que el otro puede o debe hacer para consumir mi servicio. Además, especialmente en las
comunicaciones sobre entornos públicos (como
<< dnm.plataforma.net
Estándares y especificaciones
WS-* que lo definen
Seguridad avanzada orientada a mensajes
con los servicios, incluyendo diferentes tipos
de autenticación, autorización, cifrado,
no tampering, firma, etc.
WS-Security, WS-SecureConversation,
WS-Trust
Mensajería estable y confiable
WS-ReliableMessaging
Soporte de transacciones distribuidas
entre diferentes servicios
WS-AtomicTransactions
Mecanismos de direccionamiento y enrutado
WS-Addressing
Metadatos para definir requerimientos
como políticas
WS-Policy
Soporte para adjuntar grandes cantidades
de datos binarios en llamadas/respuestas
a servicios (imágenes y/o adjuntos
de cualquier tipo)
MTOM
Internet), debemos proteger la información, ofreciendo confidencialidad e
integridad de los datos enviados.
Por todo esto, he decido que en este
artículo me voy a centrar exclusivamente en las posibilidades que nos ofrece WCF sobre diferentes aspectos de
la seguridad en las comunicaciones de
nuestros servicios.
Una vez centrados en la seguridad,
vamos a ver entonces qué áreas pueden
ser interesantes e importantes en las
comunicaciones. Probablemente no
hablemos de todas, pero por lo menos
vamos a poner un poco de luz sobre las
áreas de seguridad que me parecen más
importantes para el diseño y desarrollo
de una aplicación distribuida y/o de un
servicio-SOA. Son las siguientes áreas:
• Autenticación. Requiere al llamador identificarse con una prueba de identidad.
• Autorización. Confirmar que el
llamador está autorizado para acceder a un recurso.
• Integridad de mensajes. Asegurarnos de que un mensaje y sus
datos no han sido cambiados
“durante el viaje”.
• Confidencialidad de los mensajes. Nos aseguramos de que solamente el destinatario de un mensaje puede ver y entender el mensaje en su forma original.
A nivel de implementación tecnológica, WCF nos ofrece un conjunto de
características para asegurar la transferencia de datos (en forma de mensajes)
en las comunicaciones y también el acceso a los recursos (componentes de negocio, fuentes de datos, etc.).
La transferencia de los mensajes se
puede asegurar básicamente de dos
formas:
• Seguridad basada en el transporte
(SSL/HTTPS).
• Seguridad basada en los mensajes
SOAP.
La seguridad basada en el transporte
la proporciona precisamente dicho transporte, normalmente HTTPS, y es algo
que ya se podía utilizar con los servicios
Web básicos. El problema es que este tipo
de seguridad “nos deja atados” a un protocolo (HTTPS) y a un tipo de seriación
(XML) de los datos de la comunicación.
Sin embargo, la seguridad a nivel de
mensajes SOAP es completamente independiente del protocolo de transporte
que elijamos. Incluso podríamos cambiarlo en el futuro de forma muy sencilla, un ejemplo claro del gran desacoplamiento que ofrece WCF (desacoplamiento del protocolo de transporte,
desacoplamiento de los procesos de hosting, desacoplamiento del servicio y
desacoplamiento del comportamiento).
Por último, el aseguramiento del
acceso a los recursos se realiza basándonos en identidades del llamador y en autorizaciones aplicadas en los recursos.
Microsoft dice que “WCF es seguro por defecto”. Esto es así porque
exceptuando el enlace (binding) básico
basicHttpBinding, el resto de enlaces
proporcionados por Microsoft tienen
habilitada la seguridad. Además, el binding especificado por defecto en un proyecto creado con el asistente de Visual
Studio (si tienes instaladas las extensiones de WCF y WPF para VS 2005) es
el wsHttpBinding, que soporta los estándares de seguridad de WS-Security; por
eso se puede afirmar lo anterior.
Hasta ahora he hecho una presentación de diferentes aspectos relacionados
con la seguridad en WCF. Sin embargo,
debido a lo amplio de cada uno de los
temas introducidos, en este artículo
vamos a limitarnos a dos de los aspectos
principales que he introducido: la autenticación y la autorización, dejando para
un próximo artículo una discusión más
profunda sobre la integridad y confidencialidad de los mensajes.
Autenticación con WCF
El proceso de autenticación (también
denominado identificación) permite a
un cliente o incluso a otro servicio (en
definitiva, al llamador/consumidor del
servicio) identificarse y que el servicio
pueda confirmar si la otra parte es quien
dice ser que es. La autenticación busca
responder a la pregunta ¿Eres quien
dices que eres? Esto lo entiende todo el
mundo. Por ejemplo, si en una tienda
<<dotNetManía
Necesidades avanzadas en los servicios
19
<< dnm.plataforma.net
cuando voy a pagar con una
tarjeta de crédito me dicen
que demuestre quién soy, me
piden autenticarme o identificarme con el DNI o pasaporte. El DNI es, en definitiva, una credencial de mi
identidad personal en el mundo real. En el mundo del software, la credencial más
común es un nombre de usuario acompañado de una clave
(password).
Hay muchos más tipos de
credenciales en el mundo del
software, además de usuario/password, como los certificados X.509 con claves privadas, credenciales Kerberos,
tokens SAML (Security Access
asegurar (cifrar), aún
en el caso de que el
cliente sea anónimo,
el servicio hace uso
de un certificado de
servidor para que el
cliente pueda asegurarse y determinar la
identidad del servicio. Además, el cifrado se basará en las
claves del certificado de servidor. Esto
es muy similar a
como funciona SSL
(un sitio Web con
acceso HTTPS que
permite acceso anónimo).
Servicio
Ninguna
Ninguna / Certificados Servidor X.509
Windows/Kerberos
Windows / Kerberos
Usuario/Password
N/A ó Certificados Servidor X.509
Membership
Certificados Servidor X.509
Certificados cliente X.509
Certificados Servidor X.509
CardSpace
Certificados Servidor X.509
<<dotNetManía
<endpoint name=”MiConfigAnonimoBasicHttp”
address=”http://miServidor:8000/MiServicio/http”
binding=”basicHttpBinding”
bindingConfiguration=”basicAnonimoBinding”
contract=”MiServicioLib.IMiContrato” />
…………………………………………………………………………………
…………………………………………………………………………………
…………………………………………………………………………………
<basicHttpBinding>
<binding name=”basicAnonimoBinding”>
<security mode=”None”/>
</binding>
</basicHttpBinding>
20
Autenticación con token de seguridad
Windows/Kerberos
Cliente
Listado 1. Configuración de un endpoint de WCF (en el fichero
.config del servicio) estableciendo acceso anónimo
como política de MiServicio
Markup Language), etc.
Cuando las credenciales se
comunican, entonces se
llaman testigos (tokens) de
seguridad.
Los tipos de credenciales soportados directamente por WCF son:
Acceso anónimo
La primera opción de
credenciales posibles es
“Ninguna”, es decir, que el
cliente sea anónimo. Sin
embargo, en el servidor, si
la comunicación se quiere
La segunda opción es “Windows/
Kerberos”. En este caso, tanto el
cliente como el servicio utilizan una
cuenta de Windows para autenticarse. WCF negociará basándose en Kerberos o en NTLM, siendo preferente Kerberos si tenemos un dominio de
Directorio Activo disponible (NTLM
realmente no autentica el servicio al
cliente; solamente autentica el cliente en el servicio). Si se quiere utilizar
Kerberos, es importante que el cliente identifique al servicio con un SPN
(Service Principal Name). Si el servicio
se piensa consumir en un entorno
basado en Directorio Activo, lo normal y la mejor opción es precisamente utilizar este tipo de credenciales
Windows/Kerberos, puesto que permite propagar el token de seguridad
del usuario actual con el que está ejecutándose la aplicación cliente (su
login actual de Windows). Esto proporciona una autenticación única
basada en el Directorio Activo. A esto
se le denomina normalmente SSO
(Single Sign-On).
<< dnm.plataforma.net
la siguiente; simplemente, en la siguiente definición estoy especificando explícitamente que quiero utilizar seguridad
Windows.
Cómo obtener dentro del servicio el
token de seguridad autenticado y propagado desde el cliente
Normalmente, después de realizarse
el proceso de autenticación nos interesará acceder al contexto del usuario cliente autenticado, para mostrarlo en algún
punto o simplemente porque queremos
hacer una depuración en la que comprobemos que ciertamente la aplicación
cliente se autenticó con un usuario concreto. Para acceder al contexto del usuario cliente, lo podemos hacer así (en C#):
Figura 1
<endpoint
name=”MiConfigWindowsWsHttp”
address=”http://localhost:8000/MiServicio/”
binding=”wsHttpBinding”
contract=”MiServicioLib.IMiContrato” />
Listado 2. Ejemplo de binding wsHttpBinding que utiliza
autenticación Windows, por defecto.
<endpoint name=”MiConfigAnonimoBasicHttp”
address=”http://miServidor:8000/MiServicio/http”
binding=”basicHttpBinding”
bindingConfigurati<endpoint
name=”MiConfigWindowsWsHttp”
address=”http://localhost:8000/MiServicio/”
binding=”wsHttpBinding”
bindingConfiguration=”SeguridadWindowsConfigBindingExplicita”
contract=”MiServicioLib.IMiContrato” />
<bindings>
<wsHttpBinding>
<binding name=” SeguridadWindowsConfigBindingExplicita “>
<security mode=”Message”>
<message clientCredentialType=”Windows”/>
</security>
</binding>
</wsHttpBinding>
</bindings>
Listado 3. Ejemplo de binding wsHttpBinding que utiliza autenticación Windows, de forma explícita
Como veis, en la definición de este
endpoint no estoy especificando nada acerca de autenticación Windows/Kerberos,
y sin embargo es la que se utilizará… ¿Por
qué? Pues porque como decía, WCF se
basa mucho en ‘por defectos’, y el ‘por
defecto en la autenticación’ es autenticación Windows/Kerberos. Relacionado
con esto, la definición anterior de endpoint funcionaría exactamente igual que
El token cliente autenticado será en
el que se base el servicio para acceder
posteriormente a los recursos (una
base de datos, ficheros o cualquier otro
recurso).
La forma de obtener la identidad
del cliente autenticado (la línea en C#
de arriba) es la misma independientemente del token utilizado. Es decir, que
podemos utilizar el código anterior
<<dotNetManía
Un esquema de la utilización de
tokens Windows/AD en aplicaciones
sería el que muestra la figura 1.
Por supuesto, en ese esquema, los servicios WCF estarían situados como una
sub-capa de interfaz de servicios “dentro” de la capa de negocio.
Y… ¿qué hay que hacer para habilitar seguridad basada en tokens Windows?
¡Nada! ☺. Bueno, no es realmente así,
pero es importante conocer que por
defecto, el tipo de autenticación que se
utiliza en el binding por defecto de WCF
(wsHttpBinding) es Windows/Kerberos.
Por ejemplo, un binding normal de
tipo wsHttpBinding, tal y como lo crea
el asistente de Visual Studio en un proyecto de servicio WCF, y sin aplicarle
ningún tipo de extensión, como se
muestra en el listado 3, ya va a estar utilizando seguridad basada en tokens Windows (autenticación Windows).
string identidad = OperationContext.Current.
ServiceSecurityContext.PrimaryIdentity.Name;
21
<< dnm.plataforma.net
para obtener la identidad de un usuario autenticado por Windows/AD,
Membership, etc.
Token de seguridad usuario/password
La tercera y cuarta opción están
basadas en usuario/password, o sea,
una credencial basada en un nombre
de usuario acompañado de una clave.
Esta pareja de datos se utilizarán para
identificar de forma inequívoca al
cliente. Por defecto, si se hace uso de
usuario y clave, el repositorio de
autenticación sería Windows/AD. Sin
embargo, esto se puede cambiar y
especificar que se quiere autenticar
contra Membership.
En el caso de querer cifrar la comunicación, se puede utilizar también en
el servicio un certificado de servidor
X.509, tanto para identificar al servicio
como para cifrar (encriptar) los datos
de la comunicación.
Autenticación con token de
seguridad Membership (tipo
especial usuario/password)
Es posible también autenticar un
cliente con una pareja usuario/password
que deba autenticarse contra un repositorio Membership.
Con .NET 2.0 y ASP.NET 2.0 apareció como novedad una tecnología de
<system.serviceModel>
<bindings>
<wsHttpBinding>
<binding name=”UsernameWithTransport”>
<security mode=”Transport”>
<transport clientCredentialType=”Basic” />
</security>
</binding>
</wsHttpBinding>
</bindings>
<services>
<service name=”MiServicioLib.MiServicio”>
<endpoint address=”https://localhost/MiServicio”
binding=”wsHttpBinding”
bindingConfiguration=”UsernameWithTransport”
contract=”MiServicioLib.IMiContrato”
name=”EndpointBasico” />
</service>
</services>
</system.serviceModel>
Listado 4. Ejemplo de endpoint configurado para hacer uso de credenciales usuario/password
<<dotNetManía
Lógicamente, en este caso de credenciales usuario/password, la aplicación
cliente es responsable de proporcionar
dichas credenciales, de una forma similar a la siguiente, por código:
22
autenticación llamada Membership (no
confundir con el antiguo Membership
de Microsoft Site Server 3.0 allá por
1999; no tiene nada que ver). El Membership de ahora no consiste en un úni-
proxy.ClientCredentials.UserName.UserName = “nombreUsuario”;
proxy.ClientCredentials.UserName.Password = “laClave”;
co y específico repositorio de usuarios
para realizar autenticación. No, se trata más bien de una capa intermedia para
realizar autenticaciones contra cualquier proveedor Membership que dispongamos nosotros ‘por debajo’. Podemos desarrollar de forma muy sencilla
un proveedor personalizado de Membership que autentique contra cualquier
fuente de datos de repositorio de usuarios. Se puede hacer uso del proveedor
ejemplo SqlMembership o bien desarrollar un proveedor contra el esquema y
SGBD propio que queramos, o incluso contra otro repositorio que no sea
un SGBD sino un directorio LDAP, etc.
Lo interesante de Membership es que
nos proporciona una interfaz estándar
de autenticación (tanto programática
mediante API como con controles Web
visuales) siempre basada en tokens usuario/password, pero contra cualquier
repositorio que configuremos.
En definitiva, por la razón que sea
(aplicación existente basada en Membership, no disponibilidad de Directorio Activo, etc.), podemos disponer de
un repositorio de usuarios expuesto a
autenticación mediante Membership y
utilizarlo para ¡basar la autenticación
de nuestros servicios WCF en Membership! (figura 2).
Para integrar Membership en un servicio WCF, el usuario debe de alguna
forma proporcionar las credenciales que
requiere Membership (siempre usuario
y clave). Para transferir esos datos al servicio WCF, debemos por lo tanto hacer
uso de un binding que soporte credenciales de tipo usuario/password, como
wsHttpbinding, y especificar explícitamente que el tipo de credenciales es
UserName. En el servicio, la seguridad de
WCF autenticará al usuario basándose
en dicha pareja de datos contra el proveedor Membership que hayamos configurado. Posteriormente incluso podríamos hacer uso de autorización de acceso a recursos (componentes de negocio,
etc.) basada en Roles-Providers de
ASP.NET.
<< dnm.plataforma.net
Una vez tenemos configurado el
proveedor Membership, tenemos que
configurar una sección de tipo Behavior
de WCF (listado 6).
La forma de obtener la
identidad del cliente
autenticado es la misma
independientemente del
token utilizado
Figura 2.
Esquema de autenticación Membership por un servicio WCF
Para configurar nuestro servicio
WCF y que utilice Membership como
sistema de autenticación, lo primero
que debemos hacer, lógicamente, es
configurar nuestro proveedor Membership, de igual forma que lo haríamos
en una aplicación normal ASP.NET
2.0. Para ello, tenemos que añadir las
siguientes secciones a nuestro fichero
.config (web.config o app.config, dependiendo del proceso host) (listado 5).
En este caso, como se puede observar, estamos utilizando un proveedor
Membership de tipo SQL Server y
además el que nos proporciona por
defecto ASP.NET 2.0 (también podría
ir contra SQL Server pero contra un
esquema propio nuestro, contra otra
base de datos como Oracle o incluso
contra otros repositorios como directorios LDAP, el propio Directorio
Activo, etc.).
<!— ***** Connection string SQL Server para MEMBERSHIP ***** —>
<connectionStrings>
<add name=”MembershipSqlServer2005” connectionString=”Data
Source=localhost;Initial Catalog=ASPNETDB;Integrated Security=True”
providerName=”System.Data.SqlClient” />
</connectionStrings>
<system.web>
<!— ***** Sql Membership Provider ***** —>
<membership defaultProvider=”SqlMembershipProvider” userIsOnlineTimeWindow=”15”>
<providers>
<clear />
<add
name=”SqlMembershipProvider”
type=”System.Web.Security.SqlMembershipProvider”
connectionStringName=”MembershipSqlServer2005”
applicationName=”/”
enablePasswordRetrieval=”false”
enablePasswordReset=”false”
requiresQuestionAndAnswer=”false”
requiresUniqueEmail=”true”
passwordFormat=”Hashed” />
</providers>
</membership>
</system.web>
Listado 5
<<dotNetManía
Configuración de servicio WCF para
soportar autenticación
Membership
23
<< dnm.plataforma.net
<system.serviceModel>
……………………………………………………
……………………………………………………
<behaviors>
<serviceBehaviors>
<behavior name=”MiSvcMembershipSecBehavior”>
<!— Configuramos la autenticación para que use MEMBERSHIP-PROVIDER —>
<userNameAuthentication
userNamePasswordValidationMode=”MembershipProvider”
membershipProviderName=”SqlMembershipProvider”/>
<!—Configuramos el certificado servidor X.509 del Servicio —>
<serviceCertificate storeLocation =”CurrentUser”
storeName =”My”
x509FindType =”FindBySubjectName”
findValue =”localhost” />
</serviceCredentials>
<!—Para debugging poner includeExceptionDetailInFaults a ‘true’—>
<serviceDebug includeExceptionDetailInFaults=”true” />
<serviceMetadata httpGetEnabled=”true”/>
</behavior>
</serviceBehaviors>
</behaviors>
……………………………………………………
……………………………………………………
</system.serviceModel>
<<dotNetManía
Listado 6
24
En esta sección definimos un behavior de servicio (comportamiento de
servicio) en el que especificamos que
la autenticación se basará en credenciales de tipo usuario/password y en
concreto en un proveedor Membership determinado (en este caso SqlMembershipProvider).
Además de eso, también se requiere un certificado de servidor X.509
exclusivamente para el servidor. Este
certificado tiene un uso similar al que
se le da en las comunicaciones seguras
SSL; es decir, sirve para identificar al
servidor y también sirve como raíz origen de las claves seguras necesitadas
para realizar encriptación (cifrado) de
la comunicación, que será automático
en caso de utilizar el binding wsHttpBinding, como es el caso del ejemplo.
Una vez tenemos definido dicho el
comportamiento (que podremos utilizar
con cualquier definición de servicio), lógicamente tenemos que tener el XML de
definición de nuestro servicio que queremos enlazar con este behavior. Como
por ejemplo, la definición de servicio
siguiente (en este caso hago hosting en una
aplicación de consola y basado en protocolo HTTP por el puerto 8000, todo gracias a Http.sys) (listado 7).
El enlace del servicio con Membership está precisamente al principio, donde especificamos el behavior llamado behaviorConfiguration=”MiSvcMembershipSecBehavior”. Además, también es nece-
sario especificar de forma explícita que el
tipo de credenciales de cliente a ser autenticadas por mi servicio son del tipo UserName (puesto que Membership es un subtipo de autenticación basada en credenciales usuario/password).
Con esto ya tendríamos configurado nuestro servicio para utilizar seguridad Membership. Solamente nos faltarían un par de cosas, como configurar nuestra aplicación cliente con unos
bindings que también soporten Membership (éstos pueden ser generados
automáticamente por la utilidad svcutil.exe o por el propio Visual Studio
cuando hacemos un “Add Service Reference…”, que realmente está utilizando svcutil.exe).
Por último, tenemos que instanciar
la clase proxy de nuestro servicio desde
la aplicación cliente y proporcionarle,
lógicamente, las credenciales usuario/password, como hacemos en el código C# del listado 8.
Para configurar un servicio WCF para que utilice
Membership,lo primero que debemos hacer es
configurar el proveedor Membership,de igual forma
que lo haríamos en una aplicación ASP.NET 2.0
<< dnm.plataforma.net
Autenticación con token de
seguridad Certificado X.509
<system.serviceModel>
……………………………………………………
……………………………………………………
<services>
<service name=”MiServicioLib.MiServicio”
behaviorConfiguration=”MiSvcMembershipSecBehavior” >
<host>
<baseAddresses>
<add baseAddress=”http://localhost:8000/MiServicio/” />
</baseAddresses>
</host>
La quinta opción es hacer uso de Certificados X.509, para el cliente y para el
servicio. En ambos casos se utilizarán para
identificarse y también lógicamente el
cifrado y firma de la comunicación se
basarán en dichos certificados. Este caso
es típico en escenarios B2B.
En este caso, en la configuración del
servicio (en el fichero .config del servidor) hay que especificar que el tipo de
seguridad requerido en el binding es de
tipo Certificate, de la siguiente forma:
<endpoint name=”ConfigMiServicioWsHttpMembershipSec”
address=” http://localhost:8000/MiServicio/Membership”
binding=”wsHttpBinding”
bindingConfiguration=”MiBindingConf”
contract=”MiServicioLib.IMiContrato” />
</service>
</services>
<bindings>
<wsHttpBinding>
<!— Binding que requiere autenticación con certificado X.509—>
<binding name=”MiBindingConf”>
<security mode=”Message”>
<message clientCredentialType=
”Certificate”/>
</security>
</binding>
</wsHttpBinding>
</bindings>
<bindings>
<wsHttpBinding>
<binding name=”MiBindingConf”>
<security mode =”Message”>
<message clientCredentialType =”UserName”/>
</security>
</binding>
</wsHttpBinding>
</bindings>
……………………………………………………
……………………………………………………
</system.serviceModel>
Listado 7
En la configuración de la aplicación
cliente que consuma este servicio se
deberá especificar un binding similar al
anterior; es decir, que el tipo de credenciales sea también de tipo Certificate ( <message clientCredentialType=”Certificate” />).
//PROPORCIONAMOS USUARIO DE MEMBERSHIP
proxy.ClientCredentials.UserName.UserName = “ctorre”; //Usuario Membership
proxy.ClientCredentials.UserName.Password = “miclave”;//Password
string resultado;
resultado = proxy.MiMetodoObtenerInfo();
proxy.Close();
Listado 8
La última opción es IssuedToken, y
es el tipo de token que se puede generar con CardSpace (conocido como
InfoCard en su versión beta) y tokens
otorgados por terceras partes, como por
ejemplo un STS (Security Token Service). En cualquiera de estos casos, realmente se trata de un token SAML, basado por lo tanto en especificaciones
estándar SAML.
<<dotNetManía
Autenticación con token de
seguridad IssuedToken
(CardSpace, SAML, etc.)
//Creamos el objeto proxy
MiContratoClient proxy = new MiContratoClient();
25
<< dnm.plataforma.net
Este tipo de credenciales es probablemente el más importante de cara al
futuro. Permite al servicio aceptar como
identificación y autenticación del cliente
unas credenciales proporcionadas originariamente por un STS. Digo que este
tipo de credenciales va a ser muy importante en el futuro porque que permitirá
escenarios de “federación de identidades”
y CardSpace (CardSpace, desde el punto
de vista de un usuario, es un selector de
identidades que aparece por primera vez
en Windows Vista e instalando .NET 3.0
en XP o Windows Server 2003).
Sobre las identidades federadas, cuando una organización se federa como partner con otra organización, lo que se está
haciendo es permitir a los usuarios del
partner que se autentiquen con cualquiera
de sus usuarios mediante el mecanismo
que prefiera. Por ejemplo, este escenario podría permitir que los usuarios de
otra organización se identifiquen y uti-
Figura 3. Ejemplo de la interfaz de usuario que muestra CardSpace para que se
seleccione la tarjeta/token a proporcionar como identificación
para realizar operaciones de autorización, auditoría, etc.
<<dotNetManía
Cuando una organización se federa como partner con
otra organización,lo que se está haciendo es permitir a
los usuarios del partner autenticarse con cualquiera de
sus usuarios mediante el mecanismo que prefiera
26
licen mi servicio aun cuando por ejemplo dichos usuarios no pertenezcan a ninguno de mis dominios de Directorio
Activo e incluso no exista una relación
de confianza tradicional de AD. Para ello,
se requiere al usuario de la otra organización que se autentique con un STS, el
cual le otorga un token SAML (Security
Assertion Markup Language). Una vez dispone de dicho token SAML, mi servicio
puede aceptarlo como token de autenticación o requerir que dicho token SAML
sea autenticado por un STS de mi orga-
nización, de forma que pueda confirmar
las credenciales de dicho token y después
otorgar un segundo token SAML que es
el que utilizará en las comunicaciones.
En el entorno de Windows y el Directorio Activo, la federación se realiza
mediante ADFS (Active Directory Federation Services) (listado 9).
En cualquiera de los casos (credencial elegida), WCF autenticará con uno
u otro tipo de credenciales, y posteriormente podrá utilizar también dicho
token y contexto de usuario autenticado
Autorización con WCF
Es muy importante no confundir nunca
la autenticación (identificación) con la
autorización. La autenticación, como
hemos visto antes, responde a la pregunta ¿Quién eres?. Al identificarse el usuario comprobaríamos que se trata, por
ejemplo, del usuario “pepe”. Sin embargo, la autorización responde a la pregunta ¿Tiene pepe autorización o permisos
para acceder a cierto recurso?
En el mundo de servicios SOA, los
recursos son lógicamente los métodos de
nuestros servicios, o incluso internamente las clases de la capa de negocio que
publique nuestros servicios. A estos recursos debemos poner barreras para que accedan a ellos solamente quienes tienen que
hacerlo, precisamente mediante mecanismos de autorización.
Una vez que llegan al servicio los
mensajes SOAP de comunicación, se deserian los tokens de seguridad y se reali-
<< dnm.plataforma.net
<services>
……………
……………
<endpoint name=”ConfigWsHttpInfocard”
address=http://miServidor:8000/MiServicio/InfoCard
binding=”wsHttpBinding”
bindingConfiguration=”RsMessageInfoCardSecurityBinding”
contract=”MiServicio.IMiContrato”>
<identity>
<!—- Utilizamos un certificado X.509 servidor para el servicio —>
<certificateReference
findValue=”MiCertificadoX509”
x509FindType=”FindBySubjectName”
storeLocation=”LocalMachine”
storeName=”My” />
</identity>
</endpoint>
</service>
</services>
<bindings>
<wsHttpBinding>
<binding name=”RsMessageInfoCardSecurityBinding”>
<security mode=”Message”>
<!— “IssuedToken” es autenticacion InfoCard (CardSpace)—>
<message clientCredentialType=”IssuedToken” />
</security>
</binding>
</wsHttpBinding>
</bindings>
Listado 9. Configuración de un endpoint de WCF (en el fichero .config del servicio) para
habilitar y exigir autenticación CardSpace/SAML como política de MiServicio
en componentes de negocio de aplicaciones N-Tier y N-Layered WCF son:
Actualmente WCF no tiene implementadas las políticas, atributos y por
lo tanto un proveedor WCF nativo de
autorización para AzMan (Windows
Authorization Manager). Es algo que
podría implementarse mediante custom
behaviors e inspectors, o por supuesto
mediante código propio in-line en la
implementación de cada método de un
servicio.
Por supuesto, no estoy teniendo en
cuenta que siempre se puede utilizar
AzMan por debajo de los ASP.NET
Role Providers, puesto que existe un
proveedor de roles de ASP.NET para
AzMan llamado AuthorizationStoreRoleProvider (disponible en .NET 2.0),
pero es un proveedor que simplemente mapea roles de AzMan para que se
puedan tratar como roles ASP.NET, por
lo que se pierde toda la potencia y desacoplamiento de los permisos de AzMan
(tasks y operations), que son los que se
deberían poder aplicar a los recursos a
autorizar (métodos del servicio), y no
simplemente aplicar a los recursos autorización basada en pertenencia a roles.
Vamos a ver cómo realizar autorizaciones en WCF con cada uno de los
otros dos métodos anteriormente mencionados (grupos Windows y roles
ASP.NET).
Sistema de autorización
Relación con sistema de usuarios
Roles/Grupos de Windows/AD
Usuarios Windows/Active Directory
Roles de ASP.NET Role Providers Usuarios Membership
Autorización con certificados
Certificados cliente X.509
Permisos y roles de AzMan
Usuarios Windows/Active Directory
(Windows Authorization Manager)
Sin embargo, WCF solamente tiene
implementadas internamente políticas y
atributos de proveedores de autorización
para las siguientes autorizaciones:
• Roles/grupos de Windows/AD.
• Roles de ASP.NET Role Providers.
Autorización con grupos de
Windows/AD
En WCF, el sistema más cómodo (y
además orientado a aspectos ☺) para
realizar autorizaciones de acceso a usua-
<<dotNetManía
za la autenticación. Justo después de este
momento es cuando se aplican las políticas de autorizaciones, y por lo tanto
cuando se comprueba si el llamador
(cliente) tiene acceso a los recursos que
requiere.
Las políticas de autorización evalúan
conjuntos de demandas (claims) extraídas de los tokens de seguridad, y tienen
que validarse contra permisos requeridos (como pertenencia a roles, etc.) que
tienen que ser cumplidos por los tokens
de seguridad. Este conjunto de demandas es proporcionado internamente al
ServiceAuthorizationManager y a la lógica dentro de la propiedad AuthorizationContext.
Los tipos más usuales de autorización en servicios SOA e internamente
• Autorización basada en Certificados X.509.
27
<< dnm.plataforma.net
rios Windows/AD comprobando si pertenecen a ciertos grupos Windows
requeridos, es basándonos en el atributo PrincipalPermissionAttribute, el cual
se puede utilizar para diferentes tipos
de autorización y tokens de seguridad,
por lo que normalmente es necesario
una configuración del tipo de seguridad
a utilizar en la autorización.
En este caso, como queremos utilizar
grupos de Windows/AD, tenemos que
realizar la siguiente configuración declarativa en el fichero .config (listado 10).
Cuando la aplicación cliente llame
a este método de nuestro servicio,
antes de ejecutarse el método se realizarán las operaciones de autorización,
y si el usuario llamador pertenece al
grupo local Administrators, entonces
simplemente el método se ejecutará de
forma normal. Por el contrario, si el
usuario no pertenece al grupo requerido, WCF lanza una excepción de tipo
“Acceso Denegado”. Esa excepción
deberá ser gestionada por nuestra aplicación.
<behaviors>
<serviceBehaviors>
<behavior name=”ComportamientoDeMiServicio”>
...
<serviceAuthorization principalPermissionMode=”UseWindowsGroups”/>
</behavior>
</serviceBehaviors>
</behaviors>
Listado 10. Configuración para autorización con grupos Windows/AD
<<dotNetManía
El comportamiento serviceAuthorization establece que vamos a utilizar grupos Windows como modo de permisos
(principalPermissionMode). Además, lo
que hace es poner un WindowsPrincipal
en el hilo de ejecución actual cada vez que
se llama al servicio.
El atributo PrincipalPermissionAttribute lo tenemos que aplicar a cada
uno de los métodos (operaciones) en
los que se quiera comprobar y aplicar
la autorización. En nuestro ejemplo,
vamos a comprobar que el llamador
pertenezca al grupo local Administrators (listado 11).
28
Autorización con roles de ASP.NET
Role providers
Los proveedores de roles ASP.NET
son roles que agrupan usuarios Membership. La verdad es que podían haberlos llamado Roles-Membership y así
estaría mucho más claro; pero el caso es
que se llaman ASP.NET Role providers.
Realizar autorizaciones con este
nuevo tipo de roles de ASP.NET 2.0 en
WCF es muy fácil porque están igual
de integrados que los grupos de Windows. Vamos, que podemos utilizar el
mismo atributo PrincipalPermissio-
[PrincipalPermission(SecurityAction.Demand,
Role = “Builtin\\Administrators”)]
public string ObtenerInfoConfidencialParaAdministrators ()
{
return “Hola!”;
}
Listado 11.Uso de atributo PrincipalPermissionAttribute con grupo local de Windows
nAttribute siempre y cuando anteriormente hayamos configurado el behavior
de autorización de nuestro servicio
WCF para que utilice ASP.NET Role
providers. Esto se hace de la forma que
explico a continuación.
Partimos de la premisa de que en
este caso vamos a basarnos en el proveedor SQL Server para Roles ASP.NET.
Primero necesitamos tener definida una
cadena de conexión que apunte a nuestra base de datos SQL Server. Lógicamente, es bastante normal utilizar la
misma cadena utilizada para el proveedor de autenticación de Membership
(listado 12).
Como se puede apreciar, estoy utilizando exactamente la misma cadena
de conexión que la utilizada antes para
la autenticación de usuarios Membership. Pero si las tablas de esquema que
definen mis roles estuvieran en otra base
de datos u otro servidor, podría utilizar
una cadena de conexión diferente.
Después necesitamos precisamente
definir el proveedor de roles; normalmente éste se define a continuación de la
definición de proveedor de Membership
(listado 13).
Hasta aquí, todo son definiciones
de ASP.NET 2.0; nada de esto forma
parte de WCF. Precisamente ahora
tenemos que empezar con la parte de
WCF, es decir, el comportamiento
(behavior) de WCF que exige autorización de tipo ASP.NET Role providers (listado 14).
El enlace de este behavior con nuestro servicio WCF es exactamente el mismo que el realizado anteriormente para
la autenticación con Membership, así
que no lo repito.
Con esto ya está todo configurado y
solamente nos queda picar código C#
donde requiramos la pertenencia del llamador a roles de Membership (ejem…,
quiero decir, Role providers de ASP.NET
2.0… ☺) (listado 15).
Como se puede observar, es algo
muy bueno que la autorización con
PrincipalPermission se programa igual
tanto si son grupos Windows como si
<< dnm.plataforma.net
Listado 12. Cadena de conexión para roles de ASP.NET y para Membership
<system.web>
<!— ***** Sql Role Provider ***** —>
<roleManager enabled =”true” defaultProvider =”SqlRoleProvider” >
<providers>
<add name =”SqlRoleProvider”
type=”System.Web.Security.SqlRoleProvider”
connectionStringName=”MembershipSqlServer2005”
applicationName=”/”/>
</providers>
</roleManager>
</system.web>
Listado 13. Definición de proveedor de ASP.NET Role providers
<behaviors>
<serviceBehaviors>
<behavior name=”MiSvcMembershipSecBehavior”>
<!— Configuramos autorización ROLE-PROVIDER —>
<serviceAuthorization principalPermissionMode =”UseAspNetRoles”
roleProviderName =”SqlRoleProvider” />
………………………………………
<!—Aquí estará también la config. de Membership, credenciales… —>
………………………………………
<serviceDebug includeExceptionDetailInFaults=”true” />
<serviceMetadata httpGetEnabled=”true”/>
</behavior>
</serviceBehaviors>
</behaviors>
Listado 14. Definición de behavior de autorización con ASP.NET Role providers
[PrincipalPermission(SecurityAction.Demand,
Role = “Desarrolladores”)]
public string ObtenerInfoConfidencialParaDesarrolladores()
{
// Devolvemos la lógica de negocio del método
return “Info confidencial para DESARROLLADORES...”;
}
Listado 15. Ejemplo de autorización WCF con roles ASP.NET 2.0 Role Providers
son roles ASP.NET, siempre y cuando
hayamos configurado “por debajo” el
behavior correspondiente, en el fichero
.config.
Autorización con certificados cliente
X.509
También podemos utilizar el ya conocido atributo PrincipalPermissionAttribute para controlar el acceso a los métodos basándonos en credenciales del tipo
Certificado cliente X.509. Para hacer
esto, antes que nada necesitamos conocer el asunto (subject) y la firma o huella digital (thumbprint) del certificado a
comprobar (se puede obtener desde
Internet Explorer viendo la información
del certificado de cliente concreto).
Por ejemplo, una huella digital de
un certificado cliente X.509 podría ser:
37 7b 89 72 2a 17 4f a9 fc e0 00 0e 7c 91
66 2c 15 93 64 2d
Y el asunto del certificado X.509,
por ejemplo, el que genera la FNMT
para hacer la declaración de la renta por
Internet, etc., es algo así:
CN = NOMBRE TORRE LLORENTE CESAR NIF 01234567D
El caso es que necesitamos estos
datos para poder realizar la comprobación de autorización (listado 16).
Destaco que la huella digital, cuando
la obtienes de IE o del snap-in de certificados, tiene un espacio entre cada dos
caracteres. Sin embargo, cuando se especifica en el código, hay que hacerlo sin
dichos espacios en blanco.
En este caso del ejemplo, solamente podrá llamar a ese método un cliente autenticado con un certificado cliente X.509 válido y cuyo asunto y huella
digital coincidan con los especificados
en la autorización.
Pero esto no funciona solamente así:
antes hay que configurar los behaviors
del servicio en el fichero .config, tal
como hemos hecho con los otros tipos
<<dotNetManía
<!— ***** Connection string SQL Server para ASP.NET Role Providers y
para Membership ***** —>
<connectionStrings>
<add name=”MembershipSqlServer2005” connectionString=”Data
Source=localhost;Initial Catalog=ASPNETDB;Integrated Security=True”
providerName=”System.Data.SqlClient” />
</connectionStrings>
29
<< dnm.plataforma.net
Conclusiones
[PrincipalPermission(SecurityAction.Demand,
Name = “ CN = NOMBRE TORRE LLORENTE CESAR - NIF 01234567D;
377b89722a174fa9fce0000e7c91662c1593642d”)]
public string ObtenerInfoConfidencialParaCliente()
{
// Devolvemos la lógica de negocio del método
return “Info confidencial para Cliente (B2B)...”;
}
Listado 16. Ejemplo de autorización basada en Certificado cliente X.509
de autorización. En él tenemos que establecer el PricipalPermissionMode para
que utilice UseAspNetRoles. Esto la verdad es que no lo han hecho muy elegante, pues aunque funciona, como
veremos a continuación, Microsoft
podía hacer creado otro literal diferente, llamado por ejemplo UseCertificates o algo así… Pero el caso es que hay
que utilizar el mismo tipo que para los
roles ASP.NET (listado 17).
to más la huella digital del certificado
cliente X.509).
Cuando se utiliza un certificado como
credencial de cliente, lo que hace WCF
es concatenar el asunto y la huella digital separándolos con un punto y coma, y
crea así un valor único para la identidad
del cliente (el llamador del servicio
WCF). Cuando se establece UseAspNetRoles como sistema de autorización en
el comportamiento de nuestro servicio,
<behaviors>
<serviceBehaviors>
<behavior name=”MiSvcCertificateSecBehavior”>
<!— Configuramos autorización —>
<serviceAuthorization principalPermissionMode =”UseAspNetRoles”/>
………………………………………
<serviceDebug includeExceptionDetailInFaults=”true” />
<serviceMetadata httpGetEnabled=”true”/>
</behavior>
</serviceBehaviors>
<<dotNetManía
Listado 17. Configuración para autorización con certificados cliente X.509
30
Fijaros que, lógicamente, puesto que
realmente no estamos utilizando ningún
proveedor real de roles ASP.NET, no
especificamos el parámetro RoleProviderName como sí hacíamos con el proveedor de roles SQL Server.
Bueno, y ahora viene la explicación
de por qué funciona así…
Resulta que al utilizar el literal UseAspNetRoles, internamente se indica a
WCF que se va a utilizar la propiedad
Name del atributo PrincipalPermissionAttribute para realizar una comparación de texto con el token de autenticación del llamador (en este caso el asun-
la identidad del cliente (llamador) se compara automáticamente con la propiedad
Name y se determina entonces si el usuario llamador (cliente) tiene o no tiene
autorización para acceder.
Pero vamos, como decía, es una pena
que no haya otro literal específico para
autorizaciones con certificados, porque
aunque funciona correctamente como
hemos dicho, no queda muy elegante que
estemos autorizando con certificados y en
cambio el literal sea UseAspNetRoles… Pero
en fin, el hecho es que los literales posibles
hoy por hoy son solamente estos: None, UseWindowsGroups, UseAspNetRoles y Custom.
En este artículo hemos hecho una introducción a la seguridad global en WCF,
y luego nos hemos centrado en la autenticación y la autorización. Concretamente, hemos visto en detalle los
siguientes puntos:
• Autenticación con WCF
–Acceso anónimo
–Autenticación con token de seguridad Windows/Kerberos
–Autenticación con token de seguridad usuario/password
–Autenticación con token de seguridad Membership (tipo especial
usuario/password)
–Autenticación con token de seguridad Certificado X.509
–Autenticación con token de seguridad IssuedToken (CardSpace,
SAML, etc.)
• Autorización con WCF
–Autorización con grupos de Windows/AD
–Autorización con roles de
ASP.NET Role providers
–Autorización con certificados cliente X.509
Lo más importante a destacar de
WCF tanto en la seguridad como en
cualquier otro aspecto son, como decía,
el desacoplamiento y la modularidad
de WCF, en la mayoría de los casos
siguiendo además el “patrón proveedor”. Por ejemplo, hoy podemos desarrollar un servicio y configurarlo declarativamente para que utilice un tipo de
seguridad, protocolo, formato de datos,
etc. y en el futuro cambiarlo declarativamente (en el .config) y utilizar otra
seguridad y otro protocolo, ¡y en
muchos casos no será necesario ni
siquiera el recompilar el servicio!
Cuanto más se conoce a Indigo
(WCF), más se aprecian el desacoplamiento y modularidad en todos los sentidos, así que os animo a dar el salto y pasar
de los básicos XML Web Services (de tipo
ASMX) a los nuevos servicios de WCF.
“¡I’m lovin’ it!” ☺.
Del 18 al 22 de junio del 2007
Miguel Katrib,
Mario del Valle,
Iskander Sierra,
Yamil Hernández
plataforma.net
Paso de páginas
en 3D con WPF
En un artículo anterior, los autores nos adentraron en el mundo de
los efectos 3D en WPF, mostrándonos cómo lograr un objeto 3D muy
utilizado, una esfera. En esta entrega nos definen un “visualizador de
páginas” que permite “hojear” un documento con un efecto similar al
de hojear un libro o una revista de papel.
Introducción
Miguel Katrib es doctor y
profesor jefe de programación del departamento
de Ciencia de la Computación de la Universidad
de La Habana. Miguel es
líder del grupo WEBOO,
dedicado a la orientación
a objetos y la programación en la Web. Es entusiasta de .NET y redactor
de dotNetManía.
Mario del Valle, Iskander
Sierra y Yamil Hernández
son instructores de programación en C# de la
cátedra de Programación
e Ingeniería de Software
del departamento de
Ciencia de la Computación de la Universidad de
La Habana. Son desarrolladores del grupo
WEBOO dedicados a la
tecnología .NET.
Hasta ahora la mayoría de las interfaces de usuario de las aplicaciones a la medida se basan en el
uso de controles básicos que brindan los entornos
de desarrollo. Algunas técnicas de interacción basadas en efectos de tres dimensiones (3D) han sido
de dominio casi exclusivo de las aplicaciones de
juegos o de aplicaciones muy especializadas que
requieren de desarrolladores expertos en estas técnicas. El acceso a recursos 3D ha estado disponible solo a través de librerías implementadas fundamentalmente en C++, como OpenGL y DirectX.
Pero no resulta sencillo integrar tales librerías con
los paquetes de controles existentes para el desarrollo de interfaces de usuario, como es el caso de
Windows Forms. Esta falta de integración ha desanimado la inclusión de efectos 3D en la interfaz de
usuario de muchas de nuestras aplicaciones.
Precisamente una de las características más
atractivas de Windows Presentation Foundation
(WPF), que ya ha sido tema de un cuaderno técnico de dotNetManía [1] y de algunos artículos
previos [2-4], es que reduce la impedancia entre
los mundos 2D y 3D. Las capacidades de extensibilidad de WPF permiten crear interfaces de usuario con efectos 3D sin exigir un conocimiento tan
especializado como el que se requiere para usar
DirectX u OpenGL. En un artículo anterior [3]
1
se hizo una primera introducción al mundo 3D
que puede lograrse con WPF, viendo cómo definir un objeto 3D importante como es el caso de
una esfera. En este trabajo veremos cómo crear
con WPF un objeto 3D que nos permite mostrar
las páginas de un documento simulando la sensación visual de hojear las páginas, como ocurre
cuando éstas son de papel1.
Simulando la realidad
La vía más simple para lograr efectos visuales 3D
es simularlos con recursos 2D. Por ejemplo, se
puede dibujar un botón que parezca abultado gracias al uso de gradientes, con colores más claros
por encima y más oscuros debajo, como los botones de la aplicación Media Player de Windows
Vista que se muestra en la figura 1. Otra solución
con más realismo sería construir un objeto tridimensional parecido a un botón real (como el de
algún equipo electrónico) y aplicarle las texturas
y colores de iluminación adecuados.
Figura 1.
Los botones de Windows Media Player.
Aunque, lamentablemente, de momento estamos muy lejos de poder sentir el olor del papel y de la tinta fresca de una
dotNetManía recién salida de imprenta.
<< dnm.plataforma.net
Figura 2. Diferentes valores del parámetro Progress
permiten obtener diferentes ángulos de inclinación de la hoja.
Figura 3. Diferentes grados de torcedura apreciados desde arriba.
Figura 4. Diferentes grados de curvatura de la página.
La mayoría de los controles intentan mostrar
una apariencia 3D con efectos en 2D (...) Pero
para lograr un mayor realismo en los efectos
3D es preferible, aunque por supuesto más
complejo, el uso de la maquinaria 3D de WPF
<<dotNetManía
La mayoría de los controles intentan mostrar una apariencia 3D con efectos en 2D. Esto es posible gracias a las
pequeñas dimensiones de los controles,
a la velocidad de movimiento cuando se
aplica una animación, o a la sutileza del
efecto, lo que permite ocultar el simulacro. Pero para lograr un mayor realismo en los efectos 3D es preferible,
aunque por supuesto más complejo, el
uso de la maquinaria 3D de WPF.
En este trabajo veremos cómo construir un objeto para mostrar una hoja
de un documento en 3D simulando los
movimientos y deformaciones que sufre
una hoja real de un libro o revista cuando se hojea.
Para comprender esta simulación,
comience por observar cómo usted
hojea las páginas de esta propia revista dotNetManía. El movimiento más
evidente es el que hace con cada hoja
cuando se rota ésta sobre su borde
interior, que hace de eje con la encuadernación. Si identificamos las distintas posiciones de una rotación sobre
este borde en una propiedad Progress,
que tome valores entre 0 y 180, donde
0 indica que la hoja está completamente de frente y 180 sería la misma
hoja rotada 180 grados, es decir
mostrándonos su reverso, podríamos
simular los movimientos de la hoja
como se muestra en la figura 2.
Sin embargo, a este efecto le falta
realismo, porque las hojas se ven rígidas. Hay que buscar un modo de
lograr un efecto de flexibilidad. Para
ello introducimos dos propiedades:
Twist y Bend. Twist representa el grado de torcedura de la hoja, con un
valor en el rango desde -1 hasta 1. Si
se mueve la hoja tomada por una
esquina, ésta se va torciendo en dirección al borde de rotación de la misma. En la figura 3 se muestra una hoja
(vista desde arriba) con diferentes grados de torcedura.
Por su parte, la propiedad Bend es
la que permite doblar o curvar la hoja
hacia fuera o hacia dentro. Con un
valor entre -1 y 1, muestra diferentes
grados de curvatura del papel, como
en la figura 4.
33
<< dnm.plataforma.net
Construcción de la malla
En primer lugar, definiremos una clase SimplePageModel3D (listado 1). Note
que la propiedad Content (que se hereda de la superclase ModelVisual3D) es de
tipo Model3D; ésta es la que indica la
malla del objeto que se visualiza.
En el constructor de SimplePageModel3D se hace:
GeometryModel3D geom3D = new
GeometryModel3D();
this.Content = geom3D;
Con lo que se crea una instancia de
GeometryModel3D (clase derivada de
Model3D) que se define a partir de una malla
o geometría tridimensional (Geometry). Es
esta instancia de GeometryModel3D la que
se asigna a la propiedad Content.
Después, al hacer:
<<dotNetManía
Figura 5. Paso de una página hacia la izquierda al cambiar los valores de Progress,
Twist y Bend con diferentes animaciones.
34
Si se varían adecuadamente los
valores de estas tres propiedades
mediante una animación, se puede
obtener el efecto visual de hojear la
página, como se muestra en los fotogramas de la figura 5.
La base de una animación en WPF
consiste en ir generando valores que, al
cambiar con ellos determinadas propiedades, provoquen los efectos deseados. Para poder animar los valores de
una propiedad ésta debe ser una DependencyProperty, y para poder ubicar un
objeto visible en un entorno 3D se debe
utilizar la clase ModelVisual3D o una
heredera de ésta. Combinando estos
dos elementos, vamos a construir la
malla 3D para visualizar cada hoja y
poder animar sus propiedades. Estrictamente hablando, la clase ModelVisual3D no es un control, sino una clase
heredera de Visual3D, por lo que puede considerarse como pariente lejano
de los controles 2D a los que estamos
acostumbrados. Para poder usar un
objeto de este tipo en la interfaz de
usuario, será necesario incluirlo dentro
de un control Viewport3D, como se verá
en la última sección.
Binding binding = new
Binding(“Material”);
public class SimplePageModel3D : ModelVisual3D {
public SimplePageModel3D() {
GeometryModel3D geom3D = new GeometryModel3D();
this.Content = geom3D;
Binding binding = new Binding(“Material”);
binding.Source = this;
BindingOperations.SetBinding(geom3D,
GeometryModel3D.MaterialProperty, binding);
binding = new Binding(“BackMaterial”);
binding.Source = this;
BindingOperations.SetBinding(geom3D,
GeometryModel3D.BackMaterialProperty, binding);
BuildGeometry();
}
public static readonly DependencyProperty MaterialProperty =
DependencyProperty.Register( “Material”, typeof(Material),
typeof(SimplePageModel3D), new UIPropertyMetadata(null));
public Material Material {
get { return (Material)GetValue(MaterialProperty); }
set { SetValue(MaterialProperty, value); }
}
public static readonly DependencyProperty BackMaterialProperty =
DependencyProperty.Register(“BackMaterial”, typeof(Material),
typeof(SimplePageModel3D), new UIPropertyMetadata(null));
public Material BackMaterial {
get { return (Material)GetValue(BackMaterialProperty); }
set { SetValue(BackMaterialProperty, value); }
}
// demás propiedades para construir la malla de la página
...
}
Listado 1. Definición del constructor de SimplePageModel3D.
<< dnm.plataforma.net
Vector3D horizontal = new Vector3D(1, 0, 0);
Vector3D vertical = new Vector3D(0, -1, 0);
Vector3D upward = new Vector3D(0, 0, -1);
double textWidthSize = 1.0 / WidthSegments;
double textHeightSize = 1.0 / HeightSegments;
AffineTransform3D progressRot =
new RotateTransform3D(new AxisAngleRotation3D(vertical,
Progress*180));
for (int y = 0; y <= HeightSegments; y++)
{
double yRelative = (double)y / HeightSegments;
for (int x = 0; x <= WidthSegments; x++)
{
double xRelative = (double)x/WidthSegments;
Vector3D vector = new Vector3D(xRelative, yRelative, 0);
//apply twist
double twistAngle = xRelative*Twist*Math.PI/2;
int posSign = Math.Sign(yRelative - 0.5);
double modulus = Math.Sqrt((vector.Y-0.5)*
(vector.Y-0.5)+vector.Z*vector.Z);
vector.Y = posSign*modulus*Math.Cos(twistAngle) + 0.5;
vector.Z = posSign*modulus*Math.Sin(twistAngle);
//apply bend
vector.X = xRelative * Math.Sqrt(1 - Bend * Bend);
vector.Z += Math.Sin(xRelative*Math.PI)*Bend/2;
//apply progress
vector = progressRot.Transform(vector);
//find final vector
vector = horizontal*vector.X*Width + vertical*vector.Y*Height +
upward*vector.Z*Width;
mesh.Positions.Add((Point3D) vector);
mesh.TextureCoordinates.Add(new Point(x * textWidthSize,
y * textHeightSize));
}
}
for (int y = 0; y < HeightSegments; y++)
{
for (int x = 0; x < WidthSegments; x++)
{
int t0 = x + y * (WidthSegments + 1);
int t1 = t0 + 1;
int t2 = x + (y + 1) * (WidthSegments + 1);
int t3 = t2 + 1;
mesh.TriangleIndices.Add(t0);
mesh.TriangleIndices.Add(t2);
mesh.TriangleIndices.Add(t3);
mesh.TriangleIndices.Add(t3);
mesh.TriangleIndices.Add(t1);
mesh.TriangleIndices.Add(t0);
}
}
geom.Geometry = mesh;
}
...
Listado 2. Método de construcción de la malla de la página.
2
binding.Source = this;
BindingOperations.SetBinding(geom3D,
GeometryModel3D.MaterialProperty,
binding);
binding = new Binding(“BackMaterial”);
binding.Source = this;
BindingOperations.SetBinding(geom3D,
GeometryModel3D.BackMaterialProperty,
binding);
Se indica que se debe asociar el mismo material para la superficie del objeto
(Material) a través de la propiedad Material, y se asocia el mismo material para
la superficie interior (BackMaterial) a
través de la propiedad BackMaterial del
modelo. En nuestro caso usaremos ambos
materiales para revestir la cara de una hoja
de la revista y su reverso.
La propiedad Geometry de GeometryModel3D toma valor en el método BuildGeometry que se llama en la última línea
del constructor, y también al cambiar
cualquiera de las propiedades de la hoja
que afecta la forma de la malla. Este método BuildGeometry (listado 2) es el que se
encarga de construir una malla a partir
de los valores de las propiedades Progress,
Twist, Bend, Width, Height, WidthSegments
y HeightSegments para describir las dimensiones de la hoja y el grado de resolución
o de definición de la malla.
Este método crea una instancia de
MeshGeometry3D que se asocia a la propiedad Geometry del Content. Las propiedades Positions, TriangleIndices,
TextureIndices y Normals de esta instancia definen la malla de un objeto tridimensional. Cada una de estas propiedades contiene una colección de diferentes tipos. Una colección de Point3D
para Positions, una colección de Vector3D para Normals, una colección de int
para TriangleIndices y una colección
de Point para TextureIndices2.
Las posiciones se refieren a la ubicación en el espacio de los vértices de la
malla, tomando como referencia al punto (0, 0, 0) como el origen de coordenadas tridimensionales. Las propiedades
Width y Height determinan las coordenadas de las cuatro esquinas de la hoja, cuando ésta no tiene ninguna deformación
aplicada. Las propiedades WidthSegments
Por limitaciones de espacio, no pueden explicarse en detalles estas propiedades aquí. El lector puede referirse a un artículo previo de dotNetManía [4]
<<dotNetManía
...
private void BuildGeometry() {
GeometryModel3D geom = (GeometryModel3D) Content;
MeshGeometry3D mesh = new MeshGeometry3D();
35
<< dnm.plataforma.net
<<dotNetManía
y HeightSegments determinan las posiciones del resto de los vértices de la malla,
interpolando posiciones entre las cuatro
esquinas de la hoja. A mayores valores de
estas propiedades se crea una mayor cantidad de vértices, por lo que al deformar
la página se logra una superficie más uniforme. Sin embargo, un mayor número
de vértices puede afectar el rendimiento.
La sintonización adecuada de estos parámetros influye por tanto en el realismo
que tendrá el efecto de hojear, ya que al
aplicar una animación a la página, se pueden notar cambios bruscos si el número
de vértices es muy grande.
Luego de ubicar los vértices se debe
“tapizar” la malla con triángulos. La propiedad TriangleIndices contiene una
colección de índices de vértices. Estos
índices deben añadirse según los tríos de
vértices que forman un triángulo.
A su vez, la colección TextureCoordinates contiene una instancia de Point
por cada vértice de la malla, para indicar qué parte de la textura corresponde con cada vértice. Estas coordenadas
de textura se dan en dos dimensiones
porque son relativas al Material que se
usa para “pintar” el GeometryModel3D.
Este material se conforma a partir de
brochas 2D.
El método BuildGeometry realiza un
recorrido por los vértices de la malla que
se va a construir. Por cada uno de ellos
calcula su posición inicial, antes de aplicar ninguna deformación producida por
los parámetros de la página. Luego va
aplicando paso a paso el efecto de las
propiedades Twist, Bend y Progress para
después llevar los vértices a la escala indi-
36
Figura 6. Coordenadas de textura,
relativas a la imagen o material utilizado
para tapizar la malla.
cada por las propiedades Width y Height.
Por cada vértice calculado, a su vez se
calcula también la posición de la textura correspondiente al vértice, que no es
afectada por las deformaciones de los
parámetros. Las coordenadas de textura son relativas al rectángulo ubicado en
la posición (0, 0) y de dimensiones
(1.0, 1.0), de manera que la esquina
superior izquierda de la textura corresponde con la coordenada (0, 0) y la inferior derecha con la coordenada (1.0,
1.0), como muestra la figura 6.
Luego de calcular los vértices, se
declaran lo triángulos que conforman
la malla. Por cada cuatro vértices que
formen un pequeño rectángulo (que en
conjunto conforman toda la malla de la
página), se deben generar dos triángu-
Figura 7. Creación de triángulos a partir de los índices asociados
a los vértices de la malla
Estrictamente hablando, la clase ModelVisual3D
no es un control, sino una clase heredera de
Visual3D, por lo que puede considerarse como
pariente lejano de los controles 2D a los
que estamos acostumbrados
los, como se muestra en la figura 7. Los
índices t0, t1, t2, t3 utilizados en BuildGeometry representan cuatro de estos
vértices.
El orden de los tres índices que
determinan el triángulo es importante.
La cara del triángulo que muestra los
vértices en el sentido contrario a las
manecillas del reloj se asocia con el
material dado por la propiedad Material de la malla. La cara opuesta se asocia con BackMaterial. Es por ello que
t0, t2, t3 y t0, t3, t2 producen el mis-
mo triángulo, pero uno muestra a la
cámara un material diferente del otro,
según se observe el sentido de los vértices desde la cámara.
Pasando la página
Una vez que tenemos definida nuestra
clase personalizada SimplePageModel3D,
solo hay que usarla adecuadamente en
el XAML de una aplicación para dar el
efecto deseado. El listado 3 nos muestra un código XAML para animar la
página moviéndola hacia izquierda (en
contra de las manecillas del reloj) y
hacia derecha (a favor de las manecillas
del reloj). Las animaciones asociadas a
cada sentido describen un trayecto para
los tres parámetros dados por las propiedades Progress, Twist y Bend, de forma de lograr un efecto de hojear la página como el que se ilustra en las imágenes de la figura 5.
Para que las animaciones tengan
acceso desde los recursos al elemento
page3D en el Viewport3D, hay que registrar el control bajo dicho nombre. Para
ello, en el constructor de la clase TestPage3D se obtiene la instancia de INameScope de la página y se registra el control page3D con el identificador “page3D”,
como muestra el listado 4.
public TestPageBuilder() {
InitializeComponent();
INameScope scope =
NameScope.GetNameScope(this);
scope.RegisterName(“page3D”,
page3d);
}
Listado 4. Se debe registrar el objeto page3D
en el ámbito de nombres de la página para
que la animación tenga acceso al mismo.
Ejecute el código que se adjunta con
este artículo y utilice los dos botones
ubicados junto con la página, para pasar
hacia izquierda y derecha. Intente hojear la página hacia un lado, y a mitad de
camino cambiar de dirección hacia el
lado opuesto. Observe cómo la animación muestra en forma suave el movimiento de la página.
<Page x:Class=”Test3D.TestPage3D”
xmlns=”http://schemas.microsoft.com/winfx/2006/xaml/presentation”
xmlns:x=”http://schemas.microsoft.com/winfx/2006/xaml”
xmlns:c3d=”clr-namespace:Test3D”
Title=”TestPageBuilder”
>
<Page.Resources>
<Storyboard x:Key=”animLeft” SpeedRatio=”0.5”>
<DoubleAnimation Storyboard.TargetName=”page3D”
Storyboard.TargetProperty=”Progress”
To=”0” Duration=”0:0:1”/>
<DoubleAnimationUsingKeyFrames Storyboard.TargetName=”page3D”
Storyboard.TargetProperty=”Bend” Duration=”0:0:1”>
<LinearDoubleKeyFrame KeyTime=”0:0:0.1” Value=”0.0”/>
<LinearDoubleKeyFrame KeyTime=”0:0:0.4” Value=”0.4”/>
<LinearDoubleKeyFrame KeyTime=”0:0:0.8” Value=”0.4”/>
<LinearDoubleKeyFrame KeyTime=”0:0:1” Value=”0.0”/>
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames Storyboard.TargetName=”page3D”
Storyboard.TargetProperty=”Twist” Duration=”0:0:1”>
<LinearDoubleKeyFrame KeyTime=”0:0:0.3” Value=”0.3”/>
<LinearDoubleKeyFrame KeyTime=”0:0:0.8” Value=”0.3”/>
<LinearDoubleKeyFrame KeyTime=”0:0:1” Value=”0.0”/>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
<Storyboard x:Key=”animRight” SpeedRatio=”0.5”>
<DoubleAnimation Storyboard.TargetName=”page3D”
Storyboard.TargetProperty=”Progress”
To=”1” Duration=”0:0:1”/>
<DoubleAnimationUsingKeyFrames Storyboard.TargetName=”page3D”
Storyboard.TargetProperty=”Bend” Duration=”0:0:1”>
<LinearDoubleKeyFrame KeyTime=”0:0:0.1” Value=”0.0”/>
<LinearDoubleKeyFrame KeyTime=”0:0:0.4” Value=”-0.4”/>
<LinearDoubleKeyFrame KeyTime=”0:0:0.8” Value=”-0.4”/>
<LinearDoubleKeyFrame KeyTime=”0:0:1” Value=”0.0”/>
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames Storyboard.TargetName=”page3D”
Storyboard.TargetProperty=”Twist” Duration=”0:0:1”>
<LinearDoubleKeyFrame KeyTime=”0:0:0.3” Value=”-0.3”/>
<LinearDoubleKeyFrame KeyTime=”0:0:0.8” Value=”-0.3”/>
<LinearDoubleKeyFrame KeyTime=”0:0:1” Value=”0.0”/>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</Page.Resources>
<Page.Triggers>
<EventTrigger RoutedEvent=”Button.Click” SourceName=”passLeft”>
<EventTrigger.Actions>
<BeginStoryboard Storyboard=”{StaticResource animLeft}”/>
</EventTrigger.Actions>
</EventTrigger>
<EventTrigger RoutedEvent=”Button.Click” SourceName=”passRight”>
<EventTrigger.Actions>
<BeginStoryboard Storyboard=”{StaticResource animRight}”/>
</EventTrigger.Actions>
</EventTrigger>
</Page.Triggers>
<Grid Background=”Beige”>
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition Height=”Auto”/>
</Grid.RowDefinitions>
<Viewport3D>
<Viewport3D.Camera>
<PerspectiveCamera Position=”0,-2,-24” LookDirection=”0,0,1”
UpDirection=”0,1,0” FieldOfView=”20”
NearPlaneDistance=”0.1” FarPlaneDistance=”10000”>
</PerspectiveCamera>
</Viewport3D.Camera>
<ModelVisual3D>
<ModelVisual3D.Content>
<<dotNetManía
<< dnm.plataforma.net
37
<< dnm.plataforma.net
<<dotNetManía
Conclusiones
38
<Model3DGroup>
<AmbientLight Color=”DarkGray”/>
<DirectionalLight Color=”LightGray” Direction=”-50,-60,100”/>
<GeometryModel3D>
<GeometryModel3D.Geometry>
<MeshGeometry3D Positions=”0 0 0 -3 0 0 -3 -4 0 0 -4 0”
TriangleIndices=”0 2 1 0 3 2”
TextureCoordinates=”0 0 1 0 1 1 0 1”
/>
</GeometryModel3D.Geometry>
<GeometryModel3D.Material>
<MaterialGroup>
<DiffuseMaterial>
<DiffuseMaterial.Brush>
<ImageBrush ImageSource=”/images/page_Page_03.jpg”>
<ImageBrush.RelativeTransform>
<ScaleTransform ScaleX=”1” CenterX=”0.5”/>
</ImageBrush.RelativeTransform>
</ImageBrush>
</DiffuseMaterial.Brush>
</DiffuseMaterial>
<SpecularMaterial Brush=”#80808080” SpecularPower=”85”/>
</MaterialGroup>
</GeometryModel3D.Material>
</GeometryModel3D>
</Model3DGroup>
</ModelVisual3D.Content>
<c3d:SimplePageModel3D x:Name=”page3d” Width=”3” Height=”4”>
<c3d:SimplePageModel3D.Material>
<MaterialGroup>
<DiffuseMaterial>
<DiffuseMaterial.Brush>
<ImageBrush ImageSource=”/images/page_Page_01.jpg”/>
</DiffuseMaterial.Brush>
</DiffuseMaterial>
<SpecularMaterial Brush=”#80808080” SpecularPower=”100”/>
</MaterialGroup>
</c3d:SimplePageModel3D.Material>
<c3d:SimplePageModel3D.BackMaterial>
<MaterialGroup>
<DiffuseMaterial>
<DiffuseMaterial.Brush>
<ImageBrush ImageSource=”/images/page_Page_02.jpg”>
<ImageBrush.RelativeTransform>
<ScaleTransform ScaleX=”-1” CenterX=”0.5”/>
</ImageBrush.RelativeTransform>
</ImageBrush>
</DiffuseMaterial.Brush>
</DiffuseMaterial>
<SpecularMaterial Brush=”#80808080” SpecularPower=”100”/>
</MaterialGroup>
</c3d:SimplePageModel3D.BackMaterial>
</c3d:SimplePageModel3D>
</ModelVisual3D>
</Viewport3D>
<Grid Grid.Row=”1” DataContext=”{Binding ElementName=page3d}”>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Button Grid.Column=”0” Name=”passLeft”
HorizontalAlignment=”Center”>Pass To Left</Button>
<Button Grid.Column=”1” Name=”passRight”
HorizontalAlignment=”Center”>Pass To Right</Button>
</Grid>
</Grid>
</Page>
Listado 3. Código XAML para animar hacia la izquierda y derecha la página de la revista.
Las capacidades de gráficos 3D que nos
ofrece WPF se llevan la palma cuando
se trata de dotar de mayor realismo a la
interfaz de usuario de una aplicación.
Esto debe estimular y ayudar a familiarizarse con más facilidad con el concepto que la aplicación quiere mostrar.
La novedad con WPF no está solo en
permitir representar elementos 3D,
como nuestro SimplePageModel3D, con
más facilidad que si se usa directamente OpenGL o DirectX. El mayor atractivo viene dado por la fácil integración
de estas capacidades con el mundo de
los controles 2D y con la lógica del
negocio de nuestras aplicaciones; por
ejemplo, las páginas a hojear pueden ser
el resultado de una búsqueda (todo lo
sofisticada que la lógica de la aplicación
pretenda).
Anímese a poner algo de 3D en su
aplicación de negocio: es solo cuestión
de inspirarse en la realidad y abstraerse un poco (o mucho, eso depende), y
claro, a veces atreverse a pasar un rato
con las matemáticas. Sus usuarios lo
apreciarán.
Es imposible explicar todos los detalles en el limitado espacio del que disponemos para este artículo. Descárguese el
código desde la página Web de dotNetManía y experimente con él.
Referencias
[ 1 ] Katrib, Miguel, Del Valle, Mario,
Sierra, Iskander y Hernández, Yamil
“Windows Presentation Foundation”.
Cuaderno Técnico Nº 7, dotNetManía,
2007.
[ 2 ] Blanco, Luis M “Estilos en XAML”,
en dotNetManía Nº 27, junio de 2006.
[ 3 ] Sierra, Iskander, Hernández, Yamil,
Del Valle, Mario y Katrib, Miguel
“Cómo definir nuestros propios paneles personalizados en WPF”, en dotNetManía Nº 35, febrero de 2007.
[ 4 ] Sierra, Iskander, Hernández, Yamil,
Del Valle, Mario y Katrib, Miguel
“Entrando en la tercera dimensión”, en
dotNetManía Nº 37, abril de 2007.
<< dnm.servidores.sql
SQL Server
Miguel Egea
Arquitecturas distribuidas
con Service Broker
En este artículo se describe de manera práctica la utilización de la tecnología Service Broker de SQL Server 2005 para implementar arquitecturas distribuidas.
mundo en que nos movemos, los nuevos bucaneros
surcan los mares digitales buscando carabelas que
abordar para usar esa información en su propio provecho. Nuestros mensajes han de ser auténticos fortines inexpugnables, incluso si uno de estos bucaneros entra en nuestro mar.
Service Broker como mecanismo
de comunicación y asincronía
El servicio Service Broker provee comunicaciones asíncronas basadas en el intercambio de mensajes. Más allá
de eso, es capaz de dotarnos de un sistema de conversación muy complejo de implementar en los sistemas
de asincronía tradicionales (como MSMQ o MQ
Series). Además, permite la encriptación sencilla de
las comunicaciones en base a certificados y también el
envío de todo tipo de mensajes, ya sean binarios o
XML, como en cualquier otro sistema de colas.
Adicionalmente, Service Broker provee de forwarding, es decir, enrutado de mensajes. Esta funcionalidad es especialmente útil para arquitecturas
en las que el envío de mensajes debe atravesar routers o firewalls. También es la herramienta indicada
cuando no se quiere exponer el servicio SQL principal a Internet, ni siquiera abriendo el puerto que
se haya elegido para las comunicaciones de Service
Broker (que no es el mismo que el puerto SQL).
Por todas estas razones, Service Broker nos proporciona una arquitectura robusta y escalable, muy adecuada para resolver el tipo de problemas que se nos
están planteando en las arquitecturas distribuidas.
<<dotNetManía
Miguel Egea
es un Mentor Asociado de Solid Quality
Learning Iberoamericana, Ingeniero Técnico en Informática de
Sistemas con más de
16 años de experiencia. MVP en SQL Server, ejerce como DBA
para importantes
empresas del Sector.
Miguel es, además,
ponente asiduo en
eventos relacionadas
con tecnologías
Microsoft.
Cada vez más, en el mundo de la tecnología las
aplicaciones distribuidas están al orden del día. Las
mejoras y abaratamiento de costes en las comunicaciones, el avance en las herramientas de programación, la introducción de conceptos como los servicios Web y las arquitecturas orientadas a servicios
no han hecho sino acelerar el uso (y disfrute en algunas ocasiones) de este tipo de instalaciones.
Muchas veces las comunicaciones son entre
máquinas; sin embargo, el concepto de conversación
como tal siempre ha resultado difícil de implementar. Sin entrar en detalles, MSMQ, por ejemplo, permite enviar mensajes de forma asíncrona, garantizando que el mensaje será entregado. MSMQ, sin
embargo, no puede garantizar el orden de entrega;
además, esperar una respuesta puede ser una tarea
compleja de realizar.
Más aún, entendemos que una conversación es algo
más que un mensaje entregado de forma asíncrona; es
la garantía de que ese mensaje se ha entregado (una
vez y solo una vez), y que podemos recibir respuestas
en orden para cada petición. De esta manera, podrían
implementarse de forma asíncrona conversaciones
entre servidores, permitiéndoles intercambiar mensajes complejos. La entrega quedaría garantizada, y
además podrían devolver información que puede resultar muy útil; en definitiva, los sistemas podrían establecer conversaciones completas.
La seguridad también es un factor cada vez más
importante a tener en cuenta. Desde siempre la información ha sido poder, y la capacidad de usurpar esa
información es una amenaza evidente. En este ciber-
39
<< dnm.servidores.sql
A partir de este momento, este artículo es puramente técnico, con numerosos ejemplos de código
y justificaciones para cada uno de los elementos de
código que se introducen. Creemos que este debe
ser su objetivo primario: servir de ayuda a los técnicos a implementar la arquitectura de Service Broker
de manera eficaz y satisfactoria.
Mensajes, contratos y colas
<<dotNetManía
Una vez que entramos en un mundo de intercambio de mensajes, la primera acción será determinar
cuál o cuáles son los tipos de mensajes que van a
intervenir en nuestra conversación; es decir, debemos establecer nuestra gramática, el modo en que
nuestros servicios se van a entender. Los tipos de
mensaje que se intercambian han de estar definidos. Existen dos tipos predeterminados, NONE y
WELL_FORMED_XML. Como sus nombres indican, NONE
no realizará ningún tipo de validación sobre los
mensajes de ese tipo, mientras que WELL_FORMED_XML
comprobará que el mensaje intercambiado es un
XML bien formado. Además de los dos tipos anteriores, el tipo de mensaje puede cumplir con las
restricciones de cualquier esquema XSD que definamos en nuestro sistema mediante la instrucción
CREATE XML SCHEMA COLLECTION). Ver listado 1.
Mediante el esquema MiEsquemaEnvio definimos
un esquema sencillo, en el que se enviará un ID de
40
CREATE XML SCHEMA COLLECTION MiEsquemaEnvio AS
N’<schema xmlns=”http://www.w3.org/2001/XMLSchema” >
<element name=”Clientes”>
<complexType>
<sequence>
<element name=”idCliente” type=”int” />
<element name=”Nombre” type=”string”/>
</sequence>
</complexType>
</element>
</schema>
‘
CREATE XML SCHEMA COLLECTION MiEsquemaRecepcion AS
N’<schema xmlns=”http://www.w3.org/2001/XMLSchema” >
<element name=”Clientes”>
<complexType>
<sequence>
<element name=”idCliente” type=”int” />
<element name=”CreditoConcedido” type=”decimal”/>
</sequence>
</complexType>
</element>
</schema>
‘
Listado 1
cliente y un nombre; para el esquema de recepción
utilizamos un esquema muy similar, que permitirá
devolver el ID de cliente y un crédito máximo concedido.
Seguidamente usaremos las siguientes instrucciones para crear el tipo de mensaje que se va a intercambiar:
CREATE MESSAGE TYPE [Envio]
VALIDATION=VALID_XML WITH SCHEMA COLLECTION
MiEsquemaEnvio;
CREATE MESSAGE TYPE [Recepcion]
VALIDATION=VALID_XML WITH SCHEMA COLLECTION
MiEsquemaRecepcion;
Una vez determinados los tipos de mensajes que
van a ser intercambiados, la siguiente acción será
crear un contrato que especifique cómo van a ser
intercambiados estos mensajes; es decir, que diga
quién envía el mensaje, quién lo recibe y qué respuesta puede enviar cada uno de ellos. Para conseguir este objetivo se utiliza la instrucción CREATE
CONTRACT , que nos servirá para definir ese intercambio y cómo se produce:
CREATE CONTRACT [ContratoIntercambio]
([Envio] SENT BY INITIATOR,
[Recepcion] SENT BY TARGET)
Ahora crearemos una cola para recibir mensajes.
Después tendremos que crear un servicio que defina la forma en que pueden llegar mensajes a esas
colas. Yendo por partes, primero crearemos la cola,
especificando en sus parámetros que la cola está lista para recibir mensajes:
CREATE QUEUE Peticion WITH STATUS=ON;
CREATE QUEUE PideRespuesta WITH STATUS=ON;
Esta operación ha de ser realizada en todos los servidores que vayan a recibir o enviar mensajes basados
en esta conversación. Service Broker no realiza ningún
tipo de sincronización sobre tipos de mensaje y contratos, sino que en el momento de la configuración
somos nosotros los que lanzamos estas definiciones
en tantos servidores como sea necesario. Aunque en
cada rol de servidor solamente crearíamos las colas
que necesite cada uno; es decir, el que va a iniciar la
conversación solamente recibirá una respuesta, así que
<< dnm.servidores.sql
Servicios
Realmente la comunicación entre distintas instancias de Service Broker es a través
de los servicios. Los servicios no hacen
otra cosa que definir, para una cola, qué
contrato o contratos son aceptables. Después, cuando se envían mensajes, en el
inicio de la conversación se expresará el
servicio de origen y el servicio de destino; de esta forma, un mensaje acaba en
una cola a través de un servicio siempre
y cuando cumpla con el contrato que
acepta el servicio. En nuestro ejemplo la
sintaxis podría quedar algo así:
CREATE SERVICE SrvPeticion ON QUEUE
[Peticion] (PeticionCredito);
CREATE SERVICE SrvRespuesta ON QUEUE
[PideRespuesta] ( PeticionCredito);
Es posible incluir más de un contrato distinto con distintos esquemas
XML que puedan enviar mensajes sobre
la misma cola. Cada caso de negocio,
cada necesidad, determinará si han de
ser especificados solamente uno o más
de un contrato en el momento de la creación del servicio.
Enviando el primer mensaje
Solamente con esta configuración ya
podríamos enviar mensajes a la cola;
vamos a ver código que lo refleja. Puesto que es necesario tener claro si el código está en el emisor o en el receptor, es
decir, en el que inicia la conversación o
en el destino, vamos a separar en distintos apartados cada una de las partes
del script.
El que envía
La primera parte del código está ejecutándose del lado del que envía un
DECLARE @Cliente xml(MiEsquemaEnvio)
DECLARE @message_type_name NVARCHAR(256)
DECLARE @conversationhandle UNIQUEIDENTIFIER
DECLARE @Conversacion TABLE(
service_instance_id UNIQUEIDENTIFIER,
handle UNIQUEIDENTIFIER,
message_sequence_number BIGINT,
service_name NVARCHAR(512),
service_contract_name NVARCHAR(256),
message_type_name NVARCHAR(256),
validation NCHAR,
message_body VARBINARY(MAX)) ;
Set @cliente=CAST(N’<Clientes>
<idCliente>10</idCliente>
<Nombre>Miguel Egea (Petición 1)</Nombre>
</Clientes>’ as xml(MiEsquemaEnvio))
Listado 2
mensaje. Las fórmulas “dispara y olvida” (fire & forget) no son nada recomendadas en Service Broker; en general, no son nada recomendables en
ningún sistema de asincronía por múltiples razones, así que no caeremos en
la tentación de poner un “hola mundo”
en ese estilo. Vamos a estudiar el código pasito a pasito.
Vea primero la declaración de algunas variables que necesitaremos y cuál
es su misión en el listado 2.
• La primera variable va a contener un
solo elemento cliente. Aunque la instrucción RECEIVE (que veremos enseguida) recibe conjuntos de registros
y no elementos individuales, haremos
una excepción (esta vez sí) para hacer
un tratamiento registro a registro.
• La segunda variable nos servirá para
determinar qué tipo de mensajes nos
están llegando. Si por ejemplo enviamos un mensaje erróneo al destino,
éste nos devolverá un mensaje de
error en la cola de origen, y este error
habrá que tenerlo previsto. También
pueden recibirse mensajes de tipo fin
de conversación, etc.
• La variable @conversationhandle nos
servirá para saber dentro de qué conversación estamos enviando mensajes. Con ese handle identificamos de
forma única la conversación, tanto
para el que inicia la conversación
como para el que contesta. De esta
forma evitamos que pudieran mezclarse preguntas y respuestas.
• La tabla @conversacion tiene un
esquema con los valores que es capaz
de devolver la función RECEIVE y la
usaremos precisamente para eso, para
recibir valores de esa conversación.
Vamos ahora a enviar un mensaje;
lo haremos creando primero una conversación y luego hablando dentro de
ella:
BEGIN TRANSACTION
BEGIN DIALOG @conversationhandle
FROM SERVICE SrvPeticion
TO SERVICE ‘SrvRespuesta’
ON CONTRACT PeticionCredito
WITH ENCRYPTION=OFF;
SEND ON CONVERSATION @conversationhandle
MESSAGE TYPE Envio (@cliente)
COMMIT
Si analizamos el código, podemos
ver que es bastante sencillo. Estamos
abriendo un diálogo que va desde el servicio que pide hasta el servicio que responde (está entre comillas porque el servicio podría ser remoto y por tanto no
hay forma de comprobar que existe) bajo
la llave del contrato PeticionCredito.
Una vez que existe la conversación, simplemente enviamos un mensaje de tipo
<<dotNetManía
solo necesita la cola de respuesta, y el que
va a responder solo necesita que le pidan,
y por tanto solo necesita la cola de petición. Al principio cuesta un poco entender este galimatías, pero después se ve
bastante bien.
41
<< dnm.servidores.sql
petición, que en nuestro caso solamente tiene un identificador de cliente y un
nombre de cliente.
Una vez que el mensaje llegue al destino, un servicio calculará el crédito a
conceder, y responderá con un nuevo
mensaje dentro de la misma conversación diciendo el crédito que se ha concedido. Veamos cómo sería esta segunda conexión.
SET @SaldoCliente= CAST(N’<Clientes>
<idCliente>’ + CAST(@id AS NVARCHAR(10))
+’</idCliente>
<CreditoConcedido>1000.36</CreditoConcedido>
</Clientes>’ as xml(MiEsquemaRecepcion));
SEND ON CONVERSATION @conversationhandle
MESSAGE TYPE Recepcion(@SaldoCliente)
END CONVERSATION @conversationHandle;
Listado 3
El que recibe
El código que tenemos a continuación se pone a esperar de forma indefinida a que llegue un mensaje a la cola
PideRespuesta:
BEGIN TRANSACTION
WAITFOR
(
RECEIVE TOP (1)
conversation_group_id,
conversation_handle,
message_sequence_number,
service_name,
service_contract_name,
message_type_name,
validation,
message_body
FROM PideRespuesta
INTO @Conversacion
);
SELECT @conversationhandle=handle,
@cliente=message_body
FROM @Conversacion
COMMIT
WHILE (1=1)
BEGIN
BEGIN TRANSACTION
WAITFOR
(
RECEIVE TOP(1)
conversation_group_id,
conversation_handle,
message_sequence_number,
service_name,
service_contract_name,
message_type_name,
validation,
message_body
FROM Peticion
INTO @Conversacion
WHERE conversation_handle = @ConversationHandle
);
SELECT CAST(Message_body as XML) FROM @CONVERSACION
COMMIT
SELECT @message_type_name=message_type_name FROM @CONVERSACION
IF @message_type_name =
‘http://schemas.microsoft.com/SQL/ServiceBroker/EndDialog’
OR @message_type_name =
‘http://schemas.microsoft.com/SQL/ServiceBroker/Error’
BEGIN
select ‘acabo’
END CONVERSATION @ConversationHandle ;
BREAK;
END
END
<<dotNetManía
Listado 4
42
Una vez que este código se haya ejecutado, lo que tendríamos es un registro en la tabla @conversacion con la petición, que ahora habría que procesar. El
código que procesa la petición debería
incorporar lógica de negocio; en nuestro caso, siempre vamos a devolver el
mismo crédito, sin mirar nada. Ver listado 3.
Es muy importante que no solo se
envía una respuesta, sino que además se
acaba la conversación mediante la instrucción END CONVERSATION. Si no fuese
así, Service Broker pensaría que en esta
conversación pueden ser enviados más
mensajes y mantendría registros de control en la vista del sistema sys.conversa-
tion_endpoints. El ámbito que se crea
entre un BEGIN DIALOG y su correspondiente END CONVERSATION puede admitir
el listado 4 se encarga de todas esas
tareas.
tantos mensajes como necesite nuestro
proceso de negocio; no está limitado ni
obligado a ningún número de mensajes
específico.
Conclusión
Procesando la respuesta
Finalmente, solo nos queda procesar la respuesta. Procesarla adecuadamente implica recibir la contestación,
hacer lo que sea necesario con ella y
acabar la conversación del lado del que
la inició. El código que se presenta en
En este artículo hemos hecho una introducción a cómo Service Broker trata los
mensajes y cómo nos permite implementar conversaciones asíncronas. Service Broker es mucho más que esto: permite arquitecturas en balanceo de carga,
forwarding de mensajes y un buen
montón de funcionalidades que no da
tiempo a tratar en un artículo introductorio; tiempo habrá para ir profundizando en estas funcionalidades.
<< dnm.inicio.taller
taller
Guillermo «Guille» Som
Serialización XML
El serializador que lo serialice... debe saber XML
En el artículo anterior vimos cómo “persistir” los objetos usando las clases
que utilizan IFormatter. En aquella ocasión tuvimos la oportunidad de ver
cómo definir los tipos que queríamos serializar por medio del atributo Serializable y la interfaz ISerializable. En este artículo veremos otra forma de serializar nuestros objetos, que utiliza XML puro como formato.
Guillermo “Guille”
Som es Microsoft MVP
de Visual Basic desde
1997. Es redactor de
dotNetManía, mentor
de Solid Quality Iberoamericana, tutor de campusMVP, miembro de
Ineta Speakers Bureau
Latin America, y autor
de los libros “Manual
Imprescindible de Visual
Basic .NET” y “Visual
Basic 2005”.
http://www.elguille.info
La serialización XML nos permite serializar las propiedades y campos públicos de los tipos, y aunque pueda parecer que tiene menos “potencia” que la serialización binaria, ya que ésta última nos permite serializar el objeto completo, seguramente será la que más
utilicemos, principalmente por el hecho de que está
basada en el estándar XML, lo que nos permite el intercambio de datos entre diferentes plataformas. Utilizando este tipo de serialización, no tendremos límites
a la hora de distribuir nuestros objetos, ya que XML
es un estándar, y por tanto cualquier lenguaje o plataforma que hable ese estándar nos comprenderá.
La clase principal para la serialización XML es
XmlSerializer (definida en el espacio de nombres System.Xml.Serialization), y para realizar las operaciones de serialización y deserialización se usan los métodos Serialize y Deserialize. Como vemos, esto es
parecido a lo que vimos en el artículo anterior, pero
la diferencia principal es que esta clase no requiere
que las clases estén marcadas con el atributo Serializable; los únicos requisitos de las clases a serializar
es que sean públicas, tengan un constructor público
sin parámetros y, por supuesto, que tengan elementos públicos que se puedan almacenar en un fichero.
La forma más simple de usar esta clase es indicando en el constructor el tipo que queremos serializar, y las operaciones de serialización se realizarán
en un fichero cuyo formato será XML. Accederemos
a ese fichero por medio de clases de tipo Stream. Por
ejemplo, si tenemos una clase llamada Colega2, pode-
mos usar el código mostrado en el listado 1 para realizar la serialización y posterior deserialización.
static void serializarXML()
{
Colega2 c = new Colega2(“Guille”,
“guille@nombres.com”);
XmlSerializer xs = new XmlSerializer(
typeof(Colega2));
StreamWriter sw = new StreamWriter(fic1, false,
Encoding.UTF8);
xs.Serialize(sw, c);
sw.Close();
}
static void deserializarXML()
{
Colega2 c = null;
XmlSerializer xs = new
XmlSerializer(typeof(Colega2));
StreamReader sr = new StreamReader(fic1,
Encoding.UTF8, true);
c = (Colega2)xs.Deserialize(sr);
sr.Close();
Console.WriteLine(“Los datos del colega: {0}”,c);
}
Listado 1.
Proceso de serialización con la clase XmlSerializer
El fichero resultante al realizar las operaciones
del código del listado 1 se muestra en el listado 2.
<<dotNetManía
Serialización XML
43
<< dnm.inicio.taller
<?xml version=”1.0” encoding=”utf-8”?>
<Colega2 xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance”
xmlns:xsd=”http://www.w3.org/2001/XMLSchema”>
<Nombre>Guille</Nombre>
<Email>guille@nombres.com</Email>
</Colega2>
Listado 2. Resultado obtenido con el código del listado 1
Requisitos de los tipos a usar
con XmlSerializer
Tal como comenté antes, las clases que podemos serializar por medio de XmlSerializer no están “obligadas”
a usar atributos especiales, pero sí deben tener ciertas características, como un constructor público sin
parámetros. Este detalle solo debe preocuparnos si
hemos definido en la clase algún constructor con parámetros, ya que el único caso en el que es el propio
compilador el que genera ese constructor predeterminado (sin parámetros) es cuando nosotros no definimos ninguno; por tanto, debemos asegurarnos de
que la clase tiene un constructor público y sin parámetros. Además, la clase debe estar definida como
pública. En el código del listado 3 tenemos la definición de la clase Colega2 que hemos usado en el ejemplo anterior, en la que además del constructor sin
parámetros también se ha definido otro que recibe
dos parámetros.
public class Colega2
{
public string Nombre;
public string Email;
Si la clase que definimos es de tipo colección, es
decir, implementa la interfaz IEnumerable o ICollection , también debe cumplir otros requisitos
además de los antes comentados. Uno de ellos es
que si nuestra clase implementa IEnumerable (o ICollection, ya que ICollection implementa IEnumerable) debe implementar un método Add que sea público y que reciba un único parámetro del mismo tipo
que el devuelto por el método GetEnumerator, que
en realidad será (o deberá ser) el tipo de datos que
la colección va a mantener. Por ejemplo, si vamos a
crear una clase que sea una colección del tipo Colega2 mostrado en el listado 3, el parámetro del método Add debe ser de ese tipo o de cualquier clase en
la que éste se base. En nuestro ejemplo, el tipo Colega2 no se deriva explícitamente de ningún otro; pero
al igual que todas las clases de .NET, desciende de
Object, y por tanto el parámetro del método Add puede ser Object o Colega2.
Debemos asegurarnos de que
la clase a serializar tiene un
constructor público y sin
parámetros.Además, la clase
debe estar definida como pública
public Colega2()
{}
public Colega2(string nombre, string email)
{
this.Nombre = nombre;
this.Email = email;
}
public override string ToString()
{
return Nombre + “, “ + Email;
}
<<dotNetManía
}
44
Listado 3. Definición de la clase Colega2
Si nuestra clase implementa la interfaz ICollection (o se deriva de cualquier clase que la implemente), debe además tener un indizador (propiedad
predeterminada en Visual Basic) que reciba un parámetro de tipo entero y devuelva el mismo tipo que
el usado en el método Add. Además, debe definir la
propiedad Count (aunque esto último es por “exigencias” de la propia interfaz); esa propiedad puede ser pública o estar implementada explícitamente, aunque es mejor definirla como pública, ya que
Count es algo que todo el mundo espera encontrar
en una colección.
Cuando se va a serializar el objeto, se comprueba
por medio de Count el número de elementos que tiene y para obtener cada uno de los elementos de la
<< dnm.inicio.taller
public class Colegas2 :ICollection
{
List<Colega2> col = new List<Colega2>();
public Colegas2()
{}
public void Add(Colega2 unColega)
{
col.Add(unColega);
}
public Colega2 this[int index]
{
get
{
return col[index];
}
}
// (el que define ICollection)
public int Count
{
get
{
return col.Count;
}
}
// (el que define IEnumerable)
public IEnumerator GetEnumerator()
{
return col.GetEnumerator();
}
// El resto solo por exigencias
// de la interfaz
#region Resto de métodos de ICollection
...
#endregion
}
Listado 4.
Clase de tipo colección de Colega2
La forma de serializar la colección
Colegas2 es como vimos en el listado 1,
pero usando Colegas2 en lugar de Colega2 como tipo de datos (elemental, que-
rido Guille). El resultado obtenido al
<?xml version=”1.0” encoding=”utf-8”?>
<ArrayOfColega2 xmlns:xsi=”...”
xmlns:xsd=”...”>
<Colega2>
<Nombre>Pepe</Nombre>
<Email>pepe@nombres.com</Email>
</Colega2>
<Colega2>
<Nombre>Guille</Nombre>
<Email>guille@nombres.com</Email>
</Colega2>
</ArrayOfColega2>
Listado 5. Resultado al serializar un objeto
Colegas2 con dos elementos
serializar esa clase será parecido al código XML mostrado en el listado 5.
XmlSerializer no puede serializar
directamente colecciones de los tipos
ArrayList o List<T>; lo que sí podemos
hacer es usar internamente esos tipos,
aunque en ese caso, el tipo expuesto por
nuestra clase debe ser alguno que esa
clase pueda serializar. En el código que
acompaña al artículo hay un ejemplo
parecido al usado en el código del listado 5, en el que internamente se usa un
array de tipo List<Colega2>. Otro tipo
de datos común que tampoco podrá
serializar esta clase son las colecciones
de tipo diccionario, ya sean normales o
genéricas; en general, cualquier clase
que implemente IDictionary no se puede serializar con esta clase.
Aplicar atributos para
controlar el XML generado
al serializar
Cuando usamos la clase XmlSerializer para guardar en un fichero el contenido de un objeto, el formato de ese
fichero es XML. Esto ya quedó claro
desde el principio, y debido a que,
entre otras cosas por falta de espacio,
no vamos a hablar en este artículo de
qué es XML, al menos debemos tener
ciertas nociones sobre el formato usado, ya que eso nos permitirá tener
mayor control sobre el fichero resultante al serializar un objeto.
Por ejemplo, si vemos el listado 2 o
el listado 5, comprobaremos que los
datos se guardan como elementos, y
siempre debe haber un elemento raíz.
En el caso del listado 5, el elemento raíz
es <ArrayOfColega2>. Ese elemento raíz
contiene el resto de elementos; siguiendo con el mismo ejemplo, hay dos elementos contenidos en el raíz ( <Colega2>). Esos elementos, a su vez, contienen otros elementos para cada uno de
los datos a serializar. De forma predeterminada, la clase XmlSerializer crea
“elementos” de cada clase que serializa,
y también crea elementos para cada
miembro público (campo o propiedad)
que la clase defina. Los nombres usados
(salvo en el caso de los arrays o colecciones) son los nombres que nosotros
hemos definido en la clase.
Mediante atributos podemos cambiar la forma predeterminada de actuar.
Por ejemplo, podemos indicar que ciertos campos o propiedades no se serialicen o que en lugar de utilizar un elemento XML para un cierto miembro de
la clase se cree un atributo. También
podemos indicar qué nombre queremos
que se utilice y algunas otras cosas más;
empecemos por las más importantes.
Para no tener en cuenta un campo
o propiedad, usaremos el atributo XmlIgnore aplicado a dicho campo o propiedad. Por ejemplo, si añadimos a la clase Colega2 un campo para la Fecha, podemos evitar que se serialice definiéndolo de esta forma:
[XmlIgnore]
public DateTime Fecha;
Si queremos usar un nombre distinto para un elemento (para que no se use
el mismo nombre del campo o propiedad), usaremos el atributo XmlElement
indicando en la propiedad ElementName
el nombre que queremos usar o bien
indicando el nombre directamente, ya
<<dotNetManía
colección se usa el indizador. A la hora
de deserializar el objeto, se obtienen los
elementos de la colección por medio de
GetEnumerator.
En el listado 4 tenemos la definición
de una clase que implementa ICollection y que mantendrá una colección del
tipo Colega2. Como vemos, y por razones de rendimiento, internamente utiliza una colección genérica de tipo
List<Colega2>.
45
<< dnm.inicio.taller
que otro de los constructores de este atributo admite una cadena para el nombre
a asignar. Por ejemplo, si queremos que
el campo Email se serialice como Correo,
usaremos el siguiente código:
[XmlElement(ElementName=”Correo”)]
public string Email;
Y si en lugar de crear un elemento,
queremos que se almacene como un atributo (los atributos se guardan dentro del
elemento que contiene la clase a almacenar), debemos aplicar el atributo XmlAttribute. Por ejemplo, para que el campo
Nombre de la clase Colega2 se guarde como
un atributo, haremos lo siguiente:
[XmlAttribute]
public string Nombre;
También podemos aplicar el atributo XmlRoot a la definición de la clase para,
por ejemplo, usar un nombre diferente. Con el siguiente código, la clase Colega2 se guardará como MiColega:
[XmlRoot(“MiColega”)]
public class Colega2
{
// ...
Por supuesto, aunque cambiemos la
forma en que se almacenará la clase, el
tipo sigue siendo el mismo.
Haciendo estos cambios a nuestra
clase y usando el mismo código del listado 1, el fichero resultante sería como
el mostrado en el listado 6, en el que
debemos notar que ahora el campo
Email se almacena como Correo y que el
campo Nombre se guarda como un atributo del elemento que define la clase,
que al haberle cambiado el nombre será
<MiColega>.
<<dotNetManía
<?xml version=”1.0” encoding=”utf8”?>
<MiColega xmlns:xsi=”...”
xmlns:xsd=”...” Nombre=”Guille”>
46
<Correo>guille@nombres.com</Correo>
</MiColega>
Listado 6. El objeto serializado con los
cambios de los atributos
Además de cambiar el nombre o si se
almacenará como elemento o atributo,
podemos indicar el tipo de datos con el que
queremos que cada dato se serialice
Como podemos imaginar, el atributo XmlAttribute también permite que
cambiemos el nombre con el que queremos que se guarde el campo o propiedad en el que lo aplicamos.
Además de cambiar el nombre o si
se almacenará como elemento o como
atributo, por medio de XmlAttribute y
XmlElement podemos indicar el tipo de
datos con el que queremos que se guarde en el fichero XML. Esto nos será de
utilidad si queremos que uno de nuestros campos (o propiedades) se exporten como otro tipo de datos que no defina el propio .NET, pero que sí esté definido por el consorcio W3C. Estas asignaciones las haremos por medio de la
propiedad DataType de los dos atributos
mencionados, y el valor que asignemos
a esa propiedad debe coincidir exactamente con el definido por el W3C
(recordemos además que XML es un
lenguaje que distingue las mayúsculas
de las minúsculas). Por ejemplo, si en la
clase Colega2 queremos añadir un campo que se exporte como si fuese del tipo
token, tendríamos que definirlo de la
siguiente forma:
[XmlElement(DataType = “token”)]
public string ID;
Aunque en el fichero resultante no
veremos nada que indique el tipo, y de
hecho se guardará como cualquier otro
valor. Y es que en realidad ese tipo de
datos que indicamos servirá para el tipo
de datos generado como un esquema
XSD (XML Schema Definition, definición de esquema XML).
Crear esquemas
con la utilidad xsd.exe
Si los datos que queremos manejar no
son totalmente compatibles con .NET
o queremos que los datos que hemos
serializado se utilicen desde otras plataformas, será conveniente que esos datos
se ciñan a ciertas características o que
exportemos el esquema usado para serializar nuestras clases.
La utilidad Xsd.exe, que se incluye
con el SDK de .NET, nos permite crear esquemas XSD a partir de ensamblados (DLL o EXE), crear clases a
partir de esquemas XSD e incluso crear esquemas a partir de un fichero
XML que contiene los datos de un
objeto serializado. Esta utilidad la usaremos desde la línea de comandos, y
como primer argumento suministraremos el fichero que queremos procesar. Opcionalmente, podemos indicar
el nombre del fichero de salida y algunas opciones adicionales para cambiar
el comportamiento predeterminado,
que es el de crear esquemas XSD a partir del fichero que indiquemos en el
primer argumento, al menos si ese
fichero tiene extensión .DLL , .EXE o
.XML; de ser así, se generará el esquema XSD, un fichero con la extensión
.XSD. Si procesamos un fichero XML,
el nombre que se le dará al esquema
<< dnm.inicio.taller
xsd Colega03.xml
Los tipos de datos XML que la utilidad usará serán los que “crea” que
son los adecuados. Por ejemplo, el tipo
ID lo hemos indicado como tipo token,
pero como en el fichero .XML no se
indica de que tipo será, la utilidad
XSD lo exportará como de tipo
string . En el listado 7 tenemos el
fichero XSD generado con la línea de
comandos anterior, en el que podemos observar que se crea un tipo DataSet que no se incluye en el fichero
procesado; pero como XSD no sabe el
tipo real de MiColega, asume que es un
tipo complejo y lo exporta con el atri-
buto IsDataSet; esto mismo hará con
las colecciones, aunque en realidad el
tipo que genera es un array del tipo al
que hace referencia, en este caso del
tipo MiColega.
Para tener un fichero de esquemas
más preciso, tendremos que generarlo a
partir del ensamblado en el que tenemos
definida la clase. Por ejemplo, si el código que hemos estado usando está compilado como SerializacionXML03_cs.exe,
podemos crear el esquema de la siguiente forma:
xsd SerializacionXML03_cs.exe
Y el fichero resultante tendrá un aspecto parecido al mostrado en el listado 8.
En este caso, se conoce cuál es el tipo
de datos de MiColega y el tipo del campo ID se indica como el que definimos
por medio de la propiedad DataType del
atributo XmlElement.
<?xml version=”1.0” encoding=”utf-8”?>
<xs:schema elementFormDefault=”qualified”
xmlns:xs=”http://www.w3.org/2001/XMLSchema”>
<xs:element name=”MiColega” nillable=”true” type=”Colega2” />
<xs:complexType name=”Colega2”>
<xs:sequence>
<xs:element minOccurs=”0” maxOccurs=”1”
name=”Correo” type=”xs:string” />
<xs:element minOccurs=”0” maxOccurs=”1”
name=”ID” type=”xs:token” />
</xs:sequence>
<xs:attribute name=”Nombre” type=”xs:string” />
</xs:complexType>
</xs:schema>
Listado 8. Esquema generado por XSD a partir del ensamblado que contiene la clase Colega2
<?xml version=”1.0” encoding=”utf-8”?>
<xs:schema id=”NewDataSet” xmlns=”” xmlns:xs=”...” xmlns:msdata=”...”>
<xs:element name=”MiColega”>
<xs:complexType>
<xs:sequence>
<xs:element name=”Correo” type=”xs:string”
minOccurs=”0” msdata:Ordinal=”0” />
<xs:element name=”ID” type=”xs:string”
minOccurs=”0” msdata:Ordinal=”1” />
</xs:sequence>
<xs:attribute name=”Nombre” type=”xs:string” />
</xs:complexType>
</xs:element>
<xs:element name=”NewDataSet” msdata:IsDataSet=”true”
msdata:UseCurrentLocale=”true”>
<xs:complexType>
<xs:choice minOccurs=”0” maxOccurs=”unbounded”>
<xs:element ref=”MiColega” />
</xs:choice>
</xs:complexType>
</xs:element>
</xs:schema>
Listado 7. Esquema generado a partir de un fichero .XML
Esta utilidad también nos sirve para
generar clases a partir de un esquema
XSD, con la idea de que podamos usar
dicha clase en nuestro proyecto para
poder acceder correctamente a los datos
serializados, por ejemplo, desde otra plataforma o por otros lenguajes. Si usamos el esquema mostrado en el listado
8 y queremos generar una clase, lo haremos escribiendo lo siguiente:
xsd schema0.xsd -c
Esto generará una clase de C#; si
quisiéramos que se genere una de Visual
Basic, debemos indicarlo después de la
opción /L:
xsd schema0.xsd -c -l:VB
Los lenguajes soportados son ‘CS’
para C#, ‘VB’ para Visual Basic, ‘JS’ para
JScript y ‘VJS’ para J#.
<<dotNetManía
será el mismo que tiene el fichero, pero
con la extensión .XSD. Si generamos
esquemas a partir de ensamblados, el
nombre que se le dará al fichero resultante será schema0.xsd.
Si queremos crear el esquema a partir del fichero XML con el resultado
del código que hemos estado usando,
tendríamos que escribir lo siguiente en
la línea de comandos (por ejemplo, con
el acceso directo que crea Visual Studio 2005):
47
<< dnm.inicio.taller
using System.Xml.Serialization;
[System.CodeDom.Compiler.GeneratedCodeAttribute(“xsd”, “2.0.50727.42”)]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute(“code”)]
[System.Xml.Serialization.XmlRootAttribute(“MiColega”, Namespace=””, IsNullable=true)]
public partial class Colega2 {
public string Correo;
[System.Xml.Serialization.XmlElementAttribute(DataType=”token”)]
public string ID;
[System.Xml.Serialization.XmlAttributeAttribute()]
public string Nombre;
}
Listado 9. Clase generada a partir de un esquema
De forma predeterminada, se crearán propiedades para cada uno de los elementos de la clase, pero
si queremos que se generen como campos, debemos
usar la opción /f:
xsd schema0.xsd -c -f
La clase generada a partir de este último comando es la mostrada en el listado 9, de la que he quitado parte del código que indica que es una clase autogenerada.
Volviendo al tema del tipo DataSet (que no es un
DataSet sino un array) que genera la utilidad cuando
procesa un fichero con extensión .XML, en realidad lo
que hace es crear un array del tipo de datos que tiene
ese fichero. Por ejemplo, si generamos una clase a partir del esquema del listado 7, además de la definición
de la clase MiColega se creará también un “tipo” llamado NewDataSet que en el fondo es un array del tipo
MiColega, tal como podemos ver en el listado 10.
Independientemente de lo que aparente ser, lo que
debe importarnos es que con la clase generada a partir de un esquema (aunque ese esquema lo hayamos
obtenido a partir de un fichero de datos XML), podremos acceder a los datos que se han serializado, incluso aunque se haya hecho con cualquier otro lenguaje
o sistema operativo. Para demostrar esto último, en
el ZIP con el código de ejemplo se incluye un fichero de datos XML con el que el lector puede practicar
lo aquí comentado; para comprobar cómo usarlo, también se incluye un proyecto que gracias a la clase generada por la utilidad xsd.exe es capaz de acceder a esos
datos. Aunque mi recomendación es que intente primero generar el proyecto y después compararlo con
el que yo he hecho. Como sugerencia, puede modificar la clase generada para que tenga un método ToString, de forma que sea fácil mostrar el contenido de
cada objeto.
Conclusiones
public partial class NewDataSet {
[System.Xml.Serialization.
XmlElementAttribute(“MiColega”)]
public MiColega[] Items;
<<dotNetManía
}
48
Listado 10. La clase NewDataSet generada a partir del
esquema del listado 7
Como hemos podido comprobar, la serialización XML
es bastante potente, y por consiguiente muy extensa
como para poder tratarla al completo en un artículo,
pero confío que lo aquí explicado sea más que suficiente para que pueda sacarle provecho. Recuerde
además que este tipo de serialización es el que utilizan los servicios Web o las aplicaciones de acceso a
datos. Como de costumbre, en el ZIP que acompaña
a este artículo está todo el código aquí presentado,
tanto para Visual Basic como para C#.
todonet@qa
Dino Esposito
es mentor de Solid
Quality Learning. Es
ponente habitual en
los eventos de la
industria a nivel
mundial.Visite su
blog en: http://weblogs.
asp.net/despos.
(ttodotNet.QA@
dotnetmania.com)
Páginas Web, indexadores y DHTML
Las aplicaciones Web están basadas en URL,y este hecho es clave para que los buscadores Web puedan indexarlos y buscarlos apropiadamente. No es poco probable que los desarrolladores Web asignen a las páginas algún tipo de “nombre científico” similar al de los animales o las flores.Este nombre no es el que se utiliza en el
lenguaje diario para indicar a ese animal o flor;se utilizaría un nombre fácil de recordar.Lo mismo ocurre para las páginas,y para implementar esta traducción automática en ASP.NET hay que reescribir las URL.Finalmente,este mes hablaremos sobre
HTML dinámico (DHTML), y en particular sobre la propiedad innerHTML.
¿Cuál es la relación entre los buscadores e indexadores Web y ASP.NET? Intento mantener mi
código todo lo limpio que puedo, y cuando echo un vistazo al código generado por ASP.NET llego a la conclusión de que no me gusta mucho. Me pregunto si esto puede afectar la manera en
que los buscadores como Google funcionan.También me pregunto si AJAX, el viewstate, scriptresource.axd y la manera en que ASP.NET gestiona los enlaces afecta a los buscadores Web.
Permítame antes que nada decir que no tengo
mucha idea sobre cómo funcionan los buscadores Web, por lo que la mayoría de las siguientes
consideraciones podrían estar basadas en suposiciones incorrectas. Solo es una posibilidad, no
obstante.
Si tuviera que escribir código para indexar
algún contenido Web, yo me centraría en la URL
pública y el contenido devuelto por ella. Básicamente, crearía algún tipo de diccionario que tuviera la URL como clave y una lista de palabras clave obtenida del contenido servido a partir de la
URL. Asumiendo que los buscadores Web realmente clasifican la información de esta manera,
lo realmente importante es el código de marcado
devuelto de la URL. El código generado por el
motor de ejecución de ASP.NET para servir la
página es simplemente la traducción del marcado
ASP.NET definido por el desarrollador. Los campos ocultos y el atributo HREF de los campos de
entrada probablemente se ignoren, o al menos se
les asignará una baja prioridad. Una información
muy valiosa se obtiene de las etiquetas textuales.
En definitiva, no pienso que el viewstate o los
enlaces especiales afecten a los indexadores.
Las cosas podrían ser diferentes en el caso de
las aplicaciones AJAX. Una aplicación AJAX se
basa en páginas en las que la mayor parte del trabajo se hace de manera asíncrona, sin un postback
completo ni la subsiguiente petición de página
completa al servidor Web. La página se alcanza
utilizando la misma URL, y en teoría una única
URL (y una única página) podría representar a
toda la aplicación. Si usted ha diseñado su aplicación para que incluya una URL como customer.aspx?id=xxx, usted no tiene una aplicación
AJAX. En un contexto AJAX, generalmente se tiene una página customer.aspx que incluye un botón
con cierto código de script asociado. Este código
de script realiza llamadas fuera de banda y recu-
<<dotNetManía
todotNet.qa@dotnetmania.com
Dino Esposito
49
<<dotNetManía
TodotNet.qa@dotnetmania.com TodotNet.qa@dotnetmania.com
<< dnm.todonet@qa
50
pera los datos que necesita para rellenar el esqueleto
de la página con información sobre un cliente dado.
Podría no existir una URL diferente para esta petición. E incluso si la URL existiera, el contenido
devuelto por ella podría no ser fácil de comprender
para un indexador. Veamos un ejemplo.
En las Extensiones AJAX para ASP.NET, usted
puede utilizar un renderizado parcial para refrescar
la página customer.aspx y hacer que ésta muestre los
datos de muchos clientes diferentes. En este caso, la
URL siempre es la misma: la URL de la página principal. Si se conecta la página customer.aspx a un servicio remoto para recuperar los datos de un cliente,
probablemente tendrá una URL de servicio (Web)
a llamar, con el nombre del método indicado en la
propia URL. Esta URL es repetible, pero información clave como los parámetros de entrada están
ocultos en el cuerpo y formateados como cadenas
JSON. Para un indexador, esto debe ser sin dudas
difícil de seguir.
En definitiva, las aplicaciones ASP.NET 2.0 no tienen problemas con los indexadores; las aplicaciones
AJAX, por su parte, parecen ser estructuralmente difíciles de indexar. Para reforzar este concepto, piense en
Adobe Flash. Si usted tiene una página desarrollada
completamente como un script de Flash, no hay manera de que Google u otros puedan indexar su contenido. Una petición Flash que se origine dentro del plugin nunca es externa a él y no puede ser capturada y procesada por los indexadores. Microsoft Silverlight —el
nuevo producto de Microsoft diseñado para ofrecer un
conjunto de servicios similares a Flash— promete resolver los problemas de indexación que caracterizan a
Flash. El tiempo dirá.
¿Qué es la reescritura de URL y en qué se diferencia de la redirección? Mi sitio Web está repleto de
URL difíciles de recordar y de páginas que han sido movidas a otra jerarquía de carpetas. La reescritura de URL atrajo mi atención como una técnica para resolver estos problemas. ¿Es esto correcto?
La reescritura de URL ocurre dentro del motor de
ejecución de ASP.NET. Es el proceso de intercepción de una petición de entrada y su mapeado a un
recurso de destino diferente. Hablando en términos lógicos, la reescritura de URL es casi lo mismo que la redirección de URL (el clásico código
de estado 302 de HTTP). Sin embargo, la similitud es solo lógica. En ambos casos, un usuario solicita una URL determinada para recibir un contenido mapeado en el servidor a otra URL y recurso
asociado.
Un ejemplo canónico es el siguiente: usted, como
usuario, solicita una página llamada joe.smith.aspx.
En vez de ello, recibe el contenido mapeado a un
recurso llamado customer.aspx?id=999&mode=lite.
¿Dónde está la diferencia? Como puede ver fácilmente, la primera URL es claramente más fácil de
recordar y teclear, tanto para usuarios finales como
para usuarios internos, como los gestores. La segunda URL es la verdadera, para la que la primera URL
representa una especie de alias. ¿Quién hace la magia
para que las dos URL coincidan? Si el mapeado se
produce a través de la clásica redirección, entonces
el navegador se hace cargo de ello. Si el mapeado se
produce a través de la reescritura de URL, es el
motor de ejecución de ASP.NET el que controla el
mapeado de la URL.
La reescritura de URL tiene lugar durante el procesamiento de la petición y determina una modificación de la URL originalmente solicitada. El objeto de
contexto HTTP de ASP.NET tiene un método llamado RewritePath definido de la siguiente forma:
public void RewritePath(string path)
El método accede a ciertos campos privados del
objeto Request y reescribe la URL de destino de la
petición. Como resultado, la página mostrada es la
que se establece mediante RewritePath; pero la página que se muestra en la barra de direcciones del navegador sigue siendo la solicitada originalmente. La sustitución de la URL final tiene lugar en el servidor y
dentro del contexto de la misma llamada. Debido a
esto, no hay manera de que el navegador pueda cambiar lo que aparece en su barra de direcciones.
Este hecho representa la mayor diferencia con la
clásica redirección de navegador. De hecho, cuando
usted llama a Response.Redirect, el navegador recibe
un código de estado HTTP 302 y repite la petición
utilizando una URL diferente.
Como puede ver, utilizar el método RewritePath es
un enfoque más eficiente que la clásica redirección, porque no requiere una segunda llamada al navegador.
Observe, no obstante, que RewritePath debe ser utiliza-
void Application_BeginRequest( object sender,
EventArgs e)
{
HttpContext context = HttpContext.Current;
if (context.Request.Url.Equals(
"customer.aspx?id=999"))
context.RewritePath("smith.aspx");
}
En ASP.NET 2.0, la reescritura de URL puede
expresarse de manera declarativa utilizando la nueva
sección urlMappings del fichero de configuración
Web.config. Éste es un ejemplo:
<urlMappings enabled="true">
<add url= "~/home.aspx"
mappedUrl="~/default.aspx?parm1=1"/>
<add url= "~/products.aspx"
mappedUrl="~/default.aspx?parm1=2"/>
</urlMappings>
El contenido de esta sección se procesa en tiempo de ejecución , y genera tantas llamadas a RewritePath como entradas hay en la sección. No hay diferencias significativas entre la reescritura de URL
declarativa o programática; usted deberá utilizar el
mapeado declarativo, a menos que necesite evaluar
condiciones complejas antes de decidor si hace el
mapeado.
Para las aplicaciones AJAX, escribir buen código JavaScript es una necesidad.Y la mayor parte de
la eficiencia de nuestras páginas depende de lo que ocurre en el cliente. Esa es la razón de mi pregunta.Veo que la documentación oficial de DOM sugiere actualizar las páginas utilizando su propia API,que no incluye la popular propiedad innerHTML.Muchos navegadores,sin embargo,soportan esta propiedad además del DOM estándar. ¿Quién tiene razón, y qué es lo mejor para mí?
Inicialmente, la propiedad innerHTML era solo una pieza clave del soporte del navegador para el modelo de
objetos de HTML dinámico (DHTML). Introducido por Microsoft con el Internet Explorer 4.0, fue
copiado por otros navegadores en lo que simplemente se conocía como modelo de objetos del navegador.
El éxito de DHTML llevó a la definición de un modelo de objetos de documento estándar: el DOM de
W3C. El DOM evolucionó a partir de DHTML y
generalizó en gran medida el modelo original.
El DOM de W3C de hecho ofrece un modelo
basado en árbol para todo el documento, y este modelo no incluye ninguna propiedad innerHTML. La mayoría
de los navegadores, sin embargo, soportan una mezcla de DOM y DHTML —básicamente, el DOM
estándar más unas cuantas propiedades útiles como
innerHTML—. De acuerdo con el DOM estándar, para
actualizar cierto contenido usted debe obtener una
referencia al nodo asociado a la etiqueta HTML deseada y asignar su texto. De la misma forma, para añadir un nuevo elemento usted debe crear el nuevo elemento y agregarlo al árbol.
Uno de los debates más interesantes dentro de la
comunidad de desarrolladores Web es si se debe utilizar DHTML para manipular las páginas, u optar por
el enfoque más “limpio” que propone el DOM de
W3C. El elemento clave a tener en cuenta es que la
utilización de la API del DOM resulta en un código
significativamente más lento que si se utiliza la propiedad innerHTML, caso en el que simplemente es necesario definir el HTML deseado e incorporarlo a la
página mediante la asignación a la propiedad. El navegador entonces se encarga del resto, renderizando ese
marcado gráficamente.
En general, tanto la manipulación mediante
DHTML como mediante DOM son útiles, dependiendo del contexto. Hay muchos sitios Web por ahí
que ofrecen pruebas de rendimiento, y DHTML es
siempre el vencedor. En cualquier caso, DOM es también perfectamente válido siempre que se utilice del
modo adecuado —esto es, crear fragmentos de HTML
y agregarlo al contenedor apropiado solo como paso
final—. La propiedad innerHTML está soportada por
prácticamente todos los navegadores, y asigna o recupera el código HTML situado entre las etiquetas de
inicio y fin del objeto indicado. Algunos navegadores,
como Internet Explorer, soportan además la propiedad innerText, que asigna o recupera el texto situado
dentro del objeto DOM indicado. Desgraciadamente, esta propiedad no está soportada por todos los navegadores: existe en IE y Safari pero no está soportada,
por ejemplo, por Firefox, que ofrece una propiedad
con comportamiento similar pero diferente nombre:
textContent.
Traducido al castellano por Octavio Hernández
<<dotNetManía
do con cuidado y fundamentalmente desde el fichero
global.asax. De hecho, si usted utiliza RewritePath en
el contexto de un evento de postback, podrá experimentar ciertos problemas con el viewstate. El siguiente código, un fragmento de un fichero global.asax de una aplicación Web, muestra cómo reescribir la URL de una
petición para apuntar a una página diferente:
TodotNet.qa@dotnetmania.com TodotNet.qa@dotnetmania.com
<< dnm.todonet@qa
51
Laboratorio.net
Octavio Hernández
Nevron .NET Vision
Este mes presentamos .NET Vision,
una suite de componentes para la capa
de presentación que le permitirá dotar
a sus aplicaciones de posibilidades de
visualización de información que realzarán en buena medida sus interfaces
de usuario.
OFERTA ESPECIAL PARA LECTORES
DE DOTNETMANíA
Con vigencia hasta el 15 de julio de 2007, Nevron ofrece a los lectores de dotNetManía un descuento especial de un 20% sobre los precios de venta, aplicable a
los nuevos pedidos de la suite .NET Vision o de cualquiera de los productos que la componen (User Interface for .NET, Chart for .NET o Diagram for .NET).
Para hacer uso de la oferta,mencione el código DNM07
al contactar con el fabricante:
Tel: 359-2-812-6444
email: sales@nevron.com
Web: http://www.nevron.com
Octavio Hernández
es Development
Advisor de Plain
Concepts, editor
técnico de
dotNetManía y tutor
de campusMVP.
Es MVP de C# desde
2004, MCSD y MCT.
.NET Vision es una suite de componentes de interfaz de usuario que hacen posible enriquecer nuestras aplicaciones, tanto para Windows como para
la Web, con elementos visuales muy efectivos a la
hora tanto de embellecer su apariencia como de presentar la información que ellas producen de una
manera que facilite una mejor interpretación. Su
fabricante, Nevron (http://www.nevron.com) es una
empresa basada en Sofía, Bulgaria que hace honor
a la bien conocida excelencia de los programadores
de Europa del Este y que en relativamente poco
tiempo ha conseguido hacerse con una impresionante cartera de clientes que puede consultarse en
su página Web.
Contenido del paquete
La suite Nevron .NET Vision integra tres productos diferentes, que también se venden por separado:
Ficha técnica
Nombre: .NET Vision
Versión: Q4 2006
Fabricante: Nevron
Sitio Web: http://www.nevron.com
Categoría: Componentes de interfaz de
usuario
Precios:
• .NET Vision Enterprise: 1.589 USD.
•.NET Vision Professional: 989 USD.
• Por un coste adicional se puede adquirir
una subscripción anual, que da derecho a
recibir todas las actualizaciones de los
productos durante un año, así como
también un paquete de soporte técnico
prioritario.
• Se aplican descuentos progresivos según
cantidad de licencias.
• Además, los productos que componen la
suite se pueden adquirir de manera
independiente.
• Nevron User Interface for .NET es una
librería de clases y controles que potenciarán
sus desarrollos Windows Forms, permitiéndole crear interfaces de usuario impactantes y
atractivas con un mínimo de esfuerzo y máxima productividad.
• Nevron Chart for .NET es una librería de
componentes visuales que facilita la incorporación a nuestras aplicaciones, tanto Windows
Forms como ASP.NET, de gráficos comerciales, científicos, etc., que a la vez que también
realzan la interfaz de usuario de éstas, facilitarán
en gran medida a los usuarios finales la interpretación de la información.
• Por último, Nevron Diagram for .NET es una
librería de clases y controles visuales, en este
caso destinada a facilitar la incorporación a nuestras aplicaciones, tanto Windows Forms como
ASP.NET, de todo tipo de diagramas (organizativos, de redes, de clases...).
<< dnm.laboratorio.net
Cada uno de estos productos se ofrece en dos ediciones: Enterprise y Professional. En todos los casos,
la edición empresarial ofrece ciertas características
avanzadas que no están disponibles en la profesional.
Consecuentemente, la suite como un todo también se
ofrece en esas dos ediciones; cada edición de .NET
Vision integra las ediciones correspondientes de cada
uno de los productos. Para conocer las diferencias
entre las dos ediciones de cualquiera de las librerías,
consulte las páginas del sitio Web del fabricante que
se listan al final de este artículo.
Algo a destacar especialmente en el caso de .NET
Vision es el hecho de que no estamos en presencia de
un “convoy” en el que se mezclan de manera artificial productos que tienen muy poca o ninguna relación entre sí; en este caso, todo el software ha sido
concebido bajo una arquitectura unificada y modular, y por ejemplo las versiones para Windows Forms
de las librerías de gráficos y diagramas se apoyan en
los componentes del paquete de interfaz de usuario;
más aún, todos los productos de la suite se apoyan en
un modelo de objetos común llamado Nevron Document Object Model (DOM), lo que se traduce en múltiples facilidades a la hora de combinar la utilización
de varios de los productos.
rrollador la instalación y
configuración inicial del
producto. .NET Vision no
es una excepción, y su programa de instalación (figura 1) se encarga de todo lo
relacionado con instalar los
componentes en el GAC y
registrarlos ante Visual Studio 2005 (o 2003, para el
que también se ofrece
soporte).
Primer uso
Una vez instalada la suite, tendremos a nuestra disposición en el cuadro de
herramientas de Visual
Studio (figura 2) una buena cantidad de componentes listos para ser utilizados
en nuestros proyectos. Los
Figura 2. Componentes de .NET Vision
principales componentes
en el Cuadro de herramientas.
que conforman cada uno
de los productos se describen más adelante en este artículo.
Instalación y primer uso
Instalación
En los tiempos que corren, raro es el producto comercial que no ofrezca un programa de instalación eficiente que haga totalmente transparente para el desa-
Figura 1. Instalación de .NET Vision
Una buena vía para familiarizarse con las posibilidades que ofrecen los diferentes productos que componen .NET Vision es ejecutar los ejemplos que ellos
incorporan (y que son colocados en la carpeta Exam-
<<dotNetManía
Figura 3.Aplicación de ejemplo de User Interface for .NET.
53
<< dnm.laboratorio.net
ples bajo el directorio de instalación de la suite). Por
ejemplo, la figura 3 muestra en acción al completo
programa demostrativo de las posibilidades que ofrece User Interface for .NET.
User Interface for .NET
User Interface for .NET extiende prácticamente todos
los controles de la paleta de componentes estándar
para Windows Forms con propiedades, métodos y
eventos adicionales para darles una apariencia estilizada y consistente. El paquete contiene más de 65
controles personalizados con los que podremos dar
un look & feel profesional a nuestras aplicaciones.
Algunas de las características más destacadas de
este paquete son las siguientes:
• Soporte completo para skins, que permite cambiar completamente la apariencia de la aplicación con solo unas pocas líneas de código. Se
incluyen 30 esquemas predefinidos, incluyendo
el de Office 2007, además de que es posible crear nuevos esquemas en tiempo de diseño o de
ejecución.
• User Interface for .NET suministra numerosos
controles de apariencia moderna, como una
barra de navegación similar a la de Outlook 2003
o una barra similar a la del explorador de Windows XP, además de un conjunto completo de
controles Windows Forms mejorados.
• Óptima velocidad y calidad de dibujo, que hace
posible utilizar sin que el rendimiento se resienta efectos de transparencia, sombreados, gradientes y otros decoradores.
• Excelente soporte para el encajado de paneles y
ventanas, basado en un motor de colocación especializado.
• El soporte de paneles incluye un sistema de gestión de documentos que facilita en gran medida la creación de interfaces MDI estándar o de
pestañas.
<<dotNetManía
La librería ofrece otros componentes que no se
encuentran en librerías similares, como Task Dialog, un
diálogo de introducción de datos al estilo de Windows
Vista, o Desktop Toolbar, que hace que un formulario
se comporte como la barra de tareas de Windows.
54
Chart for .NET
Nevron Chart for .NET es uno de los componentes
más completos del mercado en su categoría, ofre-
ciendo una enorme cantidad de tipos de gráficos para
propósitos comerciales, financieros, científicos o de
presentación. Como quiera que en fechas relativamente recientes hemos analizado otro producto similar (ver dotNetManía Nº 30), aquí únicamente enumeraremos las características que diferencian a Chart
for .NET de la competencia:
• El componente es muy rápido. El fabricante indica que Chart for .NET es el único componente
del mercado en su categoría capaz de hacer uso
de la aceleración de gráficos por hardware, característica muy importante para la graficación en
tiempo real.
• Todos los tipos de gráficos se pueden renderizar
nativamente en 3D.
• El producto ofrece un modelo de ejes único, totalmente personalizable y extensible.
• Soporte para características de dibujo avanzadas, como filtros de imágenes, suavizado de sombras, efectos de iluminación 3D o gradientes y
sombras para texto.
Figura 4.Aplicación de ejemplo de Chart for .NET
Diagram for .NET
El otro paquete que forma parte de esta suite es Diagram for .NET, destinado a satisfacer las más diversas necesidades de diseño y visualización de diagramas de muy diversos tipos: organizativos, de flujo, de
clases, de estados, de redes, de arquitectura… Se trata de una librería realmente única, que integra las tecnologías más actuales de dibujo vectorial y de mapas
de bits para ofrecer amplias posibilidades de diseño y
un alto nivel de interactividad. Diagram .NET permite organizar los diagramas como jerarquías de docu-
<< dnm.laboratorio.net
• Persistencia del estado a través de
diferentes “viajes” de ida y vuelta,
para un rendimiento superior.
• Posibilidad de asociación de “zonas
calientes” a imágenes.
Dado el hecho de
que el paquete User
Interface for .NET
incluye únicamente
componentes para
aplicaciones de escritorio, es natural que se
eche en falta la inclusión en .NET Vision
de una librería similar
a la anterior para el
desarrollo de aplicaciones Web ASP.NET.
Figura 5.Aplicación de ejemplo de Diagram for .NET
El fabricante conoce
este hecho y ha venido
figuras, conectores, grupos y plantillas
trabajando en ello; como resultado, al
predefinidas.
cierre de esta edición anunciaba un
La figura 5 muestra en ejecución al
acuerdo al respecto con Intersoft Soluprincipal programa demostrativo que
tions (ver recuadro “Novedades”).
acompaña a este componente. Como
puede observarse, el diseñador de diagramas no solo puede utilizarse en tiemConclusiones
po de diseño, sino también en tiempo
de ejecución.
En este artículo hemos presentado, de
la manera resumida que nos exigen las
limitaciones de espacio, las principales
características de Nevron .NET Vision,
Sobre los componentes
una potente suite de componentes visuaASP.NET
les para la capa de presentación de apliLo más destacable de las versiones
caciones tanto para Windows como para
para ASP.NET de Chart for .NET y
la Web, que recomendamos sin duda
Diagram for .NET es que se apoyan
alguna a nuestros lectores.
en los mismos motores fiables y de alto
rendimiento en los que se basan sus
homólogas para Windows Forms. A
Referencias
la hora de devolver los gráficos y diaPuede obtener más información
gramas que generen “al vuelo” nuessobre el producto en la página
tras aplicaciones ASP.NET, disfrutaWeb del fabricante,
remos de todas las posibilidades que
http://www.nevron.com.
cabría esperar de una librería “seria”
de componentes de imagen para la
Toda la documentación técnica de
Web, como son:
los productos que componen la
• Detección de navegador para adapsuite está disponible online en la
tar las respuestas a las capacidades
URL http://www.nevron.com/
del mismo.
DotNetVision/Index.htm.
• Posibilidad de serialización directa
de imágenes al navegador cliente.
Novedades
.NET Quark, fruto del acuerdo de
Nevron con Intersoft Solutions
Casi coincidiendo con el envío a
imprenta de este ejemplar, Nevron
ha hecho público un acuerdo con
Intersoft Solutions para sacar al mercado .NET QuarX, un paquete combinado que incluye .NET Vision
(que analizamos en este ejemplar) y
WebUI Studio.NET, una librería de
componentes visuales para aplicaciones ASP.NET de Intersoft.
WebUI Studio .NET ofrece un
amplio conjunto de controles que
hacen posible implementar con relativamente poco esfuerzo interfaces
Web que ofrecen experiencias de
usuario ricas apoyándose en los más
recientes avances tecnológicos en esta
área, como AJAX. Ambas compañías
han creado un nuevo sitio Web conjunto, http://www.dotnetquarx.com,
en el que podrá encontrar más información.
ATENCIÓN
La oferta para los productos Nevron que
se presenta a principios de esta sección no
es aplicable a .NET QuarX, que ya sale
al mercado con un agresivo precio introductorio –1.999 USD–.
VistaDB 3.0 disponible
Recientemente, VistaDB Software ha sacado al mercado VistaDB 3.0, un gestor de base de
datos embebible escrito 100% en
C# y que, con sus 600 Kb de huella de memoria, soporte simultáneo para .NET, .NET Compact
Framework y Mono, compatibilidad con SQL Server 2005 en cuanto a tipos de datos y sintaxis T-SQL
y proveedor nativo de ADO.NET,
parece una excelente alternativa a
SQL Server CE. Más información
en http://www.vistadb.net.
noticias • noticias
<<dotNetManía
mentos e incorpora potentes conceptos
organizativos como las capas y los
modelos. Como parte de esta librería de
clases se ofrece una gran cantidad de
55
❑ 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€)
❑ Nº31 (6,50€)
❑ Nº32 (6,50€)
❑ Nº33 (6,50€)
❑ Nº34 (6,50€)
❑ Nº35 (6,50€)
❑ Nº36 (6,50€)
❑ Nº37 (6,50€)
✃❑
❑
Oferta válida hasta el 30 de junio de 2007 o hasta agotar existencias
Deseo suscribirme a dotNetManía por un año (11 números) por un precio de 65,00€ IVA incluido. 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 suscripciones@dotnetmania.com, o también puede
enviarlos por correo postal a la siguiente dirección:
de 2007
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)
biblioteca.net
Pro C# with .NET 3.0, Special Edition
Andrew Troelsen
Editorial: APress
Páginas: 1150
Publicado: febrero, 2007
ISBN: 1-59059-823-7
Idioma: inglés
Todo un clásico entre los libros dedicados a C# se renueva, expandiendo el amplio
material que ya cubre (que incluye todos los principales temas relacionados con el
lenguaje, la descripción de las principales librerías, una amplia cobertura de la estructura y funcionamiento de los ensamblados y la programación a bajo nivel, así como
amplios capítulos relativos al desarrollo de los principales tipos de aplicaciones y servicios para .NET Framework –Windows Forms, Web Forms, Web Services, aplicaciones distribuidas con Remoting–) con seis nuevos capítulos, dedicados a las nuevas librerías incorporadas a .NET 3.0 (Presentation Foundation, Communication
Foundation, Workflow Foundation) y a las nuevas posibilidades que estaremos aprovechando dentro de poco: C# 3.0 y LINQ.
Hoy por hoy, si tuviera que elegir un único libro de C# para llevarme a una isla desierta, creo que éste es el que escogería. Altamente recomendado.
Expert .NET 2.0 IL Assembler
Serge Lidin
Editorial: APress
Páginas: 476
Publicado: septiembre, 2006
ISBN: 1-59059-646-3
Idioma: inglés
novedades
Sin duda alguna, este libro es la referencia definitiva si desea conocer en profundidad las estructuras internas y mecanismos en los que se apoya el Common Language Runtime (CLR) para la carga y ejecución de aplicaciones, y hasta los más mínimos detalles relacionados con el Lenguaje Intermedio (Intermediate Language, IL)
y el desarrollo de aplicaciones en ese lenguaje, el ensamblador de .NET Framework.
El libro ofrece muchísima información imposible de encontrar en otras fuentes, como
la estructura interna de los ejecutables de código manejado o los códigos internos de
las instrucciones IL. Lidin trabaja desde 1999 en el equipo del CLR en Microsoft, y
formó parte del equipo que diseñó el lenguaje intermedio e implementó ILASM,
ILDASM y otras utilidades de bajo nivel de .NET.
Ajax con ASP.NET
Wallace B. McClure, Scott Cate, Paul Glavich y Craig Shoemaker. Editorial Anaya Multimedia/Wrox. Páginas.: 432. Publicado: mayo, 2007. ISBN: 978-84-415-2207-7.
Curso de CSS
Christopher Schmitt. Editorial: Anaya Multimedia/O’Reilly. Páginas: 576. Publicado:
mayo, 2007. ISBN: 978-84-415-2198-8.
TEXTO: OCTAVIO HERNÁNDEZ
desván
Marino Posadas
Microsoft Popfly, una revolución del diseño Web
El logo y el nombre
son un tanto extraños
y no dicen mucho
acerca del producto en
sí, pero se trata de
algo tremendamente innovador en su interfaz de usuario y su
metáfora operativa, y con unas posibilidades sorprendentes:
tanto en lo que se puede conseguir con él (fácilmente), como
por la sencillez de su programación (de hecho, para muchas
opciones basta con una fase de diseño). Se trata de una aplicación que permite construir y compartir mashups, gadgets,
páginas Web y aplicaciones de una forma fácil y divertida.
No existe una beta aún (se encuentra en versión alpha), pero
es posible suscribirse a una lista para que cuando la beta esté
disponible podamos probarla. Merece la pena ver un webcast
sobre su funcionamiento (http://msdn.microsoft.com/vstudio/media/en/popfly/PopFlyin15.wvx) y además el producto ya
dispone de su sitio Web donde se anticipan su funcionalidad
y posibilidades: http://www.popfly.ms/Overview. Como verá el
lector, casi todo está pre-montado y el usuario solo tiene que
escoger lo que le gustaría que tuviese su sitio, el aspecto visual
–totalmente personalizable– que deseamos darle a las páginas, y –para poder añadir funcionalidad– los eventos y el código Javascript que deseamos añadir. No obstante, dado lo temprano de su fase de desarrollo, no creemos que esté disponible hasta el otoño/invierno de este año.
noticias.noticias.noticias
<<dotNetManía
¿Conoce los “Easter Eggs”
(huevos de pascua)?
58
Se trata de pequeños trucos funcionales “escondidos” en las aplicaciones más populares. Algunos de ellos han sido colocados por el equipo
de desarrollo simplemente como una firma, como un sello de identidad. Otros, sin embargo, tienen una funcionalidad más práctica, como
es el caso del que podemos encontrar en el nuevo Microsoft Word
2007. El truco no es nuevo: se abre un documento en blanco, y se teclea
exactamente lo siguiente: =rand(x,y), donde se sustituirán x e y por
dos números enteros. ¿Qué sucede? Pues que Word genera texto
automáticamente siendo la norma que x es el número de párrafos a
generar e y el número de veces que se repite ese párrafo. En versiones
anteriores, el programa generaba una frase que contenía todas las letras
del alfabeto inglés, (the quick brown fox jumps over the lazy dog), pero la
cosa ha cambiado en esta versión, y ahora se genera un texto más lógico que es una especie de popurrí de datos de la ayuda. Sigue siendo útil
para esos propósitos, pero su aspecto es más similar al que tendría un
texto real.
noticias.noticias.noticias
documentos en la red
El MIX’07 terminó, pero pueden verse los
restos, en el sitio Web creado a tal efecto por
los chicos de publicidad del evento. Hay noticias, entrevistas, algunos materiales descargables, el típico regusto de aquello que terminó,
y como dice el logo adjunto “no todo lo que pasa en Las Vegas
se queda allí”, hay una parte que puede consultarse en la página: http://visitmix.com.
2007 Office System Document: Bringing Web 2.0 to the
Enterprise with the 2007 Office System es un amplio
documento sobre cómo aprovechar
las nuevas capacidades de Microsoft
Office System 2007 para crear contenidos y aplicaciones. Una mezcla de
divulgación y presentación de funcionalidad. Disponible en
http://www.microsoft.com/downloads/thankyou.aspx?familyId=8b48bd31-f043-4ab4-96eb-c6e958fe4ec9&displayLang=en
sitios del mes
Sitio CardSpace. La propuesta de seguridad e identidad de
Microsoft, que aparece por primera vez en Vista, tiene su propia página, donde se pueden encontrar documentos, código de
ejemplo, herramientas y noticias sobre la evolución de este subsistema, que veremos también en el próximo Windows Server
2008. Se puede empezar por la página http://cardspace.netfx3.com.
WebLog sobre identidad de Kim Cameron. Y ya que hablamos de identidad y autenticación, qué mejor
que completar la visita anterior con un paseo
por la lista de propuestas y noticias que nos
ofrece Kim Cameron, un especialista en el
tema, desde su sitio: http://www.identityblog.com.
Blog de Adolfo Wiernik. Una visita a datos de actualidad,
con énfasis especial en los temas de .NET y SQL Server y lo
que sucede a su alrededor, especialmente en América Latina.
Adolfo Wiernik radica en San José de Costa Rica, pero sus
actividades abarcan desde el cono sur hasta México. Se puede visitar en: http://www.wiernik.net.
utilidades del mes
Vista Codec Package. De nuevo los chicos de MSFN nos
traen cosas de utilidad. Los usuarios de Vista que tengan
problemas para visualizar algún vídeo o audio y que duden
si los codec descargables por ahí son válidos o no para el
sistema, pueden recurrir a Vista Codec Package. Está disponible para descarga en la página http://www.msfn.org.
Gadwin PrintScreen.Es una sencilla utilidad de captura de
pantalla, que permite realizar la tarea con una simple pulsación, y almacenar lo capturado hasta en 6 formatos gráficos distintos. Es gratis y en su sitio Web (http://www.gadwin.com/products.htm) pueden verse también otras utilidades interesantes.
Descargar