Performancing Metrics

Return(GiS);

Return(GiS);

Añadir web references en Visual Studio 2010

 

Como curiosidad, hoy me topé con la necesidad de añadir una referencia web en Visual Studio 2010 cuando mi sorpresa fue no encontrar dicha opción como esperaba, al igual que en versiones anteriores.
 

Visual Studio 2008

 

 Sin embargo en Visual Studio 2010 esta opción desaparece como tal.

Visual Studio 2010

¿Cómo agregamos referencias web entonces?

 

En esta nueva versión del IDE lo que debemos hacer es seleccionar en primer lugar Add Service Reference…  y pulsamos directamente sobre el botón Advanced…

 

En la parte inferior del nuevo cuadro de diálogo aparece un apartado llamado Compatibility donde podemos añadir las referencias web a través de la misma ventana que utilizábamos en versiones anteriores :D .
 

 

Espero que sea de utilidad :)

¡Saludos!
Posted: 10/1/2011 13:27 por Gisela | con 1 comment(s)
Archivado en:
PowerShell para la administración de nuestras aplicaciones en Windows Azure

 

 
 
En muchos post hemos visto la forma de utilizar el portal de la plataforma para desplegar, actualizar, eliminar, etcétera los servicios que tenemos actualmente ejecutándose en la nube. Pero esta no es la única alternativa para realizar estas tareas más propias del administrador ;) . La otra opción es utilizando la API de administración que nos proporciona Windows Azure. Podemos hacer uso de la misma a través de REST o también usando Windows Azure Management CmdLets,  un snap-in para PowerShell que actúa como wrap de la API facilitándonos el trabajo. Podemos descargarlo a través del siguiente enlace.
Una vez descargado, descomprimimos el archivo y abrimos con Visual Studio la solución alojada en la carpeta code para compilar la misma. Es posible que no encuentre la librería Microsoft.WindowsAzure.StorageClient por lo que debemos eliminar la referencia existente y agregar la última versión del SDK 1.3 de esta librería. Compilamos la solución y ejecutamos el archivo startHere.cmd para instalar los componentes necesarios, además del snap-in.
Ya estamos listos para administrar nuestras aplicaciones a golpe de comando :) . Abrimos una ventana de Windows PowerShell/Windows PowerShell ISE  y ejecutamos lo siguiente:
Add-PSSnapin AzureManagementToolsSnapIn
Con este comando lo único que estamos haciendo es añadir el snap-in que acabamos de instalar a la sesión actual. Para comprobar que funcionó correctamente podemos recuperar los comandos disponibles:
Get-Command -PSSnapIn AzureManagementToolsSnapIn

Lanzar un nuevo despliegue

 Uno de los objetivos más comunes sería desplegar un paquete en uno de los entornos. Para ello utilizaremos el comando New-Deployment con los siguientes parámetros obligatorios:
New-Deployment -serviceName <LOWER_CASE_SERVICENAME>
-storageServiceName <LOWER_CASE_STORAGE_SERVICE_NAME>
-subscriptionId <YOUR_SUBSCRIPTION_ID>
-certificate (get-item cert:\CurrentUser\MY\<CERTIFICATE_THUMPRINT>)
-slot staging –package <PACKAGE_LOCATION> -configuration <CONFIGURATION_LOCATION>
-label "From PS"
Un ejemplo del comando anterior podría ser el siguiente:
New-Deployment -serviceName returngis -storageServiceName myazurestorage
-subscriptionId 5rtegtsw-0i93d-46b0-5tre-nh64w24
-certificate (get-item cert:\CurrentUser\MY\327BBBABFE909FDJGR9ERJGFGDDFS30E76D370F2F95)
-slot staging –package c:\Deploy\WindowsAzurePowerShell.cspkg
-configuration C:\Deploy\ServiceConfiguration.cscfg -label "From PS"
(Los datos son ficticios ;) )
Si utilizamos un cliente para visualizar los containers en la cuenta de Storage que hemos incluido en la llamada, podemos ver que existe un nuevo container llamado mydeployments con todos los paquetes utilizados para los despliegues a través de PowerShell.
 
 
Si bien con el anterior comando hemos conseguido desplegar un nuevo paquete en el entorno de staging, la máquina virtual no ha sido arrancada :( Afortunadamente esta acción también podemos ejecutarla desde PowerShell utilizando el Set-DeploymentStatus:
Set-DeploymentStatus -status running -slot <staging/production>
-serviceName <LOWER_CASE_SERVICENAME>
-SubscriptionId <YOUR_SUBSCRIPTION_ID>
-certificate (get-item cert:\CurrentUser\MY\<CERTIFICATE_THUMPRINT>)
Un ejemplo de lo anterior podría ser lo siguiente:
Set-DeploymentStatus -status running -slot staging
-serviceName returngis -SubscriptionId 5rtegtsw-0i93d-46b0-5tre-nh64w24
-certificate (get-item cert:\CurrentUser\MY\327BBBABFE909FDJGR9ERJGFGDDFS30E76D370F2F95)

Eliminiar despliegue

Para eliminar un despliegue los parámetros son prácticamente los mismos que al realizar la subida, a excepción de especificar los paquetes.
Remove-deployment -slot staging -serviceName <LOWER_CASE_SERVICENAME>
 -subscriptionId <YOUR_SUBSCRIPTION_ID>
 -certificate (get-item cert:\CurrentUser\MY\<CERTIFICATE_THUMPRINT>)
Si nos fijamos en la consola, podemos pensar que el despliegue se ha eliminado correctamente… Lo cual no es cierto.
 
 
El mensaje de error nos avisa que Windows Azure no puede eliminar un despliegue cuando el mismo se está ejecutando, por lo que tendremos que utilizar el comando anterior, Set-DeploymentStatus, pero esta vez para suspender la ejecución de la máquina virtual.
Set-DeploymentStatus -status suspended -slot <staging/production>
-serviceName <LOWER_CASE_SERVICENAME>
-SubscriptionId <YOUR_SUBSCRIPTION_ID>
-certificate (get-item cert:\CurrentUser\MY\<CERTIFICATE_THUMPRINT>)

¿Cómo podemos saber cuándo ha finalizado un proceso?

Debido a que las acciones que lanzamos se llevan a cabo en segundo plano no podemos saber cuándo ha finalizado el proceso. Por ello, podemos asignarle un comando adicional separado por un pipeline para permanecer en espera hasta que la ejecución finalice. Este comando es Get-OperationStatus -WaitToComplete
Set-DeploymentStatus -status running -slot staging -serviceName <LOWER_CASE_STORAGE_SERVICE_NAME>
-SubscriptionId <YOUR_SUBSCRIPTION_ID>
-certificate (get-item cert:\CurrentUser\MY\<CERTIFICATE_THUMPRINT>) | Get-OperationStatus -WaitToComplete
Si estamos utilizando Windows PowerShell ISE aparecerá una nueva ventana con el progreso:
 
 
Espero que sea de utilidad :)
¡Saludos!

 

Posted: 9/1/2011 20:32 por Gisela | con no comments
Archivado en:
Cloudes: Computación en Windows Azure

 

 
El 26 de Enero comenzamos con los eventos online en Cloudes, grupo de usuarios de cloud computing en España :D

Si bien ya habíamos anunciado nuestra existencia en LinkedIn, empezamos apostando fuerte por los eventos online con el objetivo de llegar al mayor número de personas posible.
 
En esta ocasión daremos una charla sobre la computación en Windows Azure. Veremos cuáles son las posibilidades hasta ahora, la forma de desarrollar, el nuevo portal de la plataforma, etcétera.
 

 

Para registraros podéis hacerlo a través del siguiente enlace.

 

¡Os esperamos!

Posted: 7/1/2011 8:55 por Gisela | con 4 comment(s) |
Archivado en: ,
Crear e instalar un servicio Windows

 

Estos días he estado trabajando con servicios Windows, los cuales se utilizan para realizar operaciones en background. Una de las principales ventajas de los mismos es que tenemos la posibilidad de ejecutarlos sin necesidad de tener un usuario logado en el sistema. 

En este post voy a mostrar la forma de crear un proyecto con una pequeña demo y varias formas para instalarlo. 

Creación del proyecto

Creamos un proyecto del tipo de Windows Service. En este post lo llamaré CheckerWindowsService
 

 

Cuando carga la plantilla de Visual Studio, vemos que tenemos un nuevo archivo llamado Service1.cs y el típico Program.cs que acompaña a las aplicaciones de consola. Si accedemos al primero de ellos, nos mostrará la parte de diseño que básicamente es un fondo gris :D Si pulsamos sobre ella con el botón derecho y hacemos clic en View Code veremos la siguiente estructura: 

 

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Linq;
using System.ServiceProcess;
using System.Text; 

namespace CheckerWindowsService
{
    public partial class Service1 : ServiceBase
    {
        public Service1()
        {
            InitializeComponent();
        } 

        protected override void OnStart(string[] args)
        {
        } 

        protected override void OnStop()
        {
        }
    }
} 
La clase Service1 debe heredar de ServiceBase para obtener todos los métodos y propiedades relacionadas con los servicios Windows. En esta plantilla se muestran los métodos que normalmente se sobrescriben: OnStart donde insertaremos el código que queremos que se ejecute nada más iniciar el servicio y OnStop en el caso de que el mismo sea parado. Para este ejemplo, voy a renombrar la clase Service1.cs a CheckerService.cs

Implementación

Lo primero que debemos modificar son las propiedades del archivo CheckerService.cs 
 
  

 
Por nombrar algunas de las propiedades más utilizadas, AutoLog se utiliza para permitir que el servicio registre o no los inicios, paradas, etcétera en el visor de eventos del sistema (opción por defecto). CanPauseAndContinue nos da la posibilidad de pausar y continuar con la ejecución del servicio, CanStop pararlo (al hacer esta opción pasará por el método OnStop) y ServiceName donde asignamos el nombre del servicio. 

En esta demo lo que vamos a hacer es que cada minuto vamos a comprobar si existe algún proceso del explorador Firefox abierto y, de ser así, vamos a finalizarlo (y si se resiste matarlo :D ).  Sobre la vista de diseño pulsamos con el botón derecho y seleccionamos View Code para agregar lo siguiente: 
protected override void OnStart(string[] args)
{

   var timer = new Timer { AutoReset = true, Interval = 60000 };
   timer.Elapsed += timer_Elapsed;
   timer.Start();
}

private void timer_Elapsed(object sender, ElapsedEventArgs e)
{
    var processes = Process.GetProcessesByName("firefox");

    foreach (var process in processes)
    {
       process.CloseMainWindow();

       if (!process.HasExited)
       {
            process.Kill();
            process.Close();
       }
    }
}

Añadir Instalador

Una vez que tengamos nuestro código implementado, es necesario añadir un instalador a la solución. Para ello nos ponemos en el modo diseño y con el botón derecho seleccionamos Add Installer

 

 
 

En este momento se agregará una nueva clase llamado ProjectInstaller.cs con dos componentes. Hacemos clic sobre serviceInstaller1 donde indicaremos el nombre del servicio (el mismo ServiceName que en CheckerService.cs) y el tipo de inicio (Manual, Automático o Deshabilitado). Además podemos indicar el nombre a mostrar y una descripción de lo que hace la aplicación. Estos dos últimos datos serán los que se mostrarán en el listado de servicios de Windows. 
 
 
 
Por último, si seleccionamos el otro elemento, serviceProjectInstaller1, podemos seleccionar el tipo de cuenta con la que queremos que se ejecute el servicio. En este caso, utilizaré LocalSystem para tener los permisos suficientes para matar procesos. 
 

 

Instalación/Desinstalación

Para la instalación del servicio Windows tenemos varias alternativas: 
  • Utilizar la plantilla para el proyecto del tipo Setup Project
  • Crear instaladores con InstallShield.
  • El comando InstallUtil.exe desde la línea de comandos. 

Setup Project

Adjuntamos a nuestra solución un nuevo proyecto del tipo Setup Project.
 
 
Seleccionamos el proyecto que acabamos de crear y añadimos la salida del proyecto del servicio web. 
 
 

Aparecerá un cuadro de diálogo con el proyecto Windows Service por defecto donde dejaremos seleccionado Primary output y confirmamos.
 

 
En el Explorer Solution hacemos click en el botón Custom Actions Editor.

 
 

 

Y aparecerá una nueva ventana donde se alojan las acciones personalizadas. Con el botón derecho añadimos una nueva como se muestra en la imagen:
 

Seleccionamos Application Folder.
 

Y por último aparecerá únicamente Primary output from CheckerWindowsService que es la que añadimos anteriormente. Pulsamos en OK y ¡Listo!
 

 
Para instalarlo, compilamos nuestra solución y posteriormente el proyecto Setup Project. Seleccionamos el proyecto de instalación con el botón derecho y hacemos click en Install.

 

 
Para desinstalar la operación sería la misma pero con Unistall :D

InstallShield
De lo poco que pude trastear con InstallShield, pude ver que las opciones de configuración son mayores que con Setup Project y te permite una mejor personalización de las instalaciones.
 Si bien con Visual Studio 2010 puedes hacer uso de InstallShield Limited Edition.
 
 

Para poder crear un installer para un windows service necesitas tener al menos una versión Premium, obviamente de pago.

InstallUtil.exe 

Desde la línea de comandos también podemos instalar/desinstalar un servicio Windows. El comando InstallUtil.exe se instala automáticamente con Visual Studio y podemos ejecutarlo a través de Visual Studio Command Prompt.
 
Instalación

InstallUtil.exe miEjecutable.exe
Desinstalación
InstallUtil.exe /u miEjecutable.exe
Espero que os sea de utilidad :D  

¡Saludos!
 

Posted: 5/1/2011 12:03 por Gisela | con 12 comment(s)
Archivado en:
Eliminar los snapshots de un blob de Windows Azure Storage

 

Si habéis tenido que trabajar alguna vez con los blobs de Windows Azure Storage, y más aún si habéis hecho uso de los snapshot, ya habréis tenido el placer de encontraros con un error como este:
 
 
Si bien teníamos una forma de eliminar un blob con todos sus snapshots
blob.Delete(new BlobRequestOptions()
{
    DeleteSnapshotsOption = DeleteSnapshotsOption.IncludeSnapshots
});
Cuando queríamos eliminar uno solo la cosa se complica :(
Hasta ahora para recuperar un snapshot la única solución era llamar al método GetBlobReference con la siguiente estructura:
blob.GetBlobReference("filename?snapshot=<DateTime>");
Además la fecha debía tener el siguiente formato: 2010-03-07T00%3A12%3A14.1496934Z 
 
La otra opción era dejar de lado el Storage Client y crear nuestra propia llamada REST con los parámetros oportunos.
En cualquiera de los dos casos no era una forma muy simplificada de llevar a cabo una acción tan sencilla como recuperar un snapshot hasta la versión 1.3 :D
A partir de ahora disponemos de una sobrecarga de CloudBlobClient.GetBlobReference (aunque yo lo habría puesto dentro de CloudBlobContainer o al menos poner la sobrecarga en ambos métodos GetBlobReference) a la cual podemos pasar como parámetros tanto la URI del blob como el DateTime del snapshot que queremos recuperar.
Un dato importante a tener en cuenta es que la fecha debe ser UTC y obviamente debe ser exacta a la almacenada. Digo esto por el incidente que tuve al intentar recuperar el DateTime desde un ActionLink de ASP.NET MVC:
<%: Html.ActionLink("Delete", "Delete", new { item.Uri, item.ContainerName, item.SnapShotTime})%>
Al hacer esto, lo que está ocurriendo es que realiza un ToString() del DateTime dejando fuera los milisegundos que tenía asociados el snapshotTime, por lo que la fecha exacta ya no coincide. En mi caso, en vez de permitir esta conversión, paso como parámetro directamente la propiedad Ticks la cual devuelve un long:
<%: Html.ActionLink("Delete", "Delete", new { item.Uri, item.ContainerName,
                          item.SnapShotTime.Ticks })%>
De esta manera mantengo la fecha exacta y sólo necesitamos realizar la conversión a DateTime UTC en el servidor:
public void DeleteBlob(string uri, string containerName, long snapShotTimeTicks)
{

    var container = GetContainer(containerName);
    CloudBlob blob;

    if (snapShotTimeTicks != 0)
    {
        var utcSnapshotTime = new DateTime(snapShotTimeTicks, DateTimeKind.Utc);
        blob = _blobClient.GetBlobReference(uri, utcSnapshotTime);
    }
    else
       blob = container.GetBlobReference(uri);

   blob.Delete();
}
Espero que sea de utilidad :)
¡Saludos!

 

Posted: 3/1/2011 16:45 por Gisela | con no comments
Archivado en:
Leer tablas de un Excel con Open XML y Linq

Hace bastante tiempo escribí un post donde explicaba cómo era posible la creación de un archivo Excel con Open XML utilizando una base de datos como fuente. Esta vez, voy a comentar cómo podemos leer datos de una hoja para poder manipularlos desde C#.

Antes de comenzar, necesitamos utilizar las referencias Windows Base y DocumentFormat.OpenXml. En este ejemplo, vamos a recuperar los siguientes valores:

La información más importante de este archivo para poder recuperar correctamente los datos son el nombre de la hoja y el número de la fila donde comienzan los datos que nos interesan.

El objetivo de nuestro código será recuperar estos datos y almacenarlos en un txt de forma formateada. Creamos un proyecto de consola y comenzamos con el siguiente código:

using System.IO;
using System.Linq;
using DocumentFormat.OpenXml.Packaging;
using DocumentFormat.OpenXml.Spreadsheet;

