Windows Azure: Working with Blob Storage in an ASP.NET Application

Posted by: Mahesh Sabnis , on 4/25/2012, in Category Windows Azure
Views: 54288
Abstract: The Blob storage service provided by Windows Azure provides manageable, scalable, high available techniques for managing BLOB data required by an application. We will create a sample application to create a container, upload and delete BLOB data. We will see how to deploy a cloud application using the Windows Azure portal.

While developing high scalable and always available applications on Windows Azure, it is important for you to think about the kind of data you want to store in the Cloud. Here data does not always mean that it is coming from a relational database. Here data could mean Images, Videos, Documents, Spreadsheets etc. A question that arises is how do you store this kind of BLOB data in the Cloud? On a local On-Premises server in the organization, you can manage to store this data in a File Server. A local application can then query the file server and download the files when required or may upload new files to it. But if you want to implement a similar functionality in an application which resides on the cloud, then it becomes necessary for you to think of the Storage Services offered by Azure.

Windows AZURE provides following Storage Services:

  • Blob Storage - This is a file System in Cloud.
  • Table Storage - Provides highly scalable structured storage.
  • Queue - Provides Reliable storage and message delivery.
  • Drives - Provides Durable NTFS for Windows Azure Application.

Windows Azure provides data center across various parts of the world. If you want to use Cloud Storage, then you as a developer must have a storage account under your cloud subscription.

 

What is the traditional approach of storing BLOB?

Earlier in software applications for storing BLOB data, we could use the following options:

  • SQL Server: Use SQL Server database to store BLOB e.g. Document, Image, Video etc. But the problem in this approach is the size constraints. The increasing size of BLOB requires more space and the cost of Data management increases
  • Network Share Drive: This is the most frequently used approach for BLOB store. You can have a dedicated file server which can be accessed by Web Services. But the problem in this approach is that if the Server Stops responding,  then the BLOBs goes inaccessible.

So to overcome the above issues, the Blob service offered by Windows Azure provides REST based APIs using which client applications can interact with the storage service using HTTP. Using these APIs, you can upload and download BLOBs.

In a simple code walkthrough, I have explained an approach of creating a container, uploading BLOB, deleting BLOB etc. For this article, I have used the following classes.

  • CloudStorageAccount: This class represents the Storage Account. It reads the Storage account name for the configuration file which has to be created before deploying an application on the cloud using a portal. This class manages all the storage services.
  • CloudBlobClient:  It provides a client for accessing the Windows Azure blob service.
  • CloudBlobContainer: This represents a container for a Blob service. This container contains all Blobs stored.

Step 1: Open VS2010 and create a new Windows Azure Web Role project and name it as ‘My_Blob_Application’. Here you get a Web Role project and an ASP.NET web application.

Step 2: Open ServiceConfiguration.Local.cscfg, and add a new ConfigurationSettings of name ‘DataConnectionString’ and set its value to ‘UseLocalDevelopmentStorage=true’. This value indicates that when the application runs, the local storage Emulator will be used.

<?xml version="1.0" encoding="utf-8"?>
<ServiceConfiguration serviceName="Mah_BlobApplication" xmlns=http://schemas.microsoft.com/ServiceHosting/2008/10/ServiceConfiguration”
osFamily="1" osVersion="*">
  <Role name="MyWebRole">
    <Instances count="1" />
    <ConfigurationSettings>
      <Setting name="Microsoft.WindowsAzure.Plugins.Diagnostics.ConnectionString"
    value="UseDevelopmentStorage=true" />
      <Setting name="DataConnectionString" value="UseDevelopmentStorage=true" />
    </ConfigurationSettings>
  </Role>
</ServiceConfiguration>

Here the Instance count=1 specifies that a single instance of the Role (i.e. Virtual Machine) will be used.

Step 3: Open ServiceDefinition.csdef and add the following configuration code below the <Imports> closing tag

<ConfigurationSettings>
      <Setting name="DataConnectionString" />
</ConfigurationSettings>

This specifies that the service uses the same settings as of the service configuration file for storage. So here in this case for BLOB storage service, it will use the local storage service using emulator.

Step 4: For storing BLOB, we need to create a container. Open Default.aspx from ASP.NET project and add a GridView, TextBox, and a button, as shown in markup below:

<p>
   <asp:TextBox ID="txtContainerName" runat="server"></asp:TextBox>
</p>
<p>
    <asp:Button ID="btnCreate" runat="server" onclick="btnCreate_Click"
        Text="Create" />
