Azure Storage Note - Code

  1. Two approaches to create storage client via Azure Client Library 
    1. via connection string
    2. via base URI and storage credential

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.WindowsAzure;
using Microsoft.WindowsAzure.StorageClient;

namespace AzureTest
{
    class Program
    {
        static void Main(string[] args)
        {
            //Approach 1 : use connectionstring
            CloudStorageAccount account = CloudStorageAccount.
            Parse(System.Configuration.ConfigurationManager.AppSettings["StorageAccountConnectionString"]);

            //Approach 2 : Use base uri + StorageCredentialsAccountAndKey
            string accountName = System.Configuration.ConfigurationManager.AppSettings["accountName"];
            string key = System.Configuration.ConfigurationManager.AppSettings["accountKey"];
            StorageCredentialsAccountAndKey credentials = new StorageCredentialsAccountAndKey(accountName, key);
            string baseUri = string.Format("http://127.0.0.1:10002/{0}", accountName);

            CloudBlobClient BlobClient = account.CreateCloudBlobClient();  
            CloudTableClient tableClient = new CloudTableClient(baseUri, credentials);  
        }
    }
}

  1. Upload File using Blob and Parallel Blob Upload using Block Blob
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.WindowsAzure;
using Microsoft.WindowsAzure.StorageClient;
using System.Threading.Tasks;
using System.IO;

namespace AzureTest
{
    class Program
    {
        static void Main(string[] args)
        {
            CloudStorageAccount account = CloudStorageAccount.
            Parse(System.Configuration.ConfigurationManager.AppSettings["StorageAccountConnectionString"]);
            
            //Blob: Upload File
            CloudBlobClient BlobClient = account.CreateCloudBlobClient();
            CloudBlobContainer ContainerReference = BlobClient.GetContainerReference("practicecontainer");
            ContainerReference.CreateIfNotExist();
            CloudBlob BlobReference = ContainerReference.GetBlobReference("blobfile.doc");
            BlobReference.UploadFile("blobfile.doc");
            byte[] DownloadAsByteArray = BlobReference.DownloadByteArray();
            Console.WriteLine(DownloadAsByteArray);
            Console.ReadKey();

            //Block Blob : Parallel Blob Uploads
            var blockBlob = BlobReference.ToBlockBlob;
            var blockLength = 100 * 1024;//each block 100KB
            var dataToUpload = File.ReadAllBytes("blobfile.doc");
            var numberOfBlocks = ((int) dataToUpload.Length / blockLength) + 1;
            string[] blockIds = new string[numberOfBlocks];

            Parallel.For(0, numberOfBlocks, x =>
            {
                var blockId = Convert.ToBase64String(Guid.NewGuid().ToByteArray());
                var currentLength = Math.Min(blockLength, dataToUpload.Length - (x * blockLength));

                using (var memStream = new MemoryStream(dataToUpload, x * blockLength, currentLength))
                {
                    blockBlob.PutBlock(blockId, memStream, null);
                }
                blockIds[x] = blockId;
            });

            blockBlob.PutBlockList(blockIds);

            DownloadAsByteArray = BlobReference.DownloadByteArray();
            Console.WriteLine(DownloadAsByteArray);
            Console.ReadKey();  
        }
    }
}

  1. Copy Blob and Snapshot Blob + use Snapshot blob to restore current blob
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.WindowsAzure;
using Microsoft.WindowsAzure.StorageClient;
using System.Threading.Tasks;
using System.IO;

namespace AzureTest
{
    class Program
    {
        static void Main(string[] args)
        {
            CloudStorageAccount account = CloudStorageAccount.
            Parse(System.Configuration.ConfigurationManager.AppSettings["StorageAccountConnectionString"]);

            CloudBlobClient BlobClient = account.CreateCloudBlobClient();
            CloudBlobContainer ContainerReference = BlobClient.GetContainerReference("practicecontainer");
            ContainerReference.CreateIfNotExist();
            BlobContainerPermissions permissions = new BlobContainerPermissions();
            permissions.PublicAccess = BlobContainerPublicAccessType.Container;
            ContainerReference.SetPermissions(permissions);

            CloudBlob BlobReference = ContainerReference.GetBlobReference("blobfile.doc");

            //Copy Blob
            BlobRequestOptions options = new BlobRequestOptions()
            {
                Timeout = TimeSpan.FromSeconds(45),
                RetryPolicy = RetryPolicies.RetryExponential(
                RetryPolicies.DefaultClientRetryCount, RetryPolicies.DefaultClientBackoff)
            };

            CloudBlob destinationBlob = ContainerReference.GetBlobReference("Copy/blobfile copy.doc");
            destinationBlob.CopyFromBlob(BlobReference, options);

            //Snapshot Blob
            BlobReference.CreateSnapshot();

            //Replace Blob With New Version
            BlobReference.UploadFile("blobfilev2.doc");

            //Get the Snapshot
            var snapshots = ContainerReference.ListBlobs(new BlobRequestOptions() 
            { BlobListingDetails = BlobListingDetails.Snapshots,
              UseFlatBlobListing = true
            });

            BlobReference.FetchAttributes();
            Console.WriteLine(BlobReference.Attributes.Properties.Length);

            foreach (CloudBlob c in snapshots.Where(item => ((CloudBlob)item).SnapshotTime.HasValue && item.Uri.Equals(BlobReference.Uri)))
            {
                BlobReference.CopyFromBlob(c);
                break;
            }

           BlobReference.FetchAttributes();
           Console.WriteLine(BlobReference.Attributes.Properties.Length);

           Console.ReadKey();  
        }
    }
}

  1. Lease Blob
using System;
using Microsoft.WindowsAzure;
using Microsoft.WindowsAzure.StorageClient;
using Microsoft.WindowsAzure.StorageClient.Protocol;
using System.IO;

namespace AzureStorageTest
{
    class Program
    {
        static void Main(string[] args)
        {

            CloudStorageAccount account = CloudStorageAccount.
            Parse(System.Configuration.ConfigurationManager.AppSettings["StorageAccountConnectionString"]);

            CloudBlobClient BlobClient = account.CreateCloudBlobClient();

            CloudBlobContainer ContainerReference = BlobClient.GetContainerReference("maincontainer");
            ContainerReference.CreateIfNotExist();

            CloudBlob BlobReference = ContainerReference.GetBlobReference("blobfile.txt");

            var leaseId = BlobReference.AcquireLease();

            // BlobReference.UploadText("new content", "123");
            BlobReference.UploadText("new content", leaseId);

            byte[] DownloadAsByteArray = BlobReference.DownloadByteArray();

            Console.WriteLine(DownloadAsByteArray);
            Console.ReadKey();

        }

       
    }

    public static class LeaseBlobExtensions
    {
        public static string AcquireLease(this CloudBlob blob)
        {
            var creds = blob.ServiceClient.Credentials;
            var transformedUri = new Uri(creds.TransformUri(blob.Uri.ToString()));
            var req = BlobRequest.Lease(transformedUri,
                90, // timeout (in seconds)
                LeaseAction.Acquire, // as opposed to "break" "release" or "renew"
                null); // name of the existing lease, if any
            blob.ServiceClient.Credentials.SignRequest(req);
            using (var response = req.GetResponse())
            {
                return response.Headers["x-ms-lease-id"];
            }
        }

        public static void UploadText(this CloudBlob blob, string text, string leaseId)
        {
            string url = blob.Uri.ToString();
            if (blob.ServiceClient.Credentials.NeedsTransformUri)
            {
                url = blob.ServiceClient.Credentials.TransformUri(url);
            }
            var req = BlobRequest.Put(new Uri(url), 90, new BlobProperties(), BlobType.BlockBlob, leaseId, 0);
            using (var writer = new StreamWriter(req.GetRequestStream()))
            {
                writer.Write(text);
            }
            blob.ServiceClient.Credentials.SignRequest(req);
            req.GetResponse().Close();
        }
    }

}

  1. Meta Data and Share Access Policy & Share Access Signatures
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.WindowsAzure;
using Microsoft.WindowsAzure.StorageClient;
using System.Threading.Tasks;
using System.IO;
using System.Collections.Specialized;