namespace ExcelOpenXML
{
    class Program
    {
        static void Main()
        {

            using (var document = SpreadsheetDocument.Open(@"C:\BooksSample.xlsx", true))
            {

                var workbook = document.WorkbookPart.Workbook;
                var workSheets = workbook.Descendants<Sheet>();

                string sheetId = workSheets.First(s => s.Name == @"Hoja1").Id;
                var sheet = (WorksheetPart)document.WorkbookPart.GetPartById(sheetId);

                var sharedStringTable = document.WorkbookPart.SharedStringTablePart.SharedStringTable;
                var books = Library.RetrieveBooks(sheet.Worksheet, sharedStringTable);
                using (var sw = new StreamWriter(@"c:\Books.txt"))
                {
                    foreach (var p in from book in books select book)
                        sw.WriteLine("{0, -40} {1, -20} ", p.Name, p.Price);
                }

            }
        }
    }
}

Si nos fijamos en el código anterior, una vez cargado el archivo tenemos que acceder al objeto workbook, solicitamos todas las hojas en orden descendente y recuperamos el id de aquella que tenga como nombre Hoja1. Con este id podemos recuperar la hoja en cuestión y, por otro lado, recuperamos un elemento llamado SharedStringTable, el cual contiene un conjunto de elementos donde están alojadas todas las cadenas utilizadas en la hoja. Para que os hagáis una idea de lo que estamos recuperando, podemos abrir el archivo con Open XML SDK 2.0 Productivity Tool for Microsoft Office y visualizar su esquema:

¿Cómo recuperamos la información entre tanto XML? :)

using System.Linq;
using System.Collections.Generic;
using System.Globalization;
using DocumentFormat.OpenXml.Spreadsheet;

namespace ExcelOpenXML
{
    public class Library
    {
        static readonly CultureInfo Culture = new CultureInfo("en-US");

        public static List<Book> RetrieveBooks(Worksheet worksheet, SharedStringTable sharedStringTable)
        {
            var result = new List<Book>();

            var dataRows = from row in worksheet.Descendants<Row>()
                           where row.RowIndex > 6 //The table begins on line 5
                           select row;

            foreach (var row in dataRows)
            {
                var textValues = new List<string>();
                foreach (var cell in from cell in row.Descendants<Cell>() where cell.CellValue != null select cell)
                {
                    if (cell.DataType != null && cell.DataType.HasValue && cell.DataType == CellValues.SharedString)
                        textValues.Add(sharedStringTable.ChildElements[int.Parse(cell.CellValue.InnerText)].InnerText);
                    else
                        textValues.Add(cell.CellValue.InnerText);
                }

                var textArray = textValues.ToArray();

                if (textArray.Count() <= 0) continue;

                var book = new Book
                {
                    Name = textArray[0],
                    Price = textArray[1] == "?" ? 0 : float.Parse(textArray[1], NumberStyles.Float, Culture),
                };

                result.Add(book);
            }

            return result;

        }
    }
}

Aunque la tabla comience en la fila 5, realmente nos interesa recuperar solamente los datos y obviar la cabecera. Una vez recuperados todos los registros, recorremos cada uno de ellos para poder almacenar la información en el objeto Book, el cual sólo contiene dos propiedades: Name y Price.

Un dato importante es utilizar la cultura en-US ya que, al recuperar los valores del archivo, el SDK de Open XML recupera los valores con punto en vez de coma. Este sería el resultado con el parseo pero sin la cultura en-US.

Introducing HTML5 (Voices That Matter)   1,756E+16
BLOCKED SCRIPT The Good Parts               1383
CSS: The Missing Manual                  1,756E+16
BLOCKED SCRIPT The Definitive Guide         2371
Programming in Objective-C 2.0           2223

Si ejecutamos la aplicación, abrirá el archivo xlsx y, una vez cargados en memoria, escribirá uno a uno en el archivo Books.txt. El resultado sería el siguiente:

Introducing HTML5 (Voices That Matter)   17,56
BLOCKED SCRIPT The Good Parts               13,83
CSS: The Missing Manual                  17,56
BLOCKED SCRIPT The Definitive Guide         23,71
Programming in Objective-C 2.0           22,23

Adjunto el proyecto por si fuera de utilidad :D

¡Saludos!

Posted: 22/12/2010 17:39 por Gisela | con 2 comment(s)
Archivado en: ,
Windows Azure Connect

Hace un par de días me dieron la oportunidad de participar en la beta de Windows Azure Connect :D . Para quien no haya oído hablar de este futuro servicio, Windows Azure Connect nos dará la posibilidad de conectar servidores on-premise con nuestros roles ubicados en la nube, lo que se conoce como VPN :) .

En este post voy a hacer una demo muy sencilla de cómo configurar este servicio y comprobar la conectividad entre dos máquinas a través de un ping.

Configuración del role en Windows Azure

Accedemos al portal y nos posicionamos en el apartado Virtual Network.

Si es la primera vez que accedemos, deberemos activar la suscripción para Azure Connect.

 Con la suscripción seleccionada, pulsamos en el botón Get Activation Token, el cual nos devolverá un token que deberemos utilizar para que nuestro role en la nube pueda formar parte de un grupo que veremos más adelante.

Para realizar esta demo, crearemos un nuevo proyecto Windows Azure Project  con un web role con el código por defecto. Lo único necesario para poder utilizarlo conjuntamente con Azure Connect es habilitar en el apartado Virtual Network de las propiedades del rol el check y pegar el token recuperado anteriormente.

Por último lo configuraremos para poder acceder a él de manera remota. Una vez realizado el paso anterior, subimos la aplicación al portal y comprobamos que la misma aparece en el aparto de Virtual Network dentro de la suscripción.

Configuración del servidor on-premise

Por parte del servidor on-premise es necesario instalar de forma manual una aplicación proporcionada desde el portal. Desde dicho servidor pulsamos sobre el botón Install Local Endpoint en la parte superior.

Al hacer click sobre este botón nos facilitará una URL para poder descargar el instalador.

Como bien indica el cuadro de diálogo, este software no puede ser guardado para ser ejecutado dentro de un periodo lejano debido a que tiene un tiempo de expiración. Copiamos el link en el explorador y, una vez descargado, ejecutamos la instalación.

Uno de los inconvenientes con los que nos podemos encontrar llegados a este punto es que, con la fase beta, no podamos ejecutar la instalación  si tenemos nuestro sistema operativo en un idioma que no sea inglés :( .

Cuando la instalación finaliza, vemos que aparece un nuevo icono en la barra de tareas, por el momento, sin conexión con la nube.

 A partir de este momento, aparecerán tanto el rol como el servidor on-premise en Activated Endpoints.

Para finalizar la configuración debemos hacer un último paso que es crear el grupo mencionado anteriormente. Para ello pulsamos esta vez sobre Create Group donde deberemos rellenar los siguientes campos:

Como datos obligatorios serán el nombre del grupo, un servidor on-premise en el apartado Connect From y un rol en Connect To.

Lo primero que ocurrirá a partir de ahora será la actualización del web role involucrado.

Y por otro lado el icono del servidor on-premise se tornará al siguiente como señal de conexión con la nube.

 

Si accedemos en remoto al web role (o desde el servidor on-premise) y abrimos una consola de comandos para hacer un ping a nuestro servidor.

 

Voilà! :D ¡Conexión completada!

Si queréis probar cómo sería posible conectar una aplicación en la nube con un SQL Server en un servidor on-premise podéis descargaros el nuevo Windows Azure Training Kit de Diciembre :)

¡Saludos!

Posted: 17/12/2010 19:54 por Gisela | con no comments |
Archivado en:
Trabajando con las queues de Windows Azure Storage

Después de haber repasado los blobs y las tablas, llegó el momento de centrarse en las queues :) . Como comenté en el post introductorio sobre qué es Windows Azure Storage, las queues se utilizan para almacenar mensajes con el objetivo de conseguir la comunicación entre distintas aplicaciones que trabajan conjuntamente. Estas colas de mensajes son FIFO (First In First Out) y son de un único sentido.

 Los mensajes están limitados a 8 KB y deben ser serializables como XML.

Accediendo a través del Storage Client

Si bien podemos realizar todas las operaciones a través de REST, esto puede resultar algo tedioso a la hora de trabajar. Por ello, podemos hacer uso de la API en .NET para facilitarnos el trabajo. Es necesario añadir una referencia a Microsoft.Windows.Azure y Microsoft.Windows.Azure.StorageClient.

¿Por dónde empiezo?

Lo primero que debemos hacer es recuperar la cadena de conexión y crear un CloudQueueClient para poder generar o recuperar las queues.

CloudStorageAccount _account = CloudStorageAccount.DevelopmentStorageAccount;
CloudQueueClient _queueClient = _account.CreateCloudQueueClient();

Crear una Queue

Al igual que en los blobs, para crear una queue necesitamos recuperar una referencia a la misma aunque esta no exista. Una vez creada llamaremos al método CreateIfNotExist.

var queue = _queueClient.GetQueueReference("myqueue");
queue.CreateIfNotExist();

