MSDN Blogs
  • WarNov Developer Evangelist

    Mi aplicación web no carga imágenes ni estilos cuando publico en IIS7!!!

    • 2 Comments

    Puede que te haya pasado que tienes una aplicación web .NET ya sea MVC o ASP.NET que en modo diseño o publicándola con el servidor Cassini (el incluido en Visual Studio) todo funcione correctamente en cuanto a carga de imágenes y estilos se refiere.

    Pero cuando lo ponen en un IIS7, Naranjas! Ya no hay ni imágenes ni estilos! Sick smile

    Miren el sitio con estilos

    Si esto les ha sucedido alguna vez, el problema puede ser muy sencillo de corregir. Solo tienen que verificar que el IIS tenga activado el módulo de presentación de contenido estático; aquí lo pueden chequear para Windows 7:

    image

    Para otros sistemas con IIS7, sigan estas instrucciones.

    Hope it helps!

  • WarNov Developer Evangelist

    REST (Representational State Transfer)

    • 2 Comments
    Creado en el 2000 hace referencia a “Representational State Transfer” o transferencia representacional de estados.

    Si uno se deja guiar por el nombre pareciera como si no tuviese nada que ver con lo que medio se ha oído por ahí acerca del tema: “que sirve para acceder a servicios sencillamente a través de URLs”, por ejemplo.

    Pero estudiándolo bien uno nota que al final si hay cierta congruencia.

    En REST participan básicamente dos roles. Un cliente y un servidor. El cliente es el sujeto de los dichosos cambios de estados. Entonces imagine el cliente como su navegador web en un estado específico (una página web). Un cambio de estado obviamente significa la transferencia a otra página web.
     
    Una transferencia representacional en web, no es más que la transferencia lograda sencillamente a través de URLs. Y es precisamente allí donde se encadena todo.

    La idea es que las acciones o verbos que originan los cambios de estado del cliente en REST están completamente definidos. Es decir, REST propone un vocabulario de acciones fijo; que permite obtener recursos del servidor, que una vez interpretados por el cliente, hacen que este cambie de estado.

    Esto último es lo que más diferencia a REST por ejemplo del tradicional SOAP. Ya que en SOAP, se le dice a cada desarrollador que defina un vocabulario nuevo y arbitrario de verbos, de acuerdo a los requerimientos de la aplicación (obtenerUsuarios(), almacenarOrden(…), etc. Todos sobreusando el verbo POST de HTTP). Paradójicamente, esto que siempre se vio como una gran ventaja, va en contravía con muchos de los aspectos inherentes del HTTP que es base de SOAP. Así que aspectos como la autenticación, caching, negociación de contenidos y demás, no se aprovechan.

    Aunque hasta aquí todo lo ejemplifiqué usando HTTP, REST es un mecanismo que no depende de ese protocolo. Las aplicaciones REST pueden basarse en otros protocolos, siempre y cuando éstas provean un vocabulario uniforme preestablecido para las aplicaciones que se construirán sobre ella. Recordemos que la idea principal de REST es maximizar el uso de las capacidades predefinidas de la plataforma que los soporte. HTTP como tal, proporciona un rico vocabulario completamente establecido y estandarizado que se ajusta perfectamente a este objetivo. Es por esto, que hoy en día al hablar de REST uno automáticamente piensa en su implementación sobre HTTP.

    Principios

    REST se fundamenta en seis principios básicos:
    • Cliente y Servidor plenamente identificados y separados
    • No hay almacenamiento de estado en las transiciones (Stateless)
    • Respuestas “cacheables” (Para mejorar las interacciones y el performance)
    • Capas: Pueden haber varias capas de servidores intermedios
    • Código por demanda: La funcionalidad de un cliente se puede extender con código trasmitido por el servidor (por ejemplo con JavaScript). Este es el único requerimiento opcional.
    • Interfaz uniforme: La misma que se discutió anteriormente.

    Objetivos

    Los principios anteriormente mencionados, están diseñados para lograr los siguientes objetivos:
    • Escalabilidad de componentes
    • Generalidad de Interfaces
    • Distribución Independiente de componentes
    • Existencia de componentes intermediaros que reducen latencia, aumentan la seguridad y encapsulan sistemas de legado.

    Recursos

    Los recursos se definen como fuentes de información específica y son muy importantes en REST. Un cliente accede a los recursos que el servidor dispone. Imagine una aplicación empresarial con información de recursos humanos. En este caso, la lista de empleados es un recurso del servidor y para acceder a ellos, se requiere un identificador único (por ejemplo una URI), que es usado por el cliente para referenciarlo y una interfaz de comunicación estandarizada (por ejemplo HTTP). Obviamente, aparte de tener claro el objeto de una acción, se debe tener clara la acción a ejecutar sobre ese objeto. Así pues, una aplicación interactúa con los recursos sabiendo su identificador único y la acción a ejecutar sobre este. Por ejemplo: Recurso: Empleado con Id:3520. Acción: Borrar. Los recursos generalmente son transmitidos entre el servidor y el cliente usando formatos como HTML, XML o JSON. No obstante, los recursos también pueden ser imágenes, texto plano o cualquier otro formato.

    Servicios Web REST

    No son más que servicios WEB implementados usando HTTP y los principios de REST que comprenden una colección de recursos de acuerdo a los siguientes aspectos:

    • Una URI base para el nombre del servicio: http://example.com/miservicio/
    • El tipo MIME de los datos soportados por el servicio
    • El conjunto de operaciones soportadas.
    • En REST sobre HTTP, lo más normal es tener estas operaciones
      • POST: Crea nuevos recursos. Como retorno, se ofrece el ID automáticamente creado
      • GET: Lista un recurso
      • PUT: Reemplaza un recurso con otro (Útil para el update)
      • DELETE: Elimina un recurso

    Entonces por ejemplo si se quisiera eliminar el empleado con ID 3520 se haría un request con DELETE a la siguiente URL desde el cliente:/span>
    http://example.com/miservicio/empleados/3520

    Conclusión

    REST, que es una arquitectura y no un protocolo como SOAP, se basa en acciones sobre recursos, para permitir la interacción de un cliente con un servidor. La implementación sobre HTTP es la más común y ha permitido la creación de otras tecnologías. Por ejemplo Microsoft, que se ha basado en este tipo de implementación REST para generar el estándar OData (Open Data) sobre el cual se construyó WCF Data Services (antes conocido como ADO.NET Data Services), y que permite simplificar el acceso interoperable a las capas de datos en aplicaciones n-tier.



  • WarNov Developer Evangelist

    Detalles de Instancias de Cómputo y Cobro en Windows Azure

    • 1 Comments

    Para comprender el detalle de cómo se cobra Windows Azure, primero observemos los detalles de las instancias que lo conforman.

    Las instancias son las unidades operativas de Azure. Cada una de ellas es completamente dedicada (no compartida) para nosotros. La mínima instancia en Azure es la instancia pequeña, que se muestra en el slide. Sin embargo, uno puede armar instancias más grandes: hasta de 8 procesadores de 1.6GHz cada uno. Obviamente esta instancia aparece como una sola con el cuádruple de poder de una pequeña:

    clip_image002

    Cada instancia corre Windows Server 2008 R2 de 64 bits en modo core (sin interfaz gráfica) por lo cual la única manera de acceder a esas instancias es a través del API de Windows Azure. Sobre esta API está por ejemplo construido el Portal del Desarrollador de Windows Azure que es el que nos permite crear cuentas, instancias, configuraciones y despliegues vía web. Esta API está disponible gratuitamente y a través de ella podemos programar fácilmente clientes que se ajusten a nuestras necesidades.

    Cualquier aplicación que corra bien sobre Windows Server 2008 R2 x64 puede correr en Windows Azure siempre y cuando no requiera permisos de administrador para correr correctamente. Además teniendo en cuenta que tenemos los servicios de IIS7, también podremos ejecutar aplicaciones PHP, Fast CGI, etc.

    Además, teniendo en cuenta el modelo de deployment sobre Azure, será necesario que cualquier aplicación que queramos correr en sus instancias pueda empaquetarse dentro del bin de una aplicación .net, para luego ser desplegada. Así pues, podría subirse cualquier .exe y .dll construidos aún en forma nativa (no .net ni C++ de Visual Studio)

    Ya con el concepto de instancia de cómputo claro, observemos las generalidades de los costos en dólares:

    clip_image004

    Aquí se nos indica que cada instancia (pequeña) funcionando por una hora nos cuesta 12 centavos de dólar.

    El cobro de las instancias tiene ciertas particularidades. Se cobran las instancias qque hayan sido desplegadas (deploy). Así estén en Staging o Production, se cobran. Si tenemos una en production y otra en staging, las dos serán cobradas. Si tenemos alguna instancia en modo suspendido, ésta también se cobrará, porque sus recursos están separados para que nadie más la pueda usar. Así que lo más recomendable cuando se sepa que una instancia no se usará, es eliminarla.

    Las fracciones de hora son cobradas como horas completas. Por ejemplo, si encendemos una instancia desde las 10:50 hasta las 11:10, se nos cobrarán dos horas: la primera de 10:50 a 11:00 y la segunda de 11:00 a 11:10. Sin embargo cualquier instancia desplegada por menos de 5 minutos, no será cobrada.

    En cuanto a SQL Azure no hay detalles especiales acerca del cobro. Sólo es necesario saber que se nos cobra US$9.99 por cada gigabyte de base de datos usado al mes. Podemos comprar bases de datos de 1 a 5GB en la versión web y de 10 a 50GB en la versión Business:

    image

  • WarNov Developer Evangelist

    La guía total del Marketplace de Windows Phone 7

    • 0 Comments

    ABSTRACT: En este post condenso en un artículo en Español, todo lo que ustedes, desarrolladores de Windows Phone 7 deberían saber acerca del marketplace, cuando ya vayan a subir sus aplicaciones a dicho portal, para comercializarlas. No se tratan aspectos técnicos. Se muestran las reglas más importantes al trabajar con el marketplace, así como links para obtener información más detallada. Si requieren aprender a programar aplicaciones de Windows Phone 7, les recomiendo este post.

    El marketplace de Windows Phone 7 es un portal en el cual podemos poner nuestras aplicaciones para este sistema operativo, de manera que puedan ser exploradas y descargadas/compradas por nuestros clientes.

    La única forma de comercializar aplicaciones para WP7, es a través de este marketplace. No se pueden instalar aplicaciones comercialmente de otro modo. Ni siquiera con los conocidos “Jailbreaks”.

    Aplicaciones en modo de prueba para desarrollo se pueden instalar directamente desde la computadora a un teléfono si éste está desbloqueado para desarrollo.

    Este desbloqueo requiere suscribirse al marketplace de WP7, para identificarnos como desarrolladores.

    Entonces, tanto si queremos subir aplicaciones o desbloquear en modo desarrollo algún WP7, es necesario suscribirse al Marketplace. Solo mayores de 18 años pueden suscribirse.

    image

    Una guía completa para la suscripción al Marketplace la encuentran aquí. Si tiene problemas en el registro, consulte este post.

    La suscripción sólo está disponible para algunos países entre los cuales se encuentra Colombia, Chile y México en Latinoamérica.

    Esta suscripción es gratuita si la persona que se está suscribiendo es un estudiante perteneciente al programa DreamSpark de Microsoft. En otro caso tiene un costo cercano a los 100 dólares anuales, que se pagan con una tarjeta de crédito. Y que permiten publicar hasta 100 aplicaciones gratuitas en el marketplace. Después de exceder este límite, cada aplicación gratuita publicada tendrá un costo de $19.99. Las aplicaciones pagas no tienen límite. Tras tener la suscripción al marketplace, se pueden subir tantas como sea deseado.

    Condiciones de la tarjeta de Crédito:

    En ocasiones al hacer el registro en el marketplace, a pesar de usar una tarjeta de crédito válida la operación no puede realizarse. Esto puede ocurrir por los siguientes motivos:

    1. El nombre en la tarjeta no coincide con el nombre usado para el registro.

    2. La dirección de la tarjeta ingresada no coincide con la dirección registrada en los registros del banco que emitió la misma tarjeta.

    3. Si el LiveID usado para el registro en el Marketplace ya ha sido usado en otros servicios online de Microsoft como por ejemplo Xbox LIVE, la información de ambas cuentas debe ser precisa e idéntica.

    Si se siguen presentando problemas tras chequear los anteriores pasos, se puede contactar al soporte para asistencia.

    Registro de Compañías:

    El registro en el marketplace se puede hacer como individuos o estudiantes (casos anteriormente descritos) y también como compañías. Este caso es especial, pues requiere una aprobación especial por un partner de Microsoft llamado GeoTrust que constata que toda la información suministrada acerca de la compañía sea correcta. Es un mecanismo para proteger su compañía de usuarios inescrupulosos que quieran usar su nombre para vender una aplicación. Una vez verificado esto, se envía un email a la persona ingresada como el Aprobador Corporativo para que apruebe la suscripción final al marketplace. Es probable que si GeoTrust lo considera necesario, solicite información física acerca de la compañía.

    Desbloqueo de teléfonos tras la suscripción al marketplace:

    Basados en el tipo de cuenta, existen límites en la cantidad de dispositivos que se pueden desbloquear:

    Cuentas individuales y de compañías: Se pueden desbloquear 3 dispositivos y se permite transferir hasta 10 aplicaciones en modo desarrollo a cada uno de los dispositivos.

    Cuentas de estudiantes: Se puede desbloquear 1 dispositivo y se permite transferir hasta 10 aplicaciones en modo desarrollo a éste.

    Cómo subir aplicaciones al Marketplace?

    Una vez registrados correctamente en el marketplace, el paso siguiente es subir las aplicaciones que queremos vender o distribuir gratuitamente. Aparte de subir el archivo .xap (el paquete de aplicación que publicaremos), debemos indicar el tipo de distribución que deseamos, pues en el marketplace podemos poner aplicaciones en modo Beta, para que nuestros clientes la prueben y nos den feedback. También podemos escoger la modalidad de distribución privada por ejemplo para aplicaciones empresariales y la distribución pública. Más detalles de los tipos de distribución, los encuentran aquí. Y aquí hay todo un tutorial acerca del proceso completo.

    Precios de las aplicaciones:

    Si queremos que la aplicación sea gratuita, en el formulario de publicación escogeremos el precio de $0. Luego, el mínimo precio posible es el equivalente en pesos a USD$0.99 y el máximo es el equivalente a USD$499.99

    En dónde estará disponible la aplicación?

    Se puede escoger en qué países se puede distribuir la aplicación. Pueden ser solo algunos, o todo el mundo donde exista marketplace activo.

    Cómo se retira una aplicación del Marketplace?

    Se debe esperar hasta que sea aprobada y luego desde el portal se escoge la opción de un-publish.

    Se pueden cobrar actualizaciones a las aplicaciones?

    No. La única vez que se puede cobrar una aplicación es la primera vez que es comprada.

    Certificación de Aplicaciones:

    Con el fin de ofrecer a sus usuarios la mejor calidad en aplicaciones de WP7, Microsoft ejecuta un riguroso proceso de certificación sobre las aplicaciones que desean ser publicadas en el marketplace.

    Este proceso evalúa condiciones que si no son cumplidas, no permiten que la aplicación se publique en el marketplace. Las condiciones son de los siguientes tipos:

    1. Reglas de Negocio: Estas reglas incluyen aspectos como que Las aplicaciones deben publicarse completas y no pueden exigir pagos a los usuarios para desbloquear contenidos adicionales. No pueden vender o promocionar planes móviles de voz. Y en general muchas reglas de este estilo, que se pueden consultar exactamente aquí.

    2. Reglas de Contenido: Establecen que por ejemplo los juegos deben incluir su clasificación. O que contenidos violentos o sexuales explícitos no son permitidos. También da indicaciones acerca de contenidos licenciados, logos y demás. Una completa guía aquí.

    3. Requerimientos en el paquete subido: Son las normas que debe cumplir el .XAP en su compilación, su archivo de manifiesto, etc., así como en los archivos que lo acompañan, como son los screenshots de la aplicación y la iconografía de la misma. Los detalles están aquí.

    4. Requerimientos Técnicos: Aquí se dictan normas acerca de la fiabilidad de la aplicación (manejo de excepciones, etc), desempeño y manejo de recursos (tiempos de renderizado, respuesta de la aplicación tras presionar los botones estándar del teléfono, empleo de memoria RAM, etc), funcionalidad del teléfono (que no haya interferencia con la calidad en las operaciones propias del teléfono como el tiempo en que se puede hacer una llamada, o enviar o recibir un SMS, etc) , Seguridad (no virus, malware ni algoritmos maliciosos), Contenido (manejo de temas que se vean fácilmente, localización del lenguaje), y finalmente, la Información de Soporte Técnico (se debe incluir el nombre de la aplicación, su versión y los datos de contacto para el soporte técnico, ubicados en una sección fácil de encontrar). Detalles más específicos acerca de estos requerimientos técnicos los puede encontrar aquí.

    5. Requerimientos adicionales de acuerdo al tipo de aplicación: Hay reglas que deben seguir las aplicaciones que son especiales por cuento usan la funcionalidad extendida del teléfono. Por ejemplo cuando tienen capacidades de geolocalización, o cuando usan las conocidas “Push Notification”, o cuando corren con el teléfono bloqueado o cuando son aplicaciones multimedia, de streaming o transferencia en segundo plano. Detalles aquí.

    En general el proceso de envío, certificación y publicación de una aplicación WP7, se puede resumir en la siguiente gráfica:

    Se necesita un certificado digital para firmar la aplicación que se sube al Marketplace?

    No, el marketplace provee uno.

    Qué pasa cuando mi aplicación no es certificada?

    Se recibe un documento que muestra cuáles fueron los puntos de falla para ser corregidos. Este es un PDF descargable del sitio que tiene información de este estilo:

    Además de esto, se pueden hacer preguntas acerca de la solución a los errores presentados a los foros

    Cuánto tarda el proceso de Certificación?

    Puede tomar en promedio 5 días hábiles. Si tarda más de 7 días hábiles, hay que contactar a soporte. Hay una opción para hacerlo desde el portal.

    Puede un comprador pedir la devolución de su dinero por una aplicación del marketplace que no le gustó?

    No. No es posible. En Microsoft recomendamos que ud. provea funcionalidad de prueba para que los consumidores puedan probar antes de comprar. Aquí mostramos cómo crear aplicaciones tipo trial.

    Cuál es el pago que obtengo por mis aplicaciones?

    Se obtiene un 70% del valor de venta. Este es enviado a su cuenta bancaria una vez alcance un mínimo de USD$200 en ventas. Para que el dinero pueda ser enviado a su cuenta bancaria, ud. debe proveer los siguientes datos: Número de cuenta y número BIC/Swift (este último se puede preguntar en su respectivo banco). Estos datos se ingresan en el App Hub en la pestaña de pagos.

    Una vez comprada una aplicación en cuántos teléfonos se puede instalar?

    La licencia incluye la instalación en 5 dispositivos.

    Hay alguna forma para solicitar que mi aplicación tenga un mercadeo especial en el marketplace?

    No. En estos momentos este es un proceso que determina el equipo de mercadeo de Windows Phone 7.

    Puedo obtener soporte Premium al desarrollar mis aplicaciones?

    Sí. Hay dos tipos de soporte Premium. El primero es a través de llamadas telefónicas. De 4 a 8 horas, tiene un costo de USD$259 y por email, un día cuesta USD$99. Para contratar este soporte visite la página de Microsoft Support e ingrese “Windows Phone Developer Tools”en el Product Finder.

    Si su problema no es de desarrollo sino de registro y Sign-in, entonces el soporte será gratuito escribiendo aquí.

    De igual forma, los foros del App Hub, son gratuitos y brindan guía en todos los temas relacionados con Windows Phone 7, desarrollo de aplicación y comercialización de las mismas.

    Existen reportes que me informen cómo se está comportando mi aplicación y cómo van sus ventas o descargas?

    Sí, en el App Hub, encuentra una herramienta de reportes que muestra el número de descargas incluyendo las aplicaciones trial, las free y las pagas. Los reportes aquí mostrados tuenen un delay de 6 días. Este delay es generado por el tiempo en que las transacciones con tarjeta de crédito tardan en llevarse a cabo. También se dispone de un reporte de los “Payouts” o transferencias a su cuenta del dinero ganado por la venta de sus aplicaciones. Todos estos reportes se pueden exportar a Excel. Por si fuera poco, un reporte de los errores que ha estado teniendo su aplicación está disponible también En este reporte puede observar el contenido de los Stack Traces, para determinar cuál es el motivo de los errores. El delay de los reportes de Crash es de 3 días.

  • WarNov Developer Evangelist

    Ultima Hora en SQL Azure

    • 0 Comments

    Importantes anuncios acerca de SQL Azure fueron emitidos durante el Tech Ed 2010 en Nueva Orleans. Evento organizado por Microsoft en el cual se tratan los últimos temas de nuestras tecnologías tanto de IT como de Desarrollo.

    Recién salidos del horno, aquí están para ustedes los últimos acontecimientos al respecto:

    1. SQL Azure aumenta el tamaño por base de datos!
      • Si! Pasa de 10GB a 50GB
      • Esta oferta estará disponible a partir de Junio 28

        image
    2. Preview de Data Sync Service
      • Un servicio que le ofrece a sus clientes flexibilidad y control sobre sus datos, permitiéndoles tomar decisiones discretas y granulares acerca de cómo sus datos son distribuidos a través de múltiples datacenters en regiones geográficas distintas. En http://www.sqlazurelabs.com pueden inscribirse para recibir una invitación de prueba del servicio.
    3. SQL Server Web Manager para SQL Azure (SSWM)
      • El CTP de esta herramienta será lanzado en este verano. Es una herramienta ligera para administración de Bases de Datos SQL Azure via Web (en varias conferencias ya me habían preguntado si no iba a haber una herramienta de este tipo). Está diseñada especialmente para desarrolladores Web y otros profesionales que buscan una solución directa para poder desarrollar y distribuir y administrar rápidamente sus aplicaciones orientadas a datos en la nube. Las funcionalidades aunque básicas, permitirán las operaciones más frecuentes del día a día: Creación y ejecución de consultas, diseño y edición de esquemas de DB, edición de datos de tablas.
    4. Acceso a bases de datos de SQL Azure a través de Microsoft Access 2010:
      • Access soporta la conexión a SQL Azure a través de ODBC (tablas linkeadas o consultas pass-through). Con esto se abren oportunidades para los usuarios de Access y proveedores de tecnología para crear experiencias enriquecidas usando el cloud computing. Para los Information Workers, esto les da una forma sencilla para conectarse directamente desde Access a Bases de Datos relacionales en la nube, ofreciendo facilidad de uso y flexibilidad de IT. Ahora hay más posibilidades para escoger cómo integrar aplicaciones de cliente enriquecido que se pueden conectar directamente tanto a la nube como a bases de datos on-premise creando soluciones únicas y ágiles.
      • Se necesitará usar el cliente “SQL Server Native Client 10.0” que viene con la instalación de SQL Server 2008 R2 (con un Express es suficiente para quedar con el driver. Posteriormente estaré publicando un video post que nos muestra cómo hacer esta conexión. 
        image 
    5. Soporte a Datos Espaciales!
      • También se prevé que para este verano tengamos disponible esta gran característica que nos permitirá almacenar el tipo de dato Spatial para guardar información basada en la locación (como coordenadas geográficas). Esto es muy necesario para operaciones espaciales como el mapeo, el cálculo de distancia entre puntos, saber si una locación está en una región dada, etc.

    6. Tablas del Sistema: Ya es posible acceder a la metadata de las bases de datos a través de las tablas del sistema. Es así como una consulta como esta:
    SELECT COUNT(*) from information_schema.tables 
    WHERE table_type = 'base table'

    Puede ejecutarse sin problemas en SQL Azure!

     

    Como ven, la evolución de SQL Azure, como de toda la plataforma de Azure en general, es vertiginosa. Y en este momento tenemos la oportunidad de ser pioneros y aprovechar toda esta tecnología para desarrollar software como nunca antes, obteniendo los mejores resultados, con los costos más bajos.

    Por cierto… qué soluciones se les ocurre cuando piensan en una base de datos en la nube? Comenten y déjenoslo saber!

     




  • WarNov Developer Evangelist

    Certificaciones gratis para estudiantes, con Microsoft DreamSpark

    • 0 Comments

     

    DreamSpark es un programa que ofrece herramientas Microsoft de forma gratuita a estudiantes secundarios y universitarios.

    Actualmente DreamSpark tiene una promoción en la cual está entregando códigos de certificación gratuitos para estudiantes, válidos hasta el 30 de junio.

    Hay un número limitado de códigos, así que pide el tuyo ya.

    1. Ingresa a DreamSpark www.dreamspark.com

    clip_image002

    2. Debes hacer sign-in con una cuenta de Windows Live.

    clip_image004

    3. Debes verificar tu suscripción: Seleccionar Colombia, que eres estudiante y que tienes un código de activación y debes poner el código que viene impreso en el volante (incluyendo los guiones).

    clip_image006

    clip_image008

    Ya estás en DreamSpark. Puedes empezar a descargar y usar el software que allí te entregamos.

    4. Para pedir tu código para los exámenes de certificación, debes ir al menú Download Software/Certifications

    clip_image010

    5. Allí obtienes el código de certificación (Get Key)

    clip_image012

    6. Luego tienes que ir a la página de Prometric, para redimir el código de certificación. http://prometric.com/microsoft. Botón Start.

    clip_image014

    7. Escoges Programar una cita

    clip_image016

    8. Seleccionas el País

    clip_image018

    9. Seleccionas tipo de examen. Importante, seleccionar “Microsoft Academic (072, 094)”. El código solo es válido para estos exámenes.

    clip_image020

    10. Debes aceptar la política de los exámenes académicos-

    clip_image022

    11. Seleccionas el examen que vas a presentar.

    clip_image024

    12. Seleccionas el centro de pruebas que te quede más cerca para presentar el examen

    clip_image026

    13. Debes ingresar con tu usuario Prometric, o crear uno nuevo si no lo tienes

    clip_image028

    14. Seleccionas Fecha y hora del examen

    clip_image030

    15. En Información de Pago debes seleccionar YES en la opción Promotion Code

    clip_image032

    16. Luego seleccionas Voucher Number. Escribes el número que te dieron en el portal de DreamSpark o el que viene impreso en la tarjeta física.

    clip_image034

    17. Una vez validado el código, confirmar el registro al examen.

    Ya estás registrado. ¡Ahora a estudiar!

  • WarNov Developer Evangelist

    Introducción a Generic Handlers en ASP.NET

    • 2 Comments

    Un Generic Handler (GH) es una clase de objeto .NET que puede procesar http requests, sin necesidad de estar dentro del scope de una página aspx (que está dirigida a presentar salidas de tipo HTML clásico). Un ejemplo de GH es el HTTP Handler. Como es bien sabido un http Handler se puede asociar a cualquier extensión de archivo (de acuerdo a lo permitido por el IIS). Los GH sin embargo, solo se pueden asociar a la extensión ASHX que está directamente soportada por los proyectos web en visual Studio 2005 y posteriores. Así que los GH en .NET se asocian a archivos con extensión ASHX.

    Todos los Handlers implementan System.Web.IHttpHandler. Además, en IIS 7 se puede alojar cualquier Handler directamente.


    El hecho que el GH pueda correr fuera del entorno de una página y aparte procesar HTTPRequests, lo hace una herramienta perfecta para ofrecer servicios similares a los que ofrecería un Web Service. De esta manera, es un muy buen candidato para reemplazarlos, cuando no se pueden implementar ya sea por requerimientos del negocio o requerimientos no funcionales.

    Por qué puede no ser deseado un WebService?

    Según la arquitectura y requerimientos de algunos clientes, es mejor recibir resultados a través de HTTPRequest "simple", debido a que por ejemplo el llamado se hace desde una plataforma distinta a .NET desde la cual se hace bastante complejo crear un llamado a un WebService, tal vez porque la herramienta no puede manejar todos los tipos estándar en los WebServices (como sucede por ejemplo con PHP antiguo).

    Entonces por qué no hacer una página Web Normal que responda a los llamados?

    Si se crea una página aspx que responde a las peticiones se incurre en adicionales encabezados y todo el overhead adicional que genera la creación de una página completa (ciclo de vida, viewstate, etc), cuando en realidad sólo se desea obtener una simple respuesta (una imágen un xml, etc).

    Entonces para ganar performance y facilidad de administración en este tipo de funciones, es posible crear un Generic Handler sin dejar de atender al requerimiento de que la comunicación permanezca sencilla.

    Entre los métodos obligatorios al estarse implementando IHttpHandler está ProcessRequest que es el que ejecuta el proceso requerido y por ende al fnal de su alcance habrá de tener un llamado a context.Response.Write o similar, que devuelva una respuesta http. Esta respuesta puede ser html, txt plano, imágenes, xml, etc.

    Uso Avanzado 

    Suponga le siguiente escenario: Existe un objeto en memoria que se desea presentar al usuario como una página html.

    Opciones:

    1. Serializar el objeto a XML, leer el XML y pasarlo a un XSLT que crea el HTML, y grabarlo en un archivo que luego es presentado en un IFrame. Como es obvio, el overhead de crear y borrar estos archivos físicos generados es absolutamente inaceptable.
    2. Otro enfoque es incluir en la página un control XML que muestre el objeto serializado y en el cual luego de hacer la transformación se vea el HTML como tal. Es una alternativa muy aceptable que a primera vista no tiene ninguna desventaja, excepto el mismo overhead y tamaño que implica una página ASP.NET.
    3. Generic Handler: Se obtiene un control más directo sin el overhead que implica agregar un control XML a una página que además tendrá otros elementos que sumaran innecesariamente peso al resultado.

    Cómo se Logra?

    Al crear un GH, éste puede ser llamado como cualquier otra página aspx. (Por ejemplo desde un browser) Además también pueden aceptar parámetros: http://warnov.com/miGH.ashx?param=valor;otroparam=otrovalor a través de su URL. Para incluir un GH en su aplicación Web, solo agreguelo como un nuevo item en el proyecto en Visual Studio.

    En el caso especial de querer mostrar un objeto serializado en XML y transformado a través de XSLT es bastante sencillo: Solo se tiene que incluir en el XML la directiva de transformación XSLT y el archivo XSLT se ha de encontrar en la ruta que allí se especifica.

    Conclusión:
    Como se observa, son muchas la aplicaciones que tienen estos objetos y es considerable la ganancia que se obtiene con su uso, aunque en general pasan muy desapercibidos.

  • WarNov Developer Evangelist

    Requerimientos para desarrollar en Windows Azure (Software - Hardware)

    • 4 Comments

    Computadora con con IIS 7 instalado. Esto automáticamente restringe los posibles sistemas operativos a Windows 7, Windows Server 2008, Windows Vista. Preferiblemente en x64 (64-bits). Si no tienen la licencia, se puede descargar un trial de aquí.

    Requerimientos de Hardware:

    o Computer with a 1.6GHz or faster processor
    o 1024 MB RAM (1.5 GB if running in a virtual machine)
    o 3 GB of available hard-disk space
    o 5400 RPM hard drive
    o DirectX 9 capable video card running at 1024 x 768 or higher-resolution display

    Además:

    · Sql Server 2008 R2 Express Edition  y SQL Server Management Studio 2008 R2 Express Edition (Tener la instancia SQLEXPRESS para el Development Storage)

    o Se descarga de aquí

    · Visual Studio 2010 Ultimate. Si no tienen la licencia, se puede descargar un trial de aquí. También se puede usar Visual Web Developer Express, pero algunas operaciones de Azure no estarán disponibles.

    · Windows Azure Tools for Microsoft Visual Studio descargables aquí

    · Windows Azure AppFabric SDK descargable de aquí

    · Windows Azure Training Kit descargable de aquí.

    · Opcional: Prelectura de estos artículos

  • WarNov Developer Evangelist

    CTE: Common Table Expressions – SQL Server 2008

    • 4 Comments

    Este es el primero de una serie de artículos que estaré escribiendo acerca de características de SQL Server 2008 para desarrolladores.

    Un CTE es un artefacto que nos mantiene en memoria el resultado de una consulta, para que lo podamos llamar luego dentro de esa misma consulta. Es como una “variable” temporal que nos evita tener que declarar una vista no persistente, o una tabla temporal.

    La sintaxis es muy sencilla:

    WITH <nombre de su CTE> <nombre de columnas>
    AS
    (
    <query de origen>
    )
    SELECT * FROM <nombre de su CTE>

    Por ejemplo:

    image

    Para qué es útil?

    Imagínense por ejemplo que tienen una tabla de ventas donde están todas las ventas hechas y el ID de los vendedores que las hicieron.

    Piensen que necesitan un reporte donde aparezca el total de ventas y el nombre del vendedor.

    Los datos extendidos del vendedor están en otra tabla. Además como el reporte totaliza la cantidad de ventas se requiere un query con una función de agregado ( count(*) ) Dado que existe este agregado no es posible usar un simple join, sino que tendríamos que usar una subconsulta o una tabla temporal:

    select Vendedores.FirstName, VentasAgrupadas.VentasTotales from
    (
       SELECT Sales.SalesOrderHeader.SalesPersonID, COUNT(*) as VentasTotales
       FROM Sales.SalesOrderHeader
       WHERE Sales.SalesOrderHeader.SalesPersonID IS NOT NULL
       GROUP BY Sales.SalesOrderHeader.SalesPersonID
    ) as VentasAgrupadas
    inner join Sales.vSalesPerson as Vendedores on Vendedores.SalesPersonID=VentasAgrupadas.SalesPersonID
    order by VentasAgrupadas.VentasTotales

    Como se aprecia esto es engorroso y poco claro.

    Con un CTE es mucho más sencillo, ya que no existe la necesidad de la subconsulta sino que parece como si declaráramos una variable de tipo tabla o vista con los resultados que queremos:

    WITH VentasAgrupadas(IdVendedor, VentasTotales)
    as
    (
      SELECT Sales.SalesOrderHeader.SalesPersonID, COUNT(*)
      FROM Sales.SalesOrderHeader
      WHERE Sales.SalesOrderHeader.SalesPersonID IS NOT NULL
      GROUP BY Sales.SalesOrderHeader.SalesPersonID
    )
    SELECT Vendedores.FirstName, VentasAgrupadas.VentasTotales
    FROM Sales.vSalesPerson as Vendedores
    INNER JOIN VentasAgrupadas ON Vendedores.SalesPersonID=VentasAgrupadas.IdVendedor
    ORDER BY VentasAgrupadas.VentasTotales

    Un caso aún más dramático puede observarse cuando queremos detectar los duplicados de una tabla.

    Por ejemplo si tengo una tabla de productos con Ids distintos pero mismo nombre, la consulta luce así:

    SELECT * FROM Products WHERE ProductID NOT IN
    (SELECT MIN(ProductID) FROM Products as P
    WHERE Products.ProductName=P.ProductName)

    Exótico no?

    Es lo que conocemos como Self-Join en SQL.

    Eso me retorna todos los registros duplicados. Observen que se logra luego de extraer el mínimo id para los duplicados, selecciono todos los duplicados cuyo id no sea ese mínimo, lo que me da como resultado los registros redundantes:

    clip_image003

    Obviamente con un CTE la complejidad del query se reduce completamente:

    WITH MinProductRecords AS
    (
      SELECT MIN(ProductID) AS ProductID, ProductName
      FROM Products
      GROUP BY ProductName
      HAVING COUNT(*) > 1
    )
    
    SELECT Products
    FROM Products AS P
    INNER JOIN MinProductRecords AS MP
    ON P.ProductName = MP.ProductName AND P.ProductID > MP.ProductID

    Aquí aunque hay más código, es más claro y administrable, pues vemos cómo primero seleccionamos los mínimos Ids y luego hacemos un join donde los Ids sean mayores a estos mínimos. Así se obtienen los mismos resultados.

    Entonces si quisiéramos además eliminar de inmediato los duplicados bastaría con reemplazar el último SELECT por un DELETE

  • WarNov Developer Evangelist

    Recursos para Windows Phone 7 Unificados

    • 3 Comments

    Dejemos que este post sea aquél en el que podamos encontrar todos los recursos que necesitamos para poder comenzar a desarrollar aplicaciones basadas en Windows Phone 7 (WP7).

    Material de Aprendizaje:

    Recursos para aprender a programar WP7

    image

    Windows Phone Development QuickStarts

    Unas guías rápidas que enseñan las bases para la creación de aplicaciones WP7. Está diseñado para dos tipos de audiencias. Los totalmente nuevos en WP7 y aquellos que tienen experiencia en la programación WP7, pero quieren aprender un poco.

    Update: Si desean estos recursos en español, los pueden encontrar aquí: Tutoriales de Desarrollo para Windows Phone–totalmente en español y gratuitos

    image

    Windows Phone 7 Development for Absolute Beginners

    Serie de videos de Channel 9, que ayudan a los desarrolladores aspirantes a dominar el desarrollo en WP7 a iniciar. Contiene código en C# y VB.

    image

    Windows Phone 7 in 7 Minutes!

    Videos de WP7 con cada uno de ellos mostrando directamente una característica de desarrollo en WP7 en menos de 7 minutos.

    image

    Windows Phone Virtual Labs

    Laboratorios virtuales que te permiten evaluar o aprender rápidamente cómo construir aplicaciones para WP7 a través de una serie de laboratorios que pueden ser completados en 90 minutos o menos. La mejor parte es que al ser un laboratorio virtual de MSDN, no se requiere instalación de ningún tipo, ya que se nos proveen máquinas virtuales de acceso directo a través de internet, que están disponibles para ti Gratis!

    image

    Windows Phone 7 Training Course

    Este curso de entrenamiento te dará un inicio rápido con la plataforma WP7 al proveer explicación paso a paso delas herramientas y conceptos claves para programar WP7.

    image

    Programming Windows Phone 7

    Este libro es un regalo del equipo de WP7 de Microsoft a la comunidad desarrolladora, escrito por Charles Petzold. Muestra los fundamentos de las aplicaciones para WP7 usando C# y XNA. Contiene laboratorios y videos.

    azure-logo

    Windows Phone 7 And The Cloud

    Laboratorio guiado que nos enseña los pasos necesarios para construir una aplicación Silverlight para Windows Phone 7, que consume servicios WCF Data Services de una aplicación hosteada en Windows Azure

    image_thumb1

    Windows Phone Programming in C#

    Este material, creado por Rob Miles, es una introducción al desarrollo de Windows Phone 7. Contiene 8 secciones con laboratorios, presentaciones de PowerPoint, demostraciones y notas detalladas.

    Recursos del Sistema

    Requerimientos de Sistema Operativo de la PC de desarrollo

    Sistemas Operativos Soportados: Windows 7 y Windows Vista

    • Windows Vista (x86 y x64) con Service Pack 2 – Todas las ediciones (Excepto Starter Edition)
    • Windows 7 (x86 y x64) – Todas las ediciones (Excepto Starter Edition)

    Datos adicionales:

    • La instalacion requiere de 3GB de espacio libre en disco
    • Memoria RAM: 2GB minimo
    • El emulador de Windows Phone 7 requiere una tarjeta grafica con capacidad de soportar DirectX 10 con el driver WDDM 1.1

    NO es recomendable el uso de Maquinas Virtuales mas detalles aqui

    Herramientas para desarrollar aplicaciones
    • Descargue las herramientas gratuitas aqui
      • Beta para trabajar con Mango
      • Beta 2 para trabajar con Mango
    • Descargue e instale la actualización de Enero de 2011 aqui
    • Opcionalmente si desea puede obtener las herramientas para desarrollo de Windows Phone 7 con Visual Basic .NET aqui
    • Visite el Create App Hub aqui

    Más información de Windows Phone 7 aquí.

  • WarNov Developer Evangelist

    Entity Framework vs. LINQ como ORM

    • 6 Comments

    LINQ inició siendo una teconología que servía tanto para consultar objetos en memoria, como para mapear tablas de bases de datos SQL a objetos de memoria. Así que luego de hacer el mapeo, con nuestro mismo lenguaje de programación sin necesidad de escribir comandos SQL a través de LINQ tendríamos la posibilidad de hacer consultas y manipulaciones sobre estas entidades en memoria sin mucho problema.

    Visto esto, observamos que con LINQ tenemos dos alcances: Como lenguaje de consultas integrado y como ORM.

    LINQ fue primero que EntityFramework; al principio LINQ "quizo" ser el ORM de Microsoft, pero demostró algunas deficiencias en ciertos aspectos como la conexión a distintos repositorios. Luego vino el EntityFramework a mejorar esas cosas en las que LINQ tenía debilidades. Pero OJO! EntityFramework solo se ocupa de las operaciones de un ORM. Y el hecho de que haya aparecido, no significa la desaparición de LINQ, dado que LINQ aparte de tener esas caractarísticas de ORM, es un potente lenguaje de consultas integrado que permite consultar tanto entidades (como las arrojadas por EntityFramework, el mismo LINQ o cualquier otro ORM), como objetos personalizados, XML, ActiveDirectory y en general cualquier estructura de datos .NET en memoria que implementen IQueryable (http://msdn.microsoft.com/en-us/library/bb546158.aspx)


    En últimas, yo recomendaría usar EntityFramework para hacer ORM y luego usar LINQ para ejecutar consultas muy sencillamente sobre las entidades generadas por el ORM. (Y sobre cualquier otra colección de datos).

  • WarNov Developer Evangelist

    Carga Dinámica de CSS en ASP.NET

    • 2 Comments

    Los descubrimientos descritos a continuación, surgieron de mi necesidad de cargar CSS dinámicamente sin estar creando numerosos temas dentro de una aplicación WEB ASP.NET. Esto es, separar la administración de CSS de los temas. Así un mismo tema podrá tener varios CSS a petición.

    En primera instancia: Toda página que referencie un tema, SIEMPRE cargará todos los CSS incluidos en el mismo, independientemente de que en realidad los necesite, y del nivel de anidamiento en el que se encuentren ubicados. Poco eficiente no es así?

    Como se sabe, los CSS finalmente son Links referenciados en el HEAD de la página que está referenciándolos. Entonces es cuestión de escribir dinámicamente allí la ruta del CSS que se desea cargar y listo.

    Lo anterior se logra agregando un ASP.NET literal control dentro del HEAD, y en el load de la página ajustarlo con el valor que se desea.

    Y listo!!!

    A pesar de que existan varios CSS en la misma ruta de aquel que está siendo referenciado, solo el referenciado se descarga.

    Ventajas?

    • Tener organizados varios CSS y no solo uno gigantesco con todo.
    • En cuanto a ancho de banda, si los CSS se dejan dentro de temas, por más separados que estén si son cargados por medio de referencia al tema desde la página, siempre bajan todos la primera vez que se llamen (luego quedan en el caché y no vuelven a descargarse si no se borra el caché o si no cambian en el server).

    Conclusión:
    Si se desea optimizar el tiempo de descarga, entonces es mejor no usar Themes para cargar los estilos, sino que estos se carguen independientemente usando el modelo de HEAD descrito anteriormente.

    Ejemplo:

    Dado que me han pedido mucho un ejemplo en código aquí va:

    Aspx

    <html xmlns="http://www.w3.org/1999/xhtml">
    <head runat="server">
        <asp:Literal ID="Literal1" runat="server"></asp:Literal>
        <title></title>
    </head>
    <body>
        <form id="form1" runat="server">
        <div>
            <asp:Label ID="Label1" runat="server" Text="Este es un ejemplo de texto"></asp:Label>
            <asp:TextBox ID="TextBox1" runat="server"></asp:TextBox>
        </div>
        </form>
    </body>
    </html>
    

     

    Codebehind

    using System;
    
    namespace WebApplication1
    {
        public partial class WebForm1 : System.Web.UI.Page
        {
            protected void Page_Load(object sender, EventArgs e)
            {
                Literal1.Text = "<link href='Styles/Site.css' rel='stylesheet' type='text/css' />";
            }
        }
    }
    

     



  • WarNov Developer Evangelist

    Web Camp Colombia 2010

    • 12 Comments

    Las inscripciones para este evento ya están abiertas aquí

    Siento un gran agrado al poder estar organizando el primer evento en Colombia en el que estaremos tratando durante un día completo temas relacionados con desarrollo Web usando estándares y empleando tecnologías y herramientas de Microsoft que lo mejor de todo: SON GRATUITAS

    Los Web Camp son eventos patrocinados por Microsoft que se realizan por todo el mundo y en esta ocasión el turno le ha tocado a Colombia.

    Flair002Flair005

    Es así como el 30 de Noviembre en las instalaciones de Microsoft Bogotá, estaremos llevando a cabo este evento todo el día en en 6 salas distintas simultáneamente, desarrollando un track diferente en cada una de ellas:

    1. WebPI: WebMatrix y CMS Kentico
    2. Windows Azure
    3. IE9 & HTML5
    4. MVC2
    5. REST+JQuery+OData
    6. ASP.NET4

    La parte teórica de los tracks será transmitida gratuitamente vía LiveMeeting a través de 6 hilos de transmisión distintos.

    La jornada que comienza a las 8.30am con el registro y se prolonga hasta las 4pm, se divide en dos grandes etapas: La primera comprende presentaciones teóricas y demos y la segunda comprende laboratorios guiados en los que los asistentes podrán practicar todo lo aprendido con la guía del speaker especialista. Por este motivo, es recomendable que los asistentes permanezcan en un solo track durante todo el día.

    Tendremos la siguiente agenda tentativa para cada uno de los tracks:

     

    Flair001

    8.30 – 9.00 Registro
    9.00 – 10.40 Primera Charla
    10.40 – 11.00 Break (Incluido)
    11.00 – 12.00 Segunda Charla
    12.00 – 13.00 Almuerzo (Incluido)
    13.00 – 15.45 Laboratorios
    15.45 – 16.00 Evaluación Evento y Cierre

     

     

    Como ven, habrá break y almuerzo incluido y es necesario traer laptop para los laboratorios. Posteriormente cuando abramos las inscripciones para el evento, especificaremos los requerimientos necesarios para cada track. Por si fuera poco, para los emprendedores vamos a tener la posibilidad de entrar en los programas de emprendimiento de Microsoft llamados WebSiteSpark y BizSpark a través de los cual tendremos acceso a licencias de herramientas Microsoft para el desarrollo de aplicaciones web, soporte y visibilidad.

    WebSiteSpark:

    BizSpark:

     

    Nuestro Request for Speakers ya ha cerrado y estos son los confirmados:

    JQuery, REST, JSON

    Frank Silva

    Windows Azure

    Gerardo Ramos

    IE9, HTML5, CSS3

    Juan Carlos Ruiz Pacheco

    MVC 2 (3)

    Hugo Zapata

    ASP.NET 4

    Roberto Alvarado

    WebPi: WebMatrix y Kentico

    Marylin Alarcón

     
    Las inscripciones para este evento ya están abiertas aquí
     


  • WarNov Developer Evangelist

    Beneficios de Windows Azure para MSDN y Bizspark

    • 12 Comments

    Los suscriptores Premium, Ultimate y Bizspark de MSDN tienen 16 meses de suscripción gratuita a los servicios de Windows Azure. A partir de noviembre los suscriptores MSDN Professional también la tendrán.

    Qué se debe hacer? para activar este beneficio?

    Si usted es suscriptor a MSDN y aún no ha comenzado a disfrutar de este beneficio visite este sitio para conocer todos los detalles.

    image

    A continuación una guía detallada de cómo acceder a estos servicios:

    Podemos llegar hasta aquí desde MSDN a través de la suscripción a la que tengamos Acceso:

    image

    Luego de esto pasamos a esta pantalla. Dele un nombre a su futura cuenta de Windows Azure, lea y acepte los términos de servicios si lo desea y de clic en siguiente:

    image

    Después, introducimos nuestra identificación y datos de tarjeta de crédito (con fines de identificación personal, pues esta tarjeta no es cargada si los consumos se ajustan a lo establecido dentro de la oferta. Si los consumos exceden a los límite0s de la oferta, en ese caso sí serán cargados)

     image

    Finalmente, tras la validación de la tarjeta de crédito y nuestra identificación personal, pasamos a la confirmación de la adquisición de los servicios. Leemos el contrato de licencia y su deseamos hacemos la compra:

    image

    Esto nos lleva a la sección de Check Out donde se hace efectiva definitivamente la transacción. Chequeamos la marca en la que confirmamos que sabemos que si excedemos los límites de la oferta, estos serán cargados a la tarjeta de crédito:

    Nos aparece entonces una confirmación como esta. Aquí confirmamos la orden.

    9. En la siguiente pantalla, activamos el servicio:

    Aquí se nos confirman los datos de nuestra suscripción y damos Finalizar:

    Luego recibiremos un mensaje de confirmación similar a este:

    Luego abrimos el portal del desarrollador de Windows Azure (http://windows.azure.com) usando el Live ID empleado para la suscripción y veremos nuestro nuevo proyecto de Azure listo para ser trabajado!

    Otra forma de llegar hasta la suscripción:

    1. Visite el portal de  servicios online de Microsoft (Microsoft Online Services Customer Portal (MOCP)). Cambie el país a Colombia, el idioma a español y haga clic en la opción continuar, para pasar a la página Primeros Pasos:

    .image

    En esta página haga Sign in con su Windows Live ID, y luego haga clic en el tab de Servicios  y allí haga click en Comprar ahora en la sección de ofertas especiales

     image

    image

  • WarNov Developer Evangelist

    Configurando identidades y Accesos en IIS 7.5

    • 3 Comments

    Abstract:

    Veremos que IIS 7.5 tiene un nuevo manejo de identidad virtual independiente para sus Application Pools, y que por ende debemos buscarlos de una manera especial cuando queramos asignarles permisos sobre los recursos del servidor, como lo son el sistema de archivos.

    Nivel: Intermedio. Tecnologías: IIS (IIS Application Pool Identities)

     

    Windows 7 y Windows 2008 R2 vienen con IIS 7.5 por defecto.

    Para muchas personas IIS 7.5 puede ser un mundo totalmente diferente; sobre todo si vienen de IIS 6.0 y anteriores. Obviamente estos grandes cambios fueron generados para hacer al servidor más usable, con más características y además más seguro.

    Hablemos de un cambio en seguridad que debemos tener en cuenta si queremos probar o poner en producción nuestros sitios en IIS 7.5.

    IIS es un servidor que corre sobre Windows. Los procesos que corren sobre Windows requieren de un usuario en nombre del cual corren. Aplicaciones como Word, corren en nombre del usuario logueado en el sistema. Pero servicios como IIS corren con usuarios internos del sistema que no requieren de un proceso de logueo que dificultaría lanzar dichos servicios.

    Las últimas versiones de IIS corrían con la identidad de NETWORKSERVICE (tal vez lo recuerden en instalaciones como las de SQLSERVER). Este usuario tiene las limitaciones de un usuario estándar así que los privilegios son bajos, por lo que ofrece cierta seguridad ya que un bug en el servicio no podría ser usado para afectar la máquina.

    Sin embargo, dado que muchos servicios comenzaron a usar este usuario para ejecutarse, lo que sí puede pasar, es que servicios maliciosos corriendo con este usuario puedan afectar y manipular otros servicios o aplicaciones con este mismo usuario, sobre todo cuando hablamos de aplicaciones de terceros que corren sobre IIS.

    Así que esto fue solucionado en IIS 7.5 a través de lo que hoy conocemos como IIS Application Pool Identities. Un mecanismo que permite crear identidades virtuales únicas para cada Application Pool en IIS. Recordemos que en IIS un Application Pool es un entorno de ejecución para las aplicaciones Web que nos permite administrarlas eficientemente. Dicho esto, si por ejemplo para instalar el CMS Orchard usamos un APPPool dedicado llamado Orchard, veremos como IIS crea un usuario virtual llamado Orchard para correr el proceso w3wp.exe (responsable de servir el sitio web como tal):

    image

    Es muy importante tener esto en cuenta sobre todo cuando nuestra aplicación requiere acceder recursos del sistema como el sistema de archivos, pues deberemos darle permisos de lecto-escritura al usuario que ha iniciado el proceso w3wp.exe. En IIS 6 y 7 lo hacíamos con el usuario NETWORKSERVICE pero en IIS 7.5 deberemos especificar el usuario virtual del AppPool donde está corriendo la app. Para lograr esto con la interfaz gráfica hay cierto detalle que no nos permite hacerlo directamente como con cualquier otro usuario, dado que es una identidad virtual:

    image

    Aquí vemos que queremos darle permisos de lecto-escritura sobre el folder App_Data a la identidad orchard que es sobre la cual corre el sitio, pero vemos que la herramienta no encuentra ese nombre (dado que es virtual). Para poderlo encontrar deberemos asegurarnos de que estamos buscando en Built-in security principals, usando la locación de la máquina donde está el server y finalmente anteponiendo IIS APPPOOL\<nombre del pool>:

    image

    Entonces al dar click en Check Names obtendremos:

    image

    Con lo que ya tendremos la identidad justa para accionarle los permisos requeridos.

    Conclusión:

    Vimos entonces que IIS 7.5 tiene un nuevo manejo de identidad virtual independiente para sus Application Pools, y que por ende debemos buscarlos de una manera especial cuando queramos asignarles permisos sobre los recursos del servidor, como lo son el sistema de archivos.

  • WarNov Developer Evangelist

    LINQ: Consultando tablas cruzadas en Visual Studio LightSwitch

     

    LightSwitch es un RAD para hacer aplicaciones basadas en datos bien sea usando Silverlight, o HTML5. En cuestión de minutos podemos tener una aplicación de ese estilo desplegada y funcionando.

    Cuando ya estamos desarrollando una app de cierta complejidad sin embargo, tarde o temprano llegamos a la necesidad de consultar data que se encuentra distribuida en varias tablas en un ambiente relacional.

    Aunque LightSwitch provee un wizard de consultas básicas, éstas últimas requieren la escritura de código.

    El código usado para escribir consultas complejas el LightSwitch no es más que LINQ.

    En mi primer intento de hacer una consulta cruzada con LINQ dentro de LightSwitch sin embargo, a pesar de escribir instrucciones completamente válidas de acuerdo a la definición de LINQ, siempre obtenía un error emitido por LightSwitch, que además dado el mensaje presentado, no da muchas luces de qué es lo que está sucediendo:

    Unable to create a constant value of type ‘LightSwitchApplication.MiTabla’. Only primitive types or enumeration types are supported in this context.

    Pasé mucho tiempo experimentando qué podría ser hasta que descubrí que el error sucede cuando en el where de la instrucción LINQ ponemos dos tablas de la DB directamente. Entonces una solución que se me ocurrió y que mi buen amigo @jramirezdev me ayudó a implementar fue descargar primero unos datos, enumerarlos en una lista y luego con joins lograr el resultado. Sin embargo, dado que esto requiere dos llamados distintos a la DB y además resulta en una consulta LINQ difícil de leer, seguí “escarbando” y encontré una gran ayuda en el operador any  de LINQ, que me permite seleccionar los datos que quiero sin tener que citar varias tablas dentro de LINQ, sino más bien explorando las propiedades de navegación del modelo de objetos.

    En este artículo, he invitado precisamente a @jramirezdev, a quien agradezco el haber escrito el proceso de problema y solución en detalle; algo muy valioso para desarrolladores que estén teniendo este mismo problema:

    ...

    Es muy común que en nuestras aplicaciones tengamos un origen de datos relacional y sobre este debamos realizar consultas en varias tablas para obtener la información que necesitamos. En LightSwitch las consultas simples se puede realizar con el diseñador integrado, pero si este no es el caso debemos recurrir a crear una consulta desde ceros, esto es, usar EntityFramework + LINQ.

    Cuando utilizamos Entity Framework en LightSwitch nos encontraremos con algunas limitaciones, es por esto que debemos ser cuidadosos pues aunque la consulta LINQ compile no significa que al ejecutarla vayamos a obtener los resultados esperados.

    Para entender esto veremos un caso específico donde realizaremos una consulta de tablas cruzadas con LINQ.

    Aplicación: Crearemos una aplicación que permitirá registrar Usuarios, Tiendas y Facturas. Para esto debemos tener en cuenta que una factura será específica de un Usuario y una Tienda, esto significa que debe existir una relación entre Usuario y Tienda para finalmente registrar las facturas de ese usuario en esa tienda.

    Modelo Relacional:

    Problema: Se necesita generar un listado de todas las facturas que existan en las tiendas donde está registrado el usuario "Jorge Ramirez".

    Para resolver este problema comenzaremos por crear una solución de LS, que se vera de la siguiente manera:

    Aquí podemos observar que debajo de la tabla "Facturas" encontramos una consulta llamada "GetFacturasPorTiendasAsociadasAlCliente", es en ese archivo que escribiremos nuestra consulta LINQ.

    Escribiré mi primer consulta de la siguiente manera.

            partial void 
    GetFacturasPorTiendasAsociadasAlCliente_PreprocessQuery
    (
    ref IQueryable<Factura> query) { //Consulta 1 var tiendas = from UsuarioTienda ut in UsuarioTiendas where ut.Usuario.Nombre == "Jorge Ramirez" select ut; var facturas = from Factura factura in query from UsuarioTienda ut in tiendas where factura.UsuarioTiendas.Tienda.Id ==
    ut.Tienda.Id select factura; query = facturas; }
    Semánticamente esta consulta es correcta, pero cuando la ejecutamos obtenemos el siguiente error:

    Resultado Consulta 1: Error.

    Este error aunque pareciera claro, no lo es, pues fácilmente nos confunde el pensar ¿Dónde creamos un Obj del tipo "UsuarioTienda"? Pues bueno, aquí es importante conocer el concepto de que son Propiedades de Navegación de EntityFramework.

    Leyendo este error vemos que existe una limitación para acceder a las tablas relacionadas/cruzadas a través de las propiedades de navegación, lo cual nos indica que debemos considera una solución más del lado semántico de TSQL donde hacemos los JOINS de forma explícita.

           partial void 
    GetFacturasPorTiendasAsociadasAlCliente_PreprocessQuery
    (
    ref IQueryable<Factura> query) { //Consulta 2 var facturas = (from UsuarioTienda utienda in UsuarioTiendas join Usuario usuario in Usuarios on
    utienda.Usuario.Id equals usuario.Id join Tienda tienda in Tiendas on
    utienda.Tienda.Id equals tienda.Id join Factura factura in query on tienda.Id
    equals factura.UsuarioTiendas.Tienda.Id where usuario.Nombre == "Jorge Ramirez" select factura).AsQueryable(); query = facturas; }

    Resultado Consulta 2: Exito.

    De esta forma EntityFramework ha logrado resolver las relaciones y entregarnos la data que necesitamos.

    También podemos considerar otra posibilidad jugando con las propiedades de navegación y una expresión Lambda para que nuestra consulta sea más corta.

            partial void 
    GetFacturasPorTiendasAsociadasAlCliente_PreprocessQuery
    (
    ref IQueryable<Factura> query) { //Consulta 3 var facturas = from Factura factura in query where factura.UsuarioTiendas
    .Tienda.UsuarioTiendas.
    Any(c => c.Usuario.Nombre == "Jorge Ramirez") select factura; query = facturas; }

    Resultado Consulta 3: Exito.

    PROFILING

    Finalmente como un proceso educativo, realizaremos uso de un perfilador (profiler) para ver como se comportan nuestras dos consultas exitosas.

    Consulta 2: Reporte

    Consula 2: Entity SQL Generado

    SELECT TOP (45) [Project1].[Id]     
    AS [Id], [Project1].[RowVersion]
    AS [RowVersion], [Project1].[Producto]
    AS [Producto], [Project1].[Valor]
    AS [Valor], [Project1].[UsuarioTienda_Factura]
    AS [UsuarioTienda_Factura], [Project1].[C1]
    AS [C1], [Project1].[C2]
    AS [C2], [Project1].[Id1]
    AS [Id1], [Project1].[RowVersion1]
    AS [RowVersion1], [Project1].[Tienda_UsuarioTienda]
    AS [Tienda_UsuarioTienda], [Project1].[UsuarioTienda_Usuario]
    AS [UsuarioTienda_Usuario] FROM (SELECT [Project1].[Id]
    AS [Id], [Project1].[RowVersion]
    AS [RowVersion], [Project1].[Producto]
    AS [Producto], [Project1].[Valor]
    AS [Valor], [Project1].[UsuarioTienda_Factura]
    AS [UsuarioTienda_Factura], [Project1].[Id1]
    AS [Id1], [Project1].[RowVersion1]
    AS [RowVersion1], [Project1].[Tienda_UsuarioTienda]
    AS [Tienda_UsuarioTienda], [Project1].[UsuarioTienda_Usuario]
    AS [UsuarioTienda_Usuario], [Project1].[C1]
    AS [C1], [Project1].[C2]
    AS [C2], row_number() OVER (ORDER BY [Project1].[Id] ASC)
    AS [row_number] FROM (SELECT [Extent1].[Id]
    AS [Id], [Extent1].[RowVersion]
    AS [RowVersion], [Extent1].[Producto]
    AS [Producto], [Extent1].[Valor]
    AS [Valor], [Extent1].[UsuarioTienda_Factura]
    AS [UsuarioTienda_Factura], [Extent2].[Id]
    AS [Id1], [Extent2].[RowVersion]
    AS [RowVersion1], [Extent2].[Tienda_UsuarioTienda]
    AS [Tienda_UsuarioTienda], [Extent2].[UsuarioTienda_Usuario]
    AS [UsuarioTienda_Usuario], N'UsuarioTiendas'
    AS [C1], N'UsuarioTiendas'
    AS [C2] FROM [dbo].[Facturas] AS [Extent1] INNER JOIN [dbo].[UsuarioTiendas]
    AS [Extent2] ON [Extent1].[UsuarioTienda_Factura] =
    [Extent2].[Id]) AS [Project1]) AS [Project1] WHERE [Project1].[row_number] > 0 ORDER BY [Project1].[Id] ASC

    Consulta 3: Reporte

    Consulta 3: Entity SQL Generado

    SELECT TOP (45) [Project2].[Id]
    AS [Id], [Project2].[RowVersion]
    AS [RowVersion], [Project2].[Producto]
    AS [Producto], [Project2].[Valor]
    AS [Valor], [Project2].[UsuarioTienda_Factura]
    AS [UsuarioTienda_Factura], [Project2].[C1]
    AS [C1], [Project2].[C2]
    AS [C2], [Project2].[Id1]
    AS [Id1], [Project2].[RowVersion1]
    AS [RowVersion1], [Project2].[Tienda_UsuarioTienda]
    AS [Tienda_UsuarioTienda], [Project2].[UsuarioTienda_Usuario]
    AS [UsuarioTienda_Usuario] FROM (SELECT [Project2].[Id]
    AS [Id], [Project2].[RowVersion]
    AS [RowVersion], [Project2].[Producto]
    AS [Producto], [Project2].[Valor]
    AS [Valor], [Project2].[UsuarioTienda_Factura]
    AS [UsuarioTienda_Factura], [Project2].[Id1]
    AS [Id1], [Project2].[RowVersion1]
    AS [RowVersion1], [Project2].[Tienda_UsuarioTienda]
    AS [Tienda_UsuarioTienda], [Project2].[UsuarioTienda_Usuario]
    AS [UsuarioTienda_Usuario], [Project2].[C1]
    AS [C1], [Project2].[C2]
    AS [C2], row_number() OVER
    (ORDER BY [Project2].[Id] ASC) AS [row_number] FROM (SELECT [Extent1].[Id]
    AS [Id], [Extent1].[RowVersion]
    AS [RowVersion], [Extent1].[Producto]
    AS [Producto], [Extent1].[Valor]
    AS [Valor], [Extent1].[UsuarioTienda_Factura]
    AS [UsuarioTienda_Factura], [Extent2].[Id]
    AS [Id1], [Extent2].[RowVersion]
    AS [RowVersion1], [Extent2].[Tienda_UsuarioTienda]
    AS [Tienda_UsuarioTienda], [Extent2].[UsuarioTienda_Usuario]
    AS [UsuarioTienda_Usuario], N'UsuarioTiendas'
    |
    AS [C1], N'UsuarioTiendas'
    AS [C2] FROM [dbo].[Facturas] AS [Extent1] INNER JOIN [dbo].[UsuarioTiendas]
    AS [Extent2] ON [Extent1].[UsuarioTienda_Factura] = [Extent2].[Id] WHERE EXISTS (SELECT 1 AS [C1] FROM [dbo].[UsuarioTiendas] AS [Extent3] INNER JOIN [dbo].[UsuarioTiendas] AS [Extent4] ON [Extent3].[Tienda_UsuarioTienda] =
    [Extent4].[Tienda_UsuarioTienda] INNER JOIN [dbo].[Usuarios] AS [Extent5] ON [Extent4].[UsuarioTienda_Usuario] =
    [Extent5].[Id] WHERE ([Extent1].[UsuarioTienda_Factura] =
    [Extent3].[Id]) AND (N'Jorge Ramirez' = [Extent5].[Nombre])))
    AS [Project2]) AS [Project2] WHERE [Project2].[row_number] > 0 ORDER BY [Project2].[Id] ASC

    Nota: El perfilador usado fue Entity Framework Profiler, podemos aprender como usarlo Aquí.

    Con esto hemos finalizado el proceso de creación y análisis de consultas LINQ to Entities en LightSwitch.

    Muchas Gracias.


    Jorge Ramírez (@JramirezDev): Es Tecnólogo de Sistemas y estudiante de Ingeniería de Sistemas, con 4 años de experiencia en desarrollo de BackEnd y FrontEnd usando .NET Framework; especialista en LINQ y WCF.  Encuentren la versión original de este post y mucho contenido adicional muy interesante en su blog.




  • WarNov Developer Evangelist

    Efecto Navideño para blogs usando HTML5

    • 2 Comments

    Luego de implementar el citado evento en mi propio blog, he recibido muchas preguntas de cómo lo logré.

    image

    He aquí la respuesta:

    Este trabajo es basado en un algoritmo de Javascript para HTML5 creado por David Flanagan que se basa en generar un elemento canvas por cada copito de nieve bajando en el blog. Entonces cada copo de nieve se agrega al DOM y es animado usando posicionamiento a través de CSS. Sin embargo se puede mejor usar un solo canvas y animar los copos dentro de este tal como lo sugiere Giorgo Sardo, con el fin de ahorrar memoria. Esto sin embargo puede producir que se bloquee la interacción normal con la página… es así que lo mejor es poner el canvas en un background de menor prioridad (atrás del contenido) tal como lo pueden ver en mi blog.    

    Este es el JavaScript requerido:

    (function () {
    
        // Start Animation only if browser support <canvas>
        if (document.createElement('canvas').getContext) {
            if (document.readyState === 'complete')
                Snow();
            else
                window.addEventListener('DOMContentLoaded', Snow,
    false); } var deg = Math.PI / 180; //Degrees to radians var sqrt3_2 = Math.sqrt(3) / 2; //Height of an eq triangle var flakes = []; // Things that are dropping var scrollspeed = 64; // How often we animate things var snowspeed = 500; // How often we add a new snowflake var maxflakes = 20;//Max number of flakes to be added var rand = function (n) { return Math.floor(n *
    Math.random()); } var canvas, sky; var snowingTimer; var invalidateMeasure = false; function Snow() { canvas = document.createElement('canvas'); canvas.style.position = 'fixed'; canvas.style.top = '0px'; canvas.style.left = '0px'; canvas.style.zIndex = '0'; document.body.insertBefore(canvas,
    document.body.firstChild); sky = canvas.getContext('2d'); ResetCanvas(); snowingTimer = setInterval(createSnowflake,snowspeed); setInterval(moveSnowflakes, scrollspeed); window.addEventListener('resize', ResetCanvas, false); } function ResetCanvas() { invalidateMeasure = true; canvas.width = document.body.offsetWidth; canvas.height = window.innerHeight; sky.strokeStyle = '#0066CC'; sky.fillStyle = 'white'; } function drawFlake(x, y, size, order) { sky.save(); sky.translate(x, y); snowflake(order, 0, Math.floor(sqrt3_2 * y), size); sky.fill(); sky.stroke(); sky.restore(); } function snowflake(n, x, y, len) { sky.save(); // Save current transformation sky.beginPath(); sky.translate(x, y);
    // Translate to starting point sky.moveTo(0, 0); // Begin a new subpath there leg(n); // Draw the first leg of the fractal sky.rotate(-120 * deg);
    // Rotate 120 degrees anticlockwise leg(n); // Draw the second leg sky.rotate(-120 * deg); // Rotate again. leg(n); // Draw the final leg sky.closePath(); // Close the subpath sky.restore();
    // Restore original transformation // Draw a single leg of a level-n Koch snowflake. // Leaves the current point at the end of // the leg it has drawn and translates the coordinate // system so the current point is (0,0).
    // This means you // can easily call rotate() after drawing a leg.
    function leg(n) { sky.save(); // Save current transform if (n == 0) { // Non-recursive case: sky.lineTo(len, 0);// Just a horizontal line } else { // Recursive case: _ _ // draw 4 sub-legs like: \/ sky.scale(1 / 3, 1 / 3);
    // Sub-legs are 1/3rd size leg(n - 1);
    // Draw the first sub-leg sky.rotate(60 * deg);
    // Turn 60 degrees clockwise leg(n - 1);
    // Draw the second sub-leg sky.rotate(-120 * deg);
    // Rotate 120 degrees back leg(n - 1); // Third sub-leg sky.rotate(60 * deg);
    // Back to original heading leg(n - 1); // Final sub-leg } sky.restore(); // Restore the transform sky.translate(len, 0);// Translate to end of leg } } function createSnowflake() { var order = 2; var size = 10 + rand(90); var t = (document.body.offsetWidth - 964) / 2; var x = (rand(2) == 0) ? rand(t) : t + 964 + rand(t);
    // Make it fit with my blog var y = window.pageYOffset; flakes.push({ x: x, y: y, vx:
    0, vy: 3 + rand(3), size: size, order: order }); if (flakes.length > maxflakes)
    clearInterval(snowingTimer); } function moveSnowflakes() { sky.clearRect(0, 0, canvas.width, canvas.height); var maxy = canvas.height; for (var i = 0; i < flakes.length; i++) { var flake = flakes[i]; flake.y += flake.vy; flake.x += flake.vx; if (flake.y > maxy) flake.y = 0; if (invalidateMeasure) { var t = (canvas.width - 964) / 2; flake.x = (rand(2) == 0) ?
    rand(t) : t + 964 + rand(t); } drawFlake(flake.x,flake.y,flake.size,flake.order); // Sometimes change the sideways velocity if (rand(4) == 1) flake.vx += (rand(11) - 5) / 10; if (flake.vx > 2) flake.vx = 2; if (flake.vx < -2) flake.vx = -2; } if (invalidateMeasure) invalidateMeasure = false; } }());
    Felices fiestas!

    snowflake, snow effect, JavaScript, html5, css, canvas, animation, christmas, blog

  • WarNov Developer Evangelist

    Stairway to Azure 6: Storage de Azure a Fondo: Escalabilidad y Límites

    • 0 Comments

    Como vimos en este post (qué es recomendable leer primero), Windows Azure ofrece tres tipos básicos de almacenamiento. En este post profundizaremos en ellos y mostraremos un nuevo tipo de almacenamiento ofrecido por Azure. Los Drives.

    Los tipos de almacenamiento convencionales:

    Blobs:

    Almacenamiento de archivos nombrados, junto con metadata.

    Tables:

    Almacenamiento escalable, masivo y estructurado. Una tabla es un conjunto de entidades. Cada una con un conjunto de propiedades. Las aplicaciones pueden manipular las entidades y consultar sus entidades.

    Queues:

    Proveen un robusto almacenamiento y distribución de mensajes para permitir la construcción de aplicaciones no acopladas y flujos de trabajo escalables entre las diferentes partes (roles) de las aplicaciones de Azure.

    Drives:

    Siendo este un tipo nuevo de almacenamiento, provee volúmenes de almacenamiento NTFS para ser usados por las aplicaciones de Windows Azure. De esta manera con los apis convencionales existentes de sistemas de archivos se puede acceder a drives de red mapeados. Cada drive está mapeado a una página de un Blob. Así que la escalabilidad de los drives, es la misma de los Blobs. De manera que sólo en mi siguiente post me estaré enfocando en los drives.

    Veamos la jerarquía de almacenamiento en Azure:

    clip_image002

    Cómo se pueden acceder los datos?

    Esencialmente*, los datos se acceden a través de REST. Cuando adquirimos una cuenta de storage, automáticamente tenemos tres servicios REST para poder ejecutar operaciones CRUD sobre cada uno de los tipos de almacenamiento (blob, table, queues).

    Cada uno de estos servicios se accede con una URL de acuerdo a la siguiente estructura:

    clip_image004

    Observen que el nombre de la cuenta <account> se extrae del nombre que se registra cuando se adquiere la misma en el Developer Portal. Así que un DNS direcciona todos los requerimientos a la cuenta adecuada. Observemos también en los hostnames las palabras clave “blob”, “table” y “queue”: esto nos indica que podríamos tener en la misma cuenta un blob, una tabla y una cola llamadas por ejemplo “music”.

    Una cuenta de almacenamiento de Windows Azure puede tener hasta 100TBs de almacenamiento. De resto, no hay limitaciones en la cantidad de contenedores, ni de blobs dentro de esos contenedores, ni de tablas ni entidades dentro de ellas, ni de colas ni mensajes dentro de ellas. Lo único, es que todo eso no debe sumar más de 100TBs.

    Blobs

    clip_image006

    En este ejemplo, tengo una cuenta de storage llamada “warnov”. A la cual le he creado dos contenedores. Estos contenedores podrían equipararse con las carpetas del sistema de archivos. Los contenedores tienen una política de sharing pública o privada. La segunda requiere siempre autenticación mientras la primera puede ser accedida por todo el mundo. Los contenedores también tienen metadata asociada a ellos en la forma <nombre, valor> y puede tener hasta 8kb de tamaño por contenedor. Los blobs pertenecientes a un contenedor también tienen este tipo de metadata, con el mismo tamaño disponible.

    Entonces para acceder a un blob determinado, usaríamos:

    http://<account>.blob.core.windows.net/<container>/<blobname>

    Básicamente tenemos dos tipos de blobs soportados:

    • Blobs de Bloque:
      • Son orientados a tareas de streaming
      • Cada blob es una lista secuencial de bloques
      • Cada bloque puede tener un tamaño máximo de 200GB
      • Las actualizaciones sobre los bloques requieren de una confirmación: Primero se suben todos los bloques a ser modificados, y luego se aceptan los cambios en una operación atómica.
    • Blobs de Página:
      • Son orientados a tareas de escritura aleatoria (manejo de archivos convencional)
      • El tamaño máximo de página es de 1TB
      • Cada blob contienen un índice no secuencial de páginas
      • No hay proceso de confirmación (al estilo sistema de archivos convencional y a diferencia de los bloques)
      • Precisamente sobre este tipo de blobs es que se montan los drives que mencioné al principio
      • También permiten ejecutar escriturar basadas en rango de un blob; o sea; tratar un blob como un archivo al cual solo se le modificarán ciertos bytes y no todo el archivo, lo que obviamente agiliza la operación. Además se puede obtener un permiso de acceso exclusivo en escenarios de concurrencia (por ejemplo cuando dos usuarios distintos tratan de modificar un mismo archivo)

    Tablas:

    clip_image008

    Las entidades son comparables a filas en una tabla de base de datos. Contienen una serie de propiedades. Todas las tablas tienen dos propiedades. Una llave de partición y una llave de fila. Estas dos propiedades conforman la llave única de la entidad. Las llaves de partición (PartitionKey) son usadas por el sistema para distribuir automáticamente y balancear las cargas de las entidades de las tablas a través de varios servidores. Esto es, una tabla se divide físicamente en particiones que se distribuyen entre varios servidores. Ejemplos de particiones por ejemplo pueden ser las fechas en las que ocurren los registros.

    Las llaves de fila (RowKey) identifican a cada registro dentro de una partición dada.

    Estas dos llaves además representan un índice de búsqueda sobre las entidades. Así que si buscamos sobre estas dos propiedades, obtendremos resultados de una manera más eficiente. Los resultados además son emitidos ordenados primero por a PartitionKey y luego en RowKey.

    Estas dos llaves siempre tienen que ser de tipo String. El resto de propiedades pueden ser: Binary, Bool, DateTime, Double, GUID, Int, Int64, String.

    Las tablas no tienen esquema fijo. Lo único que almacenan son propiedades y cada propiedad se compone de un nombre y un valor. De esta manera, puede darse que en una misma tabla, puedan haber entidades muy diferentes en estructura. O que Dos entidades tengan propiedades llamadas igual pero con distinto tipo de valor. La única restricción es que en una sola entidad no se puede repetir el nombre de las propiedades.

    Una entidad puede tener hasta 255 propiedades. Cada entidad puede ser máximo de 1MB de tamaño. Estas propiedades son Case Sensitive y se pueden equiparar con columnas en una DB.

    Para manejar una concurrencia optimista cada entidad es marcada un una versión mantenida por el sistema a través de un TimeStamp interno (que en últimas es otra propiedad).

    Colas:

    clip_image010

    En las colas generalmente guardamos mensajes que representan los requerimientos de nuestros clientes. Este sistema nos permite almacenar todos los requerimientos para que de manera escalable, los podamos atender sin que se pierdan.

    Las colas pueden tener metadata asociada a ellas en la forma de <llave, valor> con un tamaño máximo de 8KB. Las colas almacenan los mensajes.-

    Un mensaje se almacena máximo por una semana. Los mensajes más viejos de una semana son eliminados por un garbage collector del sistema.

    Los mensajes pueden ser hasta de 8KB de tamaño. Para almacenar dartos más grandes, recurriremos pues al blob storage o table storage y en el mensaje almacenamos la referencia al lugar en que hemos guardado el resto de la información.

    Finalmente, a pesar de que podemos poner mensajes en la cola de manera binaria, cuando los traemos nuevamente, la respuesta se da en formato XML y codificado con base64.

    Particiones

    No solo las tablas usan particiones.

    Todos los objetos de almacenamiento de Azure lo hacen. Las particiones son usadas para localizar los elementos requeridos y para hacer balanceo de carga y partición de objetos a través de los servidores para satisfacer las necesidades de tráfico.

    Todos los objetos de una misma partición se agrupan en el mismo grupo físico. Esto permite básicamente:

    • Ejecutar operaciones atómicas fácilmente en la misma partición
    • Ejecutar un cacheo local para mejorar el performance

    Cuál es la partición para los distintos objetos?

    • Blobs: ContainerName + BlobName
    • Entities: TableName + PartitionKey
    • Messages: QueueName

    Más de límites

    Como lo mencioné anteriormente, cada cuenta de Almacenamiento en Windows Azure tiene hasta 100TB de espacio.

    Una suscripción de Windows Azure, brinda hasta 5 cuentas de almacenamiento.

    Si en nuestra aplicación llegáramos a necesitar Petabytes de información, se puede contactar al soporte al cliente para solicitar más cuentas aparte de las 5 obtenidas.

    Entonces es bueno tener en mente que no vamos a crear una cuenta por cada cliente que tengamos, sino por ejemplo representar cada cliente en un container.

    En cuanto a transacciones, en una sola cuenta se pueden tener hasta 5000 requests por segundo y en ocupación de ancho de banda hasta 500Mbps.

    Ahora, hablando de límites por partición tenemos:

    Transacciones por segundo permitidas para una partición: 500. Esto quiere decir, por ejemplo que una cola puede ser solicitada 500 veces en un segundo (recordemos que cada cola ocupa su propia partición).

    Pero en una tabla, donde podemos tener varias particiones, esos 500 requests por segundo podrían escalarse a varios miles!

    En cuanto a blobs, dado que cada blob tiene su propia partición, tenemos que el único límite sería el ancho de banda para cada blob que en este caso es de 60Mbps

    Qué pasa si se superan los límites de trabajo para una partición en particular? Se empezaran a producir errores “503 Server Busy”. Cuando se detectan estos errores, una buena práctica es comenzar a usar un algoritmo de “exponential backoff” para disminuir la carga de la partición. Pero si esto continúa muy frecuentemente, la aplicación debería tratar de mejorar su partición de datos y tasa de transferencia de la siguiente manera:

    Blobs: Considerar usar mejor el Windows Azure Content Delivery Network (CDN) para permitir acceso anónimo a blobs que tienen mucho acceso. Una solución de Windows Azure que provee a los desarrolladores una solución global para distribuir contenido de alto ancho de banda. Esperen un post al respecto.

    Tablas: Usar una PartitionKey más granular que permita a Azure distribuir las particiones entre más servidores.

    Colas: Hacer batch de varios work ítems en un solo mensaje, para aumentar la cantidad de trabajo resuleto en cada uno de ellos, o usar múltiples colas.

    Para finalizar, en este post de Brad Calder (basado en el cual está este mío), encontré un comentario donde una persona decía que 500 transacciones por segundo para una cola era algo muy pequeño. Y que en realidad esperaba que fuera al menos 100 veces mejor, para justificar el cuento de la nube y poder desarrollar algo como twitter.

    Esto tiene mucho sentido desde cierto punto de vista. Pero si tenemos en cuenta que Windows Azure no nos impone límite sobre el número de colas que puedo crear y si además mandamos varias requisiciones para un solo mensaje, si yo empaquetase 10 requerimientos por mensaje y tuviera 10 colas, fácilmente lograría 100 veces más rendimiento que un solo mensaje y una sola cola. Con esta misma metodología podría lograr rendimientos aún mayores!

  • WarNov Developer Evangelist

    Libros gratis de Microsoft para Kindle y otros Readers

    • 6 Comments

    Y la gente sigue creyendo que en Microsoft todo es pago…

    En esta oportunidad tenemos estos libros fundamentales para el aprendizaje en programación de teléfonos móviles con Windows Phone 7, Visual Studio, Sql Server, Windows Server y además una guía de actualización de capacidades, genial para aquellos que requieren un lineamiento para definir su carrera profesional en el mundo de la tecnología.

    Todos gratis y además en formatos que van desde el PDF, pasando por el EPUB y llegando al MOBI. De esta manera, va a ser muy cómodo y sobretodo ECOLOGICO aprender, usando readers como el Kindle, el Nook (Barnes & Noble), el Sony Reader, el Kobo eReader y como si fuera poco el iPad. No nos duele brindar el conocimiento a otras plataformas. Lo importante para nosotros, es compartir el conocimiento.

    He aquí los links:

    Programming Windows Phone de Charles Petzold PDF, EPUB y MOBI

     

     

    Adicionalmente, en este post encuentras todo lo necesario para seguir con tu conocimiento de Windows Phone 7: http://wnov.it/wp7Info

     

     

     

     

     

     

    Moving to Microsoft Visual Studio 2010 por Patrice Pelland, Pascal Paré, y Ken Haines PDF, EPUB y MOBI.

    Introducing Microsoft SQL Server 2008 R2 por Ross Mistry y Stacia Misner is PDF, EPUB y MOBI.

    image

    Introducing Windows Server 2008 R2 por Charlie Russel y Craig Zacker con el equipo de Windows Server de Microsoft PDF, EPUB y MOBI.

    image

    Own Your Future, Update Your Skills with Resouces and Career Ideas from Microsoft por Katherine Murray  PDF, EPUB y MOBI.

    image

  • WarNov Developer Evangelist

    Windows Phone 7? Y qué pasa con mis aplicaciones de Windows Mobile?

    • 0 Comments

    Es usted un desarrollador de aplicaciones móviles empresariales?
    Se siente preocupado porque Windows Phone 7 no soporta las aplicaciones hechas para Windows Mobile 6.x?

    En ese caso, este artículo es para ud.

    Comprendo su situación. Más aún cuando para lanzar una plataforma tan novedosa como Windows Phone 7, desde Microsoft debemos enfilar nuestros esfuerzos a promoverla a toda costa.

    Pero tranquilo que esto no significa que Windows Mobile desaparezca. Las aplicaciones que ud ha hecho para Windows Mobile 6.x aún serán compatibles por mucho más tiempo.

    Tal vez usted hasta haya contemplado la posibilidad de migrar de plataforma. Por ejemplo a Android que ha tenido un éxito innegable y tiene un futuro muy prometedor.

    Pero con un poco más de investigación descubrirá que tanto IPhone como Android y el mismo Windows Phone 7 están basados en una arquitectura de “SandBox” en la cual las aplicaciones solo pueden acceder a una zona del sistema operativo desde la cual no pueden acceder nativamente ni al software ni al hardware del aparato. Estos sistemas operativos de teléfonos pertenecen a un segmento distinto al de Windows Mobile. No son orientados a aplicaciones empresariales ni de negocio, sino a aplicaciones de consumidor o de usuario final. Entre otras cosas es por eso que son aplicaciones muy restringidas, pues requieren proteger los intereses de un mundo de usuarios mucho más grandes y ofrecer un entorno absolutamente estándar para que muchos desarrolladores puedan hacer sus aplicaciones fácilmente sobre esta plataforma, pues finalmente lo que asegura mantener un sistema consumidores es tener la mayor cantidad de aplicaciones posibles; sin embargo esto imposibilita por ejemplo la habilidad de apagar los radios internos de los quipos para ahorrar energía, o bloquear o limitar la experiencia de usuario de acuerdo a las necesidades de la aplicación, o la instalación de componentes de software especiales como bases de datos que requieren un acceso nativo a la plataforma. Obviamente esto acarrea por ejemplo la imposibilidad de administrar todo el sistema desde una sola aplicación; condición apenas básica para muchas aplicaciones empresariales.

    En un ambiente de aplicaciones de este tipo entonces observaríamos una fragmentación debido a la necesidad de soportar periféricos especializados, seguridad y funciones de administración De manera que los desarrolladores de aplicaciones empresariales deberían suministrar sus propios drivers y además sus propias extensiones de aplicación; en caso de que esto se diera, sería muy poco probable que cada desarrollador creara las misma utilidades que su competencia y aquí es donde se vería esta fragmentación que limitaría a un cliente su movimiento de una aplicación a otra; cosa que no sucede en Windows Mobile! Así que los clientes que decidan pasarse a usar las aplicaciones empresariales que tras mucho esfuerzo puedan lograrse en plataformas como Android deben tener muy en cuenta que ese software está arquitecturado de una manera tal que las características comunes y las propietarias están separadas. Así pues cuando un cambio de hardware de un proveedor sea necesario las áreas de software que requieren cambios y pruebas serán fácilmente detectables.

    Otra limitante puede ser el requerimiento que muchas industrias tienen de soportar transacciones altamente seguras a través de estándares como el FIPS (Federal Information Processing Standard) que exige certificación de hardware y software. Aunque hoy estas certificaciones son muy comunes en Windows Mobile, es muy poco probable que se empiecen a implementar en otras plataformas antes del 2013.

    En síntesis, va a ser muy complicado de lograr obtener las mismas características a las que Windows Mobile nos tenía acostumbrados. Con toda esta posible fragmentación Windows Mobile sigue siendo la mejor opción para aplicaciones de línea de negocio para dispositivos móviles (handhelds).

    Si no han oído mucho de la evolución de Windows Mobile, déjenme decirles que si sigue evolucionando y lo que conocíamos como Windows CE ahora se conocerá como Windows Embedded Compact 7 (para dispositivos muy específicos como automóviles, minicomputadoras especializadas, etc.) y lo que era Windows Mobile hoy se conoce como Windows Embedded Handheld 6.5 (telefonía, compatibilidad entre distintos dispositivos, seguridad avanzada). Estos dos sistemas operativos ofrecen toda la confianza gracias al nivel empresarial de soporte de Microsoft que hoy asegura 10 años más de soporte y 15 años más de disponibilidad de producto.

    Además:

    • Acceso al Cellcore (toda la telefonía de costumbre)
    • Wi-Fi, Bluetooth y Ethernet
    • Integración a soluciones de administración y seguridad como System Center Configuration Manager y Microsoft Exchange Server
    • Integración con otros servidores como Sql Server, Sharepoint y Windows Server
    • Varios métodos de entrada disponibles (touch, stylus, teclado y más)
    • Múltiples resoluciones de pantalla
    • Procesadores ARM soportados
    • Periféricos adicionales como lectores de códigos de barras, RFID, y lectores de cintas magnéticas.
    • Encripción de datos, borrado remoto, política de obligación de password
    • Tránsito sobre SSL hasta de 256 o VPN

    Pero cómo programo para Windows Embedded Handheld?

    Es cierto. El soporte a este tipo de proyectos fue retirado de Visual Studio 2010. Pero no será para siempre. Por ahora se puede usar Visual Studio 2005/2008 (que se pueden instalar en paralelo con el 2010) en compañía de Windows Mobile 6 SDK y el Compact Framework 3.5.

    Y qué si mi aplicación no requiere tanto poder sino solo un sencillo acceso a base de datos y multitarea mientras se mantienen todas las características de teléfono de usuario final?

    En ese caso también hay buenas noticias porque Windows Phone 7 en su siguiente release (7.5 o Mango) Incluye la base de datos SQL CE para apoyar este tipo de aplicaciones, así como un mejor soporte al multitask ; además aceleración por hardware para HTML5 que en pruebas preliminares arrojan unas velocidades asombrosas sobre otros teléfonos de usuario final actuales. Si solo necesita de estas dos capacidades, bien puede pasarse a trabajar con Windows Phone 7. Eso sí tenga en cuenta: Las herramientas de desarrollador salen el 24 de Mayo. Pero el update como tal para los teléfonos se espera para el otoño de este año.

    En cualquier caso como siempre digo, las tecnologías de Microsoft no mueren ni se reemplazan entre ellas. Solo evolucionan y se especializan para dar más beneficios a los usuarios.

    Get Microsoft Silverlight
     
     
    Get Microsoft Silverlight
  • WarNov Developer Evangelist

    Resultados del ICFES: Ahora sobre Windows Azure

    • 11 Comments
     

    Es hasta el momento la aplicación más grande en el país, montada sobre Windows Azure y es para mí muy agradable declararla como mi primer pequeño hijo Azure, luego de linear la arquitectura de su funcionamiento y de haber pasado derecho 24 horas programándola. Esto, dado que empezar de ceros y terminar en tiempo record, pues existían ciertos problemas con la anterior plataforma entre ellos la incapacidad de re direccionar correctamente al sitio original del ICFES para mostrar información distinta a la de los resultados y también el precio que en total es más de 8 veces más alto que el logrado con Windows Azure (de cerca de US$25.000 pasamos a US$3000: exagerando)

    Todo comenzó con la noticia de que uno de nuestros principales socios de negocio certificados: ASESOFTWARE (CMMI 5) estaba interesado en desarrollar la plataforma que serviría para presentar los resultados del Examen de Estado ICFES a la nación colombiana (600.000 resultados). Al oír esto, de inmediato me desplacé a sus instalaciones para apoyarlos en este proceso.

    Fue una misión compleja. Estábamos sobre el tiempo y necesitábamos salir al aire lo más rápido posible. Sin embargo es esto mismo lo que demuestra las bondades de Azure, que nos permiten aprovechar todos los conocimientos que ya tenemos sobre .NET y sumados a algo de teoría de Cloud Computing nos permiten salir muy rápido a producción. Gracias al empeño y gran experiencia en desarrollo de ASESOFTWARE pudimos aprovechar y capitalizar todas estas ventajas.

    Básicamente necesitábamos subir esa gran cantidad de data a la nube, y crear una aplicación web bajo los lineamientos del ICFES para mostrarlos al público.

    image

    Análisis de la solución:

    Necesitábamos una capa de alimentación de datos, otra capa de negocio para implementar la lógica y finalmente una capa de presentación Web para los usuarios finales. Nótese que en este caso no necesitamos una capa de servicios, dado lo puntual de la solución. Si se hubiese necesitado igual no habría habido ningún problema porque Windows Azure está totalmente preparado para estos casos.

    Capa de Alimentación de Datos

    La decisión más simplista, hubiese sido usar SQL Azure y subir todos los datos a la Base de Datos en la nube. Esto se hubiese podido hacer con Integration Services y se hubiese podido obtener un resultado más que aceptable.

    Pero en Windows Azure existe el storage nativo en tablas no relacionales. Un tipo de almacenamiento que se ajusta perfectamente a requerimientos como este en el que solo es necesario tener datos estructurados que no se relacionan con tablas adicionales. Un claro ejemplo de una base de datos NOSQL. SQL Azure está más enfocado a servir como Base de Datos a aplicaciones altamente relacionales y transaccionales cuyo modelo de operación es difícilmente concebible con tablas sin integridad referencial (ERPs, CRMs, etc.) Entonces para qué incurrir en los altos costos de SQL Azure sin necesidad? SQL Azure es 66 veces más costoso que el almacenamiento en tablas de Windows Azure (US$0.15 por Gb por mes). Y esto es apenas lógico, dado que por debajo existe todo un motor relacional que administra la integridad referencial, la ejecución optimizada de consultas y un sinfín de aspectos adicionales.

    Esto, sin mencionar que las tablas tienen un rendimiento mayor a SQL Azure, dado que su acceso se hace directamente sin pasar por un motor de validaciones adicional. Y por otro lado, son altamente escalables, desde que una vez definida una columna de partición en nuestras tablas, Windows Azure encarga de distribuir automáticamente los datos en distintos nodos físicos, de manera que el acceso siempre es lo más optimizado posible. En este caso por ejemplo, hicimos particiones por colegios. Así que los resultados de cada colegio se almacenaron en una partición distinta sin mayor esfuerzo. Por si fuera poco, cada registro grabado en una tabla de Windows Azure, queda respaldado con otras dos copias de seguridad, para brindar redundancia. Esto se ejecuta sin costo alguno (tiempo, dinero, o programación) además sucede lo mismo con los blobs, las colas y el mismo SQL Azure.

    Así pues, procedí a crear un aplicativo Windows que tomaba la información de resultados del ICFES y la llevaba hasta la nube.

    Capa de Negocio y Presentación WEB

    El equipo de desarrollo de Asesoftware tomó una interfaz de acceso a datos Web que ya existía y le hizo la adaptación para consultar los datos de las tablas. Estos datos eran presentados en formato HTML y también sirvieron para construir un PDF que se distribuye a los usuarios de la aplicación que contiene el boletín con los resultados del examen. Estos PDFs luego de ser construidos, se almacenan en el espacio de BLOBs de Windows Azure, que también nos brinda unos costos súper bajos de almacenamiento (US$0.15 por Gb).

    En estas capas hubo que tener en cuenta ciertas consideraciones, como por ejemplo el manejo de las interfaces con los esquemas de almacenamiento de Windows Azure, los modelos de redirección de la aplicación al dominio original, etc. En general estrategias puramente técnicas que ya he publicado en mis artículos de Windows Azure dentro de este blog, o que estaré publicando próximamente.

    Solución Desplegada

    Siendo sinceros, esta solución fue desplegada en Azure con una estrategia de sobre-estimación dado que es la primera vez que se sale al aire con un proyecto de esta magnitud en el país y se quería prevenir cualquier eventualidad que pudiera dar una mala imagen de la plataforma. Fue así como la solución se desplegó en cuatro WebRoles de tamaño grande (CPU: 1.6Ghzx4, RAM: 1.7Gbx4) lo que al final nos da una capacidad de 25.6GHz de procesamiento en conjunto y 27.2GB de RAM. En realidad estimo que para la situación actual, sería suficiente con el 70% de esta capacidad. Pero gracias a los precios de Azure, se pudo establecer este esquema holgado, sin un mayor impacto a la inversión. Además, en las noches cuando hay menos carga, se bajan máquinas para disminuir los costos. Por eso, cuando hablé de un total de US$3000 para tener la aplicación desplegada durante una semana, dije que estaba exagerando. En realidad el costo es menor. Recuerden que el costo antes de Azure también por una semana estaba alrededor de los US$25.000!

    Conclusión

    Windows Azure permitió a ASESOFTWARE sacar en muy corto tiempo (contra reloj) una aplicación de consumo masivo para un gran cliente como lo es el ICFES que ha respondido y superado perfectamente sus expectativas, con unos costos muchísimo menores (8x) y también con la ventaja de que la solución final es totalmente dinámica en su despliegue permitiendo pagar solo lo que se consume, sin necesidad de contratos o tarifas planas que pueden generar desperdicios en la inversión de capital para el cliente.



  • WarNov Developer Evangelist

    Desarrollo sin código? En Windows Phone 7 se puede… y gratis!

    • 2 Comments

    Para algunos puede ser el sueño del desarrollo de aplicaciones… que se generen sin escribir ni una línea de código y súmenle que se pueda hacer gratuitamente!

    Así es; si necesitas hacer una aplicación para Windows Phone 7 en menos de 20 minutos y gratis, http://appmakr.com es la solución.

    Allí se ofrece la posibilidad de hacer aplicaciones obviamente enfocadas a un aspecto único, con el fin de poderlas hacer de una manera tan automatizada; en este caso, las aplicaciones que podemos desarrollar allí, son aquellas orientadas a mostrar información de feeds que vienen en RSS o ATOM.

    Podemos modificar la fuente del feed, poner varios tabs con distintos feeds, escoger los íconos e imágenes de cabecera de nuestra aplicación y además monetizarla a través de Adds!

    Como siempre un video vale más que una giga de palabras y aquí se los dejo para que vean todo el proceso:

    Para desplegar tu aplicación con appmakr, solo se necesita tener instalados los tools de Windows Phone 7.
    Si deseas hacer aplicaciones más complejas y no sabes cómo comenzar, te recomiendo este post.
     
    Quieres además ganar un Windows Phone 7, pues con tu aplicación hecha en appmakr puedes participar. Detalles aquí.
  • WarNov Developer Evangelist

    NaCl: El Silverlight/Flash de Google?

    • 9 Comments

    En mi continuo transitar por las novedades tecnológicas (no sé a que hora visito tanto sitio…) Me encontré con que Google de una manera bastante discreta estaba lanzando una tecnología abreviada como la sal: NaCl. Acrónimo de Native Client.

    NaCl = Sal

    Native Client es una idea supernovedosa

    Con la cual de acuerdo a lo que encontramos en el sitio del proyecto, tenemos un fabuloso SDK que permitirá al browser ejecutar código nativo para construir aplicaciones web de alta respuesta e interactividad… (no les suena esto familiar?)

    Lo cual, me parece bastante curioso, dado todo lo que Google ha dicho acerca de su firme apoyo a HTML 5, que pretende solucionar el mismo tipo de problema.

    Dijo el vice presidente de ingeniería Vic Gundotra en el Google I/O de 2009: “HTML 5, will be the future of the web”.

    Y si es así? Para qué desgastarse tratando de implementar toda una tecnología para correr código nativo desde el browser? Sobretodo cuando se ha criticado al mismo tipo de tecnologías ya implementadas como Silverlight y Flash?

    Será que en el fondo no creen mucho en HTML5? O será que en el fondo creen mucho en tecnologías Silverlifght/Flash?

    NaCl tiene un SDK que funciona en Windows, Linux y Mac… Genial! Y lo mejor de todo, es que las aplicaciones las programaríamos en una suerte de sancocho (léase mescolanza o MIX para los más modernos) de CSS, HTML, Javascript y sí, el amigable C/C++! Todo para lograr que la aplicación no se vea como un frame embebido dentro del HTML, sino como puro HTML.

    Este C/C++ nos permitirá crear de una forma bastante sencilla gráficos en 2D/3D, ejecutar audio y responder a eventos del mouse y teclado!

    Pero…

    Cuál es el AS bajo la manga de Google que aventajará a Silverlight y Flash?

    Pues que no se requerirá plugin! No habrá que instalar nada!!!
    Bueno, excepto el propio browser de Google (Chromium). Entonces ha de ser que para ellos no existen más browsers :

    “all without requiring users to install a plugin. These web apps run in recent versions of Chromium with the --enable-nacl flag.”

    Bueno; pero pongamos esas des-virtudes a un lado y démosle una oportunidad de prueba; observemos cómo sería la programación. Primero, veamos cómo sería la página web que hospedaría la sal; digo, NaCl:

       1:  <!DOCTYPE html>
       2:  <html>
       3:    <!--
       4:    Copyright (c) 2010 The Native Client Authors. All rights reserved.
       5:    Use of this source code is governed by a BSD-style license that can be
       6:    found in the LICENSE file.
       7:    -->
       8:  <head>
       9:    <title>Hello, World!</title>
      10:   
      11:    <script type="text/javascript">
      12:      hello_world = null;  // Global application object.
      13:      status_text = 'NO-STATUS';
      14:   
      15:      function moduleDidLoad() {
      16:        hello_world = document.getElementById('hello_world');
      17:        updateStatus('SUCCESS');
      18:      }
      19:   
      20:      // If the page loads before the Native Client module loads, then set the
      21:      // status message indicating that the module is still loading.  Otherwise,
      22:      // do not change the status message.
      23:      function pageDidLoad() {
      24:        if (hello_world == null) {
      25:          updateStatus('LOADING...');
      26:        } else {
      27:          // It's possible that the Native Client module onload event fired
      28:          // before the page's onload event.  In this case, the status message
      29:          // will reflect 'SUCCESS', but won't be displayed.  This call will
      30:          // display the current message.
      31:          updateStatus();
      32:        }
      33:      }
      34:   
      35:      function fortytwo() {
      36:        try {
      37:          alert(hello_world.fortytwo());
      38:        } catch(e) {
      39:          alert(e.message);
      40:        }
      41:      }
      42:   
      43:      function helloworld() {
      44:        try {
      45:          alert(hello_world.helloworld());
      46:        } catch(e) {
      47:          alert(e.message);
      48:        }
      49:      }
      50:   
      51:      // Set the global status message.  If the element with id 'status_field'
      52:      // exists, then set its HTML to the status message as well.
      53:      // opt_message The message test.  If this is null or undefined, then
      54:      //     attempt to set the element with id 'status_field' to the value of
      55:      //     |status_text|.
      56:      function updateStatus(opt_message) {
      57:        if (opt_message)
      58:          status_text = opt_message;
      59:        var status_field = document.getElementById('status_field');
      60:        if (status_field) {
      61:          status_field.innerHTML = status_text;
      62:        }
      63:      }
      64:    </script>
      65:  </head>
      66:  <body onload="pageDidLoad()">
      67:   
      68:  <h1>Native Client Simple Module</h1>
      69:  <p>
      70:    <button onclick="fortytwo()">Call fortytwo()</button>
      71:    <button onclick="helloworld()">Call helloworld()</button>
      72:   
      73:    <!-- For development, use a #develop location, which loads the develop
      74:    version of the module.
      75:    -->
      76:    <div id="nacl_helloworld_content"></div>
      77:    <script type="text/javascript">
      78:      contentDiv = document.getElementById('nacl_helloworld_content');
      79:      if (window.location.hash == '#develop') {
      80:        // Load the develop version of the module.
      81:        contentDiv.innerHTML = '<embed name="nacl_module" '
      82:                               + 'id="hello_world" '
      83:                               + 'width=0 height=0 '
      84:                               + 'type="pepper-application/hello_world" />';
      85:        moduleDidLoad();
      86:      } else {
      87:        // Load the published .nexe.  This includes the 'nexes' attribute which
      88:        // shows how to load multi-architecture modules.  The relative URLs in
      89:        // the following table should be matched with a similar directory
      90:        // structure on your server.
      91:        var nexes = 'x86-32: hello_world.nacl/x86_32/hello_world.nexe; '
      92:                    + 'x86-64: hello_world.nacl/x86_64/hello_world.nexe; '
      93:                    + 'ARM: hello_world.nacl/arm/hello_world.nexe; ';
      94:        contentDiv.innerHTML = '<embed name="nacl_module" '
      95:                               + 'id="hello_world" '
      96:                               + 'width=0 height=0 '
      97:                               + 'src="hello_world.nexe" '
      98:                               + nexes
      99:                               + 'type="application/x-nacl-srpc" '
     100:                               + 'onload=moduleDidLoad() />';
     101:      }
     102:    </script>
     103:  </p>
     104:   
     105:  <p>If the module is working correctly, a click on the "Call fortytwo" button
     106:    should open a popup dialog containing <b>42</b> as value.</p>
     107:   
     108:  <p> Clicking on the "Call helloworld" button
     109:    should open a popup dialog containing <b>hello, world</b> as value.</p>
     110:   
     111:  <h2>Status</h2>
     112:  <div id="status_field">NO-STATUS</div>
     113:  </body>
     114:  </html>

    Bastante código para un Hello World no?

    Independientemente de eso, observemos la estructura. Básicamente se trata de una página web convencional, cuyo DOM es manejado por un Javascript que accede a un objeto embebido (finalmente si se embeben objetos) que es precísamente el gestor de NaCl, el cual carga archivos binarios de tipo “.nexe” escritos en C++ (Entonces lo que uno hace es indicar la ruta de dicho .nexe; muy parecido a Flash o Silverlight, donde uno indica la ruta del .xap). Hasta aquí noto algunas desventajas con Silverlight… por ejemplo, no se sabe si la página carga antes o después del NaCl; así que hay que escribir lógica adicional para cuando esto sucede. También tenemos que estar mezclando en todo lado Javascript, para traer los datos desde el NaCl al DOM de la página. Finalmente siempre tienen que diferenciarse las versiones de desarrollo de las de producción. En Silverlight, no hay tal diferenciación. Sin embargo, he de decir, que no son diferencias tan graves y que en el fondo el funcionamiento es muy similar, en cuanto a la idea como tal.

    Pero ahora veamos, cómo se programa la parte nativa de la aplicación.

    Como ya les había comentado, usamos el poderoso y amigable C/C++ para dicha programación.

    Luego de muchos tropiezos, por fin logré sacar el código que me daría un mensaje de texto que diría Hello World, el cual se transfiere a la página a través de Javascript y se muestra en un ‘alert´.

    Veamos el código:

       1:  // Copyright 2008 The Native Client Authors. All rights reserved.
       2:  // Use of this source code is governed by a BSD-style license that can
       3:  // be found in the LICENSE file.
       4:   
       5:  #include <stdbool.h>
       6:  #include <stdio.h>
       7:  #include <stdlib.h>
       8:  #include <string.h>
       9:   
      10:  #if defined(__native_client__)
      11:  #include <nacl/nacl_npapi.h>
      12:  #else
      13:  // Building a develop version for debugging.
      14:  #include "third_party/npapi/bindings/npapi.h"
      15:  #include "third_party/npapi/bindings/nphostapi.h"
      16:  #endif
      17:   
      18:  // These are the method names as JavaScript sees them.
      19:  static const char* kHelloWorldMethodId = "helloworld";
      20:   
      21:  // This function creates a string in the browser's memory pool and then returns
      22:  // a variable containing a pointer to that string.  The variable is later
      23:  // returned back to the browser by the Invoke() function that called this.
      24:  static bool HelloWorld(NPVariant *result) {
      25:    if (result) {
      26:      const char *msg = "hello, world.";
      27:      const int msg_length = strlen(msg) + 1;
      28:      // Note: |msg_copy| will be freed later on by the browser, so it needs to
      29:      // be allocated here with NPN_MemAlloc().
      30:      char *msg_copy = reinterpret_cast<char*>(NPN_MemAlloc(msg_length));
      31:      strncpy(msg_copy, msg, msg_length);
      32:      STRINGN_TO_NPVARIANT(msg_copy, msg_length - 1, *result);
      33:    }
      34:    return true;
      35:  }
      36:   
      37:  static NPObject* Allocate(NPP npp, NPClass* npclass) {
      38:    return new NPObject;
      39:  }
      40:   
      41:  static void Deallocate(NPObject* object) {
      42:    delete object;
      43:  }
      44:   
      45:  // Return |true| if |method_name| is a recognized method.
      46:  static bool HasMethod(NPObject* obj, NPIdentifier method_name) {
      47:    char *name = NPN_UTF8FromIdentifier(method_name);
      48:    bool is_method = false;
      49:    if (!strcmp((const char *)name, kHelloWorldMethodId)) {
      50:      is_method = true;
      51:    } else if (!strcmp((const char*)name, kFortyTwoMethodId)) {
      52:      is_method = true;
      53:    }
      54:    NPN_MemFree(name);
      55:    return is_method;
      56:  }
      57:   
      58:  static bool InvokeDefault(NPObject *obj, const NPVariant *args,
      59:                            uint32_t argCount, NPVariant *result) {
      60:    if (result) {
      61:      NULL_TO_NPVARIANT(*result);
      62:    }
      63:    return true;
      64:  }
      65:   
      66:  // Invoke() is called by the browser to invoke a function object whose name
      67:  // is |method_name|.
      68:  static bool Invoke(NPObject* obj,
      69:                     NPIdentifier method_name,
      70:                     const NPVariant *args,
      71:                     uint32_t arg_count,
      72:                     NPVariant *result) {
      73:    NULL_TO_NPVARIANT(*result);
      74:    char *name = NPN_UTF8FromIdentifier(method_name);
      75:    if (name == NULL)
      76:      return false;
      77:    bool rval = false;
      78:   
      79:    // Map the method name to a function call.  |result| is filled in by the
      80:    // called function, then gets returned to the browser when Invoke() returns.
      81:    if (!strcmp((const char *)name, kHelloWorldMethodId)) {
      82:      rval = HelloWorld(result);
      83:    } else if (!strcmp((const char*)name, kFortyTwoMethodId)) {
      84:      rval = FortyTwo(result);
      85:    }
      86:    // Since name was allocated above by NPN_UTF8FromIdentifier,
      87:    // it needs to be freed here.
      88:    NPN_MemFree(name);
      89:    return rval;
      90:  }
      91:   
      92:  // The class structure that gets passed back to the browser.  This structure
      93:  // provides funtion pointers that the browser calls.
      94:  static NPClass kHelloWorldClass = {
      95:    NP_CLASS_STRUCT_VERSION,
      96:    Allocate,
      97:    Deallocate,
      98:    NULL,  // Invalidate is not implemented
      99:    HasMethod,
     100:    Invoke,
     101:    InvokeDefault,
     102:    NULL,  // HasProperty is not implemented
     103:    NULL,  // GetProperty is not implemented
     104:    NULL,  // SetProperty is not implemented
     105:  };
     106:   
     107:  NPClass *GetNPSimpleClass() {
     108:    return &kHelloWorldClass;
     109:  }

    Cristalino no?

    Y solo para un “Hello World!“


    Ahora veamos lo mismo con Silverlight

       1:  using System;
       2:  using System.Windows;
       3:  using System.Windows.Controls;
       4:   
       5:   
       6:  namespace HelloSilverlight
       7:  {
       8:      public partial class MainPage : UserControl
       9:      {
      10:          public MainPage()
      11:          {
      12:              // Required to initialize variables
      13:              InitializeComponent();
      14:          }
      15:   
      16:          private void Button_Click(object sender, System.Windows.RoutedEventArgs e)
      17:          {
      18:              MessageBox.Show("Hello World");
      19:          }
      20:      }
      21:  }

    Bueno; el código habla por sí solo!!!

    Por si fuera poco, observemos el tamaño del ejecutable que finalmente tiene que descargar el usuario:

    NaCl:

    image

    Silverlight:

    image

    Hum… 1143 veces menor

    Bueno; a favor de Google digamos que esta es la primera muestra en público de la plataforma y que todavía no está en producción. Pero que o recuerde, Silverlight en sus primeras apariciones no tenía esos inconvenientes.. yo creo que deberían refinar un poco más el producto a mostrar, antes de sacar su preview!

    Por otro lado, también pienso que así evolucione mucho, (disminuir el tamaño final, simplificar la comunicación con el DOM, etc.) La programación como tal del cliente nativo no tendrá nada que hacer en cuanto a productividad si no se usa un lenguaje administrado.

    Hoy en día los recursos de hardware que existen para la mayoría de las aplicaciones (yo diría un 96%) permiten que las ligeras ventajas en tiempo de ejecución logradas con lenguajes no administrados como C/C++ sean imperceptibles… así que vamos… cuál es el punto?

     

  • WarNov Developer Evangelist

    Aceleración por Hardware de Firefox 4 vs. Internet Explorer 9

    • 25 Comments

    Una de las características que más anuncia Firefox para su última versión es la inclusión de aceleración por Hardware compatible aún con Windows XP (tengamos en cuenta que IE9 no corre en XP, con el fin de poder dar al usuario lo último en tecnología aprovechando el poder de Windows 7).

    En esta demo clásica ya desde los Platform Preview (aka. betas de IE9) vemos que a pesar de que Firefox anuncia con bombos y platillos esta característica, aún el rendimiento en aplicaciones HTML5 de alta demanda de gráficos es bastante pobre.

    Investigando un poco más, me di cuenta de que la aceleración de Hardware de Firefox solo es posible para algunos sitios especiales en Internet que usen una tecnología llamada WebGL que básicamente es una implementación abierta de OpenGL enfocada a la web a través de HTML5 con su canvas. Así que se debe saber de OpenGL para desarrollar sitios web con esta tecnología. IE9 no soporta esta tecnología:

    clip_image002

    http://webglsamples.googlecode.com/hg/aquarium/aquarium.html

    Curiosamente, al hacer la prueba con Firefox obtengo esto:

    clip_image004

    O sea, nada. Si alguien sabe qué se debe hacer para que funcione, le agradezco.

    Esta prueba la hice en varios equipos y nunca obtuve el resultado que FF4 ofrece en su página:

    clip_image005

    En conclusión, la aceleración por Hardware de FF4 que aplica no solo a W7 y XP sino a Mac, etc. Se ve reducida a una sola aplicación (sitios web basados en WebGL). Y en caso de que en realidad allí sea efectiva, veríamos que es un alcance muy corto.

    Para aplicaciones HTML5 más estándares como la del video, el comportamiento sigue siendo precario.

    IE9 soporta aceleración no solo para estos elementos de HTML5, sino que también es aprovechada para el renderizado de fuentes más finas y para ejecutar procedimientos gráficos trazados con Javascript.

    Una cosa es decirlo, otra es hacerlo.

  • WarNov Developer Evangelist

    Nuevo Ciclo del Conocimiento ALM con Visual Studio 2010

    • 3 Comments

    Como ya es toda una tradición, en Microsoft Colombia cada martes a partir de las 6.30pm, venimos realizando ciclos de conocimiento de manera presencial en nuestras instalaciones y también via LiveMeeting, para que personas de otras locaciones o los que no puedan asistir no se queden sin disfrutar de este contenido técnico.

    El mes pasado tuvimos nuestro ciclo de Windows Phone 7 Series. En este, nos estaremos enfocando en estudiar la herramienta Visual Studio 2010 en lo concerniente a la Administración del Ciclo de Vida del Software o ALM.

    image

    Es por esto, que para ustedes tenemos preparadas las siguientes 5 sesiones:

    1-Jun-10 Planeación de Proyectos con Visual Studio 2010: Introducción a VS2010 como herramienta de AALM, Planeación de Proyectos, Branching y Merging
    8-Jun-10 Arquitectura de Software con Visual Studio 2010 Primera Parte: Introducción y Descubrimiento de código usando las herramientas de arquitectura
    15-Jun-10 Arquitectura de Software con Visual Studio 2010 Segunda Parte: Class Coupling y Architecture Explorer
    22-Jun-10 Calidad de Software I: Introducción y creación y ejecución de pruebas Manuales. Administración de casos de prueba con Microsoft Test Manager
    29-Jun-10 Calidad de Software II: Introducción a las pruebas automatizadas de interfaz de usuario. Depuración con Intellitrace usando VS2010

    En este link pueden registrarse para asistir presencialmente o via Live Meeting.

    Los esperamos!

Page 2 of 13 (324 items) 12345»