namespace AzureTest
{
    class Program
    {
        static void Main(string[] args)
        {
            CloudStorageAccount account = CloudStorageAccount.
            Parse(System.Configuration.ConfigurationManager.AppSettings["StorageAccountConnectionString"]);

            CloudBlobClient BlobClient = account.CreateCloudBlobClient();
            CloudBlobContainer ContainerReference = BlobClient.GetContainerReference("practicecontainer");
            ContainerReference.CreateIfNotExist();
            //BlobContainerPermissions permissions = new BlobContainerPermissions();
            //permissions.PublicAccess = BlobContainerPublicAccessType.Container;
            //ContainerReference.SetPermissions(permissions);

            CloudBlob BlobReference = ContainerReference.GetBlobReference("blobfile.doc");
            var metadata = new NameValueCollection();
            metadata["Id"] = "1";
            metadata["Filename"] = "doc file";
            metadata["ImageName"] = String.IsNullOrEmpty("blobfile.doc") ? "unknown" : "blobfile.doc";
            metadata["Description"] = String.IsNullOrEmpty("description") ? "unknown" : "description";
            metadata["Tags"] = String.IsNullOrEmpty("") ? "unknown" : "";
            // Add and commit metadata to blob
            BlobReference.Metadata.Add(metadata);

            //CloudBlobContainer.FetchAttributes Method:
            //Retrieves the container's attributes, including its system properties and user-defined metadata.
            //CloudBlobContainer container = BlobClient.GetContainerReference(containerName);
            //container.FetchAttributes();
            
            //Get Meta data
            var items = BlobReference.Metadata.AllKeys.SelectMany(BlobReference.Metadata.GetValues,(k, v) => new {key = k, value = v});
            foreach (var item in items)
            {
                Console.WriteLine(String.Format("Name :{0}, Value:{1}",item.key, item.value));
            }

            //OR 
            foreach (string key in BlobReference.Metadata.Keys)
            {
                Console.WriteLine(String.Format("Name :{0}, Value:{1}", key, BlobReference.Metadata[key]));
            }

            //ACL(Access Control List) -  Container Level
            BlobContainerPermissions permission = new BlobContainerPermissions();
            /*
             * Full public read access: Container and blob data can be read via anonymous request. 
             *                          Clients can enumerate blobs within the container via anonymous
             *                          request, but cannot enumerate containers within the storage account.

                Public read access for blobs only: Blob data within this container can be 
             *                          read via anonymous request, but container data is not available. 
             *                          Clients cannot enumerate blobs within the container 
             *                          via anonymous request.

                No public read access: Container and blob data can be read by the account owner only.
             * */
            permission.PublicAccess = BlobContainerPublicAccessType.Off;

            ContainerReference.SetPermissions(permission);

           //Share Access policy - Container Level
           SortedList<string, SharedAccessPolicy> policies = new SortedList<string, SharedAccessPolicy>();
           permission.SharedAccessPolicies.Clear();
           SharedAccessPolicy policy1 = new SharedAccessPolicy()
           {
               Permissions = SharedAccessPermissions.List | SharedAccessPermissions.Read | SharedAccessPermissions.Write | SharedAccessPermissions.Delete,
               SharedAccessStartTime = DateTime.UtcNow,
               SharedAccessExpiryTime = DateTime.UtcNow.AddHours(1)
           };
           policies.Add("Policy1", policy1);
           policies.Add("Policy2", new SharedAccessPolicy()
           {
               Permissions = SharedAccessPermissions.Read,
               SharedAccessStartTime = DateTime.Parse("2010-01-01T09:38:05Z"),
               SharedAccessExpiryTime = DateTime.Parse("2012-12-31T09:38:05Z")
           });
           if (policies != null)
           {
               foreach (KeyValuePair<string, SharedAccessPolicy> policy in policies)
               {
                   permission.SharedAccessPolicies.Add(policy.Key, policy.Value);
               }
           }

           ContainerReference.SetPermissions(permission);

           //GenerateSharedAccessSignature via policy
           string signature = ContainerReference.GetSharedAccessSignature(policy1);

           Console.WriteLine("Container Shared Access Signature via policy: " + signature);
           //GenerateSharedAccessSignature via policy string
           signature = ContainerReference.GetSharedAccessSignature(new SharedAccessPolicy(), "Policy1");

           Console.WriteLine("Container Shared Access Signature via policy name: " + signature);

            //Share Access Signature - Blob Level
           permission.PublicAccess = BlobContainerPublicAccessType.Off;
           permission.SharedAccessPolicies.Clear();
           ContainerReference.SetPermissions(permission);

           var sas = BlobReference.GetSharedAccessSignature(new SharedAccessPolicy()
            {
                Permissions = SharedAccessPermissions.Read
                                |SharedAccessPermissions.Write,
                SharedAccessExpiryTime = DateTime.UtcNow + TimeSpan.FromMinutes(5)
            });
            Console.WriteLine("This link should work for the next five minutes:");
            Console.WriteLine(BlobReference.Uri.AbsoluteUri + sas);

            Console.ReadKey();  
        }
    }
}



  1. Tables Operations
    1. set IgnoreResourceNotFoundException
    2. insert entity
    3. ReplaceUpdateEntity + Entity GroupTransactions
    4. Merge update
    5. Upsert - InsertOrReplace
    6. Upsert - InsertOrMerge 
    7. Delete Entity
    8. Show Result
    9. Delete Table
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data.Services.Common;