Listar las queues disponibles

Con ListQueues recuperaremos todas las queues disponibles en esa cuenta.

_queueClient.ListQueues();

Eliminar una Queue

 Cuando eliminamos una queue, es recomendable limpiar primero su contenido y posteriormente eliminarla a través del método Delete, así como anular su referencia a cualquier variable.

queue.Clear();
queue.Delete();
queue = null;

Añadir un mensaje

string message = "Hello world!";
queue.AddMessage(new CloudQueueMessage(message));

Procesar un mensaje (Polling)

using System.Diagnostics;
using System.Net;
using System.Threading;
using Microsoft.WindowsAzure;
using Microsoft.WindowsAzure.ServiceRuntime;
using Microsoft.WindowsAzure.StorageClient;

namespace QueueReader_WorkerRole
{
    public class WorkerRole : RoleEntryPoint
    {
        public override void Run()
        {
            var account = CloudStorageAccount.DevelopmentStorageAccount;
            var queueClient = account.CreateCloudQueueClient();
            var queue = queueClient.GetQueueReference("myqueue");
            queue.CreateIfNotExist();

            while (true)
            {
                var message = queue.GetMessage();

                if (message != null)
                {
                    Trace.WriteLine(message.AsString);

                    queue.DeleteMessage(message);
                }
                else
                    Thread.Sleep(2000);
            }
        }

        public override bool OnStart()
        {
            ServicePointManager.DefaultConnectionLimit = 12;

            return base.OnStart();
        }
    }
}

En este proceso, normalmente ejecutado desde un worker role, lo que estamos haciendo es comprobar cada 2 segundos si existe algún mensaje en la queue y de ser así (si el resultado no es nulo) procesarlo. Una vez finalizado el proceso debemos eliminar el mensaje de la queue para que no sea re procesado de nuevo. Cuando un mensaje es recuperado a través de GetMessage permanece invisible durante 30 segundos por defecto, con el objetivo de que no pueda ser recuperado por nadie más. Este tiempo puede ser extensible hasta 2 horas como máximo y, de no ser procesado el message y posteriormente eliminado, volvería a la queue para que fuera recuperado de nuevo por el mismo worker role o cualquiera de sus instancias.

“Ojear” un mensaje (Peek a message)

Existe una alternativa a la hora de conocer el contenido de un mensaje sin la necesidad de sacarlo de la queue. Esta acción es conocida como “peek”, que significa ojear, y puede ser útil para revisar su contenido sin que afecte a su visibilidad. Podemos ojear un mensaje por defecto o indicar a la función PeekMessage el número de mensajes que necesitemos revisar.

var message = queue.PeekMessage();
var messageList = queue.PeekMessage(5);

Connection String

La cadena de conexión sería exactamente la misma que para cualquiera de los otros dos servicios de Windows Azure Storage.

<Setting value="DefaultEndpointsProtocol=http;AccountName=returngis;
AccountKey=KoJ9maUaV29LDdoajvkA....AUVOdb2ehHw5nN21XI2KF7Q==" />

Espero que sea de utilidad :D

¡Saludos!

Posted: 14/12/2010 11:42 por Gisela | con no comments
Archivado en:
Trabajando con las tablas de Windows Azure Storage

Siguiendo la serie de post relacionados con Windows Azure Storage, hoy me gustaría centrarme en las tablas, donde podemos almacenar datos de una forma estructurada pero no relacional.  Este servicio es muy simple, altamente escalable y supone un coste menor que toda una base de datos relacional.

¿Qué no puedo hacer?

Debido a que no se tratan de tablas relacionales, no podremos:

  • Crear foreign keys para las relaciones entre tablas.
  • Realizar joins.
  • Crear índices personalizados en las tablas.

¿Por dónde empiezo?

Antes de comenzar a programar, debemos conocer los tres pasos necesarios para crear nuestra tabla:

  1. Definir la entidad que almacenaremos en ella: Antes de crear una tabla necesitamos alguna forma de describir qué es lo que queremos almacenar.
  2. Definir el contexto: El contexto tratará las acciones que podremos realizar (creación, modificación, eliminación, etcétera), o lo que es lo mismo: Cómo queremos operar con ella.
  3. Creación de la tabla: Una vez que tenemos decidido el qué y el cómo estamos listos para su creación basándonos en los dos puntos anteriores.

Definir la entidad

La definición de la entidad se trata de una clase con sus correspondientes atributos. Para ser capaces de almacenar nuestra clase en una tabla de Windows Azure Storage necesitaremos además tres atributos adicionales que serán heredados de TableServiceEntity: PartitionKey, RowKey y Timestamp. Los dos primeros necesitamos inicializarlos en el momento de la creación de un nuevo objeto (el lugar ideal sería en el constructor) y el  Timestamp será asignado de forma automática. Estas propiedades serán las que nos ayudarán a localizar un registro, y más en concreto PartitionKey será responsable de conseguir una escalabilidad eficiente si lo utilizamos de manera correcta.

Este podría ser un ejemplo de la definición de una entidad:

using System;
using Microsoft.WindowsAzure.StorageClient;

namespace StorageManager_MvcWebRole.Models.Tables
{
    public class Profile : TableServiceEntity
    {

        public Profile()
        {
            PartitionKey = "Users";
            RowKey = Guid.NewGuid().ToString();
        }

        public string UserName { get; set; }
        public string Email { get; set; }
        public int Age { get; set; }
        public string BlogUrl { get; set; }
    }
}

Definir el contexto

Una vez que tenemos el qué, podemos saber cómo vamos a manejarlo :D Creamos una nueva clase que herede de TableServiceContext. Si utilizamos Resharper nos advertirá antes de la compilación de que es necesario importar la librería System.Data.Services.Client.

 

De otro modo, si compilamos la solución, Visual Studio nos informará del mismo error:

Por otro lado, debemos implementar el constructor heredado de TableServiceContext ya que nos avisa de que no existe un constructor sin parámetros para la clase base y es necesario que la nuestra implemente uno. El motivo es que para crear el contexto de la tabla es necesario tener la dirección donde se aloja la misma, así como las credenciales para acceder.

using System.Linq;
using Microsoft.WindowsAzure;
using Microsoft.WindowsAzure.StorageClient;

namespace StorageManager_MvcWebRole.Models.Tables
{
    public class ProfileTableServiceContext : TableServiceContext
    {
        private const string TableName = "Profiles";

        public ProfileTableServiceContext(string baseAddress, StorageCredentials credentials)
            : base(baseAddress, credentials) { }

        public IQueryable<Profile> Profiles
        {
            get { return CreateQuery<Profile>(TableName); }
        }

        public void AddProfile(Profile newProfile)
        {
            AddObject(TableName, newProfile);
            SaveChanges();
        }

        public void RemoveProfile(string rowKey)
        {
            DeleteObject((from item in Profiles
                          where item.PartitionKey == "Users" && item.RowKey == rowKey
                          select item).First());
            SaveChanges();
        }

        public void UpdateProfile(Profile profileUpdated)
        {
            var profile = (from item in Profiles
                           where item.PartitionKey == "Users" && item.RowKey == profileUpdated.RowKey
                           select item).First();

            profile.UserName = profileUpdated.UserName;
            profile.Age = profileUpdated.Age;
            profile.Email = profileUpdated.Email;
            profile.BlogUrl = profileUpdated.BlogUrl;

            UpdateObject(profile);
            SaveChanges();
        }

    }
}

Creación de la tabla

Por último ya podemos crear la tabla tanto en la nube como en local. Si bien es un paso que sólo debemos realizar una vez, podemos utilizar una aplicación externa como Cloud Storage Studio o en mi caso he utilizado la clase WebRole.cs que se genera cuando creamos un proyecto de tipo Windows Azure Project.

using System.Configuration;
using Microsoft.WindowsAzure;
using Microsoft.WindowsAzure.ServiceRuntime;
using Microsoft.WindowsAzure.StorageClient;
using StorageManager_MvcWebRole.Models.Tables;

namespace StorageManager_MvcWebRole
{
    public class WebRole : RoleEntryPoint
    {
        public override bool OnStart()
        {

            CloudStorageAccount.SetConfigurationSettingPublisher((configName, configSetter) =>
            configSetter(ConfigurationManager.ConnectionStrings[configName].ConnectionString));

            var storageAccount = CloudStorageAccount.DevelopmentStorageAccount;
            CloudTableClient.CreateTablesFromModel(typeof(ProfileTableServiceContext), storageAccount.TableEndpoint.AbsoluteUri, storageAccount.Credentials);

            return base.OnStart();
        }
    }
}

Si quisiéramos conectar con una tabla en la nube, la cadena de conexión sería similar a la siguiente:

<Setting name="StorageAccount" value="DefaultEndpointsProtocol=http;AccountName=returngis;
AccountKey=KoJ9maUaV29LDdoajvkAIKzi98CH.....D1PJVpAUVOdb2ehHw5nN21XI2KF7Q==" />