</p>
<p>
    <asp:GridView ID="gdvContainer" runat="server" BackColor="#DEBA84"
        BorderColor="#DEBA84" BorderStyle="None" BorderWidth="1px"
        CellPadding="3" CellSpacing="2"
        OnRowCommand="gvContainers_RowCommand"
        OnRowDeleting="gvContainers_RowDeleting"
        onselectedindexchanged="gdvContainer_SelectedIndexChanged">
        <FooterStyle BackColor="#F7DFB5" ForeColor="#8C4510" />
        <HeaderStyle BackColor="#A55129" Font-Bold="True" ForeColor="White" />
        <PagerStyle ForeColor="#8C4510" HorizontalAlign="Center" />
        <RowStyle BackColor="#FFF7E7" ForeColor="#8C4510" />
        <SelectedRowStyle BackColor="#738A9C" Font-Bold="True"
        ForeColor="White" />
        <SortedAscendingCellStyle BackColor="#FFF1D4" />
        <SortedAscendingHeaderStyle BackColor="#B95C30" />
        <SortedDescendingCellStyle BackColor="#F1E5CE" />
        <SortedDescendingHeaderStyle BackColor="#93451F" />

        <Columns>
              <asp:CommandField ShowSelectButton="True" />
              <asp:TemplateField>
                   <ItemTemplate>
                     <asp:LinkButton ID="btnDelete" runat="server" Text="Delete"
                     CommandName="Delete" CommandArgument='<%#Eval("Name")%>'/>
                   </ItemTemplate>
              </asp:TemplateField>
              <asp:HyperLinkField Text="View"
                    DataNavigateUrlFields="Name"
                    DataNavigateUrlFormatString="Blobs.aspx?Container={0}" />
        </Columns>
    </asp:GridView>
</p>

The UI renders as:

container-ui

Step 5: Open Default.aspx.cs and add the following code. Use the following namespaces so that the necessary classes for creating container and cloud Blob client can be accessed:

using Microsoft.WindowsAzure;
using Microsoft.WindowsAzure.StorageClient;
using Microsoft.WindowsAzure.ServiceRuntime;

In the Page_Load event, add the following code which specifies that the settings from the .csdef file must be read to access the Blob Storage:

protected void Page_Load(object sender, EventArgs e)
{
    if (IsPostBack == false)
    {
        //Read the Configuration form .csdef
        CloudStorageAccount.SetConfigurationSettingPublisher(
        (configName, configSetter) =>
        {
            configSetter(RoleEnvironment.GetConfigurationSettingValue(configName));
        });
    
    }

    GridBind();
}

Also add the following helper method which will read the Cloud Storage name from the configuration file i.e. the DataConnectionString. The code also creates an instance of CloudBlobClient which Lists all the containers which are already available and displays all containers in the GridView as below:

private void GridBind()
{
    //S1: Read the Local Development Storage
    CloudStorageAccount account1 =
    CloudStorageAccount.FromConfigurationSetting("DataConnectionString");
    //S2: Create a Blob Client
    CloudBlobClient blobClient1 = account1.CreateCloudBlobClient();
    gdvContainer.DataSource = blobClient1.ListContainers();
    gdvContainer.DataBind();
}

To create a new container for storing Blobs, write the following code which will read the CloudStorageAccount from the configuration file. By reading the CloudStorageAccount, it will create a CloudBlobClient. Once this is created, it will get the container reference based upon the text entered in the TextBox. The new container will be created from the name entered in the TextBox. The code is as below:

protected void btnCreate_Click(object sender, EventArgs e)
{
 
    //S1: Read the Local Development Storage
    CloudStorageAccount account =
    CloudStorageAccount.FromConfigurationSetting("DataConnectionString");
    //S2: Create a Blob Client
    CloudBlobClient blobClient = account.CreateCloudBlobClient();
    //S3: Get the reference to the Container
    CloudBlobContainer container =
    blobClient.GetContainerReference(txtContainerName.Text.ToLower());
    //S4:Create a Container
    container.Create();

    GridBind();
}

Now if we can create a container, we can delete it also! The code for deleting the container is as shown below:

/// <summary>
/// Helper Method to Delete Container
/// </summary>
void DeleteConainer(string ContainerName)
{
    //S1: Read the Local Development Storage
    CloudStorageAccount account =
    CloudStorageAccount.FromConfigurationSetting("DataConnectionString");
    //S2: Create a Blob Client
    CloudBlobClient blobClient = account.CreateCloudBlobClient();
    //S3: Get the reference to the Container
    CloudBlobContainer container =
    blobClient.GetContainerReference(ContainerName);
    container.Delete();
}

The code is similar to create container, the only difference is that the delete method is called on the CloudBlobContainer class.

Since we are using the GridView for displaying Container information and deleting it, we need to implement RowCommand and RowDeleting events as shown below:

protected void gvContainers_RowCommand(object sender, GridViewCommandEventArgs e)
{
    if (e.CommandName == "Delete")
    {
        DeleteConainer(e.CommandArgument.ToString());
    }
    GridBind();
}

protected void gvContainers_RowDeleting(object sender, GridViewDeleteEventArgs e)
{
   
}

Step 6: Run the application and enter a Text in the TextBox and click on the ‘Create’ button. The Container gets created which can be viewed from the Server Explorer Window of VS2010.

creating-container

You can view the created container using a server explorer as shown below:

container-explorer

Step 7: Now to upload Blobs in the Container, add a new WebForm in the ASP.NET Project and name it as ‘Page_Upload_Blob.aspx’. Open Default.aspx and add a new Button to it. Name it as ‘btnUploadBlob’. Add the following code on the click event of the ‘btnUploadBlob’ and the event SelectedIndexChanged event of the GridView as shown below:

protected void btnUploadBlob_Click(object sender, EventArgs e)
{
    Response.Redirect("./Page_Upload_Blob.aspx");
}

protected void gdvContainer_SelectedIndexChanged(object sender, EventArgs e)
{
    Session["ContainerName"] = gdvContainer.SelectedRow.Cells[3].Text;
}

The above code stores the selected Container Name and redirects to the newly added page i.e. Page_Upload_Blob.aspx.

Step 8: On the Page_Upload_Blob.aspx, add the FileUpload Control and a GridView as shown below:

 

<asp:Label ID="Label1" runat="server" Text="Select File to Upload"></asp:Label>
<asp:FileUpload ID="blobFileUpload" runat="server" />
<br />
<asp:Button ID="btnUpload" runat="server" onclick="btnUpload_Click"
    Text="Upload File" />
<br />
<br />
<br />
<br />
<asp:Label ID="lblErrorMessage" runat="server" Text="Label"></asp:Label>
<br />
<br />
<br />
<asp:GridView ID="gdvBlobs" runat="server" BackColor="#DEBA84"
    BorderColor="#DEBA84" BorderStyle="None" BorderWidth="1px" CellPadding="3"
    CellSpacing="2" onrowdeleting="gdvBlobs_RowDeleting"
    AutoGenerateColumns="False">
    <Columns>
        <asp:BoundField DataField="Name" HeaderText="Name" />
        
        <asp:TemplateField HeaderText="Image">
            <EditItemTemplate>
                <asp:TextBox ID="TextBox1" runat="server"></asp:TextBox>
            </EditItemTemplate>
            <ItemTemplate>
                <asp:Image ID="imgBlob" runat="server"
                ImageUrl='<%# Eval("Uri") %>' Height="50px" Width="50px"  />
            </ItemTemplate>
        </asp:TemplateField>
        
        <asp:CommandField ButtonType="Button" ShowDeleteButton="True" />
    </Columns>
    <FooterStyle BackColor="#F7DFB5" ForeColor="#8C4510" />
    <HeaderStyle BackColor="#A55129" Font-Bold="True" ForeColor="White" />
    <PagerStyle ForeColor="#8C4510" HorizontalAlign="Center" />
    <RowStyle BackColor="#FFF7E7" ForeColor="#8C4510" />
    <SelectedRowStyle BackColor="#738A9C" Font-Bold="True" ForeColor="White" />
    <SortedAscendingCellStyle BackColor="#FFF1D4" />
    <SortedAscendingHeaderStyle BackColor="#B95C30" />
    <SortedDescendingCellStyle BackColor="#F1E5CE" />
    <SortedDescendingHeaderStyle BackColor="#93451F" />
</asp:GridView>

Step 9: Add the following code in the code behind of the Page_Upload_Blob.aspx. Use the following references for accessing Blob classes:

using Microsoft.WindowsAzure;
using Microsoft.WindowsAzure.StorageClient;
using Microsoft.WindowsAzure.ServiceRuntime;

Write the helper method which will List and Display all Blobs uploaded in the container in a specific storage account as shown below:

/// <summary>
/// The below Helper method will List All Blobs uploaded by the User
/// </summary>
void ListandDisplyBlobs()
{
    //S1: Read the Local Development Storage
    CloudStorageAccount account =
    CloudStorageAccount.FromConfigurationSetting("DataConnectionString");
    //S2: Create a Blob Client
    CloudBlobClient blobClient = account.CreateCloudBlobClient();
    //S3: Get the reference to the Container
    CloudBlobContainer container =
    blobClient.GetContainerReference(Session["ContainerName"].ToString());

    // Set the Permission at Container Level for Public Access
    // So that the data stored inside it can be accessed publically
    var permission = container.GetPermissions();
    permission.PublicAccess = BlobContainerPublicAccessType.Container;
    container.SetPermissions(permission);

    // S4: List All Blobs Available in the Container
    gdvBlobs.DataSource = container.ListBlobs();
    gdvBlobs.DataBind();
}

The above code reads the container name passed using the Session object. Now to access the container, the public access permission on the container must be specified using BlobContainerPublicAccessType enumeration. Using ListBlobs() method of the CloudBlobContainer class, all the Blobs are read and displayed into the GridView.

Add the following code in the Loaded event which informs the application to read the Storage account name from the configuration file:

protected void Page_Load(object sender, EventArgs e)
{
if (this.IsPostBack == false)
{
    CloudStorageAccount.SetConfigurationSettingPublisher(
    (configName, configSetter) =>
    {
        configSetter(RoleEnvironment.GetConfigurationSettingValue(configName));
    });
    ListandDisplyBlobs();
}
}

Write the following code on the on the ‘btnUpload’ click event which will read the storage account and get the container reference associated with the Storage account using a Session object. The code creates the CloubBlob object using the GetBlobReference method of the CloudBlobContainer object, by passing posted file name to it.

The most important thing you need to keep in mind is about the Blob Content type - it is used while processing the file after or during upload. To do this, we need to specify the blob content type using the content type of the uploaded file and then this file is uploaded using UploadFromStream() method of the CloudBlob object.

/// <summary>
/// The Following Button Click Event will Upload Blob in the Container selected
/// by the User
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
protected void btnUpload_Click(object sender, EventArgs e)
{
    try
    {
        //S1: Read the Local Development Storage
        CloudStorageAccount account =
        CloudStorageAccount.FromConfigurationSetting("DataConnectionString");
        //S2: Create a Blob Client
        CloudBlobClient blobClient = account.CreateCloudBlobClient();
        //S3: Get the reference to the Container
        CloudBlobContainer container =
        blobClient.GetContainerReference(Session["ContainerName"].ToString());
        //S4:Get the Blob Reference by Reading the FileName from the File Upload Control
        var blob = container.GetBlobReference(blobFileUpload.PostedFile.FileName);

        blob.Properties.ContentType = blobFileUpload.PostedFile.ContentType;
        //S5: Upload the File as ByteArray
       // blob.UploadByteArray(blobFileUpload.FileBytes);
        blob.UploadFromStream(blobFileUpload.FileContent);

        //S6:List All Blobs
        ListandDisplyBlobs();
    }
    catch (Exception ex)
    {
        lblErrorMessage.Text = ex.Message;
    }
}

Now if we can upload the blob we can delete it also. Write the following helper method to delete the BLOB.

/// <summary>
/// The method used to Delete the selected Bolb from the Selected Container
/// </summary>
/// <param name="selBlobName"></param>
void DeleteSelectedBlob(string selBlobName)
{
    //S1: Read the Local Development Storage
    CloudStorageAccount account =
    CloudStorageAccount.FromConfigurationSetting("DataConnectionString");
    //S2: Create a Blob Client
    CloudBlobClient blobClient = account.CreateCloudBlobClient();
    //S3: Get the reference to the Container
    CloudBlobContainer container =
    blobClient.GetContainerReference(Session["ContainerName"].ToString());
    //S4:Get the Blob reference  using Name
    var blobNameToDelete = container.GetBlobReference(selBlobName);
    //S5: Delete the blob
    blobNameToDelete.Delete();
  
}

The code calls the ‘Delete()’ method of the CloudBlob class. Call this method on the RowDeleting event of the GridView as shown below:

protected void gdvBlobs_RowDeleting(object sender, GridViewDeleteEventArgs e)
{
    string blobName = gdvBlobs.Rows[e.RowIndex].Cells[2].Text;
    DeleteSelectedBlob(blobName);
    ListandDisplyBlobs();
}

Step 10: Now run the application and in the ‘Default.aspx’, select the container name from the GridView as shown below:

select-container-name

