In this post, you will create the UI that enables the user to perform read, write operations on the GuestBookEntry table. You will update the web role project generated when you created the Windows Azure service. Specifically, you will perform the following tasks:
Happy Holidays
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="GuestBook_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 id="Head1" runat="server"> <title>Windows Azure Guestbook</title> <link href="main.css" rel="stylesheet" type="text/css" /> </head> <body> <form id="form1" runat="server"> <asp:ScriptManager ID="ScriptManager1" runat="server"> </asp:ScriptManager> <div class="general"> <div class="title"> <h1> Windows Azure GuestBook </h1> </div> <div class="inputSection"> <dl> <dt> <label for="NameLabel">Name:</label></dt> <dd> <asp:TextBox ID="NameTextBox" runat="server" CssClass="field"/> <asp:RequiredFieldValidator ID="NameRequiredValidator" runat="server" ControlToValidate="NameTextBox" Text="*" /> </dd> <dt> <label for="MessageLabel">Message:</label> </dt> <dd> <asp:TextBox ID="MessageTextBox" runat="server" TextMode="MultiLine" CssClass="field" /> <asp:RequiredFieldValidator ID="MessageRequiredValidator" runat="server" ControlToValidate="MessageTextBox" Text="*" /> </dd> <dt> <label for="FileUpload1">Photo:</label></dt> <dd> <asp:FileUpload ID="FileUpload1" runat="server" size="16" /> <asp:RequiredFieldValidator ID="PhotoRequiredValidator" runat="server" ControlToValidate="FileUpload1" Text="*" /> <asp:RegularExpressionValidator ID="PhotoRegularExpressionValidator" runat="server" ControlToValidate="FileUpload1" ErrorMessage="Only .jpg or .png files are allowed" ValidationExpression="([a-zA-Z\\].*(.jpg|.JPG|.png|.PNG)$)" /> </dd> </dl> <div class="inputSignSection"> <asp:ImageButton ID="SignButton" runat="server" AlternateText="Sign GuestBook" onclick="SignButton_Click" ImageUrl="~/sign.png" ImageAlign="Bottom" /> </div> </div> <asp:UpdatePanel ID="UpdatePanel1" runat="server"> <ContentTemplate> <asp:DataList ID="DataList1" runat="server" DataSourceID="ObjectDataSource1"> <ItemTemplate> <div class="signature"> <div class="signatureImage"> <a href="<%# Eval("PhotoUrl") %>" target="_blank"> <img src="<%# Eval("ThumbnailUrl") %>" alt="<%# Eval("GuestName") %>" /> </a> </div> <div class="signatureDescription"> <div class="signatureName"> <%# Eval("GuestName") %> </div> <div class="signatureSays"> says </div> <div class="signatureDate"> <%#((DateTime)Eval("Timestamp")).ToShortDateString() %> </div> <div class="signatureMessage"> "<%# Eval("Message") %>" </div> </div> </div> </ItemTemplate> </asp:DataList> <asp:Timer ID="Timer1" runat="server" Interval="15000" OnTick="Timer1_Tick"> </asp:Timer> </ContentTemplate> </asp:UpdatePanel> <asp:ObjectDataSource ID="ObjectDataSource1" runat="server" DataObjectTypeName="GuestBook_Data.GuestBookEntry" InsertMethod="AddGuestBookEntry" SelectMethod="Select" TypeName="GuestBook_Data.GuestBookEntryDataSource"> </asp:ObjectDataSource> </div> </form> </body> </html>
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="GuestBook_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 id="Head1" runat="server"> <title>Windows Azure Guestbook</title> <link href="main.css" rel="stylesheet" type="text/css" /> </head> <body> <form id="form1" runat="server"> <asp:ScriptManager ID="ScriptManager1" runat="server"> </asp:ScriptManager> <div class="general"> <div class="title"> <h1> Windows Azure GuestBook </h1> </div> <div class="inputSection"> <dl> <dt> <label for="NameLabel">Name:</label></dt> <dd> <asp:TextBox ID="NameTextBox" runat="server" CssClass="field"/> <asp:RequiredFieldValidator ID="NameRequiredValidator" runat="server" ControlToValidate="NameTextBox" Text="*" /> </dd> <dt> <label for="MessageLabel">Message:</label> </dt> <dd> <asp:TextBox ID="MessageTextBox" runat="server" TextMode="MultiLine" CssClass="field" /> <asp:RequiredFieldValidator ID="MessageRequiredValidator" runat="server" ControlToValidate="MessageTextBox" Text="*" /> </dd> <dt> <label for="FileUpload1">Photo:</label></dt> <dd> <asp:FileUpload ID="FileUpload1" runat="server" size="16" /> <asp:RequiredFieldValidator ID="PhotoRequiredValidator" runat="server" ControlToValidate="FileUpload1" Text="*" /> <asp:RegularExpressionValidator ID="PhotoRegularExpressionValidator" runat="server" ControlToValidate="FileUpload1" ErrorMessage="Only .jpg or .png files are allowed" ValidationExpression="([a-zA-Z\\].*(.jpg|.JPG|.png|.PNG)$)" /> </dd> </dl> <div class="inputSignSection"> <asp:ImageButton ID="SignButton" runat="server" AlternateText="Sign GuestBook" onclick="SignButton_Click" ImageUrl="~/sign.png" ImageAlign="Bottom" /> </div> </div> <asp:UpdatePanel ID="UpdatePanel1" runat="server"> <ContentTemplate> <asp:DataList ID="DataList1" runat="server" DataSourceID="ObjectDataSource1"> <ItemTemplate> <div class="signature"> <div class="signatureImage"> <a href="<%# Eval("PhotoUrl") %>" target="_blank"> <img src="<%# Eval("ThumbnailUrl") %>" alt="<%# Eval("GuestName") %>" /> </a> </div> <div class="signatureDescription"> <div class="signatureName"> <%# Eval("GuestName") %> </div> <div class="signatureSays"> says </div> <div class="signatureDate"> <%#((DateTime)Eval("Timestamp")).ToShortDateString() %> </div> <div class="signatureMessage"> "<%# Eval("Message") %>" </div> </div> </div> </ItemTemplate> </asp:DataList> <asp:Timer ID="Timer1" runat="server" Interval="15000" OnTick="Timer1_Tick"> </asp:Timer> </ContentTemplate> </asp:UpdatePanel> <asp:ObjectDataSource ID="ObjectDataSource1" runat="server" DataObjectTypeName="GuestBook_Data.GuestBookEntry" InsertMethod="AddGuestBookEntry" SelectMethod="Select" TypeName="GuestBook_Data.GuestBookEntryDataSource"> </asp:ObjectDataSource> </div> </form> </body>
</html>
To allow the user to enter guest information and store the entry in Table Storage and the related image in the Blob Storage, you must execute the following steps.
using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.UI; using System.Web.UI.WebControls; using System.Net; using GuestBook_Data; using Microsoft.WindowsAzure; using Microsoft.WindowsAzure.ServiceRuntime; using Microsoft.WindowsAzure.StorageClient; using System.Text; namespace GuestBook_WebRole { public partial class _Default : System.Web.UI.Page { private static bool storageInitialized = false; private static object gate = new Object(); private static CloudBlobClient blobStorage; private static CloudQueueClient queueStorage; protected void Page_Load(object sender, EventArgs e) { if (!Page.IsPostBack) { Timer1.Enabled = true; } } protected void SignButton_Click(object sender, EventArgs e) { if (FileUpload1.HasFile) { InitializeStorage(); // upload the image to blob storage CloudBlobContainer container = blobStorage.GetContainerReference("guestbookpics"); string uniqueBlobName = string.Format("image_{0}.jpg", Guid.NewGuid().ToString()); CloudBlockBlob blob = container.GetBlockBlobReference(uniqueBlobName); blob.Properties.ContentType = FileUpload1.PostedFile.ContentType; blob.UploadFromStream(FileUpload1.FileContent); System.Diagnostics.Trace.TraceInformation( "Uploaded image '{0}' to blob storage as '{1}'", FileUpload1.FileName, uniqueBlobName); // create a new entry in table storage GuestBookEntry entry = new GuestBookEntry() { GuestName = NameTextBox.Text, Message = MessageTextBox.Text, PhotoUrl = blob.Uri.ToString(), ThumbnailUrl = blob.Uri.ToString() }; GuestBookEntryDataSource ds = new GuestBookEntryDataSource(); ds.AddGuestBookEntry(entry); System.Diagnostics.Trace.TraceInformation( "Added entry {0}-{1} in table storage for guest '{2}'", entry.PartitionKey, entry.RowKey, entry.GuestName); // queue a message to process the image var queue = queueStorage.GetQueueReference("guestthumbs"); var message = new CloudQueueMessage(String.Format("{0},{1},{2}", uniqueBlobName, entry.PartitionKey, entry.RowKey)); queue.AddMessage(message); System.Diagnostics.Trace.TraceInformation( "Queued message to process blob '{0}'", uniqueBlobName); } NameTextBox.Text = ""; MessageTextBox.Text = ""; DataList1.DataBind(); } protected void Timer1_Tick(object sender, EventArgs e) { DataList1.DataBind(); } private void InitializeStorage() { if (storageInitialized) { return; } lock (gate) { if (storageInitialized) { return; } try { // Create a new instance of a CloudStorageAccount object from a specified configuration setting. // This method may be called only after the SetConfigurationSettingPublisher // method has been called to configure the global configuration setting publisher. // You can call the SetConfigurationSettingPublisher method in the OnStart method // of the web role or in the Application_Start method in the Global.asax.cs file. // If you do not do this, the system raises an exception var storageAccount = CloudStorageAccount.FromConfigurationSetting("DataConnectionString"); // create blob container for images blobStorage = storageAccount.CreateCloudBlobClient(); CloudBlobContainer container = blobStorage.GetContainerReference("guestbookpics"); container.CreateIfNotExist(); // configure container for public access var permissions = container.GetPermissions(); permissions.PublicAccess = BlobContainerPublicAccessType.Container; container.SetPermissions(permissions); // create queue to communicate with worker role queueStorage = storageAccount.CreateCloudQueueClient(); CloudQueue queue = queueStorage.GetQueueReference("guestthumbs"); queue.CreateIfNotExist(); } catch (WebException) { StringBuilder buffer = new StringBuilder(); buffer.Append("Storage services initialization failure."); buffer.Append(" Check your storage account configuration settings."); buffer.Append(" If running locally,"); buffer.Append(" ensure that the Development Storage service is running."); throw new WebException(buffer.ToString()); } storageInitialized = true; } } } }
using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.UI; using System.Web.UI.WebControls; using System.Net; using GuestBook_Data; using Microsoft.WindowsAzure; using Microsoft.WindowsAzure.ServiceRuntime; using Microsoft.WindowsAzure.StorageClient; using System.Text; namespace GuestBook_WebRole { public partial class _Default : System.Web.UI.Page { private static bool storageInitialized = false; private static object gate = new Object(); private static CloudBlobClient blobStorage; private static CloudQueueClient queueStorage; protected void Page_Load(object sender, EventArgs e) { if (!Page.IsPostBack) { Timer1.Enabled = true; } } protected void SignButton_Click(object sender, EventArgs e) { if (FileUpload1.HasFile) { InitializeStorage(); // upload the image to blob storage CloudBlobContainer container = blobStorage.GetContainerReference("guestbookpics"); string uniqueBlobName = string.Format("image_{0}.jpg",
Guid.NewGuid().ToString()); CloudBlockBlob blob = container.GetBlockBlobReference(uniqueBlobName); blob.Properties.ContentType = FileUpload1.PostedFile.ContentType; blob.UploadFromStream(FileUpload1.FileContent); System.Diagnostics.Trace.TraceInformation( "Uploaded image '{0}' to blob storage as '{1}'", FileUpload1.FileName, uniqueBlobName); // create a new entry in table storage GuestBookEntry entry = new GuestBookEntry() { GuestName = NameTextBox.Text, Message = MessageTextBox.Text, PhotoUrl = blob.Uri.ToString(), ThumbnailUrl = blob.Uri.ToString() }; GuestBookEntryDataSource ds = new GuestBookEntryDataSource(); ds.AddGuestBookEntry(entry); System.Diagnostics.Trace.TraceInformation( "Added entry {0}-{1} in table storage for guest '{2}'", entry.PartitionKey, entry.RowKey, entry.GuestName); // queue a message to process the image var queue = queueStorage.GetQueueReference("guestthumbs"); var message = new CloudQueueMessage(String.Format("{0},{1},{2}", uniqueBlobName, entry.PartitionKey, entry.RowKey)); queue.AddMessage(message); System.Diagnostics.Trace.TraceInformation( "Queued message to process blob '{0}'", uniqueBlobName); } NameTextBox.Text = ""; MessageTextBox.Text = ""; DataList1.DataBind(); } protected void Timer1_Tick(object sender, EventArgs e) { DataList1.DataBind(); } private void InitializeStorage() { if (storageInitialized) { return; } lock (gate) { if (storageInitialized) { return; } try { // Create a new instance of a CloudStorageAccount object from a specified configuration setting. // This method may be called only after the SetConfigurationSettingPublisher // method has been called to configure the global configuration setting publisher. // You can call the SetConfigurationSettingPublisher method in the OnStart method // of the web role or in the Application_Start method in the Global.asax.cs file. // If you do not do this, the system raises an exception var storageAccount = CloudStorageAccount.FromConfigurationSetting("DataConnectionString"); // create blob container for images blobStorage = storageAccount.CreateCloudBlobClient(); CloudBlobContainer container = blobStorage.GetContainerReference("guestbookpics"); container.CreateIfNotExist(); // configure container for public access var permissions = container.GetPermissions(); permissions.PublicAccess = BlobContainerPublicAccessType.Container; container.SetPermissions(permissions); // create queue to communicate with worker role queueStorage = storageAccount.CreateCloudQueueClient(); CloudQueue queue = queueStorage.GetQueueReference("guestthumbs"); queue.CreateIfNotExist(); } catch (WebException) { StringBuilder buffer = new StringBuilder(); buffer.Append("Storage services initialization failure."); buffer.Append(" Check your storage account configuration settings."); buffer.Append(" If running locally,"); buffer.Append(" ensure that the Development Storage service is running."); throw new WebException(buffer.ToString()); } storageInitialized = true; } } } }
In order for the web role to use the Windows Azure storage services, you must provide account settings as shown next.
Figure 6 Configuring Storage Account For Web Role
A storage account is a unique end- point for Windows Azure blob, queue and table services. You must create a storage account to use these services. For more information, see Windows Azure Platform.
This walkthrough uses the development storage included in the Windows Azure SDK development environment to simulate blob, queue, and table services available in the cloud. Windows Azure by default uses SQL Server Express to simulate these services. You can also use a local instance of the SQL Server. To do so you must define the connection string that the development storage can use to connect to the server. For more information, see Using Windows Azure Development Environment Essentials.
To use the development storage, you set the value of the UseDevelopmentStorage keyword in the connection string for the storage account to true. When you deploy your application to Windows Azure, you need to update the connection string to specify storage account settings including your account name and shared key. For example, <Setting name="DataConnectionString" value="DefaultEndpointsProtocol=https;AccountName=YourAccountName;AccountKey=YourAccountKey" />
For related topics, see the following posts.
Question, where is the .css file coming from? I don't see a download or anything.