Ya tenemos todos los ingredientes necesarios para trabajar con nuestra nueva tabla :D Lo único que faltaría sería usar el contexto para relacionarnos con la misma. Para realizar este ejemplo he creado un proyecto ASP.NET MVC y en pocas líneas hago uso de cada una de las acciones posibles:

using System;
using System.Linq;
using System.Web.Mvc;
using Microsoft.WindowsAzure;
using StorageManager_MvcWebRole.Models.Tables;

namespace StorageManager_MvcWebRole.Controllers
{
    public class TableController : Controller
    {
        private readonly CloudStorageAccount _account;
        private readonly ProfileTableServiceContext _profileServiceContext;

        public TableController()
        {
            _account = CloudStorageAccount.DevelopmentStorageAccount;
            _profileServiceContext = new ProfileTableServiceContext(_account.TableEndpoint.ToString(), _account.Credentials);
        }

        public ActionResult Index()
        {
            return View(_profileServiceContext.Profiles);
        }

        public ActionResult Create()
        {
            return View();
        }

        [HttpPost]
        public ActionResult Create(Profile newProfile)
        {
            _profileServiceContext.AddProfile(newProfile);

            return RedirectToAction("Index");
        }

        public ActionResult Delete(string rowKey)
        {
            _profileServiceContext.RemoveProfile(rowKey);

            return RedirectToAction("Index");
        }

        public ActionResult Edit(string rowKey)
        {
            return View((from profile in _profileServiceContext.Profiles
                         where profile.PartitionKey == "Users" && profile.RowKey == rowKey
                         select profile).First());

        }

        [HttpPost]
        public ActionResult Edit(Profile profileUpdated)
        {
            _profileServiceContext.UpdateProfile(profileUpdated);

            return RedirectToAction("Index");
        }
    }
}

 

Espero que sea de utilidad :)

¡Saludos!

Posted: 14/12/2010 11:36 por Gisela | con 2 comment(s)
Archivado en:
Trabajando con los blobs de Windows Azure Storage

La palabra Blob se corresponde con las siglas de Binary Large OBject y tiene como objetivo el almacenamiento de archivos de gran tamaño, como por ejemplo:

Cada archivo corresponde a un blob y cada blob está contenido a su vez en un container. Para que os hagáis una idea, un ejemplo podría ser el siguiente: Tengo una cuenta de storage,  a la que puse por nombre MediaStorage, donde quiero almacenar mis archivos de música. A su vez, me gustaría tener un container para separar mis archivos por género pop y rock.

Visto esto, podemos decir que un container se trata de una especie de carpeta, la cual agrupa nuestros blobs.

En este post voy a centrarme en un wrapper disponible a través del SDK de Windows Azure para encapsular las llamadas REST necesarias para cada una de las opciones.
Necesitaremos importar Microsoft.Windows.Azure y Microsoft.Windows.Azure.StorageClient.

¿Tengo entorno de desarrollo?

Si :D A día de hoy se llama Storage Emulator y podemos trabajar con blobs, tablas y colas.

¿Dónde puedo encontrar los archivos almacenados en desarrollo?

La forma más sencilla es a través de Visual Studio 2010. En la ventana Server Explorer podemos ver los archivos almacenados en cada uno de los containers.

Al igual que podemos visualizar nuestro entorno de desarrollo, podríamos adjuntar una cuenta de Storage en la nube y ver su contenido.

¿Cómo conecto con mi cuenta de Storage?

Mientras estamos creando la aplicación, podemos utilizar el entorno de desarrollo local para realizar las pruebas necesarias. El código sería el siguiente:

CloudStorageAccount _account = CloudStorageAccount.DevelopmentStorageAccount;
CloudBlobClient _blobClient = new CloudBlobClient(_account.BlobEndpoint, _account.Credentials);

Una vez finalizado el desarrollo, sería necesario modificar la primera línea para recuperar los valores del archivo de configuración.


CloudStorageAccount.SetConfigurationSettingPublisher((configName,configSetter) => configSetter(RoleEnviroment.GetConfigurationSettingValue(configName)));
CloudStorageAccount _account = CloudStorageAccount.FromConfigurationSetting("StorageAccount");
CloudBlobClient _blobClient = new CloudBlobClient(_account.BlobEndpoint, _account.Credentials);

Un ejemplo de cadena de conexión válida podría ser el siguiente:

<Setting name="StorageAccount" value="DefaultEndpointsProtocol=http;AccountName=returngis;
AccountKey=KoJ9maUaV29LD .... +4D1PJVpAUVOdb2ehHw5nN21XI2KF7Q==" />

Creación de un container

Lo primero que debemos crear es un contenedor donde almacenar nuestros blobs ya que estos últimos no pueden ser creados si no están dentro de alguno.

private CloudBlobContainer GetContainer(string containerName)
{
   var cloudBlobContainer = _blobClient.GetContainerReference(containerName);
if (cloudBlobContainer.CreateIfNotExist())
{
var blobContainerPermissions = cloudBlobContainer.GetPermissions();

         blobContainerPermissions.PublicAccess = BlobContainerPublicAccessType.Container;
         cloudBlobContainer.SetPermissions(blobContainerPermissions);
    }

    return cloudBlobContainer;
}

Con el método CreateIfNotExist nos aseguramos de que el mismo sea generado si no fue creado con anterioridad. Si es la primera vez , este método devolverá true y le asignaremos los permisos para que un usuario anónimo pueda acceder al contenido.

Creación de un blob

Para la creación de un blob, únicamente debemos recuperar el container donde queremos que se aloje y "simular" su recuperación a través de GetBlobReference. Llegados a este punto se creará un nuevo objeto del tipo CloudBlob a través del cual podremos subir un nuevo archivo a la nube.

public void SaveBlob(Stream file, string filename)
{
    var blob = GetContainer("myContainer").GetBlobReference(filename);

    blob.UploadFromStream(file);
}

En este caso he utilizado el método UploadFromStream pero es importante saber que tenemos otros métodos para realizar la subida de archivos:

  • UploadByteArray
  • UploadFile
  • UploadFromStream
  • UploadText

Eliminar un blob

Para eliminar un blob debemos, en primer lugar, recuperar el contenedor (he utilizado el método anterior para ello), recuperar el blob y finalmente llamar al método Delete del mismo.

public void Delete(string uri, string containerName)
{
     var container = GetContainer(containerName);
     var blob = container.GetBlobReference(uri);
     blob.Delete();
}

Crear una copia de un blob


public void Copy(string uri, string containerName)
{
    var container = GetContainer(containerName);
    var blob = container.GetBlobReference(uri);
    var newBlob = container.GetBlobReference(string.Format("Copy of {0}", blob.Uri.Segments[blob.Uri.Segments.Length - 1]));

    newBlob.CopyFromBlob(blob);
}

Crear un snapshot de un blob


public void Snapshot(string uri, string containerName)
{
     var container = GetContainer(containerName);
     var blob = container.GetBlobReference(uri);
     blob.CreateSnapshot();
}

¿Qué diferencia hay entre una copia y un snapshot?

Los snapshots proporcionan una versión sólo de lectura de un blob. Esta funcionalidad puede ser útil para restaurar una versión anterior de un blob después de ser modificado. Sin embargo, una copia  es un blob distinto ,creado a partir de otro, el cual se puede modificar.

Añadir metadatos


public void AddMetadata(string uri, string containerName)
{
     var container = GetContainer(containerName);
     var blob = container.GetBlobReference(uri);

     var metadata = new NameValueCollection();
     metadata["Language"] = "es";
     metadata["Date"] = DateTime.Now.ToShortTimeString();

     blob.Metadata.Add(metadata);
}

Espero que sea de utilidad :)

¡Saludos!

Posted: 10/12/2010 19:28 por Gisela | con no comments
Archivado en:
¿Qué es Windows Azure Storage?

Además de poder utilizar la plataforma de Windows Azure para subir nuestras aplicaciones, tenemos un servicio llamado Windows Azure Storage el cual nos permite almacenar datos de tres formas distintas:

  • Blobs: Se utilizan para almacenar archivos de gran tamaño, ya sean música, video, imágenes, binarios, etcétera. Disponemos de un endpoint por cada archivo para poder acceder a ellos. En cuanto a tamaños, exiten dos tipos: Por un lado tenemos los Blocks, los cuales pueden tener un tamaño máximo de 200 GB, y las Pages con un máximo de 1 TB.
  • Tables: En ocasiones es posible que necesitemos almacenar información estructuradas sin llegar a ser relacional. Es por ello que el uso de las tablas puede ser de gran ayuda :) . El objetivo de las mismas es almacenar entidades con hasta un máximo de 252 propiedades por entidad e incluso con la posibilidad de almacenar distintos tipos de estructura dentro de una misma tabla (no muy recomendable :( ).
  • Queues: Uno de los objetivos de almacenar pequeña información puede ser para la comunicación entre aplicaciones a través de las colas de mensajes. Gracias a las Queues podemos manejar estos mensajes de manera sencillas a modo de tickets. El máximo por mensaje son 8 KB.

Para crear una cuenta de Windows Azure Storage, podemos hacerlo a través del portal, posicionándonos en el apartado Storage Accounts (dentro de Hosted Services, Storage Accounts & CDN) y  seleccionando en el menú superior la opción New Storage Account.

Una vez creada podremos ver sus propiedades (direcciones de cada servicio, claves, etcétera) seleccionando la nueva cuenta.

Mi objetivo con esta pequeña introducción es poder profundizar más en estos puntos y conocer la forma de programar y administrar cada uno de estos servicios ofrecidos por la plataforma Azure :)

