Good afternoon, dear colleagues.
The first five parts of the cycle are available
here . In this part of the series, we will look at how to migrate our simple website to Cloud Services (ex-Hosted Services) using a simple application that will use the WIndows Azure role model, the Windows Azure Service Bus, and storage services.
Let's consider the following scenario: you have already deployed your web site (for example, a standard ASP.NET MVC 4 web site, which will be further considered) on Windows Azure Web Sites, but after some time you discovered that additional web sites are required functionality - it is necessary that the user can go to your website and upload images to their own gallery. We implement such a scenario with the help of one website functionality, however, the list of requirements also includes the condition of flexible scalability of your website. In the event that you use only Windows Azure Web Sites, you can scale your website only as a whole, which is an inefficient solution - most likely, the main burden will be on image handlers rather than on the user web interface. Migrating the website to Cloud Services and rethinking the architecture based on the Windows Azure Cloud Services role model, as well as using Windows Azure Blob Storage and Service Bus Queues will help create an effective implementation of such a scenario. In this part of the loop, you will create a cloud application, which will consist of two layers:
')
1) Web interface implemented as a web role. On the main page of the application, the user will be able to upload images, as well as view already downloaded images. After the image is loaded, the web role will send the image to the blob storage in the blob container, whose name will be preset to simplify the task, then put the message consisting of a link to the image blob into the Service Bus queue.
2) An image processor implemented as a Worker role. The handler in the infinite loop will poll the Service Bus queue for messages from the Web role, and if there is a message in the queue, pick it up, receive a link to the blob with the image, then use the copy-source blob mechanism to create a new blob with with the same image and put it in the blob storage.
Setup of Cloud Services on the Windows Azure platform
Open
http://windows.azure.com in your web browser and log in using your Windows Live ID, which has a Windows Azure account associated with it.
Create a new storage account in which the application data will be stored. In the Windows Azure menu, click
New Storage Account . In the
Create a New Storage Account dialog box that appears, select your subscription in the
Choose a subscription drop-down list. In the
Enter a URL text box, type the name of your storage account, for example,
<yourname> gallery , where
<yourname> is a unique name. Windows Azure uses this value to create the URLs of the vault account services entry points. Select
Create or choose an affinity group and click in the
Create a new affinity group drop-down list. In the
Create a New Affinity Group dialog box, type the name of the affine group in the
Affinity Group Name text box, select a location from the drop-down list and click
OK. Back in the
Create a New Storage Account dialog box, click
Create to create a new storage account.
Wait until the end of the initialization process and update the
Storage Accounts “tree”. Notice that the Properties panel shows the
URL associated with each service in the storage account. Record the public name of the storage account — the first segment of the URL of your entry points. Click the
View button
, located next to the
Primary access key in the Properties panel. In the
View Storage Access Keys dialog box, click
Copy to Clipboard (next to
Primary Access Key) . The copied value will be needed to configure the application.
Create a computational service that will execute the code for your application: in the left pane, click
Hosted Services and click the
New Hosted Service button located in the menu. In the
Create a new Hosted Service dialog box, select your subscription from the
Choose a subscription drop-down list. Enter the service name in the
Enter a name for your service text box and enter the URL by entering the appropriate value
Enter a URL prefix for your service , for example,
<yourname> gallery , where
< yourname > should be a unique name. Windows Azure uses this value to create a URL for entry points to the service. In the
Create or choose an affinity group drop-down list, select the affine group that you created earlier for the storage account. Specify
Do not Deploy. Click
OK to create the service and wait until the initialization process is complete. Click the
Service Bus tab
, Access Control & Caching. Click the
Service Bus tab
. Click
New . In the
Create a new Service Namespace dialog box that opens, enter the name of your
Namespace (for example,
mytestservicebus) , select the location region and click
Create Namespace. . Select the created namespace and click the
View button on the
Properties panel in the
Default Key field
. Copy the
Default Issuer and
Default Key values from the
Default Key dialog box.
Deployment and storage services are configured; Service Bus namespace created.
Configuring an ASP.NET MVC 4 Application
Open Visual Studio 2012 with admin rights.
Click
New Project . Select the
Web \ ASP.NET MVC 4 Web Application template (Fig. 1). Name the project
MVC4Gallery . Select
Internet Application and uncheck the option
Create a unit test project. Click
OK. Wait for the creation of the project.
![clip_image001 [6] clip_image001[6]](http://hpcru.files.wordpress.com/2012/08/clip_image0016.png)
Fig. 1. List of web project templates in Visual Studio 2012
Right-click on the
Models directory
. Click
Add => Class. In the dialog that opens, enter
Image. cs and click
OK . Replace the contents of the
Image file
. cs to the code below.
using System; using System.Collections.Generic; using System.Linq; using System.Web; namespace MVC4Gallery.Models { public class Image { public string Title{ get; set; } public string Link{ get; set; } }}
Open the
Views \ Home \ Index file
. cshtml and replace its contents with the code below.
<header> <div class="content-wrapper"> <div class="float-left"> <p class="site-title"> - </div> </div> </header> <div id="body"> <section class="featured"> <div class="content-wrapper"> <form action="/Home/Upload" method="post" enctype="multipart/form-data"> <label for="title"> <label for="FileData"> </label> <input type="file" id="FileData" name="FileData" /><br /> <input type="submit" value="" /> </form> "": @foreach (var image in ViewData.Model) { @image.Title <br /> <img width="100" height="100" src="@image.Link" /><br /> } </div> </section> </div>
Open the file
Controllers \ HomeController. cs and replace its contents with the code below. The required dependencies and libraries will be added in the next paragraph.
using System; using System.Collections.Generic; using System.Collections.Specialized; using System.Web; using System.Web.Mvc; using Microsoft.ServiceBus.Messaging; using Microsoft.WindowsAzure; using Microsoft.WindowsAzure.StorageClient; using MVC4Gallery.Models; namespace MvcApplication1.Controllers { public class HomeController : Controller { public ActionResult Index() { List<Image> images = getBlobs("ourgallery"); return View(images); } [HttpPost] [ActionName("Upload")] public ActionResult Upload(string author, string title) { this.SendBlobToStorage(author); return RedirectToAction("Index"); } public void SendBlobToStorage(string author) { try { HttpPostedFileBase file = Request.Files[0]; CloudBlob blob = getBlobContainer("ourgallery").GetBlobReference(file.FileName); NameValueCollection metadata = new NameValueCollection(); metadata["title"] = file.FileName; blob.UploadFromStream(file.InputStream); BrokeredMessage msg = new BrokeredMessage(blob.Uri.AbsoluteUri); SendBrokeredMessageToServiceBusQueue(msg); } catch (StorageClientException e) { Console.WriteLine(" : " + e.Message); System.Environment.Exit(1); }} public List<Image> getBlobs(string author){ CloudBlobContainer container = getBlobContainer(author); List<Image> images = new List<Image>(); foreach (CloudBlob blob in container.ListBlobs()) { blob.FetchAttributes(); Image image = new Image(); image.Link = blob.Uri.AbsoluteUri; image.Title = blob.Metadata["title"]; images.Add(image); } return images; } public static CloudBlobContainer getBlobContainer(string userId) { var account = CloudStorageAccount.FromConfigurationSetting("storageaccount"); CloudBlobContainer container = account.CreateCloudBlobClient().GetContainerReference(userId); container.CreateIfNotExist(); var permissions = container.GetPermissions(); permissions.PublicAccess = BlobContainerPublicAccessType.Container; container.SetPermissions(permissions); return container; } public static void SendBrokeredMessageToServiceBusQueue(BrokeredMessage msg) { QueueDescription qd = new QueueDescription("servicebustest"); qd.MaxSizeInMegabytes = 5120; qd.DefaultMessageTimeToLive = new TimeSpan(0, 1, 0); string connectionString = CloudConfigurationManager.GetSetting("Microsoft.ServiceBus.ConnectionString"); QueueClient Client = QueueClient.CreateFromConnectionString(connectionString, "servicebustest"); Client.Send(msg); }}}
Right-click on the
References directory
. Select
Add Reference . In the dialog that opens (pic. 3), select the following assemblies:
Microsoft.WindowsAzure.StorageClient 1.7.0.0Microsoft.WindowsAzure.Configuration 1.7.0.0Microsoft.WindowsAzure.ServiceRuntime 1.7.0.0Microsoft.ServiceBus 1.7.0.0System.Runtime.Serialization 4.0.0.0![clip_image003 [4] clip_image003[4]](http://hpcru.files.wordpress.com/2012/08/clip_image0034_thumb.jpg)
Fig. 3. Selection of assemblies for the project.
Open the
Global file
. asax and add the code below to the
Application _ Start () method.
CloudStorageAccount.SetConfigurationSettingPublisher((configName, configSettingPublisher) => { var connectionString = RoleEnvironment.GetConfigurationSettingValue(configName); configSettingPublisher(connectionString); });
Right click on the project
. Select
Add Windows Azure Cloud Service Project (Figure 4).
![clip_image005 [4] clip_image005[4]](http://hpcru.files.wordpress.com/2012/08/clip_image0054_thumb.jpg)
Fig. 4. Add a cloud project to the solution
Right-click on
Roles in the created
MVC 4 Gallery project
. Azure . Select
Add . Click the
New Worker Role Project (Figure 5).
![clip_image006 [4] clip_image006[4]](http://hpcru.files.wordpress.com/2012/08/clip_image0064_thumb.png)
Fig. 5. Adding a project for the Worker role to the solution
In
Windows Azure Tools 1.7 , a new Worker-role template has been added, already configured to use the
Service Bus. In the
Add New Role Project window, select
Worker Role with Service Bus Queue and click
Add (Figure 6).
![clip_image008 [4] clip_image008[4]](https://habrastorage.org/getpro/habr/post_images/60f/7a1/e77/60f7a1e77f0857088da1fcb08b5800b0.jpg)
Fig. 6. Adding a Worker Role Project Configured to Use Service Bus Queue
Open the
WorkerRole.cs file and replace its contents with the code below.
using System; using System.Collections.Specialized; using System.Diagnostics; using System.Net; using System.Threading; using Microsoft.ServiceBus; using Microsoft.ServiceBus.Messaging; using Microsoft.WindowsAzure; using Microsoft.WindowsAzure.ServiceRuntime; using Microsoft.WindowsAzure.StorageClient; namespace WorkerRoleWithSBQueue1 { public class WorkerRole : RoleEntryPoint {
Add the
WebRole.cs file to the
MVC4Gallery project and replace its contents with the code below.
using System; using System.Collections.Generic; using System.Linq; using Microsoft.WindowsAzure; using Microsoft.WindowsAzure.Diagnostics; using Microsoft.WindowsAzure.ServiceRuntime; using Microsoft.WindowsAzure.StorageClient; namespace MVC4Gallery { public class WebRole : RoleEntryPoint { public override bool OnStart() { RoleEnvironment.Changing += RoleEnvironmentChanging; return base.OnStart(); } private void RoleEnvironmentChanging(object sender, RoleEnvironmentChangingEventArgs e) { if (e.Changes.Any(change => change is RoleEnvironmentConfigurationSettingChange)) { e.Cancel = true; }}}}
Double-click with the right mouse button on the
MVC 4 Gallery in the
Roles cloud project in order to open the graphical user interface of the web-role (Fig. 7).
![clip_image010 [4] clip_image010[4]](http://hpcru.files.wordpress.com/2012/08/clip_image0104_thumb.jpg)
Fig. 7. Graphical Web Role Management Interface
On the
Configuration tab, uncheck the
Enable Diagnostics option
. Go to the
Settings tab, click
Add Setting and create a new configuration setting named
storageaccount . Specify its type as a Connection String, then click on the button with the ellipsis and configure the connection string. The required data was recorded in
Part 1. Click
Add Setting and enter the name
Microsoft.ServiceBus.ConnectionString (type -
String) , and then insert the following line in the
Value field:
Endpoint = sb: // [namespacename] .servicebus.windows.net; SharedSecretIssuer = owner; SharedSecretValue = [DefaultKey]
Where is the namespace name for the
Endpoint part
, Default Issuer for
SharedSecretIssuer and
Default Key for
SharedSecretValue . Click
OK. Double-right-click on
WorkerRoleWithSBQueue 1 in the
Roles cloud project to open the Worker-role graphical user interface.
On the
Configuration tab, uncheck the
Enable Diagnostics option
. Go to the
Settings tab, click
Add Setting and create a new configuration setting named
storageaccount . Specify its type as a Connection String, then click on the button with the ellipsis and configure the connection string. The required data was recorded in
Part 1. Click
OK. Paste the required values into the connection string to customize the
Microsoft.ServiceBus.ConnectionString. The required data was recorded in
Part 1 - the name of the namespace for the
Endpoint part
, Default Issuer for
SharedSecretIssuer and
Default Key for
SharedSecretValue . Save the changes and close the GUI for managing the Worker role.
Run the project by pressing
F5. The project will start in the local compute emulator and launch the browser with the
Home / Index view
.Select an image and click
Save . After loading the image, the page will refresh. Please note that at the moment only one image is shown - the one that you downloaded. After a while (just a few seconds is enough) refresh the page - it will take the image handler to interrogate the queue, receive a message from the web role, load a blob, create a copy of it and put a new blob in the repository.
Deploying an ASP.NET MVC 4 application to Windows Azure platform in Cloud Services from Visual Studio 2012
In order to deploy the application to Cloud Services on the Windows Azure platform, you need to adjust the publishing functionality in Visual Studio 2012 accordingly.
Right-click on the
MVC 4 Gallery cloud project
. Azure. Click
Publish . In the dialog that opens, expand the list under
Choose your subscription and select
<Manage ...> (fig. 12).
![clip_image012 [4] clip_image012[4]](http://hpcru.files.wordpress.com/2012/08/clip_image0124_thumb.jpg)
Fig. 12.
In the
Windows Azure Cloud Service Project Management dialog that opens, click
New. Enter any convenient name for the new certificate that will be used to deploy the application. Click
Ok Click the
Copy the full path link
. Navigate to the Windows Azure Management Portal. Click the
Hosted Services, Storage Accounts & CDN tab
. . Click on the
Management Certificates tab
. . On the
Management Certificates tab, click
Add Certificate . In the
Add New Management Certificate dialog box that opens, click
Browse and paste the path to the certificate from the Visual Studio to the
File Name field. Click
Open. Click
Ok. Go to the
Hosted Services tab and copy the
Subscription ID from the
Properties panel. Go to Visual Studio 2012. Paste the copied subscription ID into the appropriate field (Figure 13). Click
OK .
![clip_image014 [4] clip_image014[4]](http://hpcru.files.wordpress.com/2012/08/clip_image0144_thumb.jpg)
Fig. 13.
Click
Close . Click
Next. On the
Windows Azure Publish Settings page
, you can configure advanced deployment options. Click
Publish. You can observe the deployment process in the
Windows Azure Activity Log view (Figure 14).
![clip_image016 [4] clip_image016[4]](https://habrastorage.org/getpro/habr/post_images/24a/b4f/79c/24ab4f79c37e9c3c3ab8d7235c4efcee.jpg)
Fig. 14. Presentation of Windows Azure Activity Log
Go to the Windows Azure Management Portal to the
Hosted Services tab
. Select the deployed application and click the link in the
DNS Name field on the
Properties panel to go to the website (Fig. 15).

Fig. 15. Windows Azure Management Portal
Note that the site looks the same as after deploying it to a local computing emulator. This is due to the fact that in both cases the real storage of Windows Azure is used. Add a new image and observe the result.