MSDN Blogs
  • WarNov Developer Evangelist

    WebAPI, Azure y Apps: Una implementación

    Esta presentación la he usado en varios eventos últimamente, como el TechDay de Cali, Medellín y algunas charlas online. Nos muestra unos temas que ya he tratado en varios de mis posts anteriormente, relacionados con Windows Azure Mobile Services, Windows Azure Storage, Web Api y Apps.

    Aquí quise integrar todos esos posts en un ejemplo de la vida real, al que le damos solución de una manera bastante sencilla:

    Cómo compartir archivos desde un dispositivo móvil a otros, a través de una Plataforma propia.

    Toda la teoría relativa a esta demostración la puedes encontrar aquí.

    Veamos pues la presentación en video:

  • WarNov Developer Evangelist

    Noding w/ @WarNov. Episodio 2: JavaScript para Orientados a Objetos

    Luego de la gran acogida del episodio de lanzamiento del curso de NodeJS que publiqué hace unos días, me permito presentarles en esta ocasión el segundo capítulo de la serie. Saliendo un poco más tarde de lo planeado debido a que lo que inicialmente concebí como un pequeño tutorial de  JavaScript, terminó siendo un curso completo de 1 hora.

    Esto me exigió repasar nuevamente toda la teoría (Una semana de lectura) y luego condensar todo esto en la menor cantidad de tiempo en video que pude durante un proceso de edición de 8 horas.

    Finalmente, aquí está el resultado:

    image

    Un recorrido súper rápido por JavaScript. Como ustedes sabrán del primer capítulo, es el lenguaje protagonista en NodeJS. Así que en este episodio encontrarán los aspectos fundamentales del lenguaje ha tener en cuenta.

    El episodio está enfocado a desarrolladores orientados a objetos en lenguajes tradicionales (De allí el título del mismo). De manera que si eres experto en C#, C++ o VB pero no has estado en contacto muy profundo con JavaScript, este curso será excelente no solo para que comiences luego con Node.JS sino también con Apps para Windows 8 en JavaScript + HTML5, HTML5 en el browser, JQuery, LIGHTSWITCH basado en HTML5 y hasta Napa: el conjunto de tools para hacer apps basadas en Office. Así pues, es un episodio que te abrirá las puertas a muchas otras tecnologías.

    Este es el segundo episodio de Noding w/ @WarNov. El curso rápido de Node.js que te permitirá de manera rápida y fácil aprender de qué se trata Node.js y cómo utilizarlo.

    Este episodio es un recorrido rápido por JavaScript para developers Orientados a Objetos (aquellos con experiencia en lenguajes como C++, C# o VB), que aunque han tenido contacto con JavaScript no tienen los conocimientos avanzados de ese lenguaje para poder incursionar en Node.js. Ya vimos en el episodio anterior que JavaScript es central en Node.js. Por esto es necesario tener conocimientos sólidos del lenguaje antes de arrancar con Node.js.

    Adicionalmente, en este video muestro como integrar Visual Studio con Node.js a través de la consola de comandos de NuGet Package Manager.

    Si ya eres experto en JavaScript y deseas pasar de inmediato a NodeJS, puedes hacer skip de este episodio y continuar con el siguiente.

    Sin más preámbulos, aquí los dejo con Noding w/ @WarNov. Episodio 2: JavaScript para Orientados a Objetos.

  • WarNov Developer Evangelist

    Office 365 for Developers!

     

    Office 365 msdn

     

    Así es para subscriptores Ultimate y Premium de MSDN
    Por un año!

    Todas las herramientas y recursos requeridos para comenzar a construir y probar apps de Office 365:

    • Un sitio en SharePoint Online personalizado para crear y personalizar apps
    • Acceso a las herramientas de Desarrollo Napa para crear y probar apps
    • Un Microsoft Seller Dashboard para exponer apps gratis y pagas para vender en el Office Store.

    Por ahora no hay disponibilidad para suscripciones adquiridas a través de programas especiales como Bizspark.

    La suscripción igual se puede comprar aquí.


    Más información acerca de cómo construir Office y SharePoint apps, próximamente en este blog.

  • WarNov Developer Evangelist

    Publiqué mi app para Windows Phone 8, pero me sigue bajando solo la de Windows Phone 7

    Como saben, ya está al alcance de todos la posibilidad de subir la versión de Windows Phone 8 de nuestras apps. Sin embargo, comencé a notar con la gente que trabajo, que cuando en el store de Windows Phone residen las dos versiones tanto para WP7 como para WP8, cuando un usuario con WP8 trata de bajar la app, le sigue bajando la misma de WP7, a pesar de que la de WP8 está también presente.

    Uno diría que se debería detectar el modelo del aparato y bajarse la adecuada.

    Desafortunadamente esto no está sucediendo, así que mientras se corrige, aquí les dejo mi solución recomendada:

    Solo basta con aumentar la versión de la app, en la versión de WP8.

    Por ejemplo, si su versión de app de WP7 es la 1.7.x, asegúrense de que en WP8 será 1.8.x

    De esta manera, sus usuarios de WP8 bajarán la versión adecuada.

    Para hacer este cambio, solo basta entrar al manifiesto de la app y hacer la respectiva modificación:

    Primero abrimos el AppManifest.xml que está dentro de la carpera properties del proyecto:

    image

    y luego  cambiamos la versión dentro del archivo:

     

    image

    Espero que con esto puedan solucionar el inconveniente, o mejor aún, puedan evitar que suceda.

  • WarNov Developer Evangelist

    Metadatos de Azure vs. Caracteres Especiales

    @lvbernal, quien hace parte de nuestro grupo de MCS, me preguntó acerca de un problema que estaba teniendo en su desarrollo con Windows Azure, al tratar de usar caracteres especiales en los metadatos de los blobs que requería subir a Windows Azure. Le di la guía que lo llevó a la solución y él muy amablemente nos estructuró la solución en este post que he puesto como invitado para su deleite.

    image

    Nos dice Leonardo:

    Estoy desarrollando una aplicación que guarda documentos en Windows Azure y quiero compartir dos decisiones de diseño:

    • No utilizo tablas que relacionen usuarios y documentos, sino que creo un contenedor para cada usuario. Eso me da mayor flexibilidad al momento de hacer transacciones o al eliminar los usuarios (tarea muy frecuente en fase de desarrollo).
    • Los datos asociados al documento como fechas, descripción, etc. los almaceno en los metadatos del blob.

    Hay un problema con la última decisión: no se pueden almacenar caracteres especiales en los metadatos. Para solucionarlo, seguí la recomendación de WarNov y utilicé un codificador HTML:

    blob.Metadata["Description"] = HttpUtility.HtmlEncode(model.Description);
    Description = HttpUtility.HtmlDecode(blob.Metadata["Description"]);


    Los nombres de los archivos tampoco pueden contener espacios porque hay navegadores que no los aceptan en las cabeceras de tipo Content-Disposition, necesarias para descargarlos. Yo los reemplazo por "_":

    blob.Metadata["FileName"] = HttpUtility.HtmlEncode(file.FileName.Replace(" ", "_"));
    Response.AddHeader("Content-Disposition", "attachment; filename=" + HttpUtility.HtmlDecode(blob.Metadata["FileName"]));

     

    Leonardo Vargas Bernal: Es Ingeniero Telemático de la Universidad Icesi, hace parte del Grupo de Investigación en Informática y Telecomunicaciones i2T, en las áreas de Aplicaciones y servicios móviles, Comunicaciones inalámbricas y Computación ubicua. Microsoft Community Specialist y MSP de 2007 a 2009, ha trabajado con tecnologías como Windows 8, Windows Azure y ASP.NET MVC. Emprendedor y amante de los retos de ingeniería. Encuentren su blog aquí.

  • WarNov Developer Evangelist

    iOS Native Development: Con Visual Studio en Windows gracias a Xamarin

    Por primera vez en la historia, gracias al brillante trabajo de Xamarin, hoy podemos escribir aplicaciones nativas de iOS en Visual Studio y Windows usando C#! Todo lo bueno que se nos ofrece en el IDE más poderoso del mundo (Resharper, TFS, addons, y demás) ahora incluye además soporte para iOS!


    Xamarin iOS for Visual Studio nos permite escribir, depurar y probar aplicaciones iOS desde máquinas Windows, siempre y cuando se cuente con al menos una Mac conectada en red que provea los servicios de build y despliegue.

    Las ventajas que ofrece este acercamiento es que podemos crear una sola solución para desarrollar cross platform apps, mientras se usan herramientas poderosas solo disponibles en VS, como TFS o Resharper, usando la experiencia familiar que nosotros developers Windows ya tenemos dentro de nuestra casa VS.

    De hecho, si lo único que tienen son MACs, pero igual quieren las ventajas de tener el IDE más poderoso del mundo para hacer desarrollos sobre iOS, la solución de Xamarin permite correrlo sobre un Windows en Parallels.

    Por qué se requiere un MAC?
    Las apps iOS no pueden ser creadas sin el compilador de Apple, y no puedes ser desplegadas sin los certificados de Apple y sus herramientas de firmado de código, que obviamente no están disponibles a terceros.

    Lo bueno, es que una vez se configura, Xamarin hace toda la conexión sin que uno se de cuenta como developer.

    Así que los requerimientos serían:
    Windows 7 u 8.
    VS2010 o VS2012.
    Plugin de Xamarin para VS

    Y en la MAC:
    OS X Lion o Mountain Lion
    Xamarin iOS SDK
    El Xcode IDE y el iOS SDK

    De acuerdo a la gente de Xamarin, la arquitectura de esta solución es:

     
    image


    Un detalle importante sin embargo, es que el emulador de iOS no corre en Windows, así que en este paso hay que ir a la MAC para ver la ejecución. Sin embargo el resto de ventajas, valen la pena.

    Este producto se puede adquirir desde USD$1000= 

  • WarNov Developer Evangelist

    NodeJS Crash Course: El curso rápido y sencillo para aprender Node.JS

    image

    Queremos sitios web realmente veloces. Sitios web que puedan atender a miles de usuarios concurrentes sin presentar fallas de escalabilidad en sus servicios.

    Necesitamos un nuevo acercamiento que nos permita a nosotros como developers poder desarrollar este tipo de sitios Web y, efectivamente, NodeJS cumple esta tarea a cabalidad.

    Este es el primer episodio del curso Noding With WarNov, en el que aprenderás a manejar Node.js para crear sitios web de última generación que funcionan a grandes velocidades y soportando grandes cargas. Node.js básicamente es una compilación de paquetes. Por un lado incluye el engine V8 JavaScript de Google. Por el otro la capa de abstracción provista por libUV y finalmente una librería core de Node.js escrita principalmente en JavaScript.

    Creado en 2009 por Ryan Dahl, hoy es altamente usado en aplicaciones web que requieren alta velocidad y manejo de tráfico optimizado. Es mantenido por Joyent, aunque sigue siendo open source. La principal característica que lo distingue de otros acercamientos similares, es que no necesita de un browser para correr, pues se ejecuta del lado del server. Además implementa un API de I/O creada específicamente para no generar bloqueos, lo que es bastión en la velocidad de respuesta del server.

    Adicionalmente Node.js incluye también un ambiente REPL (Read, Evaluate, Print, Loop) que permite el testing interactivo de instrucciones Node.js.

    En este video, veremos cómo todos los elementos mostrados anteriormente se integran para producir sitios web, de una manera básica.

    En siguientes capítulos iremos avanzando sobre el estudio de esta tecnología.

     

    Bien. A manera de documentación, aquí les dejo el código que usé para hacer nuestro primer servidor Web basado en Node.js:

    var http = require('http');
    var serv = http.createServer(
        function (req, res) {
            res.writeHead(200, { 'Content-Type': 'text/html' });
            res.end('<marquee>Noding with @WarNov</marquee>');
    
            var d = new Date();
            var hours = d.getHours();
            var minutes = d.getMinutes();
            var seconds = d.getSeconds();
    
            var time = hours + ":" + minutes + ":" + seconds;
            console.log('Somedoby just node with @WarNov at ' +
                time);
        });
    serv.listen(3000);
  • WarNov Developer Evangelist

    El negocio de las Apps. De dónde viene y para donde va

    Este video fue grabado en Noviembre de 2012 y contiene mi charla acerca del negocio de las apps en el marco del evento realizado por el Ministerio de las Tecnologías de Información y Comunicación en Colombia, llamado Colombia 3.0.

    Observamos aquí un recorrido por la historia de la industria de las aplicaciones y cómo han llegado a convertirse hoy en apps. Así como en los principios fundamentales para establecer un negocio alrededor de este tema:

    image

  • WarNov Developer Evangelist

    SharePoint 2010 MySite en Windows 8

    Presentación

    Hoy, en mi post invitado del mes, les presento a Andrés Ortiz. Lo he invitado porque desarrolló una interesante manera de generar clientes WindowsRT para aplicaciones de SharePoint. En este interesante artículo, nos cuenta su experiencia su experiencia:

    Contenido

    Desde hace ya unos meses que Windows 8 viene cobrando mucha fuerza en diferentes campos: usuarios finales (portátiles, tablets, teléfonos), desarrolladores, diseñadores y más. Esto ha sido definitivamente un cambio de paradigma total de Microsoft de cara a su ya famoso sistema operativo, que básicamente no había tenido una evolución trascendental hasta que apareció Windows 7. Pero con Windows 8, se cambió definitivamente de página.

    Por esta razón, hemos decido explorar lo que ofrece Windows 8 en el campo de los desarrolladores, específicamente para los que desarrollamos sobre la plataforma SharePoint, y definitivamente ha sido una experiencia muy gratificante. Nuestro resultado actual y el motivo de esta entrada, es una aplicación que corre en Windows 8, despliega Tiles en vivo con ítems de una lista de noticias (Thumbnail + Título de la noticia), y cuando se ingresa a la aplicación, se conecta a MySite de una granja de SharePoint y despliega la información de las personas que tengan su sitio personal creado. A continuación vamos a comentar los aspectos más importantes del desarrollo de esta aplicación.

    Capa de Servicios: Cuando comenzamos a implementar la solución, lo primero que se nos vino a la mente es cómo íbamos a conectar la aplicación Windows 8 con la información almacenada en el servidor SharePoint. Como ya sabemos, SharePoint ofrece servicios Web, a través de los cuales se puede consumir la información almacenada en sus listas, y también la información de los perfiles, lo cual es necesario para obtener información de MySite. Por tal razón lo primero que debíamos implementar era la capa de servicios, a través de un proyecto .NET de tipo Windows Communication Foundation. En este sentido, tendríamos toda nuestra lógica de negocio, y temas de consumo de datos bien separados y aislados en un proyecto WCF totalmente dedicado a esa parte.
    La Interfaz del servicio WCF es similar a la siguiente y resume los métodos utilizados que se deberán implementar para consumir la información:

    [ServiceContract]
    public interface IService1
    {
        [OperationContract]
        List<TGNews> GetNewsTile();
        [OperationContract]
        List<TGUsers> GetUserInfo();
        [OperationContract]
        TGUsers GetUserInfoDetails(string loginName);
        [OperationContract]
        CompositeType GetDataUsingDataContract(CompositeType composite);
    }  
    

    Los servicios Web que estamos consumiendo en nuestra solución cuando se implementan los métodos descritos en la interfaz, son los siguientes: El consumo de la información de la lista de Noticias se realiza a través del consumo del servicio REST que ofrece SharePoint 2010, similar al siguiente ejemplo:
    public List<TGNews> GetNewsTile()  
    {        
       TGNews item = null;  
       List<TGNews> items = new List<TGNews>();  
       try  
       {  
            HomeDataContext dataContext = new HomeDataContext(new Uri("http:
            //server/_vti_bin/listdata.svc"));  
            dataContext.Credentials = new System.Net.NetworkCredential("user"
            , "password", "dominio");  
            var news = from temp in dataContext.Noticias  
                          select temp;  
            foreach (NoticiasItem temp in news)  
            {  
                 item = new TGNews();  
                 item.Title = temp.Título;  
                 item.Thumbnail = temp.Thumbnail;  
                 if (!string.IsNullOrEmpty(item.Thumbnail))  
                 {  
                      GetImageNews("http://server" + item.Thumbnail, 
                      item.Title);  
                      item.Thumbnail = "ms-appx:///Assets/" + item.Title +
                      ".png";  
                 }  
                 items.Add(item);  
            }       
       }  
       catch (Exception ex)  
       {  
            //Log de la excepción  
            throw;  
       }  
       return items;  
    }
    El método anterior muestra claramente que se obtiene una referencia al servicio REST, luego a través de LINQ se consulta la información de la lista específica llamada Noticias y finalmente se itera por los resultados obtenidos, dando como resultado el listado genérico de tipo TGNews. Esta clase TGNews es la clase entidad encargada de transportar los datos entre las capas, específicamente título y thumbnail de la noticia. Posteriormente esa es la información que sirve de fuente para el Tile en la aplicación Windows 8.
    Seguidamente el método encargado de consumir la información de los perfiles es similar a lo siguiente.
    public List<TGUsers> GetUserInfo()  
    {  
       UserGroup userGroup = new UserGroup();  
       userGroup.Credentials = new System.Net.NetworkCredential("user",
       "password", "dominio");  
       XmlNode allUsers = userGroup.GetAllUserCollectionFromWeb();  
       XNode xNode = XDocument.Parse(allUsers.OuterXml);  
       return (from root in xNode.Document.Elements()  
        from users in root.Elements()  
        from user in users.Elements()  
        let loginName = (string)user.Attribute("LoginName")  
        let userInfo = GetUserInfoDetails(loginName)  
        //Filter out admin accounts.  
        //Strangely enough I couldn’t find a consistent  
        //correlating property.  
        where loginName != "SHAREPOINT\\system" &&  
          loginName != "NT AUTHORITY\\LOCAL SERVICE" &&  
          loginName != "NT AUTHORITY\\SERVICIO LOCAL" &&  
          loginName != "NT AUTHORITY\\usuarios autentificados"  
        select new TGUsers()  
        {  
          Title = userInfo.Title,  
          Image = userInfo.Image,  
          Id = loginName,  
          Phonenumber = userInfo.Phonenumber,  
          Manager = userInfo.Manager,  
          Cellphone = userInfo.Cellphone,  
          Birthay = userInfo.Birthay,  
          Department = userInfo.Department,  
          HireDate = userInfo.HireDate,  
          JobTitle = userInfo.JobTitle,  
          Localitationoffice = userInfo.Localitationoffice,  
          Titulo = userInfo.Titulo,  
          Workemail = userInfo.Workemail  
        }).ToList();  
     }  
    
     public TGUsers GetUserInfoDetails(string loginName)  
     {  
        TGUsers userInfo = new TGUsers();  
        if (loginName != "SHAREPOINT\\system" && loginName != 
         "NT AUTHORITY\\LOCAL SERVICE")  
        {  
          //Set the default picture URL. Silverlight can't use the
          //default GIF  
          //provided by SharePoint.  
          userInfo.Image = "ms-appx:///Assets/usuario.jpg";  
          try  
          {  
            UserProfileService userProfileService = 
             new UserProfileService();  
            userProfileService.Credentials =
             new System.Net.NetworkCredential("user", "password", "dominio");  
            PropertyData[] data = userProfileService.
             GetUserProfileByName(loginName);  
            string pictureUrl = GetPropertyData(data, "PictureURL");  
            if (!string.IsNullOrEmpty(pictureUrl))  
            {   
              GetImage(pictureUrl, loginName.Split('\\')[1]);  
              userInfo.Image = "ms-appx:///Assets/"+ 
             loginName.Split('\\')[1] + ".png";  
            }  
            userInfo.Title = GetPropertyData(data, "FirstName") + 
             " " + GetPropertyData(data, "LastName");  
            if (string.IsNullOrWhiteSpace(userInfo.Title))  
            {  
              userInfo.Title = GetPropertyData(data, "AccountName");  
            }  
              userInfo.Phonenumber = GetPropertyData(data, "WorkPhone");  
              userInfo.Cellphone = GetPropertyData(data, "CellPhone");  
              userInfo.Manager = GetPropertyData(data, "Manager");  
              userInfo.Department = GetPropertyData(data, "Department");  
              userInfo.Birthay = GetPropertyData(data, "SPS-Birthday");  
              userInfo.HireDate = GetPropertyData(data, "SPS-HireDate");  
              userInfo.JobTitle = GetPropertyData(data, "SPS-JobTitle");  
              userInfo.Localitationoffice = 
             GetPropertyData(data, "SPS-Location");  
              userInfo.Titulo = GetPropertyData(data, "Title");  
              userInfo.Workemail = GetPropertyData(data, "WorkEmail");  
          }  
          catch (System.Web.Services.Protocols.SoapException ex)  
          {  
            if (!ex.Message.Contains("A user with the account name"))  
            {  
              //throw;  
            }  
          }  
          catch (Exception ex)  
          {  
               throw;  
          }  
        }  
        return userInfo;  
      }      

    Los métodos anteriores se encargan principalmente de obtener diferentes propiedades del perfil de un usuario específico, a través de su Login,  y retornar esa información como una lista genérica de tipo TGUser. De ese modo la primera pantalla de la aplicación Windows 8 se encarga de listar a todas las personas, y luego podremos navegar al detalle de la información de cada uno de esos contactos. Vale la pena destacar del método anterior y también del método que trae la información de la noticia, la manera de manipular las imágenes. Aunque para el caso del Tile se pueden consumir imágenes a través de una URL, en este caso específico, dichas imágenes se encuentran en una biblioteca de SharePoint. Al momento de querer consumirlas a través de su URL obteníamos un error de permisos y no fue posible. Por tal razón la solución fue, descargarlas primero a la carpeta Assets de la aplicación Windows 8, y desde ahí, si darle la ruta a la aplicación para que las cargue. Esa fue la solución que le dimos a esa parte para poder que las imágenes se desplegaran, tanto las fotos de las noticias, como las fotos del perfil de cada usuario.
    Hasta este punto ya teníamos listas genéricas, con información de la lista de Noticias y de los Perfiles. Era el momento de sentarnos a escribir la capa Cliente, donde básicamente lo que se hace, es en Visual Studio 2012 crear un proyecto de tipo Windows 8.
    Con el proyecto de Windows 8 creado, lo primero era referenciar el proyecto WCF a través de una referencia de servicio. Con esto tendríamos acceso a los métodos expuestos por el servicio.

    Tile en Vivo: Los tiles son una de las características interesantes de Windows 8, y quizá lo que le da vida a la interfaz del usuario final. Es muy llamativo ingresar al escritorio del Sistema Operativo en la interfaz estilo “Metro” y ver toda esa información en vivo, por cada una de las aplicaciones instaladas: lectores RSS, correo, mensajería, juegos, entre otros. En nuestro caso la idea era desplegar el thumbnail y título de las Noticias almacenadas en una lista de SharePoint, y dicha información ya estaba lista en el método respectivo ofrecido por el servicio WCF. El tile luce similar a la siguiente imagen enmarcada en rojo, cuando la aplicación es desplegada en Windows 8:

    Tile

    El código encargado de obtener la información de las noticias y la creación del tile es el siguiente:

    public void Actualizartile()  
     {  
       var tileUpdateManager = TileUpdateManager.
        CreateTileUpdaterForApplication();  
       tileUpdateManager.EnableNotificationQueue(true);  
       ServiceReference.Service1Client client = 
        new ServiceReference.Service1Client();  
       Task<List<TGNews>> news = client.GetNewsTileAsync();  
       List<TGNews> items = news.Result;  
       foreach (TGNews temp in items)  
       {  
         if (!string.IsNullOrEmpty(temp.Thumbnail))  
         {  
           tileUpdateManager.Update(new TileNotification(  
            CrearIconoCuadradoYLargo(temp.Title, 
            "ms-appx:///Assets/" + temp.Title + ".png"))  
           {  
             ExpirationTime = DateTime.UtcNow.AddMinutes(60) 
           });  
         }  
         else  
         {  
           tileUpdateManager.Update(new TileNotification(  
            CrearIconoCuadradoYLargo(temp.Title, 
            "ms-appx:///Assets/default.png"))  
           {  
             ExpirationTime = DateTime.UtcNow.AddMinutes(60) 
           });  
         }  
       }  
     }  

    Del método anterior lo primero que debemos observar es el uso de la clase TileUpdateManager, que será la encargada de permitirnos manipular la funcionalidad de Tiles de Windows 8. Luego de definirla, encontramos que debido que en nuestro caso debemos cargar más de un Tile, y que se repita durante una cantidad de tiempo, es indispensable activar la Cola de Notificaciones del Tile:
    var tileUpdateManager = TileUpdateManager.CreateTileUpdaterForApplication();
    tileUpdateManager.EnableNotificationQueue(true);
    Luego de eso, se puede observar cómo se instancia la referencia del servicio y con eso poder consumir los métodos que ya hemos explicado, en este caso el método GetNewsTileAsync().
    Nuevamente volviendo al objeto de tipo TileUpdateManager, podemos observar que se crea una plantilla para desplegar los Tiles amplios, y otra para desplegar los Tiles cuadrados. Esto es muy importante porque es una característica de Windows 8, que el usuario puede activar cuando desee, y si esto no se implementa, la experiencia de usuario se desmejora. Esto se hace en la llamada al método CrearIconoCuadradoYLargo() cuya implementación es similar a lo siguiente:  
    private XmlDocument CrearIconoCuadradoYLargo(string texto,
            string rutaimagen)  
         {  
           //obtenemos el xml del del icono largo  
           var larga = CrearIconoLargoTextoImagen(texto, 
            rutaimagen);  
           //obtenemos el xml del icono cuadrado y extraemos su
            etiqueta binding  
           var cuadrada = larga.ImportNode(CrearIconoCuadradoTexto(texto).
            GetElementsByTagName("binding")[0], true);  
           // insertamos en el xml del icono largo el binding del icono 
            //cuadrado y hacemos que sean hermanos ambos tienen a visual como padre  
           larga.GetElementsByTagName("visual")[0].AppendChild(cuadrada);  
           return larga;  
         }  
    
         private XmlDocument CrearIconoCuadradoTexto(string texto)  
         {  
           var tilexml = TileUpdateManager.GetTemplateContent(
            TileTemplateType.TileSquareText04);  
           tilexml.GetElementsByTagName("text")[0].AppendChild(
            tilexml.CreateTextNode(texto));  
           return tilexml;  
         }  
    
         private XmlDocument CrearIconoLargoTextoImagen(string texto,
             string rutaimagen)  
         {  
           var tilexml = TileUpdateManager.GetTemplateContent(
            TileTemplateType.TileWideImageAndText02);  
           //añadimos nuestro texto  
           tilexml.GetElementsByTagName("text")[0].InnerText = texto;  
           //obtenemos la etiqueta image  
           dynamic imagen = tilexml.GetElementsByTagName("image");  
           //añadimos la ruta de la imagen dentro del atributo "src"  
           imagen[0].SetAttribute("src", rutaimagen);  
           return tilexml;  
        }  

    El método CrearIconoCuadradoTexto() se encarga de retornar la plantilla de tipo TileTemplateType.TileSquareText04, la cual básicamente nos permite desplegar un mensaje de texto cuando se despliega el Tile en formato cuadrado o pequeño. El método CrearIconoLargoTextoImagen() se encargará a través de la plantilla TileTemplateType.TileWideImageAndText02 de desplegar la imagen y el título de la noticia cuando el Tile se despliega más grande.

    Página de Items Agrupados: En el instante que el usuario hace clic en la aplicación lo primero que verá será el grupo de perfiles que se consultan a través del servicio Web de SharePoint 2010 ya  explicado. Básicamente el grupo de perfiles mostrará por cada persona su foto y su nombre, luciendo similar a lo siguiente:

    Principal

    La imagen anterior es el consumo de los perfiles de un sitio Demo de SharePoint 2010, por lo cual se ven algunas fotos repetidas, pero esto no sucederá consumiendo los servicios de un sitio SharePoint donde ya se tengan datos de perfiles de usuarios reales. Lo importante es que observemos entonces lo interesante de la solución, y es que desde una interfaz de Windows 8 muy amigable, podamos consultar la información de nuestros compañeros en la organización, sin tener que navegar a la interfaz Web del sitio en SharePoint. Esto significa un acceso rápido a información de compañeros de trabajo que podamos requerir consultar rápidamente.

    Luego que se han cargado todos los perfiles, se puede hacer clic en alguno de ellos, y posteriormente se desplegará una ventana donde se muestra el detalle de las propiedades de dicho perfil, similar a la siguiente imagen:

    informacion

    Bien, hasta este punto hemos mostrado lo interesante que es implementar soluciones en Windows 8, porque definitivamente las plantillas que ofrece para carga de información y su consecuente navegación, el modelo de objetos, y todas las facilidades para implementar interfaces WOW para el usuario final, ya están listas, es solo comenzar a utilizarlo. Y por otro lado toda la riqueza que SharePoint 2010 ofrece para consumir su información, esta vez desde una aplicación cliente como Windows 8, son definitivamente una reunión de tecnologías muy interesantes para crear soluciones mucho más avanzadas y con mayor funcionalidad. Todo esto ha sido construido en una máquina con Windows 8 instalado y Visual Studio .NET 2012 Ultimate. La granja SharePoint 2010 está totalmente aislada de todo esto y gracias a los servicios Web y REST se puede consumir su información sin requerir mucho más de eso.

     Andres Ortiz Es Ingeniero de Sistemas de la Universidad del Cauca, con más de 10 años de experiencia en el desarrollo de soluciones de Software y actualmente apasionado y especializado en la plataforma Microsoft SharePoint. Con más de 4 años de experiencia en SharePoint, trabajo en la compañía TopGroup, como Líder de Proyectos del área SharePoint, diseñando la arquitectura e implementando soluciones sobre esta plataforma para una gran variedad de clientes. Puede contactarlo en aortiz@topgroup.com.ar si está interesado en crear soluciones SharePoint de alto impacto en su compañía.

  • 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

    Async, Await y Task: for Dummies

    • 0 Comments

    Cuando queremos brindarle al usuario una experiencia rápida y fluida, lo más importante es no dejar que la interfaz se congele mientras se ejecuta alguna operación adicional, tal como cargar un archivo o conectarse a un servicio.

    En la antigüedad, esto se lograda con Threading, luego BackgroundWorkers y después TPL. Pero la evolución continuó para bien y hoy se logra a través de métodos asíncronos.

    Es un mecanismo por defecto del Framework 4.5 mediante el cual un método marcado como asíncrono, no congela la interfaz de usuario, pues por debajo empieza a correr en otro hilo distinto a aquel que hizo el llamado.

    Para marcar un método como asíncrono, le ponemos la palabra clave async antes del tipo de retorno del mismo.

    private async void ProcedimientoAsincrono()
    {
       for (int i = 0; i < 5; i++)
       {
           //Ejecutar subproceso i
    } }

    En este caso, el proceso  ejecuta todos los subprocesos, sin que la interfaz se congele, dado que ese es uno de los principales motivos de disgusto de los usuarios con las apps.

    Ilustración de un circuito contador asíncrono

     

    Sin embargo, dado que se inicia otro hilo de la app para ejecutar otro proceso… cuándo sabemos que este acaba? Cómo hacemos para proceder en consecuencia?

    Por ejemplo: Si queremos cargar tres páginas de contenido bajado de la web, necesitamos saber cuándo tenemos ya ese contenido en memoria antes de usarlo.

    En la antigüedad, teníamos siempre mecanismos de Callbacks a los que nos suscribíamos de manera que cuando el hilo nuevo terminaba lanzaba un evento y nosotros actuábamos en virtud a ello, asignándole un manejador. En lo personal, puedo decir que aunque es algo que funciona, no es muy natural, por el mismo hecho de que hay que agregar manejadores de eventos y demás.

    No sería más natural hacer el llamado al método y saber que cuando la ejecución pase a la siguiente línea es porque el método anterior ya se ejecutó y lo mejor de todo sin bloquear la interfaz?

    Bueno, para eso está la otra palabrita mágica protagonista de este post: await o sea, esperar. Si ponemos la palabra await antes del llamado a un método asíncrono, esto le dice al sistema que hasta que no acabe de ejecutarse el método llamado, la ejecución no puede avanzar hacia la siguiente línea. Lográndose entonces una ejecución natural sin tener que crear hilos ni objetos extraños e insisto: Sin bloquear la interfaz:

    await ProcedimientoAsincrono();
    SiguienteProcedimiento();

    Tengan muy en cuenta sin embargo, que no siempre vamos a querer este comportamiento.

    A veces por ejemplo requeriremos que se inicie el hilo y corra por su cuenta, mientras otra cosa pasa sin tener que esperar a que termine el procedimiento asíncrono. Por ejemplo, supongan que mientras cargan muchos datos, ponen una animación para entretener al usuario. En ese caso, lo que se debe hacer es lanzar el procedimiento asíncrono sin el await y luego lanzar la animación. De lo contrario, la animación solo comenzará a ejecutarse cuando el asíncrono haya terminado, lo que claramente no es nuestro objetivo. Así que es bueno tener una variable de finalización que sea actualizada por el método asíncrono. La animación entonces chequeará el valor de esta variable y solo se detendrá hasta que observe que la variable tiene el valor adecuado. Cuando este es nuestro objetivo, omitimos entonces el await en el llamado.

    Una vez entendidos los conceptos de async y await, pensemos en lo siguiente:

    Qué pasa si debemos llamar a un método que no fue creado como async?

    Nos veríamos obligados a usar threading o background workers? No. Ni siquiera tenemos acceso a ellos desde el perfil del Framework disponible en WinRT. En este caso, regresamos un poco al Framework 4.0 donde con TPL (Task Parallel Library) Tenemos acceso a la clase Task que nos permite de inmediato ejecutar un proceso en otro hilo; cosa muy útil, cuando este proceso no ha sido declarado como asíncrono.

    Entonces solo basta decirle a Task que ejecute el proceso que queremos:

    Task.Run(()=>ProcedimientoNoAsincrono());
    SiguienteProcedimiento();

    Como se observa, Task.Run recibe una Action, que no es más que una Lambda apuntando al procedimiento no asíncrono que existe en algún otro sitio. El procedimiento llamado por Task, también puede ser asíncrono, pero en este caso es más fácil llamarlo directamente, como vimos arriba.

    El llamado a Task también es susceptible a ser esperado usando await, así que obtenemos las mismas ventajas:
    No se bloque la interfaz y decidimos si trabajar en paralelo o de manera síncrona.

    En conclusión vimos qué nos ofrece el Framework .NET 4.5 para generar interfaces de usuario rápidas y fluidas. En el proceso, comprendimos sin muchas complicaciones para qué son y cómo se usan estos tres sujetos: async, await y task.

    Para ver async y await en acción, les dejo este post, donde capturamos imágenes desde la cámara de un dispositivo con Windows 8.


    asincronía, asincrónico, paralelo, hilos, threads, background, fluido, interfaz fluida, fast, framework 4.5, Windows 8,  metro style, apps, winRT, WindowsRT

  • WarNov Developer Evangelist

    Concierto Gratis de Monsieur Periné para Apps Developers

    • 0 Comments

    Tal como lo leen.

    Así es, Monsieur Periné  Se llevará a cabo este miércoles 12 de diciembre en la Puerta Grande de Bogotá.

    Para desbloquear tu entrada a este evento, solo debes estar cursando alguno de los Bootcamps gratuitos de Apps.co: Windows 8 y Windows Phone. Si no estás registrado, aún hay tiempo. Hazlo aquí. aportar una idea de App para Windows 8 o para Windows Phone aquí y adicionalmente, aprovechar un taller de ideas que tendremos este día.

    Aquí les dejo una muestra de esta gran agrupación colombiana y nos vemos allí!

     

     

    Invitan Microsoft y el MinTIC con su programa APPS.CO

  • WarNov Developer Evangelist

    Escalado Automático de imágenes en Windows Store Apps

    • 0 Comments

    Las apps del Windows Store, a diferencia de las de cualquier otro Store de apps, ofrecen una gran versatilidad de presentación, pues pueden ejecutarse en diversos dispositivos que por ende presentarán diversos tamaños de pantalla.

    Por ejemplo, podemos ir desde netbooks de 1024x768, pasando a tablets como la Surface de 1366x768 y laptops o desktops de 1280x1024 y muchos intermedios hasta llegar a dispositivos HD como televisores a 1920x1200 y más.

    Entonces es lógico concluir que las imágenes que incluyamos en nuestras apps, no van a servir para todas las resoluciones. Deberíamos entonces generar todo programáticamente con vectores, cosa que no es sencilla aunque es posible y soportada en Windows 8.

    Cuál es entonces la solución?

    Igual recomiendo que comiencen a pensar en vectores. Cuando creen una imagen, háganlo en formato vectorial… olviden el dibujito jpg…. literalmente no escala y cuando escala se pixela. Recuerdan la premisa de que la app debe ser linda y así se debe ver en cualquier tipo de resolución? Pues bien; una de las grandes características de los gráficos vectoriales es que escalan muy bien y es fácil generarlos para varias resoluciones. Los gráficos vectoriales vienen en versiones como *.SVG que ya es un estándar. Y pueden exportarse fácilmente a los formatos convencionales. Además al igual que los *.PNG, soportan muy bien las transparencias. Desafortunadamente las apps como tal no soportan gráficos *.SVG. Siempre tenemos que pasarles las versiones *.PNG preferiblemente.

    Pero en ese caso, cómo se logra el escalado para cada tipo de resolución?

    image

    Muy sencillo. Windows 8 soporta que pongamos tres versiones de un mismo archivo, para que este pueda escalar adecuadamente. La idea es que cada archivo tenga una escala específica para cada tipo de monitor. En Windows 8 se han definido tres escalas. Normal (basada en una pantalla de 1366x768) o 100%, luego viene una mediana que es de 140% y finalmente la grande de 180% que soporta resoluciones HD sin distorsionar las imágenes. Y dependiendo de la resolución detectada, Windows 8 carga automáticamente el archivo adecuado. Nosotros solo lo referenciamos con la raíz del nombre y Windows 8 escoge el adecuado; otra opción es usar la convención de un folder por cada tipo de escala. Entonces al final implementaríamos de alguna de estas dos maneras:

    image

    En este caso, una imagen de 100x100 pixeles, tendría otras dos acompañantes: una de 140x140 y otra de 180x180.

    Como se aprecia, es un mecanismo bastante sencillo, ya que teniendo una imagen vectorial, podemos exportarla con las distintas resoluciones, incluirlas en nuestros assets y luego dejar que Windows 8 se encargue del trabajo sucio.

  • WarNov Developer Evangelist

    Visual Studio 2012 Update 1 y la nueva interfaz del Package.appxmanifest

    • 0 Comments

    Tal como fue prometido, VS 2012 estará liberando updates frecuentes para mejorar rápidamente la experiencia que con esta herramienta tenemos como desarrolladores. Es el caso del update 1, que aparece solo pocas semanas tras el lanzamiento oficial. Es así como ya no tenemos que esperar a que aparezcan los pesados Service Pack que venían a ejecutar una serie de mejoras, pero con un alto costo de instalación.

    El Update de Visual Studio 2012 es detectado automáticamente por la herramienta y se instala desde ella misma. No hay que bajar nada manualmente. Es un proceso bastante sencillo.

    Hace solo un día, liberé la segunda versión de mi app PhotoRanker. Y una de las correcciones que le hice, fue incluir el ícono del logo para el store, pues anteriormente había olvidado hacerlo.

    Por qué lo olvidé? Fácil: Porque estando trabajando solo con Visual Studio en el editor del Package.appxmanifest que es donde encontramos el “wizard”para ajustar las imágenes requeridas para el store, en ningún lado nos pide esta imagen. Así que uno debe cambiarla manualmente, reemplazando el archivo StoreLogo.png que se encuentra dentro del folder de Assets. Esto es algo muy fácil de olvidar, claramente:

     

    oldpackagemanifest

    Qué tiene que ver esto con el update de Visual Studio 2012?

    Pues que entre muchas otras mejoras, el editor del Package.appxmanifest ha cambiado, incluyendo un manejador de imágenes mucho más avanzado y adecuado:

    NewPackageManifest

    Como se aprecia, aquí sí aparece el espacio para incluir el Store Logo de nuestra app. Así que ya no vamos a requerir un update solo para esto (cosa de la que yo fui victima). Pero por si fuera poco, además del nuevo orden que se le ha dado, podemos especificar también las tres escalas que manejamos en Windows 8 para poder presentar siempre imágenes de alta resolución sin importar el tamaño del dispositivo de presentación, tal como lo explico en este post.

    Es una gran mejora que facilita la vida a nosotros developers al momento de preparar nuestros paquetes de apps para certificar en el store.

    Otras mejoras incluidas en el update:

    • Code Analysis para apps de Windows Phone 8
    • Mejoramiento en el ALM para aplicaciones de SharePoint sobretodo en el campo de testing.
    • Mejoras para el trabajo en equipos ágiles en la administración de proyectos. Esto incluye soporte a Kanban; una herramienta para hacer tracking de proyectos.
    • La Calidad Continuada ha sido protagonista de mojoras también; por ejemplo con el update ya se puede ejecutar el code coverage en pruebas manuales de ASP.NET, sin mencionar que ya se puede ejecutar también grabado de pruebas en Internet Explorer, que después pueden reproducirse en los browsers modernos, para poder ejecutar pruebas cross-browsing.

    Si aún no te ha llegado el update y quieres aplicarlo ahora, puedes ejecutarlo desde aquí.

  • WarNov Developer Evangelist

    Heridas de guerra en la publicación de apps al Windows Store

    • 2 Comments

    No son tan graves como el título; pero tener conocimiento de ellas, nos ayudará a evitar tener que perder tiempo en envíos/rechazos de nuestras apps al store.

    Este artículo contiene información extraida de este post de uno de nuestros MVPs. Se trata de Roberto Alvarado, quien ha estado trabajando mucho con el desarrollo móvil, aún desde Windows Mobile. Así que me he permitido invitarle a mi blog con su post acerca de esta experiencia y él muy amablemente quiso acompañarnos. También tiene información extraida de este post de Juan Carlos Ruiz, colega mío dentro de Microsoft Colombia, y finalmente de mis propias experiencias desde que ha estado al aire el store de Windows. Es así como primero listaré las observaciones de Roberto y luego las de Juan, adicionando algunos comentarios donde sea requerido: 

    De Roberto Alvarado:

    1. Seleccionar el idioma de la App y de la tienda.

    image

    Independiente que el idioma de Visual Studio sea ingles, el idioma de la aplicación y sobre el cual se certificará en la tienda debe ser claro y especifico.

    En mi caso, el idioma es español y en Colombia.

    Nota de WarNov: Este cambio de idioma tan importante se ejecuta dentro de Visual Studio. No en el store. Se hace en el archivo  Package.AppManifest que tiene un editor visual para hacer el cambio. Los detalles de este procedimiento los pueden encontrar en este post que he creado.

    2. La descripción de la aplicación que se va a colocar en la tienda debe ser una frase que tenga mínimo 7 palabras, no debe ser una palabra. Debe describir de manera rápida y sencilla lo que hace la aplicación.

    image

    3. Se deben enviar mínimo 2 imágenes de 1366 x 768, a pesar de que solo se exige 1, si se envía 1 imagen nos rechazan la App.

    image

    4. Es muy importante tener una pagina web o Url en donde se publique una Política de privacidad para nuestra App.

    image

    Si no tiene una, puede utilizar esta, que fue provista por WarNov para su difusión: tiene el texto tanto en ingles como en español. http://bdotnet.wix.com/privacypolicy

    Además tu App debe tener un charm en donde indique la política de privacidad que utilizas, en este link te indico como puedes crear este charm: Crear página de Política de Privacidad de un App Windos 8

    Nota de WarNov: Solo es requerido que tu app incluya una política de privacidad, si en las capacidades de la app dentro del manifiesto de la misma, se especifica que la app se conecta a internet:

    image

    En el ejemplo ven el manifiesto de mi app PhotoRanker y como ven, dado que mi app no usa internet, no requiere una política de privacidad.

     

    5. Llenar o dar las instrucciones necesarias al equipo de testing en el store, sobre el manejo de la aplicación para que no sea rechazada porque no la saben manejar.

    image

    En la imagen un ejemplo sobre este punto.

    6. Es muy importante el rango de edad en el cual coloca su App, si su rango de edad es de 3 años o superior, o de siete años o superior, su App no debe tener conexión a Internet ni hacer utilización de la cámara del dispositivo.

    image

    Tengamos muy en cuenta las opciones y recomendaciones que nos da la misma tienda de Windows para ubicar nuestra App en uno de los rangos de fechas disponibles.

    En este momento no hay posibilidad si no de estas 4 opciones para nuestro App.

    Nota de WarNov: Para la mayoría de Apps, es recomendable escoger el límite de edad 12+.

    7. La imágenes del App, si verificamos la carpeta Assets del explorador de soluciones de Visual Studio, debemos dejar los mismos nombres de las imágenes, el mismo formato y principalmente las mismas dimensiones de lo contrario nuestra App será rechazada el momento de ejecutar el kit de Certificación de App para Windows 8.

    Un ejemplo de esto:

    image

    Si cambia el nombre de la imagen del logo por ejemplo debe indicarlo en el manifiesto también del App de manera correcta.

    8. Si utiliza una base de datos local, como SQLite, debe asegurarse que en las propiedades del proyecto en la pestaña de Compilación (Build) esté seleccionado el procesador correcto de su PC, y asegurarse que en las referencias del proyecto, la referencia de SQLIte no tenga una advertencia, si la tiene, elimine la referencia y vuelva a crear la referencia a SQLite.

    9. Al publicar su App debe asegurarse que tener en “Release” su App al momento de las compilaciones y verificaciones que se realizan con el KIT de Certificación.

    image

     

    De Juan Carlos Ruiz:

     

    1. Website

      • La aplicación debe estar publicada en un sitio web del publicador o uno específico para la App con vínculos claros que permitan descubrir la aplicación a los usuarios a través de la pagina web
      • No tienes sitio web? no sabes como crearlo? hay muchas formas de crear sitios web sencillos rápidamente sin una línea de código, solo búscalos en internet Guiño

    Nota de WarNov: No es necesario crear un sitio web para la app como tal. Por ejemplo poner tu url de twitter como desarrollador, será suficiente. Aunque sin lugar a dudas, es mucho mejor tener un website dedicado a la app donde tengas info de la misma como instrucciones y changelog, tal como lo hice para mi app PhotoRanker, usando los WebSites de Windows Azure, que son totalmente gratuitos.

    2. Estabilidad

    • Cero fallos después de abrir y cerrar varias veces
    • Desconexión de red, la app no debe hacer crash si no hay dispositivos de red o la red esta caída
    • Desconexión internet la app no debe hacer crash si no hay conexión a internet
    • La aplicación no debe presentar ningún fallo o app crash durante su uso

     

    3. Contenidos

    • Aptos para todos: no sexo explícito , no agredir religiones, no terrorismo, no discriminación de ninguna índole
    • Si la aplicación se clasifica en el rating para niños menores de 7 años NO SE PUEDE HACER USOS DE DISPOSITIVOS NI DE INTERNET, en este caso la aplicación debe considerarse para mayores de 7años de forma obligatoria.
    • Si la aplicación puede mostrar contenidos sensibles como desnudos artísticos parciales o violencia real moderada etc. se recomienda establecerla para mayores de 16 años

     

    4. Funcionalidad

    • La aplicación DEBE soportar Snapped View, con esto no digo que tengan que desarrollar esta vista adicional, pero por lo menos sino lo hacen deben evitar que en ese espacio se muestre la información de manera desordenada o desagradable , en dado caso sino se va a soportar la funcionalidad entonces colocar una banner que cubra todo el espacio, tal como lo hace la propia App del Windows Store
    • Si implementan funcionalidades de búsqueda, esta debe estar creada usando el Charm de búsqueda (Search), cualquier implementación diferente causa el rechazo de la App.

    Nota de WarNov: De la anterior regla de búsqueda, quedan excluidas las apps que tengan funcionalidades de búsqueda avanzada que requieran de más de un campo de búsqueda. Por ejemplo una app para buscar vehículos para comprar puede requerir buscar por modelo, color o placa. En este caso, sí se justifica una búsqueda adicional a la incluida en el charm.

    • No deben haber botones para cerrar la App
    • Si en el manifest se marca que la App soporta determinadas posiciones de la tableta, así debe ser, si falta alguna de las seleccionadas la aplicación es devuelta.
    • La app no debe ser solo para mostrar publicidad, la publicidad debe ser utilizada en justa medida, pero no puede ser el objeto principal de la App.
    • La aplicación debe ser 100% funcional utilizando solo dispositivos Mouse y Teclado
    • La aplicación debe ser 100% funcional utilizando solo dispositivos Touch
    • La aplicación debe tener descripción adecuada, todos los logos necesarios y screenshots en Windows Store y en el Package.appmanifest
    • La aplicación no debe incluir en su nombre palabras como “trial”, “test”, “beta”, “demo” , si es requerido informar que la aplicación esta en etapa preliminar, utilizar la palabra "preview"
    • La aplicación no debe tener en la pantalla principal ninguna característica, marco, tableta, botón o label que indique que es una funcionalidad futura, es decir evitar palabras como "coming soon”, “more to come”, “not available yet” . "próximamente", "en construcción" etc.
    • Las funcionalidades principales de la aplicación no deben re direccionar el usuario al browser. Solo características no principales en el 2do o 3er nivel de navegación son permitidas para direccionar al browser. Las funcionalidades principales deben estar dentro de la App.
    • Se recomienda incluir información para soporte técnico en el Charm de configuración (settings ) y en la página web de la aplicación, con alguno de los siguientes mecanismos de contacto:
        • email de contacto
        • url
        • teléfonos etc.

    5. Información para Windows Store

    • Si la aplicación requiere de usuario y contraseña u otros mecanismos para garantizar el acceso a todas sus características se debe enviar junto con la aplicación la información de acceso necesaria para realizar las pruebas. Hay una sección llamada ‘Notas para testers’ donde se debe depositar dicha información.
    • Si la aplicación requiere información o trámites de pago para activar funcionalidades, en las notas para los testers se debe incluir información de pago que puedan utilizar para acceder a estas características de la aplicación y realizar pruebas.
    • Validar que toda la información del Windows Store este correctamente diligenciada, poniendo especial atención a los ratings y publico objetivo, así como a la descripción de la aplicación, el vínculo a la política de privacidad etc.

    6. Localización y Lenguaje

    • La localización y lenguaje de la aplicación debe ser establecido en el package.appmanifest. Ejemplo: si la app esta en español pero en el manifest dice EN-US será rechazada, puesto que esta cadena de localización indica que la App esta en inglés  y esto no es cierto.
    • Localización: La aplicación debe estar completamente localizada para los lenguajes que se hayan establecido en el package.appmanifest, esto incluye: textos y logos, screenshots etc. Si la aplicación va a nivel mundial se recomienda soportar 100% ingles.
    • Todo lenguaje soportado debe tener personalizados el 100% de los textos, imágenes etc. Localizaciones parciales son rechazadas automáticamente

    7. Política de Privacidad

    • Si la aplicación recopila información del usuario de alguna índole esta DEBE TENER una política de privacidad asociada

    Nota de WarNov: En realidad la condición no es recopilar info del usuario o no, sino el mero hecho de que en las capacidades de la app dentro del manifiesto de la misma, se especifica que la app se conecta a internet, como lo muestro en mi segunda anotación arriba.

    • Aunque la app no haga uso de ninguna información del usuario, se recomienda indicar eso en una política de privacidad sencilla.
    • La política de privacidad que se declara dentro del sitio web creado para la App, debe estar conforme a la estructura del sitio y no ser un archivo de texto nada más. La política debe ser descubrible por vínculos dentro del sitio.
    • Se recomienda que la política de privacidad sea accesible desde el Charm de configuración
    • Si se comparte información con terceros,  en el Charm de configuración junto con la política de privacidad se debe agregar una opción visible para autorizar o denegar ese uso de los datos.
    • Si el usuario no autoriza dicho uso la aplicación no debe perder toda funcionalidad, esto no es aceptado, la restricción de funcionalidad debe ser limitada.

     

    Muy bien, espero que puedan valerse de toda esta experiencia adquirida para minimizar la probabilidad de que sus apps sean devueltas tras un proceso de certificación fallido.

    Muchos éxitos!

  • WarNov Developer Evangelist

    No confundir el idioma de tu app, con los países en los que se verá

    • 0 Comments

    Las apps para el Windows Store y Windows Phone Store, manejan un lenguaje por defecto que se encuentra en el manifiesto de cada una de ellas.

    Este lenguaje se ajusta de acuerdo al lenguaje de la máquina del desarrollador. Por ejemplo si el desarrollador tiene su máquina ajustada a Inglés de Estados Unidos, este será el lenguaje por defecto de la app.

    Sin embargo, este lenguaje es configurable; pero al encontrarse en una ubicación no muy visible, puede pasar que no lo observemos y luego pasemos al proceso de publicación dejando un lenguaje por defecto incorrecto, porque puede que haya quedado en Inglés y nuestra app vaya solo en español.

    Cuando pasamos al proceso de publicación en ambos store nos piden los idiomas en los que está disponible nuestra app. También nos piden los países en los que queremos visible nuestra app.

    Ojo que son cosas distintas que no deben confundirse: Uno como developer puede poner su app visible en diversos países, independientemente del o de los idiomas que esté exponiendo. Hay developers que piensan que dado que nuestra app solo expone español, entonces no puede ponerse en mercados que no hablan español, pero esto no es así. Lamentablemente este hecho nos puede quitar oportunidades de darle visibilidad a nuestra app al ponerla en varios países, tal como lo describo en este post.

    Por ejemplo yo como developer colombiano puedo poner mi app visible en Colombia, Estados Unidos e Inglaterra, habiéndola publicado solo en español. Y esto es válido y la app puede ser publicada sin ningún problema.

    Sin embargo observen este hecho curioso: Supongan que escogemos Español. Y que agregamos todos los recursos e imágenes en español necesarias para este fin. Además que pusimos nuestra app disponible en todo el mundo.

    Pero luego de un tiempo nos llega el rechazo de la app porque dizque no subimos los recursos necesarios para los lenguajes especificados. Será porque escogimos países que no hablan español?

    Como lo expliqué anteriormente, este no es el motivo.

    Por qué pasa esto?

    Como les comenté al principio, dado que las apps además quedaron con lenguaje por defecto Inglés Estados Unidos, pues el store espera que subamos esos recursos también.

    Así que la forma de solucionar este problema es modificar estos lenguajes y culturas por defecto, antes de subir la app al respectivo  store.

    En el caso de Windows Phone, esta información se encuentra en las propiedades de la app. Así que abriendo el cuadro de diálogo propiedades desde el explorador de soluciones dando click derecho obtenemos el editor de propiedades. Allí escogemos la información del assembly y allí modificamos el valor. En este ejemplo vemos como estamos cambiando desde Inglés Estados Unidos a Español Colombia:

    image

    En Windows 8, esta información se configura desde el editor del Package.appxmanifest (doble click al archivo con este nombre para abrir el editor):

    image

     

    Aquí solo basta corregir “en-US” por es o por ejemplo “es-CO”.

    Y listo!

    De esta manera ya le estamos diciendo al store que no espere recursos de Inglés Estados Unidos, porque ahora la cultura por defecto es el Español.

    Conclusión: No se confundan si su app es rechazada por motivos de idioma. Esto no tiene nada que ver con los países de publicación elegidos, sino con la cultura por defecto que viene configurada cuando ustedes arrancan a desarrollar una app.

  • WarNov Developer Evangelist

    Cómo seleccionar automáticamente un elemento dentro de un Panorama

    • 0 Comments

    Dice el corresponsal:

    “Hola Walter, como hago en una App WP8 para navegar a una pagina con control panorama y abrir inmediatamente un index diferente a 0. es que tengo un menú y según seleccionen abrir la pagina que tiene el panorama pero el ítem seleccionado. Gracias”

    R./ Suponiendo que tenemos una página inicial con un botón que hace la transferencia a una segunda página panorama, podemos agregarle al llamado de la segunda página un parámetro que nos indique el ítem que deseamos en el panorama:

    private void Button_Click_1(object sender, RoutedEventArgs e)
    {
         NavigationService.Navigate(new Uri
    ("/PanoramaPage1.xaml?item=2",UriKind.Relative)); }

    Luego solo basta manejar el evento OnNavigated de la página de destino, en la cual debemos de haberle dado un nombre al panorama para poderlo referenciar y luego ajustarle el ítem por defecto para cuando se abra la página:

     

    override protected void OnNavigatedTo(NavigationEventArgs e)
    {
        var item = int.Parse(NavigationContext.QueryString["item"]);
        pnrControl.DefaultItem=pnrControl.Items[item];
        base.OnNavigatedTo(e);
    }
    

    y voilà!

    image

  • WarNov Developer Evangelist

    PhotoRanker: Making of a WinRT App

    • 0 Comments

    Este es un post en el que quiero compartirles la experiencia de publicar una app en el store de Windows 8 desde el punto de vista de un desarrollador estándar que ha sufrido en el proceso y ha dejado huella de sus heridas en el código que escribió… mostraré no solo los aspectos técnicos que se tuvieron que superar, sino también los procedimientos de publicación requeridos por el store. Tengan en cuenta sin embargo, que esta no es una guía que enseña a desarrollar apps y que parto del hecho de que ya se sabe como tener una cuenta en el Windows Store, pues tampoco explico cómo se abre una de ellas aquí.

    Objetivo

    PhotoRanker es una app con un único y claro objetivo… como todas las apps deberían ser. El objetivo es poner rating a las fotografías (estrellas) de una forma rápida y eficiente. De esa manera sabes cuáles realmente merecen ser editadas y cuales otras no valen ni un centavo y mejor borrarlas de una.

    Una app debe tener claro su objetivo, para poder de esa manera ser clara en su implementación y clara en su uso. Estamos en un mundo de cientos de miles de apps. En este mundo cada app solo tiene una oportunidad. Si no es buena a primera vista, lo más probable es que genere una desinstalación inmediata. De hecho, personalmente me he visto haciendo eso como consumidor de apps que soy. Así que si no encuentro de inmediato cómo manejar la app, me frustro y le doy uninstall… suerte es que le digo.

    Release Often, Release Fast

    Otra ventaja de tener bien claro el objetivo, es que tu app va a salir rápido al store. No van a pasar eones mientras por fin terminas de implementar las toneladas de funcionalidad que pueden ir pegadas a una app. De hecho, esta app me consumió 9 horas de desarrollo incluyendo dificultades técnicas, ya que no es un simple RSS. Lo importante, es que pude salir al aire pronto con mi app. Esta nueva tendencia de la industria nos lleva al famoso: “Release often. Release fast”. Naturalmente, cuando publicamos nuestra app con su funcionalidad principal claramente establecida, es fácil comenzar a ver los puntos de mejora y extensión para liberar nuevas versiones. Anyway el update de una app no vale nada… solo es necesario subir la nueva versión y por experiencia os digo, que la liberación de un update tarda mucho menos que la del estreno de la app. Además como usuario, uno se siente muy agradado de recibir updates de las apps que usa, pues solo la mera curiosidad de ver qué mejoró, me hace entrar de nuevo a la app. Sentimos entonces como usuarios que el developer está pendiente de la app y que cada vez encontraremos mejoras en ellas; al final esto se ve representado en buenos rating, mercadeo viral y por ende, más descargas.

    Diseño

    Tal vez este sea el requisito más trillado en el tema de apps. Si una app es fea, le va pasando algo parecido a cuando es difícil de manejar: produce frustración y el peor de los males desinstalación, acompañado tal vez de un @#$%^&*( en los reviews, que para nada nos favorece. Para Windows 8 hay muchas guías de diseño. Tener un amigo o socio o equipo diseñador, es lo más recomendado. Pero si somos Hard Die Alone Developers, tal vez tengamos que desarrollar ciertos skills de diseño, para hacer toda la app por nuestra propia cuenta; o al menos los bosquejos de la misma. Para este proceso además de alguito de talento, necesitaremos algunas tools que nos facilitarán la vida.

    Entonces es cuando recomiendo que comiencen a pensar en vectores. Olviden el dibujito jpg…. literalmente no escala y cuando escala se pixela. Recuerdan la premisa de que la app debe ser linda y así se debe ver en cualquier tipo de resolución? Pues bien; una de las grandes características de los gráficos vectoriales es que escalan muy bien y es fácil generarlos para varias resoluciones. Los gráficos vectoriales vienen en versiones como *.SVG que ya es un estándar. Y pueden exportarse fácilmente a los formatos convencionales. Además al igual que los *.PNG, soportan muy bien las transparencias. Desafortunadamente las apps como tal no soportan gráficos *.SVG. Siempre tenemos que pasarles las versiones *.PNG preferiblemente.

    Pero en ese caso, cómo se logra el escalado para cada tipo de resolución?

    Muy sencillo. Windows 8 soporta que pongamos varias versiones de un mismo archivo de imagen en la carpeta en donde los estemos almacenando. La idea es que cada archivo tenga una escala específica para cada tipo de monitor. En Windows 8 se han definido varias escalas. Normal (basada en una pantalla de 1366x768) o 100%, luego viene una mediana que es de 140% y finalmente la grande de 180% que soporta resoluciones HD sin distorsionar las imágenes. Y dependiendo de la resolución detectada, Windows 8 carga automáticamente el archivo adecuado. Nosotros solo lo referenciamos con la raíz del nombre y Windows 8 escoge el adecuado; otra opción es usar la convención de un folder por cada tipo de escala. Entonces al final implementaríamos de alguna de estas dos maneras:

    image

     

    Supongan entonces que se han bajado Visual Studio Express for Windows 8 que es totalmente gratuito y permite comercializar sin problemas las apps que con éste diseñemos. Pues bien… si pagamos 0 por esa herramienta, deberíamos de pagar un montón por una buena herramienta de dibujo y manejo vectorial? Hacerla de piratas y arriesgar nuestra máquina a que se llene de malware tratando de bajar una versión pirata de dicho editor gráfico? Por supuesto que no! Así que en este punto me permito recomendar una gran herramienta free y OSS llamada Inkscape. Con capacidades similares a las de Illustrator, es de manejo muy sencillo y da productividad rápida. La verdad es que yo no sabía mucho de edición de vectores, pero en poco tiempo ya estaba cómodo con la interfaz que me permite manejar capas, hacer operaciones entre objetos (adicionarlos, sustraerlos, intersectarlos), exportar y muchas cosas más. Efectivamente con esa herramienta junto con Paint.Net una tool free creada con .NET y que podría definir como un mspaint con esteroides o PhotoShop light que permite ya manejar los mapas de bits finales (no vectoriales), generé todo el arte requerido para el store de Windows 8, cuando subía a certificación PhotoRanker.

    SiteHeader

    Logo

    entre otras…

    The Store

    Ya que hablamos del arte requerido para el store, algunos puntos al respecto:

    Primero, podría mencionar que es muy fácil ejecutar el proceso de publicación una vez se ha terminado la app. Existe un archivo dentro del proyecto de nuestra app que contiene toda la información relevante con este fin. Ese archivo es el Package.appxmanifest. Visual Studio provee un amigable editor para configurar este archivo antes de subirlo al store. En este, podemos por ejemplo especificar las imágenes de arte a usar para que nuestra app se liste gráficamente en el store, para los tiles, las capacidades de los dispositivos que la app requerirá y muchos otros más.

    oldpackagemanifest

    Vemos allí como se nos piden los diversos archivos de arte y otra metadata para el store. De aquí quiero hacer la primera salvedad. En este diálogo no se nos pide un logo para el store. Así que si no hacemos algo al respecto, nos aparecerá nuestra app con un horrible logo con una X dentro de un cuadrado. Créanlo… a mí me pasó…

    image

    Y así quedará publicada nuestra app. Para corregir esto, lo que debemos hacer es cambiar la imagen existente en Assets\StoreLogo.png, por la imagen personalizada que generalmente es un PNG de 50x50: (tuve que lanzar una nueva versión al store solo por esto)

    StoreLogo

    Afortunadamente, acabo de notar que tras la instalación del Update 1 de Visual Studio 2012, esta situación mejoró sustancialmente al proveerse un nuevo diálogo para este archivo, que permite hasta especificar las imágenes de arte en distinta escala:

    NewPackageManifest

    Vean más detalles en este post.

    Existen muchas otras condiciones para tener en cuenta en la publicación, como las que enumero en este post. Pero luego las leen. Por ahora continuemos con la experiencia en general.

    Versiones y Apps Huérfanas:

    Son ustedes padres desalmados? Por favor  no dejen huérfanas sus apps. No se trata de subirlas y dejarlas en el store sin nadie que las mantenga. Cada minuto que empleen ustedes en hacer una app, es un potencial minuto que puede traerles retorno de la inversión… ganancia. Si dejan su app sin mantener, están desperdiciando esos minutos que invirtieron previamente.

    Pídale a sus amigos que le den opiniones de la app. Qué cosas ven que estaría bien que incluyeran. Ustedes mismos pueden tener sus propias ideas. Comiencen implementando una por una… o si está muy fácil, suban un grupo de tres nuevos features. El Store facilita mucho el proceso. Entre otras cosas, pide que pongan los detalles de las novedades  de la versión.

    Personalmente, le cree un portal a mi app. Lo creé gratuitamente en Windows Azure a través de Windows Azure Websites. En este sitio web, puse una sección de Version History, en la cual muestro la evolución de mi app en cada versión. Esto me permite mostrar que la app está en continua evolución… esto obviamente fideliza a mis actuales usuarios y me trae nuevos. Imaginen que están vendiendo ads publicitarios en sus apps (sé de apps de desarrolladores independientes que han llegado a hacer USD$100.000 en solo ads); en ese caso hay que hacer todo lo posible por que permanezcan con nuestra app. Precisamente esto me lleva al otro punto de este post.

    Cuida tu código:

    Siendo el desarrollador independiente de hoy, querrás estar en permanente movilidad y que el código que hagas vaya contigo a todo lado. Que esté actualizado y que además puedas manejar versionamiento de una manera bastante cómoda…. correcto, te estoy hablando de tener un administrador de código fuente… y sí en Microsoft también ofrecemos un manejador gratuito: Team Foundation Server Express, que gratuitamente les soporta hasta 5 developers. Se lo pueden bajar e instalar, pero yo prefiero usar la versión online que me evita la fatiga de la instalación y me permite tenerlo everywhere. Solo hay que registrarse aquí. Luego de esto, solo queda hacer checkins, checkouts y terminar nuestra app.

    Cuida tus clientes:

    Efectivamente si queremos que nuestra app nos dé ganancia, hay que dar un valor agregado a los usuarios. Por esto es bueno tener un portal dedicado a nuestra app en el que podamos tener flexibilidad para acompañarla con información adicional, avisos, y demás. Una vez tengamos el portal, obviamente es requerido que dentro de nuestra app le demos la posibilidad al usuario de saber que este portal existe y obviamente de acceder al mismo. Un sitio adecuado para esto, es en el About, dentro del charm de settings de la app. No lo vayan a poner grandote en todas las páginas de su app, porque eso no es nice. En el peor de los casos, al menos háganle una página en FB. Es gratis y sirve para enganchar conversaciones que le dan buzz a tu app. Aprovecha los logos oficiales del Windows Store que encuentras aquí para poner el link a tu app en el store (te llega por correo una vez es aprobada; te recomiendo que de una vez le saques un short url pues es complejo) y por favor sigue las reglas de uso de esos logos que están ahí no los vayas a deformar, recortar ni adornar con maripositas.

    Explota la plataforma

    Windows 8 tiene una gran cantidad de features para enamorar al usuario. Es un total desperdicio entonces terminar haciendo apenas una app lectora de rss que no tiene en cuentas estos features. En la creación de PhotoRanker he tratado de incluir la mayor cantidad de features de Windows 8 que tenga sentido para este tipo de app. Algo muy válido eso sí, es que la primera versión salga muy sencilla, pero luego le vamos agregando estos features que realmente harán que nuestros usuarios se sientan muy agradado de usar nuestra app. Por ejemplo, en mi primera versión no soportaba portrait ni snap view mode. Tampoco guardaba settings de la app. Pero ya en la tercera, todo esto está soportado. Y por supuesto la idea es en futuras versiones incorporar más features. Por ejemplo un live tile que muestre fotografías rankeadas con 5 estrellas, la posibilidad de buscar fotografías por número de estrellas usando el charm de search y usar el charm de share para compartir determinada fotografía.

    Modos de presentación:

    Las apps de Windows 8 tienen 3 modos de presentación principales: Full o Landscape, Snap y Portrait. La utilidad de Snap hace mucho sentido en esta app, pues es bien viable que uno por ejemplo esté rankeando sus imágenes mientras ve por ejemplo un video al mismo tiempo. En Windows 8 la mayoría del trabajo de presentación en Snap View se hace automáticamente, pero casi siempre quedan pequeños detalles por corregir. Por ejemplo, en mi app cuando está en fullscreen mode, la fotografía se centra verticalmente:

    image

    Pero al pasar a Snap, si dejo el comportamiento automático, la imagen se reduce también y al ser pequeña, se ve muy afectada por la superposición de las estrellas:

     

    image

    La imagen queda perdida en el control.

    En este caso algunos ajustes adicionales al modo snap son requeridos. Es muy fácil ejecutarlos una vez identificamos el sitio donde se maneja este evento de cambio de posicionamiento:

    public void OnSizeChanged(object sender, Windows.UI.Core.WindowSizeChangedEventArgs args)
    {
    switch (ApplicationView.Value)
    {
    case ApplicationViewState.FullScreenLandscape:
    VisualStateManager.GoToState(this, "Full", false);
    break;
    case ApplicationViewState.Snapped:
    VisualStateManager.GoToState(this, "Snapped", false);
    break;
    case ApplicationViewState.FullScreenPortrait:
    VisualStateManager.GoToState(this, "Portrait", false);
    break;
    default:
    break;
    }
    }

    Como se observa, solo basta interceptar el evento de OnSizeChanged y luego con un sencillo case actuar de acuerdo al cambio experimentado. En este caso, para corregir el pequeño error del snap view, lo que hago es en el respectivo case, cambiar la alineación vertical de la imagen, y ponerla en TOP:

    image

    Ese pequeño cambio que hice, significa una mejora sustancial en la experiencia del usuario, ya que aprovecho mejor el espacio y la imagen se ve completamente despejada. Además noten cómo dejo los controles abajo, de manera que ergonómicamente hablando, están muy accesibles para el usuario. Un inconveniente que experimenté en la vista de Snap View,  fue a través del uso del folder picker cuando está en esta vista. Sucede que si abrimos un folder picker y la app está en snap view, se genera una excepción, porque el folder picker no puede trabajar en este modo. Es por esto que con código debemos obligar a la app a expandirse antes de abrir el folder picker. En este post explico cómo hacerlo.

    Del portrait mode puedo mencionarles que no requirió ningún ajuste porque la auto organización que da WinRT ya es suficiente:

    image

    Pero sí quiero hacer una salvedad y es que no olviden además de manejar el código requerido para portrait dentro del manejador del evento OnSizeChanged, especificar en el Package.appxmanifest que la app soporta portrait mode (yo lo olvidé porque creí que con sólo escribir el código bastaba):

    image

    También les cuento que acabo de notar que aunque controlo muy bien el comportamiento de la ventana principal (donde manipulo las imágenes) en las distintas presentaciones, olvidé controlar la presentación de la primera pantalla en Portrait y Snap, así que se ve algo desquiciado en estos momentos (pruébenlo por ustedes mismos y observen qué cosas deberían corregirse; traten de pensar cómo lo harían). Para la versión 4 estaré corrigiendo esto y agregando un par de funcionalidades más.

    Manejo de Estados:

    Como novedad para la versión 3 de PhotoRanker, incluí que la app recordará en que foto íbamos. De manera que si el usuario se sale de la app o la cierra, cuando vuelva a abrirla, tenga la posibilidad de escoger si arranca desde donde estaba la última vez:

    image

    Como ven, tengo un botón destinado para esto. Así el usuario decide si arranca un trabajo nuevo o continúa con el último que estaba haciendo. Esto es muy útil, pues en realidad le da mucha agilidad a la app. En otros escenarios, no es tan lógico preguntar si se quiere arrancar desde el último estado, sino que de inmediato cuando se vuelve a abrir la app, pasamos a este estado. Aquí en mi app sin embargo, sí quise dar la opción. Otros asuntos que guardo, es por ejemplo la elección del usuario de hacer auto-advance mientras hace rating a las fotos. Esta opción de auto-advance, permite que tan pronto el usuario hace tap sobre una estrella para calificar, la siguiente foto sea cargada inmediata y automáticamente, para agilizar así aún más el proceso. Así pues, el valor de esta opción queda almacenado y la app siempre lo recuerda y usa, hasta que el usuario cambie dicho valor.

    El proceso de almacenamiento de settings y valores de variables es supremamente sencillo:

    Windows.Storage.ApplicationData.Current.
    LocalSettings.Values["AutoAdvance"] = true; Windows.Storage.ApplicationData.Current.
    LocalSettings.Values["LastIndex"] = 45;

    Y recuperar los valores es exactamente igual, eso sí haciendo el respectivo Convert, dado que los valores son almacenados como objetos.

    Splash  Screen Animado

    Una muy buena forma de arrancar impactando con nuestra app, es extendiendo el splash screen para que no sea una simple imagen estática, sino que podemos agregar una animación que “entretenga” al usuario mientras ejecutamos por ejemplo algunas cargas iniciales.

    Por naturaleza el Splash Screen de WinRT no se puede animar. Lo que sí se puede hacer, es una simulación de animación, ubicando una nueva página que inicialmente se vea exactamente igual al Splash Screen y luego allí haciendo las animaciones requeridas.

    Esto es fácil de lograr comprendiendo el mecanismo.

    Sucede que cuando la app arranca, se dispara un evento llamado OnLaunched en el App.xaml.cs. Ese evento trae unos argumentos args. Y dentro de estos argumentos, viene una referencia al SplashScreen que no es más que la imagen que especificamos en el manifiesto de la app para serlo.

    Este objeto splash screen tiene entre otros atributos, un rectángulo llamado ImageLocation que determina exactamente las coordenadas en las que se encuentra la imagen que hemos escogido para mostrar. Obviamente, la importancia de este rectángulo radica en que basados en sus coordenadas, ubicaremos la imagen en una nueva página que es donde ejecutaremos la animación:

     


    var splashImageRect = splash.ImageLocation;
    extendedSplashImage
    .SetValue(Canvas.LeftProperty, splashImageRect.X);
    extendedSplashImage.SetValue(Canvas.TopProperty, splashImageRect.Y);
    extendedSplashImage.Height = splashImageRect.Height;
    extendedSplashImage.Width = splashImageRect.Width;

    De esta manera obtenemos una página idéntica al Splash Screen, sobre la cual ejecutaremos una animación mientras hacemos la carga inicial.

    Asincronía

    Y ya que mencioné animaciones mientras se carga “algo”, de inmediato se me viene a la mente la asincronía. Porque efectivamente estoy hablando de un hecho en el cual asíncronamente se muestra una animación mientras se cargan elementos en memoria por ejemplo. Todo esto sin bloquear la interfaz del usuario, para que éste no sienta que la app es un ladrillo lento y no se aburra… y no desinstale… y recomiende. Es por esto que la asincronía es tan importante en las apps de WinRT. Es un mecanismo súper importante para lograr apps Fast and Fluid. Premisa número 1 de las Windows Store Apps. Sin ella, la interfaz se congelaría a menos de que usaramos complejos procesos con threads y demás.

    Precisamente para aprovechar el splash screen y cargar los settings del usuario, lo que hago es generar una animación, mientras en otro hilo a través de un método asíncrono inicio la ejecución del proceso de carga de una manera muy sencilla.

    Para comprender mejor este tema, les recomiendo este post, donde explico de una manera bien elemental éste proceso.

    De manera similar resuelvo situaciones en las que la app debe tomarse su tiempo, para que el usuario siempre sienta que la app le responde adecuadamente (por ejemplo cuando se lee el directorio con las fotos que se van a rankear)

    Conclusiones

    He tratado en este artículo de mostrar de una manera bastante informal, las principales experiencias que he tenido publicando una app con cierto nivel de complejidad en el Windows Store. La idea es que ustedes se puedan llevar algo de este conocimiento y que además les sirva para tener nuevas ideas a implementar en sus apps.

    Espero a medida de que mi app va evolucionando, ir escribiendo continuaciones a este post que sirvan para enriquecer el conocimiento de la comunidad en cuanto a apps se refiere.

    Las apps, a diferencia de otros tipos de desarrollo, son individualizadas con un dueño perfectamente identificado… por eso afirmo que una app es un hijo digital del developer… es su descendencia.

    Procuremos tener una descendencia remarcable. Sonrisa

  • WarNov Developer Evangelist

    Windows Store: Un análisis

    • 0 Comments

    El Windows Store a un mes de haber sido lanzado, se ha estado convirtiendo en un importante canal de distribución digital de software.

    Este protagonismo entre otras cosas ha causado que empresas independientes como Distimo que se dedican al estudio independiente de la industria de las apps a nivel mundial, lo hayan estudiado, considerándolo un importante actor en el mercado.

    Este artículo está basado en los estudios publicados por Distimo para el fin de Noviembre de 2012, sobre nuestro store. Esto, con el fin de mostrar un punto de vista no sesgado, sino imparcial, toda vez que la firma mencionada es independiente de cualquier proveedor de tiendas de Apps online.

    Los principales hallazgos incluyen:

    1. Hasta hoy, el número diario de descargas de las 300 apps más importantes del Windows Store, es tres veces mayor al que se experimenta con las 300 Apps más populares del Apple Mac App Store. Sin embargo, al mirar las apps pagas, se están comprando más en éste último. No obstante, es de notarse que ya están comenzando a arribar apps como Angry Birds, Fruit Ninja y Microsoft Office que pueden cambiar rápidamente esta proporción:

    image

    2. Microsoft está haciendo un gran trabajo para darle mayor visibilidad al contenido local en el store. En general, 10% de todas las Apps en los ranking locales, son apps locales. Y esta tasa aumenta viendo países pequeños. Por ejemplo en Japón, el 41% de las top apps son locales.

    3. El Windows Store presenta hoy 21.183 apps en total. De estas solo el 65% están disponibles en Estados Unidos. Aquí para efectos comparativos, cabe mencionar que en el resto de stores, la proporción es de 85%. De estas, 21.129 están disponibles para x86, 21.175 para x64 y 19.657 para ARM.

    4. El Windows Store, ha sido el que ha tenidos más apps disponibles tras su primer mes de lanzamiento (20K). El número para la Apple Mac App Store fue de solo 13K.

    5. Comparación con otros mercados:

    image

    Obsérvese por ejemplo que en solo un mes, el Windows Store ha mostrado tener más apps que todo el Apple Mac App Store durante casi dos años.

    6. Paid vs Free:
    Según el estudio, el Windows Store es aquel con una mayor proporción de apps free: 86% En el Google Play, el porcentaje es de 35% y en el Apple Mac App Store es del 16%.

    7. Porcentaje de Apps locales populares

    image

    Aquí resulta bien interesante mostrar por ejemplo que en Colombia ya se está proporcionando mucho impulso a las apps locales.

    8. Top 10 de publishers a nivel Mundial:

    image

    9. Top 10 de Apps en Colombia

    image


    10. Conclusiones

    “Observando estos primeros hallazgos acerca del Windows Store, es claro que existe mucho potencial y esto no es solo debido a que el número de consumidores crecerá inmensamente debido al gran alcance que tiene Windows, sino también debido a que Microsoft se ha apropiado de las mejores prácticas en la industria de apps y las ha implementado bien. Dividir el mercado del desktop y las tablets y además estableciendo un alto foco en el contenido local, también es una estrategia promisoria.¨

  • WarNov Developer Evangelist

    Tarde de Tecnología

    • 0 Comments

    Este jueves 22 de noviembre estaremos en Cali en una edición más de nuestro Microsoft Tech Day.

    Tendremos como es acostumbrado, dos tracks. Uno de Developers y otro de ITPros. La programación es esta:

    image

    En cuanto al tema de desarrollo, estaremos viendo dos temas muy importantes que tienen que ver con el mundo de servicios para nuestras apps. La primera parte, nos mostrará servicios móviles provistos por Window Azure pensando precisamente en las apps, otorgándonos facilidades para la autenticación, notificaciones y almacenamiento. Luego veremos el nuevo framework de WebAPI que nos permite hacer servicios Web basados en REST de una manera bastante sencilla, y como ejemplo veremos cómo almacenar archivos de manera segura, desde nuestras apps a la nube de Windows Azure.

    No se lo pierdan, en el Hotel Sheraton.

    Regístrense gratis aquí.

  • WarNov Developer Evangelist

    Usando WebAPI para generar Azure SAS para tus apps

    • 0 Comments

    He venido escribiendo una serie de posts acerca de los diversos mecanismos que existen para poder subir archivos desde nuestras apps de Windows 8 o de Windows Phone a Windows Azure.

    En este artículo explico por qué es importante un mecanismo que nos permita autorizar solo por un tiempo determinado manejar un archive determinado en el Storage de Azure, de manera que no expongamos nuestra información de cuenta de storage a que un hacker la pueda descubrir hacienda ingeniería inversa de nuestras apps. Este mecanismo es lo que se conoce como Shared Access Signature de Windows Azure y no es más que una URL que tiene validez temporal, con la cual podemos consultar un archive, eliminarlo, modificarlo o crearlo.

    En este otro artículo, muestro cómo podemos usar los Mobile Services de Windows Azure para poder obtener dichas SAS. Es un mecanismo que nos permite ahorrarnos tener web servers y que escala muy bien, porque maneja muy poca transferencia. Además nos economiza la administración. Todo esto, versus tener un servicio web que reciba las fotografías y las envíe al storage de Windows Azure, ya que toda la responsabilidad de ese servicio recae sobre nosotros.

     

    image*Azure + Web + Apps

    Estas ventajas son muy válidas. Pero sucede que para poder ejecutar los Mobile Services, se requiere por el momento, tener una base de datos de SQL Azure, y esto puede generar costos adicionales. Además, Mobile Services se encuentra en etapa de preview, por lo que salir a producción usándolos, puede ser riesgoso.

    Por estos motivos, he creado este post, en el que explico una manera alternativa para que nuestras apps puedan acceder a las codiciadas SAS, para poder subir archivos a Azure.

    Dado que las SAS son fácilmente generables a través del API de Storage de Azure: Microsoft.WindowsAzure.StorageClient,  es muy fácil pensar en un servicio Web que use esta API para retornar la SAS, dado un nombre de blob determinado. Y es esto precísamente lo que vamos a hacer. Pero será un servicio web muy liviano y además que permita un fácil acceso desde diversas plataformas. Todo esto se logra gracias a WebAPI. Un framework basado en ASP.NET para poder exponer construir de manera sencilla Servicios HTTP disponibles para una gran variedad de clientes que manejan REST.

    Como el framework es muy liviano y el proceso a ejecutar también lo es (solo se recibe una palabra y se retorna una URL), entonces es totalmente plausible que éste servicio se despliegue en un par instancias pequeñas de Windows Azure y soporte muy buena carga. De hecho, cuando los Windows Azure WebSites ya salgan de preview y comiencen a estar en producción, tendremos una alternativa aún más económica ya que está basada en servidores compartidos que luego pueden escalar y convertirse en servidores dedicados si las exigencias de nuestras apps así lo demandan. De hecho, algo que hoy en día existe que es la posibilidad de tener hasta 10 WebSites gratuitos, se mantendrá cuando el servicio pase a producción. En ambos casos (tanto con Cloud Services como con WebSites), nos ahorramos el despliegue de una Base de Datos y tenemos un poco más de control que con los Mobile Services.

    Aprovecho en este punto entonces para hacer notar que he mostrado varias opciones y ninguna de ellas es la absolutamente recomendable para todos los casos. Las condiciones de cada problema son particulares y por ende lo son sus soluciones. Mi misión es mostrarles las posibilidades. La de ustedes, elegir inteligentemente.

    Entonces continuando con nuestra solución basada en WebAPI tenemos nuestro controlador:

    SERVER:

    public class SASController : ApiController
    {
    
        //Esto es solo un ejemplo y pongo aquí directamente
        //los datos de la cuenta de acceso. 
        //Estos deberían estar en el config encriptados.
        static CloudStorageAccount _account;
        static bool _accountSet=false;
    
        //En bien se construye la clase, se trata de ajustar
        //la cuenta de almacenamiento de Azure
        static SASController()
        {
            string accountName = "tunombredecuenta";
            string pak = "fP4fXF9Vg...";
            _accountSet = CloudStorageAccount.TryParse(
                String.Format("DefaultEndpointsProtocol=https;"+
                "AccountName={0};AccountKey={1}",
                accountName,
                pak), out _account);
        }
    
    
        // GET api/sas/nombredeblob
        public string GetSAS(string id)
        {
            //Si la cuenta ha sido ajustada correctamente
            if (_accountSet)
            {
                //Creamos un container por defecto. 
                //Se puede trabajar tambien como parámetro
                var container = _account
                    .CreateCloudBlobClient()
                    .GetContainerReference("testcontainer");
                container.CreateIfNotExist();
    
                //Obtenemos una referencia al blob que se subirá
                var blob = container.GetBlobReference(id);
    
                //Creamos la sas que da permiso únicamente 
                //para ese blob, y solo por dos minutos
                //qué seguro no?
                var sas = blob.GetSharedAccessSignature
    (new SharedAccessPolicy() { Permissions = SharedAccessPermissions.Read | SharedAccessPermissions.Write, SharedAccessExpiryTime = DateTime.UtcNow +
    TimeSpan.FromMinutes(2) }); //Armamos la url en la cual podremos
    //poner el blob desde el cliente
    return blob.Uri.AbsoluteUri + sas; } else return "The API has not been configurated yet, "+ "pray to the heavens for them to configure it"; } }

    Vemos como solo bastó importar la librería del API de Storage, inicializar la cuenta de almacenamiento a través de un constructor estático y luego en la acción Get del controlador SAS usar la cuenta inicializada para producir la SAS basados en el nombre del blob que nos llega como parámetro “id”. Le dejé ese nombre para hacer prevalecer el paradigma de “Convention over Configuration”que al igual que en MVC, está muy presente en WebAPI.

    Vemos cómo es posible configurar el tipo y tiempo de acceso que otorgará la SAS. Todo eso queda incluido en la URL que se retorna al cliente. Algo del tipo: https://cuenta.blob.core.windows.net/img/archivo.jpg?sv=201324kjn,mnetc

    Con esta URL luego el cliente lo único que tiene que hacer es instanciar un HTTPClient y a través de este, poner el contenido del archivo con los headers específicos en dicha URL. Veámos el código de una app de Win8 para este fin:

    CLIENT

     

    //Escogemos el archivo
    var filePicker = new FileOpenPicker();
    filePicker.FileTypeFilter.Add(".jpg");
    var file = await filePicker.PickSingleFileAsync();
    
    if(file!=null)
    {
        //Con un cliente http nos comunicamos
        //al web api para bajar la SAS
        //luego con ese mismo cliente subimos el archivo
        using (var client = new HttpClient())
        {
            //Bajando la SAS
            var sas = await client.GetStringAsync
                ("http://localhost:47805/api/sas/" + file.Name);
            sas = sas.Substring(1, sas.Length - 2);
    
            //Cargamos la imagen con el HttpClient al blob 
            //service usando la SAS obtenida desde WebAPI
    
            //Obtenemos el stream de un storage file definido anteriormente
            using (var fileStream = await file.OpenStreamForReadAsync())
            {
                var content = new StreamContent(fileStream);
                content.Headers.Add("Content-Type", file.ContentType);
                content.Headers.Add("x-ms-blob-type", "BlockBlob");
    ”
    //Con el PutAsync, enviamos el archivo a Azure //a través de la URL autorizadora que está en SAS using (var uploadResponse = await client.PutAsync(new Uri(sas), content)) { //Agregar cualquier post proceso adicional } } } }

    Con el HTTPClient hemos descargado la SAS luego de tener el archivo escogido con su nombre identificado y luego aprovechamos ese mismo HTTPClient para poner el contenido del archivo al cual le hemos añadido unos headers para que pueda ser manejado correctamente por los Servicios REST del storage de Azure. Es importante notar aquí que la transferencia del archivo se realiza directamente desde el cliente a los Servicios de storage de Azure. El servicio web solo da la SAS. Esto es económico, veloz y escalable.

    Quise usar el anterior ejemplo para mostrar un escenario de uso de WebAPI. Pero a decir verdad, hay otra manera aún más liviana de lograrlo y es a través del uso de un manejador genérico de ASP.NET o ASHX. Un ASHX solo requiere de la Plataforma más elemental de ASP.NET (no requiere un motor de ruteo por ejemplo) para funcionar y lo hace también a través de la versatilidad de HTTP. Además el código es idéntico, except que el nombre del blob ya no va embebido en la ruta del request sino como un parámetro del querystring y el método como tal ya no va como una acción dentro del controller, sino como el ProcessRequest del handler.

    Summary:

    En conclusión, hemos visto cómo producir SAS desde Servicios web basados en HTTP, como lo proveen la WebAPI y los Generic Handlers. Luego vimos cómo usar esas SAS para poder subir archivos desde nuestras apps a Azure.

     

  • WarNov Developer Evangelist

    Adicionando archivos de Apps al Storage de Azure con Mobile Services

    • 0 Comments
     
    Los Windows Azure Mobile Services, proveen un mecanismo para permitir que clientes móviles (por ahora Windows 8, Windows Phone y iOS) se conecten a Windows Azure para almacenar y leer información tabular. Además ofrecen funcionalidad de push notifications, logging y autenticación.

    Pero cómo benefician estos servicios a la necesidad de poder almacenar archivos en el storage?

    En este post están los detalles que permiten justificar que para acceder a una cuenta de Storage desde un dispositivo es muy riesgoso dejar allí los datos de la cuenta de Azure, pues pueden ser extraídos con Ingeniería Inversa. Además de que el acceso se dificulta por falta de un API que abstraiga el acceso a REST directo. Windows Azure entonces dispone de un mecanismo llamado “Shared Access Signature” o SAS, que proporciona unas credenciales temporales para que se pueda acceder al storage.
        
    Tener un servicio Web que reciba las imágenes y desde su memoria las suba al storage de Azure de manera segura, es una opción, pero muy poco escalable, porque puede que miles de usuarios quieran subir sus fotos. Disminuir la carga del web server haciendo solo que exponga las credenciales SAS a los dispositivos para que estos luego puedan acceder directa y fácilmente al storage es mejor opción, pero sigue siendo algo cara, pues requiere un web server y un desarrollo asociado, así como todo el overhead de mantenimiento.
        
    Entonces la idea es aprovechar los Mobile Services para obtener esta SAS.
        
    No obstante, en las funcionalidades que mencioné, en ninguna está la del suministro de la SAS. Pero aquí es donde la imaginación y el ingenio juegan parte importante. Lo que sí mencioné es que se puede acceder a unas tablas a leerlas o modificarlas. Para ello se han dispuesto unas APIs especialmente diseñadas para WP y WinRT; hasta para iOS hay versión. Y en las tres plataformas pueden ser incluidas y usadas sin ningún problema de funcionamiento ni certificación cuando la app se sube al store. Pues bien, las operaciones CRUD que hacemos sobre estas tablas (que se pueden diseñar desde el portal de administración de Azure sin código alguno), están sujetas a que se ejecuten triggers que se dispararán cuando nosotros lo especifiquemos. Por ejemplo, cuando haya una inserción. En últimas esto se puede tomar como un servicio web asíncrono, en el cual insertamos un request en la tabla y luego la volvemos a consultar para ver la respuesta obtenida, que obviamente se encontrará en otra columna.
        
    El primer paso entonces, es crear el Mobile Service en el portal de Windows Azure. Esto es totalmente gratuito. Solo es requerido crear una cuenta, cosa que también es gratis. Un paso a paso muy bien elaborado lo pueden encontrar aquí.
        
    Básicamente lo que hicimos en ese paso a paso, fue crear el servicio y luego desde el portal, usar unas funcionalidades muy útiles que tenemos allí, como la de crear automáticamente nuestra primera tabla de datos. Y luego bajarnos una solución preconstruida que va a consumir esa tabla. Esa solución puede ser para phone, Windows 8 o iOS.
        
    clip_image002
    Obviamente, también podemos conectarnos a apps existentes. No solo a nuevas. Con este fin el portal nos suministra un código con una clave que debe tener la app para poderse conectar. Este código en el caso de Windows 8 por ejemplo, se pone en el App.xaml.cs:
    //This MobileServiceClient has been configured to communicate
    //with your Mobile Service's url and application key.
    //You're all set to start working with your Mobile Service!
    public static MobileServiceClient MobileService =
    new MobileServiceClient( "https://warserv.azure-mobile.net/", "ElSmsvstPUsdXWsHJqFteqhkLxDVcdr15" );

    Obviamente para que el código nos funcione, debemos de haber referenciado la dll que contiene el tipo MobileServiceClient. Esta dll ya viene agregada si nos bajamos la solución de ejemplo del portal. Si estamos habilitando una solución preexistente, la incluimos manualmente. Se llama Windows.Azure.Mobile.Services.Managed.Client y queda disponible luego de que instalemos el Mobile Services SDK.

    Después de esto, nuestra app ya queda lista para conectarse directamente con el servicio y empezar por ejemplo a hacer inserciones en la tabla que construimos en el paso a paso (o cualquier otra tabla que creemos dentro del servicio usando el portal).
        
    Ahora lo que haremos es generar el trigger para nuestro servicio, de manera que cada vez que exista un insert, se dispare una rutina que nos retorne dentro de ese registro insertado, la SAS que necesitamos. Esta rutina la debemos escribir con Javascript, que se ejecutará en el server, a través de un editor online que tenemos en el portal. Para acceder a ese editor, ubicamos nuestro servicio y luego allí escogemos la tabla en cuestión (1). Después vamos a SCRIPT (2) y finalmente escogemos la operación (Insert) de esta manera, ejecutaremos la acción especificada en el script con cada insert que hagamos en la tabla.
        
    clip_image003
        
    El código del script lo pueden descargar de aquí. Y la parte más importante del mismo es ésta:
       
    function insert(item, user, request) {
        var accountName = '<SU NOMBRE DE CUENTA>';
        var accountKey = '<SU PAK>';
    
        //Note: this code assumes the container already 
    //exists in blob storage. //If you wish to dynamically create the container then implement
    //guidance here -
    //http://msdn.microsoft.com/en-us/library/windowsazure/dd179468.aspx
    var container = 'test'; var imageName = item.ImageName; item.SAS = getBlobSharedAccessSignature(accountName,
    accountKey, container, imageName); request.execute(); }
    Como ven, tienen que poner los datos de la cuenta en los placeholders. También se aprecia que el ítem insertado viene como parámetro. Y que luego a ese ítem se le ajusta la propiedad SAS con una función que recibe el nombre de la cuenta, la clave, el contenedor y la imagen. Esto nos va a retornar una SAS que no es más que una URL que contiene unos permisos temporales implícitos, para que luego a esa URL podamos subir un archivo de nombre item.ImageName. Al final, vemos como se ejecuta el request y es en este momento cuando se inserta el registro como tal en la tabla del servicio. Además el ítem actualizado baja al cliente automáticamente y desde allí podremos consultar el valor de la SAS.
        
    Entonces, para el manejo desde nuestra app, necesitamos una clase que nos represente al ítem:
        //la estructura de la tabla que tenemos
        //en el Mobile Service. 
        //Es una clase generada por nosotros 
        //de acuerdo a nuestras necesidades.
        public class TodoItem
        {
            public int Id { get; set; }
    
            [DataMember(Name = "text")]
            public string Text { get; set; }
    
            [DataMember(Name = "ImageName")]
            public string ImageName { get; set; }
    
            //Es en este campo, donde quedará almacenada la SAS
            [DataMember(Name = "SAS")]
            public string SAS { get; set; }
    
            [DataMember(Name = "complete")]
            public bool Complete { get; set; }
        }
    
    Esta clase la creamos con los campos por defecto que se crean las tablas en Mobile Services, y le agregamos los campos requeridos.
        
    Luego de esto, cuando ya tenemos el archivo que queremos subir a la nube, lo que hacemos, es crear una inserción en la tabla:
    StorageFile file = await openPicker.PickSingleFileAsync();
    if (file != null)
    {
        //agrega un item a la tabla de Mobile Service, disparando un trigger
        //que retorna el item.SAS, como un valor en otra columna de la tabla,
    //que se transfiere automáticamente al ítem.
    var todoItem = new TodoItem() { Text = "test image",
    ImageName = file.Name }; await todoTable.InsertAsync(todoItem); items.Add(todoItem); //Cargamos la imagen con el HttpClient al blob //service usando la SAS generada en item.SAS using (var client = new HttpClient()) { //Obtenemos el stream de un storage file definido anteriormente using (var fileStream = await file.OpenStreamForReadAsync()) { var content = new StreamContent(fileStream); content.Headers.Add("Content-Type", file.ContentType); content.Headers.Add("x-ms-blob-type", "BlockBlob"); //Con el PutAsync, enviamos el archivo a Azure //a través de la URL autorizadora que está en SAS de la forma: //"https://--------------.blob.core.windows.net/test/
    //androidsmartglass.jpg?etc //donde etc es la cadena de validación
    using (var uploadResponse = await client.PutAsync(new Uri(todoItem.SAS), content)) { //Agregar cualquier post proceso adicional } } } }

    De esta manera, ya habremos podido subir nuestro archivo al storage de Azure, desde un cliente móvil, sin arriesgar nuestra cuenta de storage, sin sobrecostos por Servidores Web y de una manera absolutamente escalable, porque este request en total pesa menos de 1Kb. Mucho menos de lo que sería subir la imagen a un servidor, para que desde allí de manera segura se pudiese enviar al storage. Ahora, el envío es directo, de manera que es más rápido!

    En síntesis, hemos visto como entre las bondades de los Windows Azure Mobile Services, podemos contar con la capacidad de generar servicios sencillos basados en código de servidor escrito con Javascript que como input puede recibir un registro en las tablas de datos y como output una respuesta que queda almacenada en ellas en otra columna distinta. Si adicionamos a esto un trigger para cada inserción, obtendremos una respuesta asíncrona que hace que el Javascript que hemos escrito actuando sobre las APIs de Azure, permita entre otras cosas generar claves SAS, útiles para que dispositivos puedan acceder de manera segura y directa al storage.
  • WarNov Developer Evangelist

    Azure como backend de storage para Windows Apps y el poder de los Mobile Services

    • 2 Comments

    Con Windows Apps, me refiero a apps para el Windows Store y para el Windows Phone Store.

    El conocimiento promedio que tenemos hoy en día de Azure y de Cloud Computing, nos indica que una gran alternativa para las necesidades de storage que tienen las apps, efectivamente es el storage de Azure. Y uno va y mira y sí… efectivamente así es. Pero hay que tener en cuenta ciertos detallitos en los que podemos pecar por ir muy a la ligera.

    Si queremos ofrecer almacenamiento en nuestra app a través de una cuenta de Azure, lo primero que se nos vendría a la mente es: fácil, uso el API de Storage y la accedo desde mi app. Pero esto tiene dos implicaciones:

    http://blogs.msdn.com/cfs-filesystemfile.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-28-02-metablogapi/2816.image_5F00_32AEF2F2.png

    1. El soporte que se le da a la API desde las plataformas de desarrollo de WP y de WinRT: En este caso, lamento informar que el Microsoft.WindowsAzure.StorageClient.dll aún no está disponible para estas plataformas, pese a que en Web, WinForms, WPF, WCF y demás sí es completamente accesible. Esto nos deja con una sola alternativa y es la de usar REST puro y duro para acceder al storage de Azure. Es decir, crear clientes HTTP dentro de del código de la app y configurarlos para hacer un request REST sobre la API del storage (recordemos que esta API es nativa REST y por ende se puede acceder de esta manera). Tanto en WP como en WinRT es completamente viable esto, ya que tenemos las clases adecuadas. Sin embargo, configurar estos clientes no es fácil ni amigable. Algunos acercamientos como la librería Windows Azure Storage Client para Windows Phone disponible a través de NuGet, pueden ayudar a alivianar la tarea, encapsulando todos estos llamados. Desafortunadamente hoy no tenemos una equivalencia para WinRT. Tal vez mediante agunos hacks, uno pudiera usar esta de phone con Windows 8. Pero entonces viene el 2do. Punto a tener en cuenta:

    2. Independientemente de que hagamos los llamados a través de REST puro o usando una librería como la citada en phone, siempre debemos incluir la información de la cuenta para poder tener acceso a Azure. Tradicionalmente esto no es un gran problema, y digo tradicionalmente refiriéndome al hecho de que si estamos acostumbrados a crear aplicaciones de servidor que acceden a Azure, sabemos que los datos de la cuenta (nombre y clave) están “seguros” en nuestros servidores que están detrás de unos balanceadores de carga y unos proxies que lo protegen. Pero en el caso de las apps…. Te sentirías seguro sabiendo que el nombre y clave de tu cuenta de Azure está “quemado” en una app que probablemente hayan bajado cientos o miles de usuarios? Cualquier usuario malicioso, podría hacer ingeniería inversa de la app para extraer los datos de la cuenta (y aunque es complicado, no es imposible).

    Entonces, no hay una API oficial y tampoco es seguro embeber los datos de la cuenta en los clientes. Así que entonces la solución que se viene a la cabeza es: Hagamos servicios web!

    De esa manera, dado que WinRT y WP, tienen completo soporte a servicios web se podrán subir los archivos al servidor web y éste, que sí tiene el poder de usar la API de Storage de Azure, tendrá muy cómodo pasar estos archivos a la nube. Además, los datos de cuenta estarán seguros dentro del server, pues los clientes solo necesitan saber la dirección del servicio web.

    Pero realmente es esto lo que queremos? Tener un servidor Web, tiene costos asociados. Además tendríamos una sobrecarga sobre esos servidores recibiendo imágenes de Raimundo y todo el mundo. Por lo tanto requeriríamos varios servidores y los costos se elevarían enormemente. Sumémosle además el hecho de que el storage de Azure se puede acceder directamente y nos ahorraríamos todos esos costos.

    Entonces… cuál sería la solución apropiada?

    Se imaginan un mecanismo en el cual cada app pudiera tener un permisito que dure solo el tiempo requerido para ejecutar la acción necesaria sobre el storage y que luego ya no sea válida? En ese caso, por más que el hacker obtenga la clave, cuando lo haga, ya no le servirá de mucho.

    Pues para sus cuentas, les informo que Azure soporta el acceso al storage a través de este mecanismo, que particularmente se llama “Shared Access Signature” o SAS.

    Obviamente, para poder generar una SAS, se requiere tener los datos de la cuenta. Y volvemos al mismo sitio: no queremos exponer esos datos. Pero hay algo bueno! Si creamos un servicio web que nos retorne esa SAS (menos de 1K de tamaño), tendremos mucha menos sobrecarga que cuando usamos web services para transferir imágenes. En este caso, solo requeriremos una pequeña respuesta del server con la SAS y ésta la usaremos para que a través de un llamado HTTP (ésta vez mucho más sencillo que cuando se desea usar los datos de la cuenta nativa, ya que este requiere ser asegurado) en el que referenciamos dicha SAS podamos ejecutar la acción requerida sobre el storage (por ejemplo subir o bajar un archivo de los blobs, o consultar un registro de las tablas) sin necesidad de suministrar al cliente los datos de la cuenta.

    Entonces se podría decir que hallamos la solución! Ponemos un servicio Web a repartir SAS a las apps. Tal vez el servicio web haga alguna validación para decidir si responde positivamente al llamado. Y listo. La logramos!

    Esta situación la podríamos optimizar aún más. Dado que ahora la carga no será tan fuerte, podríamos entrar a analizar la posibilidad de usar web servers compartidos, disminuyendo enormemente los costos. Pero aquí tendremos que entrar a balancear costo contra disponibilidad.

    No sería mejor entonces tener un servicio pre-construido en la nube que ya nos proveyera la capacidad de emitir las SAS a las apps? Que nos quitara la necesidad de crear todo un web server para este fin?

    Sí, existe! Son los Windows Azure Mobile Services. Sevidores configurados para que clientes con una clave definida puedan entrar a escribir en unas tablas que quedan disponibles para este fin. Adicionalmente, también ofrecen servicios de Push Notifications y sobre ambos se pueden establecer estrategias para que solo usuarios autenticados puedan acceder a estos servicios.

    Subyacentemente, los Mobile Services tienen servidores web compartidos o dedicados que cuestan menos que los Web Sites de Azure. De hecho, hoy en día, se pueden tener hasta 10 Mobile Services gratuitamente. Estos servidores subyacentes, se pueden escalar a discreción. Aunque entonces parece que es lo mismo que tener los Web Servers tradicionales, la ventaja es que no tenemos que desplegar ningún código para que funcionen. La funcionalidad ya está en producción.

    No obstante, en las funcionalidades que mencioné, en ninguna está la del suministro de la SAS. Pero aquí es donde la imaginación u el ingenio juegan parte importante. Lo que sí mencioné es que se puede acceder a unas tablas a leerlas o modificarlas. Para ello se han dispuesto unas APIs especialmente diseñadas para WP y WinRT; hasta para iOS hay versión. Y en las tres plataformas pueden ser incluidas y usadas sin ningún problema de funcionamiento ni certificación cuando la app se sube al store. Pues bien, las operaciones CRUD que hacemos sobre estas tablas (que se pueden diseñar desde el portal de administración de Azure sin código alguno), están sujetas a que se ejecuten triggers que se disparán cuando nosotros lo especifiquemos. Por ejemplo, cuando haya una inserción. En últimas esto se puede tomar como un servicio web asíncrono, en el cual insertamos un request en la tabla y luego la volvemos a consultar para ver la respuesta obtenida, que obviamente se encontrará en otra columna.

    De esta manera, imaginen entonces que queremos subir una imagen al blob storage de Azure. Así que a modo de request, insertamos el nombre de esa imagen en una tabla de un Mobile Service previamente configurado, a través de las apis mencionadas.

    El servicio tiene un trigger sobre las inserciones. Y ese trigger detecta que hubo una inserción. Entonces ejecuta un código de servidor basado en Node.js (Javascript en el Server). Este código es suministrado por nosotros. Lo escribimos en el portal de administración de Azure; en la sección de configuración del servicio. Es así como podemos escribir un código que nos inserte en el mismo registro de la tabla la SAS que requerimos para acceder al container en el que queremos poner el archivo. Entonces cuando ordenamos la inserción asíncrona, pasamos el ítem a insertar y cuando termina esa inserción, podemos obervar que el ítem ya traerá la SAS que hemos generado.

    Luego usando esa SAS subimos el blob con tres líneas de código y ya está!

    En síntesis:

    Para poder acceder al storage de Azure desde apps sobre las cuales no tenemos control una vez han sido descargadas de las distintas tiendas de aplicaciones, la mejor alternativas es usar las SAS de Azure. La alternativa más cómoda y económica para obtener esas SAS, viene siendo los Mobile Services de Azure a través de las tablas de datos, ya que se proveen APIs de acceso a esas tablas que funcionan muy bien en WP7, Win8 y iOS. Con la SAS accedemos de manera segura para todos al storage.

    Una vez comprendido esto, continuemos con un paso a paso de cómo desplegar una solución de este tipo, en este post:

    Cómo adicionar archivos al Blob Storage de Windows Azure desde Windows Apps, a través de Mobile Services.

  • WarNov Developer Evangelist

    SQL Azure BACPAC - DB BACKUP en la nube (Nuevo Portal)

    • 0 Comments

    El formato de archivo BACPAC, se refiere a un nuevo tipo de archivo que contiene tanto el esquema, como los datos de una base de datos.

    En el Nuevo portal de Administración Windows Azure, en la sección de Bases de Datos, existe una opción para exportar una db existente, lo que nos produce un archive BACPAC que es almacenado en una de nuestras cuentas de almacenamiento de Azure. Además cuando se va a crear una nueva DB, se da la opción de importarla desde un BACPAC existente.

     

    Por ejemplo para exporter, nos ubicamos sobre la db a exporter y le damos click o tap a Export, lo que nos muestra el siguiente cuadro de diálogo:


    newbacpac


    Esta operación requiere una cuenta de almacenamiento de Windows Azure para guardar esa copia BACPAC en el blob storage. En este caso, debemos especificar los datos de la cuenta y el container dentro de esa cuenta donde va a quedar la copia BACPAC.

    Luego de especificar la cuenta, comienza a generarse la copia. Este es un proceso asíncrono, cuyo estado se puede consultar entrando a la sección de mensajes del portal:

    image

        

    Una vez creada la copia, podemos importer a través del botón que tiene ese nombre en la sección de Databases del portal, o a través de las opciones de crear una nueva DB:

    newimport1

    Luego de esto específicamos la ruta dentro del almacenamiento de Azure  donde dejamos el bacpac.

    newimport2


    newimport3

    Luego de esto, comienza la importación de la DB

    Lo mejor: Estas operaciones son susceptibles a ser automatizadas gracias al API de REST para acceder a los servicios de BACPAC; de esta forma, podemos programar los backups de nuestras DBs, y estos quedarán almacenados en el blob storage de Azure, que vale un centavo de dólar la giga al mes.

  • WarNov Developer Evangelist

    Cómo agregar y consultar info personalizada a Bing Maps

    • 0 Comments

    Bing Maps tiene abiertos sus servicios de mapeo, para que los desarrolladores puedan hacer uso de ellos. Como vemos en esa breve reseña del servicio, se tiene un tipo de cuenta gratuita (developer) para trabajar con estos servicios y otra paga (Enterprise).

    Cuando trabajamos con una cuenta de developer, solo podemos usar datos que ya tiene Bing Maps en sus bases de datos. Pero puede que nuestra necesidad de negocio requiera mapear puntos propios del negocio que no están en Bing Maps. Por ejemplo para tenerlos en un caché y que se dibujen siempre sin necesidad de requests adicionales a los servidores. Puede que además necesitemos obtener información personalizada y extendida de esos puntos personalizados y queramos hacver consultas sobre esa información. En ese caso, deberemos subir nuestra información a Bing Maps. Esta funcionalidad es brindada por Bing Spatial Data Services que solo es accesible en la versión Enterprise.

    Estos servicios proveen la funcionalidad de tener puntos de interés preestablecidos a través de fuentes de datos propias y generar diversas consultas tradicionales o geoespaciales sobre ellos. Aquí podemos encontrar algunos ejemplos de las implementaciones posibles.

     

    Las fuentes de datos personalizadas son accesibles muy fácilmente a través de directorios online que contienen ubicaciones (lat/long, campos de dirección y otros campos personalizados). Estos son creados cuando subimos y publicamos un archivo que contiene estos datos en un esquema estándar. Esto se hace a través del portal de Bing Maps o con el uso del API de administración de fuentes de datos.

    En conclusión, para poder manejar nuestros propios puntos como si fueran originarios de Bing Maps, hemos de subirlos a la nube de Bing Maps, a través de Bing Maps Data Services; una solución solo disponible para usuarios de tipo Enterprise.

Page 2 of 13 (317 items) 12345»