¡Comencemos!

Posted: 10/12/2010 19:11 por Gisela | con 2 comment(s)
Archivado en:
File upload en ASP.NET MVC

Es posible que tarde o temprano todos aquellos seguidores de ASP.NET MVC tengamos la necesidad de utilizar el típico FileUpload de Web Forms. Si nos fijamos, no existe un helper para este escenario por lo que necesitamos utilizar otra estrategia :D

En primer lugar debemos crear un formulario donde hagamos uso del tag input con el type=”file”. Pero eso no es todo, ya que además necesitaremos especificar a nivel de formulario el atributo enctype. Este atributo indica el tipo de contenido que se va a enviar al servidor. Como nos cuentan en la página oficial de W3, cuando el método utilizado es post el valor por defecto de este atributo es “application/x-www-form-urlencoded”. Sin embargo, si necesitamos hacer uso del elemento input de tipo file debemos modificar este valor por “multipart/form-data”. Dicho esto, nuestro formulario sería de la siguiente manera:

<%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<dynamic>" %><asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server">
    Create a blob
</asp:Content>
<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">
    <h2>
        Create a new blob
    </h2>
    <div>
        <% using (Html.BeginForm("CreateBlob", "Home", FormMethod.Post, new { enctype = "multipart/form-data" }))
           {%>
        <p>
            <input type="file" id="newFile" name="newFile" size="23" />
        </p>
        <p>
            <input type="submit" value="Upload file" /></p>
        <% } %>
    </div>
</asp:Content>

Por otro lado, para recuperar el archivo en la acción CreateBlob utilizaremos la clase HttpPostedFileBase junto con el name del elemento que recoge el archivo para poder bindearlo.

[HttpPost]
public ActionResult CreateBlob(HttpPostedFileBase newFile)
{
  if (newFile.ContentLength > 0)
  {
   SaveBlob(newFile.InputStream);
  }   return RedirectToAction("Index");
}

Espero que sea de utilidad :)

¡Saludos!

Posted: 9/12/2010 23:55 por Gisela | con 3 comment(s)
Archivado en:
Acceder en remoto a nuestras instancias en Windows Azure

Una de las características más esperadas por los usuarios de la plataforma Windows Azure era la posibilidad de conectarnos en remoto a nuestras instancias. Por defecto, no es una opción que esté habilitada ya que es necesaria una configuración previa.

Configuración

El primer paso que debemos dar para habilitar la opción de conexión remota es configurar el certificado que queremos utilizar y habilitar un check desde Visual Studio 2010 que especifica que esta característica estará disponible. Para ello, pulsamos sobre el proyecto cloud con el botón derecho y seleccionamos la opción Publish...

Acto seguido nos aparecerá un cuadro de diálogo donde se muestra un enlace que nos permitirá configurar las conexiones de acceso remoto.

Al hacer click en este link, aparecerá una nueva ventana donde activaremos la opción Enable connections for all roles para tener acceso a los demás campos.

Ahora bien, es posible que la primera vez que accedamos a esta ventana no tengamos disponible ningún certificado, por lo que deberemos generarlo a través del primer combo seleccionando la opción <Create...>, donde deberemos elegir un nombre para el mismo. Una vez creado, especificaremos las credenciales para el acceso remoto y una fecha de expiración para la cuenta.

Si aceptamos los cambios que hemos realizado y se genera el paquete para su despliegue, en un principio estaríamos listos para realizar el deployment de la aplicación en el portal. Sin embargo, cuando intentamos subir el paquete nos avisa de lo siguiente:

Básicamente nos informa de que el certificado asociado con el paquete que intentamos subir no está disponible en nuestro servicio en la nube y que por lo tanto es necesario instalarlo. ¿Y dónde podemos encontrar dicho certificado?

Si bien en la versión anterior Windows Azure era necesario subir el archivo .cer, en esta nueva versión volvemos a necesitar el archivo .pfx utilizado en una versión anterior. Para conseguir el mismo, podemos hacerlo de la siguiente forma:

  1. Volvemos a seleccionar el proyecto cloud y pulsamos de nuevo en la opción Publish...
  2. Accedemos de nuevo a la configuración de las conexiones de escritorio remoto.
  3. Teniendo el certificado elegido en la subida, pulsamos sobre el botón View...

  4. Aparecerá una ventana nueva con la información del certificado seleccionado. Pulsamos en la segunda correspondiente a los Detalles y hacemos clic sobre el botón Copiar en archivo...

  5. Como opciones en el asistente, seleccionamos Exportar la clave privada, pulsamos siguiente, y dejamos la opción por defecto Intercambio de información personal: PKCS #12 (.PFX). Añadimos una contraseña para proteger la clave privada y por último seleccionamos la ubicación del archivo.
  6. Accedemos al portal de Windows Azure y nos posicionamos en el Hosted Service donde vamos a desplegar la aplicación. Si pulsamos sobre la flecha del servicio, veremos que cuelga del mismo una carpeta llamada Certificates.

  7. Pulsamos en el botón Add Certificate ubicado en el menú superior.

  8. Y por último añadimos el archivo pfx y la contraseña asociada.

A partir de este momento estamos listos para subir sin problemas el paquete del despliegue de nuestra aplicación. Una vez arriba y completado el status hasta el modo Ready. Veremos que aparece una nueva opción habilitada en el menú superior.

Si hacemos clic sobre el icono Connect nos devolverá un archivo del tipo rdp con la configuración necesaria para el acceso de nuestra instancia :)

Espero que sea de utilidad :D

¡Saludos!

Posted: 2/12/2010 23:26 por Gisela | con 4 comment(s)
Archivado en:
Windows Azure SDK 1.3 + Windows Azure Tools + Nuevo portal disponibles

Ayer por la noche (hora española) se liberó la nueva release del SDK de Windows Azure con varias de las novedades expuestas en el PDC 2010. Cabe decir que las nuevas herramientas para la plataforma sólo están disponibles para Visual Studio 2010.

Para poder descargar el SDK podemos haccerlo a través de este link.

¿Cuáles son las nuevas funcionalidades?

  • Virtual Machine (VM) Role en versión beta: Nos permitirá crear una imagen personalizada usando Windows Server 2008 R2 y usarla en la nube.
  • Remote Desktop Access: Una de las características más esperada por algunos era la posibilidad de conectarnos en remoto a las máquinas virtuales que residen en Azure.
  • Full IIS support in a Web Role: A partir de ahora nos dan la posibilidad de hostear web roles en un entorno de IIS.
  • Virtual Network (CTP): Gracias a esta nueva característica, tendremos la posibilidad de conectar nuestra máquinas ubicadas en la nube con nuestros servidores on-premise como si de una red VPN se tratara.
  • Diagnostics: Se mejora la recolección de diagnósticos con más condiciones de error.
  • Networking Enhancements: Se habilitan roles para restringir el tráfico inter-rol, además de arreglar los puertos en los InputEndpoints.
  • Performance Improvements: Se realizan mejoras de rendimiento en el deployment en el entorno local.
  • Nuevo portal en Silverligth: Si bien todavía no está totalmente disponible en SL y para algunos servicios tendremos que utilizar el antiguo portal (por ejemplo, para el apartado de App Fabric) ya podemos disfrutar de la mayoría de las funcionalidades en un portal considerablemente mejorado.

Modificaciones en las tools de Visual Studio

De lo primero que me percaté fue del cambio de nombre de las herramientas Development Fabric por Compute Emulator y Development Storage por Storage Emulator.

En la GUI de configuración de los roles, tenemos nuevas opciones disponibles:

1. Aparece el nuevo tamaño Extra small para nuestros roles:

2. Configuración de la cadena de conexión para los diagnósticos desde el GUI (hasta el día de hoy debíamos modificar este valor desde la pestaña Settings)

3. Nueva pestaña para la red virtual

Curiosidades

Para conocer las tareas disponibles de una forma más usable, tenemos a nuestra disposición una barra de tareas con todo lo que podemos crear:

Las tres primeras ya son conocidas: las dos primeras se han dividido para dar una mayor visibilidad, ya que son servicios distintos, la tercera correspondería con SQL Azure y una cuarta con la creación de redes virtuales (Azure Connect).

