ASP.NET Podcast Show #132 - Windows Azure Blob Storage - video

Subscribe to All!

Subscribe to WMV.

Subscribe to M4V (iPod).

Subscribe to MP3.

Download WMV.

Download MP4 for iPod.

Download MP3 (audio only).

Win a ticket to the MDC in Detroit.  Enter here.

ASP.NET Podcast Url: http://aspnetpodcast.com/CS11/blogs/asp.net_podcast/archive/2008/12/22/asp-net-podcast-show-132-windows-azure-blob-storage-video.aspx

Show Notes:

  • Azure SDK.
    •  Vista SP1.
    • Visual studio 2008/.NET 3.5 SP1.
    • Local Development.Speed.
    • VPC.
    • Improvements are coming.
    • YMMV.
  • Project type.
    • Configuration settings.
    • Web Project.
  • Storage Client.
  • Local Development Fabric.
  • Local Development Storage.
  • Hands on Labs. This example is taken, with modifications, from the hands on labs.

Local Development Storage Setup:

Development Storage Setup

Local Development Storage:

Storage Icon

Source Code for Default.aspx.cs file:

using System;
using System.Collections;
using System.Collections.Specialized;
using System.Configuration;
using System.Data;
using System.Globalization;
using System.Linq;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Xml.Linq;
using Microsoft.ServiceHosting.ServiceRuntime;
using Microsoft.Samples.ServiceHosting.StorageClient;

namespace CloudImageService_WebRole
{
    public partial class _Default : System.Web.UI.Page
    {
        private string unknownValue = "unknown";
        protected void Page_Load(object sender, EventArgs e)
        {
            if (!Page.IsPostBack)
            {
                RefreshGallery();
            }
        }

        protected void upload_Click(object sender, EventArgs e)
        {
            if (imageFile.HasFile)
            {
                status.Text = "Inserted [" + imageFile.FileName +
                    "] - Content Type [" + imageFile.PostedFile.ContentType + "]";
                SaveImages(Guid.NewGuid().ToString(), imageName.Text, imageDescription.Text,
                    imageTags.Text, imageFile.FileName, imageFile.PostedFile.ContentType,
                    imageFile.FileBytes);
                imageTags.Text = String.Empty;
                imageDescription.Text = String.Empty;
                imageName.Text = String.Empty;
                RefreshGallery();
            }
            else{
                status.Text = "No image file uploaded.";
            }
        }

        private void SaveImages(string id, string name, string description, string tags, string fileName, string contentType, byte[] data)
        {
            BlobProperties properties = new BlobProperties(string.Format(CultureInfo.InvariantCulture, "image_{0}", id));
            NameValueCollection metadata = new NameValueCollection();
            BlobContainer container = GetContainer();
            metadata["Id"] = id;
            metadata["Filename"] = fileName;
            metadata["ImageName"] = String.IsNullOrEmpty(name) ? unknownValue : name;
            metadata["Description"] = String.IsNullOrEmpty(description) ? unknownValue : description;
            metadata["Tags"] = String.IsNullOrEmpty(tags) ? unknownValue : tags;
            properties.Metadata = metadata;
            properties.ContentType = contentType;
            BlobContents imageBlob = new BlobContents(data);
            container.CreateBlob(properties, imageBlob, true);
           
        }

        protected void OnBlobDataBound(object sender, ListViewItemEventArgs e)
        {
            BlobContainer container = GetContainer();
            if (e.Item.ItemType == ListViewItemType.DataItem)
            {
                Repeater metadataRepeater = e.Item.FindControl("blobMetadata") as Repeater;
                BlobProperties blob = ((ListViewDataItem)(e.Item)).DataItem as BlobProperties;
                NameValueCollection metadata = container.GetBlobProperties(blob.Name).Metadata;
                metadataRepeater.DataSource = from key in metadata.AllKeys
                                              select new
                                              {
                                                  Name = key,
                                                  Value = metadata[key]
                                              };
                metadataRepeater.DataBind();
            }
        }

        protected void OnDeleteImage(object sender, CommandEventArgs e)
        {
            BlobContainer container = GetContainer();
            if (e.CommandName == "Delete")
            {
                string blobName = (string)e.CommandArgument;
                if (container.DoesBlobExist(blobName))
                {
                    container.DeleteBlob(blobName);
                }
                else
                {
                    status.Text = "Item does not exist";
                }
                RefreshGallery();
            }
        }

        private void RefreshGallery()
        {
            BlobContainer container = GetContainer();
            images.DataSource = container.ListBlobs(String.Empty, false);
            images.DataBind();
        }

        /// <summary>
        /// This is code written against an early CTP.
        /// It is neither production ready or a best of breed.
        /// It is merely code that works today.
        /// </summary>
        /// <returns></returns>
        private BlobContainer GetContainer()
        {
            string blobContainer = RoleManager.GetConfigurationSetting("ContainerName");
            BlobStorage blobStorage = BlobStorage.Create(StorageAccountInfo.GetDefaultBlobStorageAccountFromConfiguration());
            BlobContainer newContainer = blobStorage.GetBlobContainer(blobContainer);
            if (!newContainer.DoesContainerExist())
            {
                newContainer.CreateContainer(null, ContainerAccessControl.Public);
            }
            return (newContainer);
        }
    }
}

