Exercise 2: Working with BlobsIn this exercise, you will use the Windows Azure Blob Service API to create an application that saves and retrieves image data stored as blobs in Windows Azure storage. It consists of a simple image gallery Web site that can display, upload and remove images in Windows Azure storage, and allows you to enter and display related metadata. The application uses a single container to store its image content as blobs. When you create a blob in Windows Azure, you associate a content type that specifies the format in which the API returns it and allows you to retrieve an image directly from the URL of the corresponding blob. Task 1 – Retrieving Blob Data from StorageIn this task, you will create an image gallery web page to display images retrieved from Windows Azure storage. The provided solution consists of a web site project with a single page that contains the elements required to display images and enter metadata. You will add the necessary functionality by editing the code-behind file. - Open Microsoft Visual Studio 2010 elevated as Administrator from Start | All Programs | Microsoft Visual Studio 2010 by right-clicking Microsoft Visual Studio 2010 and choosing Run as administrator.
- In the File menu, choose Open and then Project/Solution. In the Open Project dialog, browse to \Source\Ex02-WorkingWithBlobs\begin, select the folder for your preferred language and open the begin.sln file.
- Update the service definition to define the configuration settings required to access Windows Azure Table service. To do this, expand the Roles folder of the RDImageGallery project in Solution Explorer, right-click RDImageGallery_WebRole, and then select Properties.
.png)
Figure 10Setting role configuration settings - In the Settings tab, click Add Setting and create a ConnectionString type named DataConnectionString. Click the button labeled with an ellipsis and set the connection string to Use storage emulator.
.png)
Figure 11Configuring a storage connection string .png)
Figure 12Storage connection string dialog - Add another setting named ContainerName and set its value to ‘gallery’.
.png)
Figure 13Creating a setting for the container name The container name must be a valid Domain Name System (DNS) name, conforming to the following naming rules: - Must start with a letter or number, and can contain only letters, numbers, and dash(-) characters. - All letters must be lowercase. - Must be from 3 to 63 characters long. - A name cannot contain a dash next to a period. - Expand the RDImageGallery_WebRole node in Solution Explorer, then right-click Default.aspx and select View Code to open the code-behind file for the user interface of the image gallery. In the next steps, you will modify this file to add some of the required functionality.
- Make sure the following namespace directives exist at the top of the code file. They are for the utility storage classes and for the ServiceRuntime classes.
(Code Snippet – ExploringWindowsAzureStorage-Ex02-01-Namespace-CS) using Microsoft.WindowsAzure;
using Microsoft.WindowsAzure.ServiceRuntime;
using Microsoft.WindowsAzure.StorageClient;
using Microsoft.WindowsAzure.StorageClient.Protocol;
(Code Snippet – ExploringWindowsAzureStorage-Ex02-01-Namespace-VB) Imports Microsoft.WindowsAzure
Imports Microsoft.WindowsAzure.ServiceRuntime
Imports Microsoft.WindowsAzure.StorageClient
Imports Microsoft.WindowsAzure.StorageClient.Protocol
- For this lab, you need to store the blobs in a public container, so they are visible on the web to normal, anonymous users. In this step, you will ensure that the container specified in ServiceConfiguration.cscfg exists. To do this, add the following method at the bottom of the _Default class.
(Code Snippet – ExploringWindowsAzureStorage-Ex02-02-EnsureContainerExistsMethod-CS) public partial class _Default : System.Web.UI.Page { ... private void EnsureContainerExists()
{
var container = GetContainer();
container.CreateIfNotExist();
var permissions = container.GetPermissions();
permissions.PublicAccess = BlobContainerPublicAccessType.Container;
container.SetPermissions(permissions);
}
} (Code Snippet – ExploringWindowsAzureStorage-Ex02-02-EnsureContainerExistsMethod-VB) Partial Public Class _Default Inherits System.Web.UI.Page ... Private Sub EnsureContainerExists()
Dim container = GetContainer()
container.CreateIfNotExist()
Dim permissions = container.GetPermissions()
permissions.PublicAccess = BlobContainerPublicAccessType.Container
container.SetPermissions(permissions)
End Sub
End Class - Next, you create a utility method to retrieve a reference to the container created by the code in the previous step. This method will be called in almost all operations since the container is involved with all blob operations. Add a method to create the container at the bottom of the _Default class. This method uses the configuration settings you entered in earlier steps.
(Code Snippet – ExploringWindowsAzureStorage-Ex02-03-GetContainerMethod-CS) public partial class _Default : System.Web.UI.Page { ... private CloudBlobContainer GetContainer()
{
// Get a handle on account, create a blob service client and get container proxy
var account = CloudStorageAccount.FromConfigurationSetting("DataConnectionString");
var client = account.CreateCloudBlobClient();
return client.GetContainerReference(RoleEnvironment.GetConfigurationSettingValue("ContainerName"));
}
} (Code Snippet – ExploringWindowsAzureStorage-Ex02-03-GetContainerMethod-VB) Partial Public Class _Default Inherits System.Web.UI.Page ... Private Function GetContainer() As CloudBlobContainer
' Get a handle on account, create a blob service client and get container proxy
Dim account = CloudStorageAccount.FromConfigurationSetting("DataConnectionString")
Dim client = account.CreateCloudBlobClient()
Return client.GetContainerReference(RoleEnvironment.GetConfigurationSettingValue("ContainerName"))
End Function
End Class - Insert the following code (shown in bold) in the Page_Load method to initialize the container and refresh the asp:ListView control on the page that displays the images retrieved from storage.
(Code Snippet – ExploringWindowsAzureStorage-Ex02-04-PageLoadMethod-CS) public partial class _Default : System.Web.UI.Page { ... protected void Page_Load(object sender, EventArgs e) { try
{
if (!IsPostBack)
{
this.EnsureContainerExists();
}
this.RefreshGallery();
}
catch (System.Net.WebException we)
{
status.Text = "Network error: " + we.Message;
if (we.Status == System.Net.WebExceptionStatus.ConnectFailure)
{
status.Text += "<br />Please check if the blob service is running at " +
ConfigurationManager.AppSettings["storageEndpoint"];
}
}
catch (StorageException se)
{
Console.WriteLine("Storage service error: " + se.Message);
}
} ... } (Code Snippet – ExploringWindowsAzureStorage-Ex02-04-PageLoadMethod-VB) Partial Public Class _Default Inherits System.Web.UI.Page ... Protected Sub Page_Load(ByVal sender As Object, ByVal e As EventArgs) Try
If Not IsPostBack Then
Me.EnsureContainerExists()
End If
Me.RefreshGallery()
Catch we As System.Net.WebException
status.Text = "Network error: " & we.Message
If we.Status = System.Net.WebExceptionStatus.ConnectFailure Then
status.Text += "<br />Please check if the blob service is running at " & ConfigurationManager.AppSettings("storageEndpoint")
End If
Catch se As StorageException
Console.WriteLine("Storage service error: " & se.Message)
End Try
End Sub ... End Class - Add the following method at the bottom of the _Default class to bind the images control to the list of blobs available in the image gallery container. The code uses the ListBlobs method in the CloudBlobContainer object to retrieve a collection of IListBlobItem objects that contain information about each of the blobs. The imagesasp:ListView control in the page binds to these objects to display their value.
(Code Snippet – ExploringWindowsAzureStorage-Ex02-05-RefreshGalleryMethod-CS) public partial class _Default : System.Web.UI.Page { ... private void RefreshGallery()
{
images.DataSource =
this.GetContainer().ListBlobs(new BlobRequestOptions()
{
UseFlatBlobListing = true,
BlobListingDetails = BlobListingDetails.All
});
images.DataBind();
}
} (Code Snippet – ExploringWindowsAzureStorage-Ex02-05-RefreshGalleryMethod-VB) Partial Public Class _Default Inherits System.Web.UI.Page ... Private Sub RefreshGallery()
Dim options As BlobRequestOptions = New BlobRequestOptions() With
{.BlobListingDetails = BlobListingDetails.All,
.UseFlatBlobListing = True}
images.DataSource = Me.GetContainer().ListBlobs(options)
images.DataBind()
End Sub
End Class - Press F5 to build and run the application. A browser window launches and displays the contents of the image gallery. Note that at this point, the container is empty and the list view displays a “No Data Available” message. In the next task, you will implement the functionality required to store images as blobs in Windows Azure storage.
.png)
Figure 14The image gallery application displaying an empty container If you have not configured the storage settings correctly or if the storage service is not running, an error similar to the one shown below is displayed. .png)
Figure 15An error caused by an invalid Windows Azure storage configuration or a service problem - Press Shift+F5 in Visual Studio to stop debugging and delete the deployment from the compute emulator.
Task 2 – Uploading Blob Data to StorageIn this task, you add functionality to the image gallery Web page to enter metadata and upload image files to Windows Azure storage. The page contains text controls that you can use to enter descriptive metadata for the selected image. An asp:FileUpload control on the page retrieves images from disk and posts them to the page, where they are stored in blob storage. - Open the Default.aspx.cs/ Default.aspx.vb file in the Visual Studio text editor. To do this, right-click the Default.aspx file in Solution Explorer and select View Code.
- Add a method at the bottom of the page to save images and their metadata as blobs in Windows Azure storage. The method uses the GetBlobReference method in the CloudBlobContainer object to create a blob from the image data array and the metadata properties.
(Code Snippet – ExploringWindowsAzureStorage-Ex02-06-SaveImageMethod-CS) public partial class _Default : System.Web.UI.Page { ... private void SaveImage(string id, string name, string description, string tags, string fileName, string contentType, byte[] data)
{
// Create a blob in container and upload image bytes to it
var blob = this.GetContainer().GetBlobReference(name);
blob.Properties.ContentType = contentType;
// Create some metadata for this image
var metadata = new NameValueCollection();
metadata["Id"] = id;
metadata["Filename"] = fileName;
metadata["ImageName"] = String.IsNullOrEmpty(name) ? "unknown" : name;
metadata["Description"] = String.IsNullOrEmpty(description) ? "unknown" : description;
metadata["Tags"] = String.IsNullOrEmpty(tags) ? "unknown" : tags;
// Add and commit metadata to blob
blob.Metadata.Add(metadata);
blob.UploadByteArray(data);
}
} (Code Snippet – ExploringWindowsAzureStorage-Ex02-06-SaveImageMethod-VB) Partial Public Class _Default Inherits System.Web.UI.Page ... Private Sub SaveImage(ByVal id As String, ByVal name As String, ByVal description As String, ByVal tags As String, ByVal fileName As String, ByVal contentType As String, _
ByVal data As Byte())
' Create a blob in container and upload image bytes to it
Dim blob = Me.GetContainer().GetBlobReference(name)
blob.Properties.ContentType = contentType
' Create some metadata for this image
Dim metadata = New NameValueCollection()
metadata("Id") = id
metadata("Filename") = fileName
metadata("ImageName") = If([String].IsNullOrEmpty(name), "unknown", name)
metadata("Description") = If([String].IsNullOrEmpty(description), "unknown", description)
metadata("Tags") = If([String].IsNullOrEmpty(tags), "unknown", tags)
' Add and commit metadata to blob
blob.Metadata.Add(metadata)
blob.UploadByteArray(data)
End Sub
End Class - Complete the code in the event handler for the Upload Image button by inserting the code (shown in bold below) to upload_Click method.
(Code Snippet – ExploringWindowsAzureStorage-Ex02-07-UploadClickMethod-CS) public partial class _Default : System.Web.UI.Page { ... protected void upload_Click(object sender, EventArgs e) { if (imageFile.HasFile)
{
status.Text = "Inserted [" + imageFile.FileName + "] - Content Type [" + imageFile.PostedFile.ContentType + "] - Length [" + imageFile.PostedFile.ContentLength + "]";
this.SaveImage(
Guid.NewGuid().ToString(),
imageName.Text,
imageDescription.Text,
imageTags.Text,
imageFile.FileName,
imageFile.PostedFile.ContentType,
imageFile.FileBytes
);
RefreshGallery();
}
else
status.Text = "No image file";
} ... } (Code Snippet – ExploringWindowsAzureStorage-Ex02-07-UploadClickMethod-VB) Protected Sub upload_Click(ByVal sender As Object, ByVal e As EventArgs) If imageFile.HasFile Then
status.Text = (("Inserted [" & imageFile.FileName & "] - Content Type [") + imageFile.PostedFile.ContentType & "] - Length [") + imageFile.PostedFile.ContentLength.ToString() + "]"
Me.SaveImage(Guid.NewGuid().ToString(), imageName.Text, imageDescription.Text, imageTags.Text, imageFile.FileName, imageFile.PostedFile.ContentType, _
imageFile.FileBytes)
RefreshGallery()
Else
status.Text = "No image file"
End If
End Sub The code retrieves metadata from the text controls and from properties in the asp:FileUpload control on the page, which include the content type of the posted file, its file name, and the array of bytes containing the image data. It then calls the SaveImage method to store the image and its metadata to Windows Azure storage. - Press F5 to build and run the application and open the image gallery page in a browser window.
- Enter metadata in the Name, Description and Tags text boxes. To select the image file, click Browse, navigate to \Source\Assets\Images, and select one of the available images.
.png)
Figure 16Entering metadata to store with the image in blob storage - Click Upload Image to post the image to the Web application. The page refreshes and the newly added image displays in the list view. A status message shows the file name, content type and size of the uploaded file. Note that at this point, no metadata is displayed for the image. In the next task, you will implement the functionality required to retrieve and display metadata for blobs stored in Windows Azure.
.png)
Figure 17The image gallery showing the uploaded image - In Visual Studio, press Shift+F5 to stop debugging and delete the deployment from the Compute Emulator.
Task 3 – Retrieving Metadata for Blobs in StorageBlobs can have metadata attached to them. Metadata headers can be set on a request that creates a new container or blob resource, or on a request that explicitly creates a property on an existing resource. In this task, you will add functionality to the image gallery page to retrieve and display metadata associated with images stored in a Windows Azure container. - Add an event handler to retrieve metadata for each blob displayed in the list view control that displays images. To do this, go to Default.aspx, right-click View Designer, select the imagesListView control, and in the Properties Window (you may need to make it visible by right-clicking the control and choosing Properties) click the Events button. Locate the ItemDataBound event in the Data category, type OnBlobDataBound and press <Enter>. Alternatively, you may edit the ASP.NET markup directly to insert the required event handler.
.png)
Figure 18Configuring the event handler to display metadata - In the code-behind file, locate the OnBlobDataBound method and insert the following code (shown in bold) that retrieves the properties for each blob bound to the list view and creates a collection that contains name / value pairs for each metadata item found. The collection is then used as a data source for an asp:Repeater control that displays metadata for each image.
(Code Snippet – ExploringWindowsAzureStorage-Ex02-08-OnBlobDataBoundMethod-CS) protected void OnBlobDataBound(object sender, ListViewItemEventArgs e) { if (e.Item.ItemType == ListViewItemType.DataItem)
{
var metadataRepeater = e.Item.FindControl("blobMetadata") as Repeater;
var blob = ((ListViewDataItem)(e.Item)).DataItem as CloudBlob;
// If this blob is a snapshot, rename button to "Delete Snapshot"
if (blob != null)
{
if (blob.SnapshotTime.HasValue)
{
var delBtn = e.Item.FindControl("deleteBlob") as LinkButton;
if (delBtn != null)
{
delBtn.Text = "Delete Snapshot";
var snapshotRequest = BlobRequest.Get(new Uri(delBtn.CommandArgument), 0, blob.SnapshotTime.Value, null);
delBtn.CommandArgument = snapshotRequest.RequestUri.AbsoluteUri;
}
var snapshotBtn = e.Item.FindControl("SnapshotBlob") as LinkButton;
if (snapshotBtn != null) snapshotBtn.Visible = false;
}
if (metadataRepeater != null)
{
//bind to metadata
metadataRepeater.DataSource = from key in blob.Metadata.AllKeys
select new
{
Name = key,
Value = blob.Metadata[key]
};
metadataRepeater.DataBind();
}
}
}
} (Code Snippet – ExploringWindowsAzureStorage-Ex02-08-OnBlobDataBoundMethod-VB) Protected Sub OnBlobDataBound(ByVal sender As Object, ByVal e As ListViewItemEventArgs) Handles images.ItemDataBound If e.Item.ItemType = ListViewItemType.DataItem Then
Dim metadataRepeater = TryCast(e.Item.FindControl("blobMetadata"), Repeater)
Dim blob = TryCast(DirectCast((e.Item), ListViewDataItem).DataItem, CloudBlob)
' If this blob is a snapshot, rename button to "Delete Snapshot"
If blob IsNot Nothing Then
If blob.SnapshotTime.HasValue Then
Dim delBtn = TryCast(e.Item.FindControl("deleteBlob"), LinkButton)
If delBtn IsNot Nothing Then
delBtn.Text = "Delete Snapshot"
Dim snapshotRequest = BlobRequest.Get(New Uri(delBtn.CommandArgument), 0, blob.SnapshotTime.Value, Nothing)
delBtn.CommandArgument = snapshotRequest.RequestUri.AbsoluteUri
End If
Dim snapshotBtn = TryCast(e.Item.FindControl("Snapshot"), LinkButton)
If snapshotBtn IsNot Nothing Then
snapshotBtn.Visible = False
End If
End If
If metadataRepeater IsNot Nothing Then
'bind to metadata
metadataRepeater.DataSource = From key In blob.Metadata.AllKeys _
Select New With {.Name = key, .Value = blob.Metadata.Get(key)}
metadataRepeater.DataBind()
End If
End If
End If
End Sub - Press F5 to build and run the application. Note that the list view now displays the metadata for the image that was uploaded in the previous exercise.
.png)
Figure 19The image gallery showing metadata retrieved from blob storage - Press Shift+F5 to stop debugging and delete the deployment from the compute emulator.
Task 4 – Deleting Blobs from StorageIn this task, you will add functionality to the image gallery Web page to delete blobs containing image data from Windows Azure storage. - Update the image list view to add an asp:LinkButton control that is used to delete images from the gallery container. To do this, right-click Default.aspx, and select View Markup and locate the ItemTemplate for the images asp:ListView control. Uncomment the ASP.NET markup located immediately following the blobMetadata repeater control (shown bolded below).
... <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> <li>
<asp:LinkButton ID="deleteBlob"
OnClientClick="return confirm('Delete image?');"
CommandName="Delete"
CommandArgument='<%# Eval("Uri")%>'
runat="server" Text="Delete" oncommand="OnDeleteImage" />
</li>
... <li>
<asp:LinkButton ID="deleteBlob"
OnClientClick="return confirm('Delete image?');"
CommandName="Delete"
CommandArgument='<%# Eval("Uri")%>'
runat="server" Text="Delete" oncommand="OnDeleteImage" />
</li>
</ul> <img src="<%# Eval("Uri") %>" alt="<%# Eval("Uri") %>" style="float:left"/></div> ... - Add code (shown in bold) to Default.aspx.cs / Default.aspx.vb to implement the command handler for the deleteBlobasp:LinkButton control. The code verifies if a blob exists in storage and deletes it.
(Code Snippet – ExploringWindowsAzureStorage-Ex02-09-OnDeleteImageMethod-CS) public partial class _Default : System.Web.UI.Page { ... protected void OnDeleteImage(object sender, CommandEventArgs e) { try
{
if (e.CommandName == "Delete")
{
var blobUri = (string)e.CommandArgument;
var blob = this.GetContainer().GetBlobReference(blobUri);
blob.DeleteIfExists();
}
}
catch (StorageClientException se)
{
status.Text = "Storage client error: " + se.Message;
}
catch (Exception) { }
RefreshGallery();
} ... } (Code Snippet – ExploringWindowsAzureStorage-Ex02-09-OnDeleteImageMethod-VB) Partial Public Class _Default Inherits System.Web.UI.Page ... Protected Sub OnDeleteImage(ByVal sender As Object, ByVal e As CommandEventArgs) Try
If e.CommandName = "Delete" Then
Dim blobUri = DirectCast(e.CommandArgument, String)
Dim blob = Me.GetContainer().GetBlobReference(blobUri)
blob.DeleteIfExists()
End If
Catch se As StorageClientException
status.Text = "Storage client error: " & se.Message
Catch generatedExceptionName As Exception
End Try
RefreshGallery()
End Sub ... End Class - Press F5 to build and run the application.
- Upload a few more images from Assets\Images in the Source folder of the Lab and click Delete on any of the images displayed to remove the corresponding blob from storage.
.png)
Figure 20Adding and deleting image blobs from storage - Press Shift+F5 to stop debugging and delete the deployment from the Compute Emulator.
Task 5 – Copying BlobsWindows Azure Blob service has support for making copies of existing blobs. In this task, you will add functionality to the image gallery Web page to copy blobs containing image data from Windows Azure storage that you added earlier. - Update the image list view to add an asp:LinkButton control that is used to copy images from the gallery container. Open the Default.aspx page in Source mode and locate the ItemTemplate for the images asp:ListView control. Uncomment the ASP.NET markup located immediately following the delete blob link button control (shown in bold text below.)
... <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> <li> <asp:LinkButton ID="deleteBlob" OnClientClick="return confirm('Delete image?');" CommandName="Delete" CommandArgument='<%# Eval("Uri")%>' runat="server" Text="Delete" oncommand="OnDeleteImage" /> <asp:LinkButton ID="CopyBlob"
OnClientClick="return confirm('Copy image?');"
CommandName="Copy"
CommandArgument='<%# Eval("Uri")%>'
runat="server" Text="Copy" oncommand="OnCopyImage" />
... </li> </ul> <img src="<%# Eval("Uri") %>" alt="<%# Eval("Uri") %>" style="float:left"/></div> ... - Add code (shown in bold) to Default.aspx.cs / Default.aspx.vb to implement the command handler for the copyBlobasp:LinkButton control. The code creates a copy of a blob based on an existing blob. It also updates the “ImageName” attribute in its metadata to reflect that it is a copy.
(Code Snippet – ExploringWindowsAzureStorage-Ex02-10-OnCopyImageMethod-CS) public partial class _Default : System.Web.UI.Page { ... protected void OnCopyImage(object sender, CommandEventArgs e) { if (e.CommandName == "Copy")
{
// Prepare an Id for the copied blob
var newId = Guid.NewGuid();
// Get source blob
var blobUri = (string)e.CommandArgument;
var srcBlob = this.GetContainer().GetBlobReference(blobUri);
// Create new blob
var newBlob = this.GetContainer().GetBlobReference(newId.ToString());
// Copy content from source blob
newBlob.CopyFromBlob(srcBlob);
// Explicitly get metadata for new blob
newBlob.FetchAttributes(new BlobRequestOptions { BlobListingDetails = BlobListingDetails.Metadata });
// Change metadata on the new blob to reflect this is a copy via UI
newBlob.Metadata["ImageName"] = "Copy of \"" + newBlob.Metadata["ImageName"] + "\"";
newBlob.Metadata["Id"] = newId.ToString();
newBlob.SetMetadata();
// Render all blobs
RefreshGallery();
}
} ... } (Code Snippet – ExploringWindowsAzureStorage-Ex02-10-OnCopyImageMethod-VB) Partial Public Class _Default Inherits System.Web.UI.Page ... Protected Sub OnCopyImage(ByVal sender As Object, ByVal e As CommandEventArgs) If e.CommandName = "Copy" Then
' Prepare an Id for the copied blob
Dim newId = Guid.NewGuid()
' Get source blob
Dim blobUri = DirectCast(e.CommandArgument, String)
Dim srcBlob = Me.GetContainer().GetBlobReference(blobUri)
' Create new blob
Dim newBlob = Me.GetContainer().GetBlobReference(newId.ToString())
' Copy content from source blob
newBlob.CopyFromBlob(srcBlob)
' Explicitly get metadata for new blob
newBlob.FetchAttributes(New BlobRequestOptions())
' Change metadata on the new blob to reflect this is a copy via UI
newBlob.Metadata("ImageName") = "Copy of """ & newBlob.Metadata("ImageName") & """"
newBlob.Metadata("Id") = newId.ToString()
newBlob.SetMetadata()
' Render all blobs
RefreshGallery()
End If
End Sub ... End Class - Press F5 to build and run the application.
- Upload a few more images from Source\Assets\Images and click Copy on any of the images displayed to make a copy of the corresponding blob from storage.
.png)
Figure 21Copying image blobs from storage - Click OK to confirm the copy operation. You should see a copy of the image has been created with ImageName metadata stating it is a copy.
.png)
- Press Shift+F5 to stop debugging and delete the deployment from the Compute Emulator.
Task 6 – Taking Blob SnapshotsWindows Azure Blob service has support for taking snapshots of blobs. The difference between a snapshot and a copy is that snapshots are read-only and the original blob maintains a relationship to its snapshots; blob copies on the other hand are editable. Once a snapshot has been taken for a blob, this source blob can no longer be deleted. Before a source blob can be deleted, all of its snapshots must be deleted first. In this task, you add functionality to take a snapshot of a blob that contains image data from Windows Azure storage. - Update the image list view to add an asp:LinkButton control that is used to snapshot images from the gallery container. Open the Default.aspx page in Source mode and locate the ItemTemplate for the images asp:ListView control. Uncomment the ASP.NET markup located immediately following the copy blob link button control (shown in bold).
<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> <li> <asp:LinkButton ID="deleteBlob" OnClientClick="return confirm('Delete image?');" CommandName="Delete" CommandArgument='<%# Eval("Uri")%>' runat="server" Text="Delete" oncommand="OnDeleteImage" /> <asp:LinkButton ID="CopyBlob" OnClientClick="return confirm('Copy image?');" CommandName="Copy" CommandArgument='<%# Eval("Uri")%>' runat="server" Text="Copy" oncommand="OnCopyImage" /> <asp:LinkButton ID="SnapshotBlob"
OnClientClick="return confirm('Snapshot image?');"
CommandName="Snapshot"
CommandArgument='<%# Eval("Uri")%>'
runat="server" Text="Snapshot" oncommand="OnSnapshotImage" />
</li> </ul> <img src="<%# Eval("Uri") %>" alt="<%# Eval("Uri") %>" style="float:left"/></div> - Add code (shown in bold) to Default.aspx.cs / Default.aspx.vb to implement the command handler for the snapshotBlobasp:LinkButton control. The code gets the source blob and takes a snapshot of it.
(Code Snippet – ExploringWindowsAzureStorage-Ex02-11-OnSnapshotImageMethod-CS) public partial class _Default : System.Web.UI.Page { ... protected void OnSnapshotImage(object sender, CommandEventArgs e) { if (e.CommandName == "Snapshot")
{
// Get source blob
var blobUri = (string)e.CommandArgument;
var srcBlob = this.GetContainer().GetBlobReference(blobUri);
// Create a snapshot
var snapshot = srcBlob.CreateSnapshot();
status.Text = "A snapshot has been taken for image blob:" + srcBlob.Uri + " at " + snapshot.SnapshotTime;
RefreshGallery();
}
} ... } (Code Snippet – ExploringWindowsAzureStorage-Ex02-11-OnSnapshotImageMethod-VB) Partial Public Class _Default Inherits System.Web.UI.Page ... Protected Sub OnSnapshotImage(ByVal sender As Object, ByVal e As CommandEventArgs) If e.CommandName = "Snapshot" Then
' Get source blob
Dim blobUri = DirectCast(e.CommandArgument, String)
Dim srcBlob = Me.GetContainer().GetBlobReference(blobUri)
' Create a snapshot
Dim snapshot = srcBlob.CreateSnapshot()
status.Text = "A snapshot has been taken for image blob:" + srcBlob.Uri.ToString() + " at " + snapshot.SnapshotTime
RefreshGallery()
End If
End Sub ... End Class - Press F5 to build and run the application.
- Click Snapshot on any of the images displayed to take a snapshot of the corresponding blob from storage.
.png)
Figure 23Taking a snapshot of image blobs from storage - Click OK to confirm the snapshot operation. You will see a status update confirming that a snapshot has been taken.
- Attempt to delete the original blob from which the snapshot was taken.
.png)
Figure 24Cannot Delete Snapshot error - You will see a status update confirms that the blob cannot be deleted.
.png)
Figure 25Cannot Delete Snapshot error To delete a blob that contains snapshots, all of its snapshots must be deleted first. (That functionality is not provided in this solution)
| |