namespace AzureTest
{
    [DataServiceKey("PartitionKey", "RowKey")]
    public class Movie
    {
        public string PartitionKey { get; set; }
        public string RowKey { get; set; }
        public DateTime Timestamp { get; set; }
        public double Rating { get; set; }
        public bool Favorite { get; set; }

        public Movie() { }
        public Movie(string partitionKey, string rowKey)
        {
            PartitionKey = partitionKey;
            RowKey = rowKey;
            Rating = 5;
            Favorite = false;
        }
    }  
}

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.WindowsAzure;
using Microsoft.WindowsAzure.StorageClient;
using System.Threading.Tasks;
using System.IO;
using System.Collections.Specialized;
using System.Data.Services.Client;

namespace AzureTest
{
    class Program
    {
        static void Main(string[] args)
        {
            CloudStorageAccount account = CloudStorageAccount.
            Parse(System.Configuration.ConfigurationManager.AppSettings["StorageAccountConnectionString"]);

            CloudTableClient tableClient = account.CreateCloudTableClient();
            tableClient.RetryPolicy = RetryPolicies.Retry(4, TimeSpan.Zero);

            string tableName = "Movies";
            tableClient.CreateTableIfNotExist(tableName);

            TableServiceContext context = tableClient.GetDataServiceContext();
            //IgnoreResourceNotFoundException 
            //Issue: FirstOrDefault() return 404 error
            //You have to set IgnoreResourceNotFoundException = true in the TableServiceContext in order 
            //to receive null when an entity is not found instead of error 404
            context.IgnoreMissingProperties = true;

            // Insert movie  
            context.AddObject(tableName, new Movie("Action", "1White Water Rapids Survival"));
            context.AddObject(tableName, new Movie("Action", "2White Water Rapids Survival"));
            context.AddObject(tableName, new Movie("Action", "3White Water Rapids Survival"));
            context.AddObject(tableName, new Movie("Action", "4White Water Rapids Survival"));
            context.AddObject(tableName, new Movie("Action", "5White Water Rapids Survival"));
            context.AddObject(tableName, new Movie("Comedy", "6White Water Rapids Survival"));
            context.AddObject(tableName, new Movie("Comedy", "7White Water Rapids Survival"));
            context.SaveChangesWithRetries();

            // ReplaceUpdateEntity + Entity GroupTransactions
            context = tableClient.GetDataServiceContext();
            var q1 = (from movie in context.CreateQuery<Movie>(tableName)
                     where movie.PartitionKey == "Action" && movie.Rating > 4.0
                     select movie).AsTableServiceQuery<Movie>();

            foreach (Movie movieToUpdate in q1)
            {
                movieToUpdate.Favorite = true;
                context.UpdateObject(movieToUpdate);
            }
            context.SaveChangesWithRetries(SaveChangesOptions.Batch | SaveChangesOptions.ReplaceOnUpdate);

            // Merge update
            context = tableClient.GetDataServiceContext();
            var q2 = (from movie in context.CreateQuery<Movie>(tableName)
                     where movie.PartitionKey == "Action" && movie.Rating > 4.0
                     select movie).AsTableServiceQuery<Movie>();

            foreach (Movie movieToUpdate in q2)
            {
                movieToUpdate.Favorite = false;
                context.UpdateObject(movieToUpdate);
            }
            context.SaveChangesWithRetries(SaveChangesOptions.Batch);

            // Upsert - InsertOrReplace (Note that insert-or-replace is not supported on the local storage emulator)
            //TableServiceContext serviceContext = tableClient.GetDataServiceContext();

            ////      Create a new customer entity
            //Movie newmovie = new Movie("Action", "9White Water Rapids Survival");
            //newmovie.Rating = 6;
            //serviceContext.AttachTo(tableName, newmovie);
            //serviceContext.UpdateObject(newmovie);
            //serviceContext.SaveChangesWithRetries(SaveChangesOptions.ReplaceOnUpdate);

            //// Upsert - InsertOrMerge  (Note that insert-or-replace is not supported on the local storage emulator)
            //serviceContext = tableClient.GetDataServiceContext();

            ////      Create a new customer entity
            //Movie newmovie2 = new Movie("Action", "9White Water Rapids Survival");
            //newmovie2.Rating = 7;
            //serviceContext.AttachTo(tableName, newmovie2);
            //serviceContext.UpdateObject(newmovie2);
            //serviceContext.SaveChangesWithRetries();

            //Delete Entity
            context = tableClient.GetDataServiceContext();
            var entity = (from movie in context.CreateQuery<Movie>(tableName)
                          select movie).FirstOrDefault<Movie>();
            context.DeleteObject(entity);
            context.SaveChangesWithRetries();

            //Show Result
            var result = (from movie in context.CreateQuery<Movie>(tableName)
                          select movie).FirstOrDefault<Movie>();
            Console.WriteLine(String.Format(
                "result.PartitionKey:{0}\n result.RowKey:{1} \n result.Timestamp:{2} \n result.Rating:{3} \n result.Favorite:{4}",
                result.PartitionKey,
                result.RowKey,
                result.Timestamp,
                result.Rating,
                result.Favorite));

            //Delete Table
            tableClient.DeleteTableIfExist(tableName);

            Console.ReadKey();  
        }
    }
}



  1. Queue Operation
    1. Create Queue
    2. Insert a Message into a Queue
    3. Change the Contents of a Queued Message
    4. Dequeue the Next Message(s)
    5. DequeueCount & Poison Message
    6. Get the Queue Length
    7. Delete a Queue
    8. schedule work (base on QueueExtensions class :http://blogs.msdn.com/b/windowsazurestorage/archive/2011/09/15/windows-azure-queues-improved-leases-progress-tracking-and-scheduling-of-future-work.aspx)
    9. Processing status (base on QueueExtensions class :http://blogs.msdn.com/b/windowsazurestorage/archive/2011/09/15/windows-azure-queues-improved-leases-progress-tracking-and-scheduling-of-future-work.aspx)
    10. Extend the visibility timeout (base on QueueExtensions class :http://blogs.msdn.com/b/windowsazurestorage/archive/2011/09/15/windows-azure-queues-improved-leases-progress-tracking-and-scheduling-of-future-work.aspx)

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.WindowsAzure;
using Microsoft.WindowsAzure.StorageClient;
using System.Threading.Tasks;
using System.IO;
using System.Collections.Specialized;
using System.Data.Services.Client;
using System.Threading;

namespace AzureTest
{
    class Program
    {
        static void Main(string[] args)
        {
            CloudStorageAccount account = CloudStorageAccount.
            Parse(System.Configuration.ConfigurationManager.AppSettings["StorageAccountConnectionString"]);

            CloudQueueClient queueStorage = account.CreateCloudQueueClient();
            queueStorage.RetryPolicy = RetryPolicies
               .RetryExponential(RetryPolicies.DefaultClientRetryCount,
               RetryPolicies.DefaultMaxBackoff);

            //Create Queue
            CloudQueue queue = queueStorage.GetQueueReference("guestthumbs");
            queue.CreateIfNotExist();

            //Insert a Message into a Queue
            for (int i = 0; i < 20; i++)
            {
                var message = new CloudQueueMessage(String.Format("{0},{1},{2}",
                i + ":uniqueBlobName",
               "entry.PartitionKey",
               "entry.RowKey"));
                queue.AddMessage(message);
                Console.WriteLine("Input Message :" + message);
            }

            //Change the Contents of a Queued Message
            CloudQueueMessage updatemessage = queue.GetMessage();
            updatemessage.SetMessageContent("Updated contents.");
            queue.UpdateMessage(updatemessage,
                TimeSpan.FromSeconds(0.0),  // visible immediately
                MessageUpdateFields.Content | MessageUpdateFields.Visibility);

            //Allow applications to schedule work to be processed at a later time
            //Processing applications can update the message content of a message they have dequeued to save progress 
            //state so that a new worker can continue from that state if the prior worker crashed
            queue.PutMessage(account.Credentials,
            EncodeMessage("new feature message", ProcessingState.VirusScan),
            24 * 60 * 60, // StartVisibilityTimeout : set to 1 day,<int=seconds>
            24 * 60 * 60 * 3, //MessageTtl set to 3 days,<int-seconds>
            60);//ServerRequestTimeout

            //Processing applications can now extend the visibility timeout on a message they have dequeued
            CloudQueueMessage extendmessage = queue.GetMessage();
            string newPopReceipt = "";
            DateTime nextVisibilityTime=DateTime.UtcNow;

            queue.UpdateMessage(account.Credentials,
                extendmessage.Id,
                extendmessage.PopReceipt,
                24 * 60 * 60,//From now extend 1 days
                extendmessage.AsString,
                60,//ServerRequestTimeout
                out newPopReceipt,
                out nextVisibilityTime);

            //Dequeue the Next Message
            IEnumerable<CloudQueueMessage> msgList = queue.GetMessages(32, TimeSpan.FromSeconds(20));

            if (msgList == null)
            {
                //Time Sleep  
                Thread.Sleep(TimeSpan.FromSeconds(5));
            }
            else
            {
                try
                {
                    foreach (CloudQueueMessage msg in msgList)
                    {
                        if (msg.DequeueCount < 8)
                        {
                            Console.WriteLine("Output Message : " + msg.AsString);
                        }
                        else
                        {
                            //Handle Poison Message  
                        }
                        queue.DeleteMessage(msg);
                    }
                }
                catch (StorageClientException ex)
                {
                    if (ex.ExtendedErrorInformation.ErrorCode == "MessageNotFound")
                    {
                        // pop receipt must be invalid  
                        // ignore or log (so we can tune the visibility timeout)  
                    }
                    else
                    {
                        // not the error we were expecting  
                        throw;
                    }
                }

            }

            //Get the Queue Length
            int freshMessageCount = queue.RetrieveApproximateMessageCount();
            int? cachedMessageCount = queue.ApproximateMessageCount;
            Console.WriteLine(String.Format("freshMessageCount:{0} /n cachedMessageCount:{1}"
                                , freshMessageCount
                                , cachedMessageCount.Value));

            //Delete a Queue
            queue.Delete();

            Console.ReadKey();
        }

        /// <summary>
        /// The processing stages for a message
        /// </summary>
        public enum ProcessingState : int
        {
            VirusScan = 1,
            Encoder = 2,
            Compress = 3,
            Completed = 4
        }
        /// <summary>
        /// Form of the queue message is: [2 digits for state][Actual Message content]
        /// </summary>
        /// <param name="content"></param>
        /// <param name="state"></param>
        /// <returns></returns>
        private static string EncodeMessage(string content, ProcessingState state)
        {
            return string.Format("{0:D2}{1}", (int)state, content);
        }
    }
}

Class QueueExtensions
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using Microsoft.WindowsAzure.StorageClient.Protocol;
using System.IO;
using Microsoft.WindowsAzure;
using Microsoft.WindowsAzure.StorageClient;

// NOTE: Please test these before using in production
public static class QueueExtensions
{
    /// <summary>
    /// Add a message to the queue. The visibility timeout param can be used to optionally 
    /// make the message visible at a future time
    /// </summary>
    /// <param name="queue">
    /// The queue to add message to
    /// </param>
    /// <param name="credentials">
    /// The storage credentials used for signing
    /// </param>
    /// <param name="message">
    /// The message content
    /// </param>
    /// <param name="visibilityTimeout">
    /// value in seconds and should be greater than or equal to 0 and less than 604800 (7 days). 
    /// It should also be less than messageTimeToLive
    /// </param>
    /// <param name="messageTimeToLive">
    /// (Optional) Time after which the message expires if it is not deleted from the queue.
    /// It can be a maximum time of 7 days.
    /// </param>
    /// <param name="timeout">
    /// Server timeout value
    /// </param>
    public static void PutMessage(
        this CloudQueue queue,
        StorageCredentials credentials,
        string message,
        int? visibilityTimeout,
        int? messageTimeToLive,
        int timeout)
    {
        StringBuilder builder = new StringBuilder(queue.Uri.AbsoluteUri);

        builder.AppendFormat("/messages?timeout={0}", timeout);

        if (messageTimeToLive != null)
        {
            builder.AppendFormat("&messagettl={0}", messageTimeToLive.ToString());
        }

        if (visibilityTimeout != null)
        {
            builder.AppendFormat("&visibilitytimeout={0}", visibilityTimeout);
        }

        HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(builder.ToString());
        request.Method = "POST";
        request.Headers.Add("x-ms-version", "2011-08-18");

        byte[] buffer = QueueRequest.GenerateMessageRequestBody(message);

        request.ContentLength = buffer.Length;
        credentials.SignRequest(request);
        using (Stream stream = request.GetRequestStream())
        {
            stream.Write(buffer, 0, buffer.Length);
        }

        try
        {
            using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
            {
                // we expect 201 for Put Message
                if (response.StatusCode != HttpStatusCode.Created)
                {
                    throw new InvalidOperationException("Unexpected response code.");
                }
            }
        }
        catch (WebException e)
        {
            // Log any exceptions for debugging
            LogWebException(e);
            throw;
        }
    }

    /// <summary>
    /// Update the message to extend visibility timeout and optionally 
    /// the message contents 
    /// </summary>
    /// <param name="queue">
    /// The queue to operate on
    /// </param>
    /// <param name="credentials">
    /// The storage credentials used for signing
    /// </param>
    /// <param name="messageId">
    /// The ID of message to extend the lease on
    /// </param>
    /// <param name="popReceipt">
    /// pop receipt to use
    /// </param>
    /// <param name="visibilityTimeout">
    /// Value should be greater than or equal to 0 and less than 7. 
    /// </param>
    /// <param name="messageBody">
    /// (optional) The message content
    /// </param>
    /// <param name="timeout">
    /// Server timeout value
    /// </param>
    /// <param name="newPopReceiptID">
    /// Return the new pop receipt that should be used for subsequent requests when 
    /// the lease is held
    /// </param>
    /// <param name="nextVisibilityTime">
    /// Return the next visibility time for the message. This is time until which the lease is held
    /// </param>
    public static void UpdateMessage(
        this CloudQueue queue,
        StorageCredentials credentials,
        string messageId,
        string popReceipt,
        int visibilityTimeout,
        string messageBody,
        int timeout,
        out string newPopReceiptID,
        out DateTime nextVisibilityTime)
    {
        StringBuilder builder = new StringBuilder(queue.Uri.AbsoluteUri);

        builder.AppendFormat(
            "/messages/{0}?timeout={1}&popreceipt={2}&visibilitytimeout={3}",
            messageId,
            timeout,
            Uri.EscapeDataString(popReceipt),
            visibilityTimeout);

        HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(builder.ToString());
        request.Method = "PUT";
        request.Headers.Add("x-ms-version", "2011-08-18");

        if (messageBody != null)
        {
            byte[] buffer = QueueRequest.GenerateMessageRequestBody(messageBody);

            request.ContentLength = buffer.Length;
            credentials.SignRequest(request);
            using (Stream stream = request.GetRequestStream())
            {
                stream.Write(buffer, 0, buffer.Length);
            }
        }
        else
        {
            request.ContentLength = 0;
            credentials.SignRequest(request);
        }

        try
        {
            using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
            {
                if (response.StatusCode != HttpStatusCode.NoContent)
                {
                    throw new InvalidOperationException("Unexpected response code.");
                }

                newPopReceiptID = response.Headers["x-ms-popreceipt"];
                nextVisibilityTime = DateTime.Parse(response.Headers["x-ms-time-next-visible"]);
            }
        }
        catch (WebException e)
        {
            // Log any exceptions for debugging
            LogWebException(e);
            throw;
        }
    }


    /// <summary>
    /// Get messages has been provided only because storage client library does not allow 
    /// invisibility timeout to exceed 2 hours
    /// </summary>
    /// <param name="queue">
    /// The queue to operate on
    /// </param>
    /// <param name="credentials">
    /// The storage credentials used for signing
    /// </param>
    /// <param name="messageId">
    /// The ID of message to extend the lease on
    /// </param>
    /// <param name="popReceipt">
    /// pop receipt to use
    /// </param>
    /// <param name="visibilityTimeout">
    /// Value should be greater than or equal to 0 and less than 7. 
    /// </param>
    /// <param name="messageBody">
    /// (optional) The message content
    /// </param>
    /// <param name="timeout">
    /// Server timeout value
    /// </param>
    /// <param name="newPopReceiptID">
    /// Return the new pop receipt that should be used for subsequent requests when 
    /// the lease is held
    /// </param>
    /// <param name="nextVisibilityTime">
    /// Return the next visibility time for the message. This is time until which the lease is held
    /// </param>
    public static IEnumerable<QueueMessage> GetMessages(
        this CloudQueue queue,
        StorageCredentials credentials,
        int? visibilityTimeout,
        int? messageCount,
        int timeout)
    {
        StringBuilder builder = new StringBuilder(queue.Uri.AbsoluteUri);

        builder.AppendFormat(
            "/messages?timeout={0}",
            timeout);

        if (messageCount != null)
        {
            builder.AppendFormat("&numofmessages={0}", messageCount);
        }

        if (visibilityTimeout != null)
        {
            builder.AppendFormat("&visibilitytimeout={0}", visibilityTimeout);
        }

        HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(builder.ToString());
        request.Method = "GET";
        request.Headers.Add("x-ms-version", "2011-08-18");
        credentials.SignRequest(request);

        try
        {
            using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
            {
                if (response.StatusCode != HttpStatusCode.OK)
                {
                    throw new InvalidOperationException("Unexpected response code.");
                }

                GetMessagesResponse msgResponses = QueueResponse.GetMessages(response);

                // force it to be parsed right away else the response will be closed
                // since QueueResponse.GetMessages parses responses lazily. 
                QueueMessage[] messages = msgResponses.Messages.ToArray<QueueMessage>();
                return messages.AsEnumerable<QueueMessage>();
            }
        }
        catch (WebException e)
        {
            // Log any exceptions for debugging
            LogWebException(e);
            throw;
        }
    }

    /// <summary>
    /// Log the exception in your preferred logging system
    /// </summary>
    /// <param name="e">
    /// The exception to log
    /// </param>
    private static void LogWebException(WebException e)
    {
        HttpWebResponse response = e.Response as HttpWebResponse;
        Console.WriteLine(string.Format(
            "Request failed with '{0}'. Status={1} RequestId={2} Exception={3}",
            e.Message,
            response.StatusCode,
            response != null ? response.Headers["x-ms-request-id"] : "<NULL>",
            e.ToString()));

        // Log to your favorite location…

    }
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章