A partir de ahora, cuando publicamos un nuevo deployment y este solamente consta de una instancia en alguno de los roles, nos aparecerá un aviso, recomendando un número de instancias mayor para obtener alta disponibilidad.

Por cada deployment tenemos una pestaña lateral que nos muestra información relativa a la misma, alguna de ella no disponible hasta ahora.

Además, tenemos un apartado de tareas comunes donde podemos ver también nueva funcionalidad como crear cuentas de administrador, conectar los equipos on-premise con Windows Azure o administrar las imágenes de las VMs.

Para conocer más sobre las nuevas características, ya podemos descargar la nueva versión de Windows Azure Training Kit :D

¡Que lo disfrutéis! :)

¡Saludos!

Posted: 30/11/2010 9:31 por Gisela | con no comments |
Archivado en:
EXECUTE permission denied on object 'sp_sdidebug', database 'master', owner 'dbo'. con la depuración automática

Esta mañana, estaba depurando un código fuente de terceros que tenía que integrar en un proyecto y no devolvía el resultado esperado. Mi sorpresa al intentar abrir una conexión con la base de datos, mientras depuraba, es la siguiente:

EXECUTE permission denied on object 'sp_sdidebug', database 'master', owner 'dbo'.

Este error sucede cuando no tenemos permisos en el procedimiento almacenado sp_sdidebug... y es posible que no sea necesario tenerlo por motivos de seguridad desde nuestra aplicación.

Para solucionarlo, simplemente debemos seleccionar Attach to process... en el menú Debug y modificar el Attach to: Native code a Managed code.

El motivo de este error es que, al tener la depuración en modo nativo de forma automática, intenta depurar absolutamente todo y necesita más privilegios de los que en algunas ocasiones tenemos.

Ya podemos depurar sin problemas :D

Espero que sea de utilidad.

¡Saludos!

Posted: 24/11/2010 7:17 por Gisela | con no comments
Archivado en:
Mad.Nug: Migración de aplicaciones VB 6 a .NET ¿mito o realidad? ¿huevo o gallina?

¡Buenos días a tod@s!

Este mes tenemos en Mad.Nug un tema más que interesante para mucho de nosotr@s: la migración de aplicaciones de VB 6 a .NET :D

Si bien en ocasiones este llega a ser un tema incluso tabú :P, debemos estar preparados para enfrentarnos a los problemas que puedan ir surgiendo de este escenario.

Para esta mesa redonda contaremos con Jorge Serrano para ayudarnos antes las grandes y pequeñas dudas que puedan ir surgiendo al respecto.

El evento será el miércoles 24 de Noviembre en las oficinas de Microsoft Ibérica.

Más información.

¡Os esperamos!

Posted: 22/11/2010 9:10 por Gisela | con no comments
Archivado en:
Greybox: La aplicación que nos avisa de nuestros deployments en Azure

Todos aquellos que estemos trabajando o realizando pruebas con Azure tenemos ese miedo común a dejar alguna aplicación de prueba corriendo en la nube generando gasto alegremente :D Para evitarlo, o al menos ser conscientes de que tenemos aplicaciones en staging o producción, tenemos a nuestra disposición una pequeña aplicación llamada Greybox que nos alerta de los deployments activos y nos permite eliminarlos de manera sencilla.

Para descargarla, podemos hacerlo a través de su página en Codeplex. Por último, Debemos descomprir el zip y modificar el archivo de configuración Greybox.exe.config.

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <appSettings>
    <add key="SubscriptionId" value="--ADD YOUR SUBSCRIPTION ID HERE--"/>
    <add key="CertificateThumbprint" value="--ADD YOUR CERTIFICATE THUMBPRINT HERE--"/>
    <add key="RefreshTimerIntervalInMinutes" value="10"/>
  </appSettings>
</configuration>

Para poder acceder a nuestra cuenta de la plataforma, es necesario indicar el ID de la suscripción, el cuál podemos localizarlo aquí:

Y asociar el Thumbprint del certificado que queramos usar para realizar las tareas de administración que necesita el programa. Para crear y subir un certificado podemos guiarnos por el siguiente post.

Una vez que tenemos todo configurado, hacemos doble click sobre Greybox.exe y veremos que aparece un nuevo icono en el area de notificación de color gris.

Si una aplicación es desplegada en la nube el icono cambiará y mostrará una ventana emergente alertándonos de la nueva subida.

A partir de este momento el icono se tornará azul y tendremos a nuestra disposición dos opciones si pulsamos con el botón derecho sobre el icono.

Por un lado tenemos la posibilidad de elegir qué deployment es el que queremos eliminar o bien si queremos eliminarlos todos. Si por ejemplo seleccionamos el deployment que tenemos activo una nueva ventana nos avisaría de la acción.

El proceso puede tardar algunos segundos. Una vez eliminado desaparecería de la lista y si únicamente existiera el deployment que acabamos de eliminar el icono volvería a su estado gris.

Espero que sea de utilidad :D

¡Saludos!

Posted: 22/11/2010 9:00 por Gisela | con 2 comment(s)
Archivado en:
Administración de certificados digitales en Windows Azure

Uno de los temas que podría interesarnos sobre la plataforma Windows Azure es si existe la posibilidad de administrar certificados digitales. Lo primero que debemos saber acerca de los certificados utilizados en Azure es lo siguiente:

  1. A día de hoy, podemos subir un total de 5 certificados a través del portal.
  2. El estándar utilizado es X.509.
  3. Es posible revocar cualquiera de ellos en cualquier momento.
  4. Son necesarios para realizar tareas con la API de administración.
  5. Podemos utilizar certificados firmados por nosotros mismos.
  6. Los certificados deben utilizar la extensión .cer.

Generar nuestros propios certificados

Para poder experimentar y/o testear nuestra aplicación podríamos hacer uso de un certificado creado por nosotros mismos. Una forma de generarlos es a través de la herramienta makecert utilizando la línea de comandos. El primer paso para comenzar a utilizar la herramienta es acceder a la consola Visual Studio Command Prompt, alojada en Visual Studio Tools, con privilegios de administrador. Un comando válido podría ser el siguiente:

makecert -pe -r -n "CN=ReturnGis" -a sha1 -len 2048 -ss My "MiCertificado.cer"

Más información sobre makecert.

Agregar certificados

Dependiendo del entorno en el cual queramos hacer uso de nuestro certificado, el modo de añadirlo es distinto.

Máquina local

El primer paso para asociar un certificado en el entorno de desarrollo es ubicar el mismo en el almacén de certificados para que sea localizado. Desde el menú de inicio ejecutamos el comando mmc y agregamos el complemento Certificados, administrando los certificados de Cuenta de equipo. Dejamos marcado Equipo local y pulsamos Finalizar para terminar con el asistente.

Nos posicionamos en el apartado Personal y a través del botón derecho seleccionamos Todas las tareas => Importar y seleccionamos el certificado que acabamos de crear. Pulsamos "Siguiente" en cada una de las ventanas, hasta finalizar el asistente :D

Abrimos nuestro proyecto en Visual Studio y hacemos doble click en la carpeta Roles sobre el rol donde vamos a utilizar el certificado. Una vez dentro de la configuración, vamos al tab Certificates y añadimos uno nuevo. Si hacemos click en el botón de Thumbprint, nos aparecerán todos los certificados que tenemos disponibles. En este caso aparecería solamente uno que es el que acabamos de crear ;) Lo seleccionamos y aceptamos.

Si nos fijamos en el archivo ServiceDefinition.csdef vemos un nuevo apartado Certificates:

<?xml version="1.0" encoding="utf-8"?>
<ServiceDefinition name="Certificates" xmlns="http://schemas.microsoft.com/ServiceHosting/2008/10/ServiceDefinition">
  <WebRole name="CertificatesWebRole">
    <InputEndpoints>
      <InputEndpoint name="HttpIn" protocol="http" port="80" />
    </InputEndpoints>
    <ConfigurationSettings>
      <Setting name="DiagnosticsConnectionString" />
    </ConfigurationSettings>
    <Certificates>
      <Certificate name="Certificate" storeLocation="LocalMachine" storeName="My" />
    </Certificates>
  </WebRole>
</ServiceDefinition>

En este nuevo apartado, vemos toda la información mostrada en la UI del Role excepto el Thumbprint. El motivo es debido a que la firma del certificado se encuentra alojada en ServiceConfiguration.cscfg.

<?xml version="1.0"?>
<ServiceConfiguration serviceName="Certificates" xmlns="http://schemas.microsoft.com/ServiceHosting/2008/10/ServiceConfiguration">
  <Role name="CertificatesWebRole">
    <Instances count="1" />
    <ConfigurationSettings>
      <Setting name="DiagnosticsConnectionString" value="UseDevelopmentStorage=true" />
    </ConfigurationSettings>
    <Certificates>
      <Certificate name="Certificate" thumbprint="9CC153A44988BF6E295C6788AFDC446227414BB1" thumbprintAlgorithm="sha1" />
    </Certificates>
  </Role>
</ServiceConfiguration>

