Azure Storage is a RESTful service


Today I had to build a demo for Azure and I noticed that I was following a tired old path where one demonstrates Azure storage services (Table/Queue/Blob) via a hosted application. My demo has two key points:

1. Look, there’s a picture that I uploaded!

2. Look, these processes can send messages via the queue!

The kicker was going to be that the messages are exchanged over the Internet, not the demo environment. I wanted a visible resource, an image of penguins, to be visible via a public URL. That was going to be the cool part.Then, I thought- “Well, the Azure SDK is just a bunch of libraries. The libraries should work fine in a console application, right?” Right! 

And guess what: the demo actually works pretty slick because I can demo the storage service in isolation. I don’t need to demo it with a deployed application. That helps me out, and gives me some ideas on how I can use Azure differently.

I started out with a little utility class that reads a connection string from a config file and returns a ready to use CloudStorageAccount instance.

 

public static class Utility
{
  private static CloudStorageAccount _account;

  public static CloudStorageAccount StorageAccount
  {
    get
    {
      if (_account == null)
      {
        _account = CloudStorageAccount.Parse(
          ConfigurationManager.AppSettings["storageAccount"]);
      }
      return _account;
    }
  }
}

The config is just the following (minus the line breaks in the ‘value’ value):

  <appSettings>
    <add key="storageAccount"
         value="DefaultEndpointsProtocol=https;
                AccountName=[your account name];
                AccountKey=[your account key]"/>
  </appSettings>

My scenario is this: I have a directory with images. I want to force those images to be uploaded to Azure blob storage. This needs to happen from the local machine. I was really surprised how easy this is to do. The Microsoft.WindowsAzure.StorageClient assembly has all the code you need to make this work. To upload the images and make them visible to the public, I just wrote the following:

static void Main()
{
  var client = Utility.StorageAccount.CreateCloudBlobClient();
  var dirInfo = new DirectoryInfo(Environment.CurrentDirectory);
  var cloudContainer = new CloudBlobContainer("friseton", client);
  var permissions = new BlobContainerPermissions
                      {
                        PublicAccess = BlobContainerPublicAccessType.Blob
                      };
  cloudContainer.CreateIfNotExist();
  cloudContainer.SetPermissions(permissions);
  foreach (var fileInfo in dirInfo.EnumerateFiles("*.jpg"))
  {
    var blobRef = cloudContainer.GetBlobReference(fileInfo.Name);
    blobRef.DeleteIfExists();
    blobRef.UploadFile(fileInfo.FullName);
  }
}

In this way, you can use Azure blob storage the same way you use Amazon’s S3. The queue can be used like the Simple Queue Service, and table can be accessed liked SimpleDB.

Yes, I understand that this has been possible for Azure all along. It finally clicked in my noggin that developing for Azure really can mean just picking and choosing the parts you want to use. You don’t need to go all in to use the service. Instead, just pick the parts that make sense and build apps!

For those that are curious, here is the queue demo too. It uses an object, Name, to send messages. This could be ANY object, I just picked something simple for demo purposes.

[DataContract]
public class Name
{
  [DataMember]
  public string FirstName { get; set; }

  [DataMember]
  public string LastName { get; set; }
}

It is sent to the queue with this code:

static void Main()
{
  var client = Utility.StorageAccount.CreateCloudQueueClient();
  var cloudQueue = new CloudQueue(
    Utility.StorageAccount.QueueEndpoint + "friseton",
    client.Credentials);
  cloudQueue.CreateIfNotExist();
  var name = new Name {FirstName = "Scott", LastName = "Seely"};
  var stream = new MemoryStream();
  var writer = XmlDictionaryWriter.CreateBinaryWriter(stream);
  var ser = new DataContractSerializer(typeof (Name));
  ser.WriteObject(writer, name);
  writer.Flush();
  var buffer = new byte[stream.Length];
  Array.Copy(stream.GetBuffer(), buffer, stream.Length);
  var message = new CloudQueueMessage(buffer);
  cloudQueue.AddMessage(message, TimeSpan.FromHours(1));
}

And read from the queue thusly:

static void Main()
{
  var client = Utility.StorageAccount.CreateCloudQueueClient();
  var cloudQueue = new CloudQueue(
    Utility.StorageAccount.QueueEndpoint + "friseton",
    client.Credentials);
  cloudQueue.CreateIfNotExist();
  var ser = new DataContractSerializer(typeof(Name));
  var timeToStop = DateTime.Now + TimeSpan.FromMinutes(2);
  while (DateTime.Now < timeToStop)
  {
    if (cloudQueue.RetrieveApproximateMessageCount() > 0)
    {
      var message = cloudQueue.GetMessage();
      var buffer = message.AsBytes;
      var writer = XmlDictionaryReader.CreateBinaryReader(buffer, 0,
        buffer.Length, XmlDictionaryReaderQuotas.Max);
      var name = ser.ReadObject(writer) as Name;
      if (name != null)
      {
        Console.WriteLine("{0} {1} {2}", name.FirstName,
          name.LastName, message.InsertionTime);
      }
      cloudQueue.DeleteMessage(message);
    }
    Thread.Sleep(TimeSpan.FromSeconds(1));
  }
}

And yes, the queue code also works from your local machine. The example above does require you to have the Azure SDK installed.

  1. Leave a comment

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: