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.