El objetivo de ello es que podamos ser capaces de modificar dicho certificado sin tener que hacer un nuevo deploy de toda la aplicación, ya que no es posible modificar ServiceDefinition.csdef sin tener que hacerlo (a diferencia de ServiceConfiguracion.cscfg).

Live Production

Cuando estemos dispuestos a subir los certificados a la nube, debemos hacerlo a través del portal. Seleccionamos el proyecto en la pestaña Windows Azure sobre el cual queremos utilizarlos (si es que tenemos más de uno) y hacemos click sobre la pestaña Account.

En este caso, seleccionamos el apartado Manage My API Certificates.

Lo único que debemos hacer es subir el archivo .cer correspondiente al certificado y automáticamente se agregará a la tabla de certificados instalados. Si quisiéramos asociar un certificado subido a la nube con la aplicación una vez en producción, bastaría modificar el archivo ServiceConfiguration.cscfg e incluir el Thumbprint correcto.

Configurar el endpoint https para utilizar el certificado

Una vez que hemos configurado el certificado en el tab Certificates, podemos enlazar el mismo a nuestro endpoint https a través del tab Endpoints desde el editor. Para poder hacerlo, basta con activar HTTPS y seleccionar nuestro certificado en SSL certificate name.

El resultado de esta configuración podríamos verlo en el archivo ServiceDefinition.csdef

<?xml version="1.0" encoding="utf-8"?>
<ServiceDefinition name="Certificates" xmlns="http://schemas.microsoft.com/ServiceHosting/2008/10/ServiceDefinition">
  <WebRole name="CertificatesWebRole">
    <InputEndpoints>
      <InputEndpoint name="HttpIn" protocol="http" port="80" />
      <InputEndpoint name="HttpsIn" protocol="https" port="443" certificate="Certificate" />
    </InputEndpoints>
    <ConfigurationSettings>
      <Setting name="DiagnosticsConnectionString" />
    </ConfigurationSettings>
    <Certificates>
      <Certificate name="Certificate" storeLocation="LocalMachine" storeName="My" />
    </Certificates>
  </WebRole>
</ServiceDefinition>

Como podemos ver, la información en este archivo es mínima para poder modificar la firma dependiendo del entorno en el que estemos :) .

¡Saludos!

Posted: 21/11/2010 15:28 por Gisela | con no comments
Archivado en:
Cloud Status: Aplicación para iPhone que nos muestra el status de la nube

Navegando por el App Store me he topado con una aplicación bastante interesante para aquellos que tengamos aplicaciones subidas a la nube o para aquellos que utilicen Google Apps. Se trata de una aplicación gratuita llamada Cloud Status y nos nuestra en qué estado se encuentra el servicio seleccionado (Amazon web services, Goggle App Engine, Google Apps, Windows Azure).

En el caso de las aplicaciones de Google, aparecen con un símbolo de prohibición pero en realidad indican que no tienen ninguna incidencia en el momento en el que se recuperó el status.

Espero que os sea de utilidad :)

¡Saludos!

Posted: 21/11/2010 14:43 por Gisela | con no comments
Almacenamiento local en los roles de Windows Azure

En determinadas ocasiones es posible que necesitemos hacer uso del almacenamiento local del servidor donde estamos ejecutando nuestra aplicación. Si bien el uso del mismo debería ser de forma temporal puede ser útil en determinadas ocasiones.

En Windows Azure, dependiendo del tamaño de nuestra máquina virtual, tendríamos la siguiente capacidad:

Tamaño de la VM Espacio en el disco local
*Extra small   20 GB
Small 250 GB
Medium 500 GB
Large 1.000 GB
Extra Large 2.000 GB

 *Este tamaño fue anunciado en el PDC 2010, aunque aún no está disponible para su uso. Al entrar en vigor dicho tamaño el resto de las máquinas virtuales se verán ligeramente modificadas.

Lo primero que debemos tener en cuenta es que este espacio está solamente disponible para la instancia del rol. Es decir, si nosotros tenemos varias instancias de un mismo rol (varios frontales) cada uno tendría su propio almacenamiento local y  no sería accesible por el resto de las instancias. Otro punto a tener en cuenta es que si esa instancia, por cualquier motivo, deja de funcionar de forma inesperada se perderían los datos almacenados en este espacio.

Entonces, si este espacio es volátil y por lo tanto no se trata de un sitio fiable para mantener información en él ¿Qué uso podríamos dar a dicho espacio?
Cuando necesitamos almacenar información en un medio fiable en la nube podríamos hacerlo usando Blobs, Tablas o bien SQL Azure, ya que sería la forma más común de compartir esa información con todas las instancias de nuestros roles. Aunque estos mecanismos serían los adecuados, las transacciones a estos supone un problema de latencia. Por ello, si utilizamos el almacenamiento local para almacenar aquellos elementos que son frecuentemente accedidos podríamos aumentar la velocidad a los datos, ya que el almacenamiento local está en nuestra propia instancia.

Configurando el almacenamiento local

Para poder configurar el almacenamiento local en un rol, haremos doble click en el rol indicado en la carpeta Roles de nuestro proyecto en Visual Studio, para poder visualizar la interfaz de configuración.

Como podemos ver en la imagen anterior, podemos crear varios registros para el almacenamiento local, lo cual significa que podemos crear varios espacios destinados a distintos fines con una cuota establecida por nosotros en megas. Además, vemos que tenemos una última opción llamada Clean on Role Recycle la cual se utiliza para indicar si queremos mantener o no los datos cuando un rol es reciclado (o lo que es lo mismo, cuando un rol es reiniciado).

Esta misma información también puede ser definida a través del archivo ServiceDefinition.csdef donde se añade un nuevo apartado llamado LocalResources.

<?xml version="1.0" encoding="utf-8"?>
<ServiceDefinition name="LocalStorage" xmlns="http://schemas.microsoft.com/ServiceHosting/2008/10/ServiceDefinition">
  <WebRole name="WebRoleLocalStorage">
    <InputEndpoints>
      <InputEndpoint name="HttpIn" protocol="http" port="80" />
    </InputEndpoints>
    <ConfigurationSettings>
      <Setting name="DiagnosticsConnectionString" />
    </ConfigurationSettings>
    <LocalResources>
      <LocalStorage name="Images" cleanOnRoleRecycle="false" sizeInMB="100" />
      <LocalStorage name="Videos" cleanOnRoleRecycle="true" sizeInMB="500" />
    </LocalResources>
  </WebRole>
</ServiceDefinition>
Usando el almacenamiento local

Para mostrar las distintas opciones, he creado un pequeño rol donde lo único que hacemos es recuperar un archivo a través de un control del tipo FileUpload y simulamos la subida a la instancia que está atendiendo nuestra petición.

Para poder comprobar ambos casos (qué ocurre cuando se reinicia un role con cleanOnRoleRecycle), he creado además un combo donde podemos elegir a qué espacio queremos enviar el archivo. Para recuperar la ruta del espacio destinado a nuestro recurso podríamos hacerlo a través del siguiente código:



using System;
using System.IO;
using Microsoft.WindowsAzure.ServiceRuntime;

namespace WebRoleLocalStorage
{
    public partial class _Default : System.Web.UI.Page
    {

        protected void btnUpload_Click(object sender, EventArgs e)
        {
            var localResource = RoleEnvironment.GetLocalResource(ddlResource.SelectedValue);
            var newFile = File.Create(localResource.RootPath + FileUploadFile.FileName);

            FileUploadFile.FileContent.CopyTo(newFile);

            newFile.Flush(true);
        }
    }
}

RoleEnviroment es una clase que pertenece a la librería Microsoft.WindowsAzure.ServiceRuntime y GetLocalResource es el método que nos permite recuperar información relativa al recurso seleccionado. Al hacer la llamada nos devolverá un objeto del tipo LocalResource el cual nos aportará información como el nombre, el tamaño máximo del recurso en megas y el path del recurso.

Supongamos que subimos dos archivos, uno al recurso Images y otro a Videos. Para poder visualizar en el entorno de desarrollo estos recursos podemos acceder a través del GUI del Development Fabric y, seleccionamos la opción Open local store... de una de las instancias.

Al pulsar sobre esta opción se nos abrirá una nueva ventana con una serie de carpetas. Para acceder al apartado que nos interesa, pulsamos sobre la llamada directory.

¡Y voilà!

Vemos dos carpetas con el nombre de nuestros recursos y una imagen en cada una correspondientes a las que acabamos de subir :D

Por último, para comprar qué ocurriría si reiniciamos dicha instancia podemos hacerlo a través de la interfaz del Development Fabric posicionando el ratón sobre el rol y pulsando en la tecla de reinicio.

Si volvemos a comprobar las carpetas de los recursos, vemos que el recurso Videos estaría vacío al haber indicado clearOnRoleRecyle :)

¡Saludos!

Posted: 6/11/2010 18:08 por Gisela | con no comments
Más artículos < Página anterior - Página siguiente >