Source code for Default.aspx:

 <%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="CloudImageService_WebRole._Default" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
    <title>Azure Blob Storage Engine Page</title>
        <style type="text/css">
        body { font-family: Verdana; font-size: 12px; }
        h1 { font-size:x-large; font-weight:bold; }
        h2 { font-size:large; font-weight:bold; }
        img { width:200px; height:175px; margin:2em;}
        li { list-style: none; }
        ul { padding:1em; }
        
        .form { width:50em; }
        .form li span {width:30%; float:left; font-weight:bold; }
        .form li input { width:70%; float:left; }
        .form input { float:right; }
        
        .item { font-size:smaller; font-weight:bold; }
        .item ul li { padding:0.25em; background-color:#ffeecc; }
        .item ul li span { padding:0.25em; background-color:#ffffff; display:block; font-style:italic; font-weight:normal; }
    </style>

</head>
<body>
    <form id="form1" runat="server">
    <div>
            <h1>Image Gallery (Windows Azure Blob Storage)</h1>
        <div class="form">
            <ul>
                <li><span>Name</span><asp:TextBox ID="imageName" runat="server"/></li>
                <li><span>Description</span><asp:TextBox ID="imageDescription" runat="server"/></li>
                <li><span>Tags</span><asp:TextBox ID="imageTags" runat="server"/></li>
                <li><span>Filename</span><asp:FileUpload ID="imageFile" runat="server" /></li>
            </ul>
            <asp:Button ID="upload" runat="server" onclick="upload_Click" Text="Upload Image" />
        </div>
        <div>
        Status: <asp:Label ID="status" runat="server" />
        </div>

            <asp:ListView ID="images" runat="server" OnItemDataBound="OnBlobDataBound">
            <LayoutTemplate>
                <asp:PlaceHolder ID="itemPlaceholder" runat="server" />
            </LayoutTemplate>
            <EmptyDataTemplate>
                <h2>No Data Available</h2>
            </EmptyDataTemplate>            
            <ItemTemplate>            
                <div class="item">
                    <ul style="width:40em;float:left;clear:left" >
                    <asp:Repeater ID="blobMetadata" runat="server">
                    <ItemTemplate>
                        <li><%# Eval("Name") %><span><%# Eval("Value") %></span></li>
                    </ItemTemplate>
                    </asp:Repeater>
                    <%-- UNCOMMENT THE FOLLOWING LINES FOR DELETE FUNCTIONALITY --%>
                        <li>
                        <asp:LinkButton ID="deleteBlob"
                                OnClientClick="return confirm('Delete image?');"
                                CommandName="Delete"
                                CommandArgument='<%# Eval("Name")%>'
                                runat="server" Text="Delete" oncommand="OnDeleteImage" />                
                        </li>
                    </ul>                    
                    <img src="<%# Eval("Uri") %>" alt="<%# Eval("Name") %>" style="float:left"/>
                </div>
            </ItemTemplate>
        </asp:ListView>
    </div>
    </form>
</body>
</html>

.csdef file:

<?xml version="1.0" encoding="utf-8"?>
<ServiceDefinition name="CloudImageService" xmlns="http://schemas.microsoft.com/ServiceHosting/2008/10/ServiceDefinition">
  <WebRole name="WebRole">
    <InputEndpoints>
      <!-- Must use port 80 for http and port 443 for https when running in the cloud -->
      <InputEndpoint name="HttpIn" protocol="http" port="80" />
    </InputEndpoints>
    <ConfigurationSettings>
      <Setting name="AccountName" />
      <Setting name="AccountSharedKey" />
      <Setting name="BlobStorageEndpoint" />
      <Setting name="QueueStorageEndpoint" />
      <Setting name="TableStorageEndpoint" />
      <Setting name="ContainerName" />
    </ConfigurationSettings>
  </WebRole>
</ServiceDefinition>

cscfg file:

<?xml version="1.0"?>
<ServiceConfiguration serviceName="CloudImageService" xmlns="http://schemas.microsoft.com/ServiceHosting/2008/10/ServiceConfiguration">
  <Role name="WebRole">
    <Instances count="1"/>
    <ConfigurationSettings>
        <Setting name="AccountName" value="devstoreaccount1" />
        <Setting name="AccountSharedKey" value="Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw==" />
        <Setting name="BlobStorageEndpoint" value="http://127.0.0.1:10000/" />
        <Setting name="QueueStorageEndpoint" value="http://127.0.0.1:10001/" />
        <Setting name="TableStorageEndpoint" value="http://127.0.0.1:10002/" />
        <Setting name="ContainerName" value="storagegallery" />
    </ConfigurationSettings>
  </Role>
</ServiceConfiguration>

No Comments