[2015/05/13] The code in this post has been updated to work with the “Windows Azure Storage 4.4.0-preview” NuGet package
Applying the ModelCommand pattern I was able to create a command that enables us to upload a serializable object as JSON and store it in an existing Blob Container.
Working with Json.NET, which can be installed using NuGet, we are able to serialize objects and send them to the Windows Azure Blob Storage. The UploadToBlogStorageAsJson ModelCommand was created specifically to simplify this process.
To upload JSON to a Blob Storage container we first have to get the Contrainer Reference using the container name provided by the constructor parameters. Then from the Container Reference we get the Blob Reference. We then prepare the Blob Reference with the provided Metadata and Properties before uploading the JSON to Windows Azure Blob Storage.
public class UploadToBlobStorageAsJson : IModelCommand<CloudStorageAccount> { private const string CONTENT_TYPE = "application/json"; private readonly object obj; private readonly string containerPath; private readonly string blobAddressUri; private readonly Dictionary<string, string> metadata; public UploadToBlobStorageAsJson(object obj, string containerPath, string blobAddressUri, Dictionary<string, string> metadata) { this.obj = obj; this.containerPath = containerPath; this.blobAddressUri = blobAddressUri; this.metadata = metadata; } public void Apply(CloudStorageAccount model) { var client = model.CreateCloudBlobClient(); var container = client.GetContainerReference(containerPath); if (!container.Exists()) container.Create(); var blobReference = container.GetBlockBlobReference(blobAddressUri); var blockBlob = blobReference; UploadToContainer(blockBlob); } private void UploadToContainer(CloudBlockBlob blockBlob) { SetBlobProperties(blockBlob); using (var ms = new MemoryStream()) { LoadStreamWithJson(ms); blockBlob.UploadFromStream(ms); } } private void SetBlobProperties(CloudBlockBlob blobReference) { blobReference.Properties.ContentType = CONTENT_TYPE; foreach (var meta in metadata) { blobReference.Metadata.Add(meta.Key, meta.Value); } } private void LoadStreamWithJson(Stream ms) { var json = JsonConvert.SerializeObject(obj); StreamWriter writer = new StreamWriter(ms); writer.Write(json); writer.Flush(); ms.Position = 0; } }
Using the UploadToBlobStorageAsJson ModelCommand
The following tests have been written to demonstrate an interesting side effect of the ModelCommand. The first test shows how to instantiate a command and upload an object to Windows Azure Blob Storage. The second test is interesting because it applies the command twice, effectively reusing the command instance.
The command holds a reference to the object that it will serialize and send to the Windows Azure Blob Storage. By preserving the Command instance, we can upload the object. Then we can modify it locally and call Apply on the command to re-upload the modified object to the same Blob in Windows Azure Blob Storage.
[TestClass] public class BlobStorageUnitTests { [TestMethod] public void TestUploadToBlobStorage() { var obj = new { By = "Alexandre Brisebois", Message = "This is a test Message" }; var uploadToBlobStorage = new UploadToBlobStorageAsJson(obj, "test", "testObject", new Dictionary<string, string>()); var storageAccount = CloudStorageAccount.Parse(GetConnectionString()); uploadToBlobStorage.Apply(storageAccount); } [TestMethod] public void TestUploadThenChangeThenUpload() { var obj = new { By = "Alexandre Brisebois", Message = "This is a test Message" }; var uploadToBlobStorage = new UploadToBlobStorageAsJson(obj, "test", "testObject", new Dictionary<string, string>()); var storageAccount = CloudStorageAccount.Parse(GetConnectionString()); uploadToBlobStorage.Apply(storageAccount); obj = new { By = "Charles Brisebois", Message = "This is a test Message" }; uploadToBlobStorage = new UploadToBlobStorageAsJson(obj, "test", "testObject", new Dictionary<string, string>()); uploadToBlobStorage.Apply(storageAccount); } private static string GetConnectionString() { return CloudConfigurationManager.GetSetting("StorageConnectionString"); } }
The CloudConfigurationManager will first look for the Cloud Configurations, if it does not find them, it will then look a matching AppSetting. In this example it found the setting in the following App.Config.
<?xml version="1.0" encoding="utf-8" ?> <configuration> <appSettings> <add key="StorageConnectionString" value="DefaultEndpointsProtocol=https; AccountName=*******; AccountKey=********" /> </appSettings> </configuration>
what is ModelCommand here ? is there any other work around for this ?
LikeLike
Hi ModelCommand is an interface I describe in this earlier post : https://alexandrebrisebois.wordpress.com/2012/06/21/build-reusable-testable-commands-part-1/
It helps me simplify my code by using the Single Responsibility Principle.
LikeLiked by 1 person
but in above code how can I use it ?public class UploadToBlobStorageAsJson : ModelCommand
I really don’t understand :(
LikeLike
Have a look at the TestUploadToBlobStorage, this is an example of how I used the UploadToBlobStorageAsJson class to upload Json to Azure Blob Storage.
LikeLike
The ModelCommand is a wrapper to the code you are looking for. you can definitely use the code from the Apply method without the class.
LikeLike
I think this code is older one can you please update the code as per new classes and methods. “CloudBlob” is also not present currently.
LikeLike
Hi Ashish, this post is more than 2 years old. It’s normal that some changes have happened. I will add an updated section below the post to reflect how it is done with SDK 2.6
LikeLike
In Windows Azure Storage 4.4.0-preview the CloudBlob object is located in the Microsoft.WindowsAzure.Storage.Blob name space. The UploadFromStream method has moved to the CloudBlockBlob object.
LikeLike
getting error “Additional information: No valid combination of account information found.” while calling this var storageAccount = CloudStorageAccount.Parse(GetConnectionString());
LikeLike
In class library I’m getting this error :(
Value cannot be null.
Parameter name: connectionString
Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.
Exception Details: System.ArgumentNullException: Value cannot be null.
Parameter name: connectionString
my code is
var obj = new
{
By = “Alexandre Brisebois”,
Message = “This is a test Message”
};
getting error at above line , please guide ? thanks a lot
LikeLike
Be sure that the connection string is on a single string with no spaces or line breaks. I place the segments on multiple lines to simplify readability.
LikeLike
very thankful for your quick response . how can i retrieve data from that Blob in a object. I mean If I have stored Customer data into blob, how could I retrieve data in customer object from that blob ? please guide thanks a lot :)
LikeLike
I made it like this var Details = blob.DownloadText();
Obj = JsonConvert.DeserializeObject(Details);
thanks
LikeLike
Hi need your help to convert list of object and stored it into blog , how can i do so?
I mean List for one key
LikeLike
Thanks Alexandre,
it worked well.
Best Regards
LikeLike