Click on the ‘Go to Upload Page’ and from the ‘Page_Upload_Blob.aspx’, click on the ‘Browse’ button of the File Upload. Select the Image file and the path will be displayed in the TextBox. Click on the ‘Upload File’ button and an Image will be uploaded and displayed in the GridView

uploaded-blob

By clicking ‘Delete’ the Blob can be deleted. Now you can see the Uploaded Blob in the Storage Explorer as shown below:

view-blob

The Blob will be displayed as shown below:

blob-list

Deployment of the Cloud Application using Windows Azure Portal

To deploy the application, you need to have an Azure subscription. You need to visit the Azure portal for one at www.azure.com

Step 12: Login to the portal using your Live-ID. This is a nice looking Silverlight UI application. Using this UI, you can create a Storage Account, New Hosted Service and can even deploy your application.

Here’s a snapshot of what the Portal looks like:

azure-portal

Click on the ‘Hosted Services, Storage Account and CDN’. You will get the following information:

storage-account-subscription

The above UI shows the status of your subscription. It also shows the number of services already hosted and Storage Accounts. (In my case I already have one Hosted Service and Storage Account.)

Click on the ‘Storage Account’ on the Left Pane and Select ‘New Storage Account’ from the Ribbon. You will see a window where you can create a Storage Account.

new-storage-account

After clicking OK, you will find the Storage Account Created as shown below:

storage-account-created

For the actual application deployment, you need to modify the ‘ServiceConfiguration.Cloud.cscfg’ as shown below:

<?xml version="1.0" encoding="utf-8"?>
<ServiceConfiguration serviceName="Mah_BlobApplication"
xmlns=http://schemas.microsoft.com/ServiceHosting/2008/10/ServiceConfiguration”
osFamily="1" osVersion="*">
  <Role name="MyWebRole">
    <Instances count="1" />
    <ConfigurationSettings>
      <Setting name="Microsoft.WindowsAzure.Plugins.Diagnostics.ConnectionString"
      value="UseDevelopmentStorage=true" />
      <Setting name="DataConnectionString" value="DefaultEndpointsProtocol=http;
      AccountName=<YOUR_STORAGE_ACCOUNT_NAME>;AccountKey=<YOUR_ACCOUNT_KEY>" />
    </ConfigurationSettings>
  </Role>
</ServiceConfiguration>

In the XML file shown above, the Storage Account is the name that you have created on the Windows Azure Portal.  All your storage services will be managed by this name. The account key provides access for the Storage.

You need to package the application for cloud deployment as below:

package-deployment

After clicking on the ‘Package’ button, you will get a ‘Service Package File’ and ‘Cloud Configuration File’. You need these files while deploying an application using the Cloud Portal.

Go back to the portal and select ‘Hosted Service’ from the left panel, and select ‘New Hosted Service’. A windows appears where you need to enter the following information:

new-hosted-service

You need to enter the Name of the service, select URL prefix and select the region for deployment. In the ‘Package Location’ section, select the Browse button, select the package files created above and then click on Ok. You will get a Warning Window. just Ignore it by clicking on ‘Yes’. You will find the application deployment progress as shown below:

deployment-stage-one

Finally your application is deployed

app-deployment

You can copy on the DNS name link and paste it in the browser. Your application will be running as explained in Step 10.

Conclusion: The Blob storage service provided by Windows Azure provides more manageable, scalable, high available mechanisms for managing BLOB data required by an application.

Give a +1 to this article if you think it was well written. Thanks!
Recommended Articles


Page copy protected against web site content infringement by Copyscape


User Feedback
Comment posted by Jeremy on Friday, May 18, 2012 7:53 AM
Thanks for explaining it so well!
Comment posted by Gaurav Singh on Friday, August 31, 2012 8:41 AM
Can you give me source code or some idea for getting diagnostic data  of window azure hosting application  by web service and save in other window azure storage for generating SSRS Report
Comment posted by Deepti on Monday, October 29, 2012 2:52 PM
Mahesh Sir, Nice article.
Comment posted by Medha on Wednesday, January 30, 2013 2:57 AM
Hi,, I run the same code, but it is giving error as external component throws an exception..

I am not getting how to solve it...

Thanks...
Comment posted by Jorge Rivera on Friday, March 8, 2013 7:07 PM
Nice article!  It has been of big help in developing my blob maintenance aspx page.

I think you just missed one step: how to download a specific blob file.  I will make my research about that.

Again, thanks for sharing your knowledge.

Post your comment
Name:  
E-mail: (Will not be displayed)
Comment:
Insert Cancel