Porting our MVC app to Azure - Adding Table storage

Posted on 12/27/2011 @ 2:47 AM in #Azure by | Feedback | 1362 views

This blogpost is part of a series on “Writing an Azure application and integrating it with SharePoint Securely”.

Table of Contents -

  1. Writing a simple MVC app
  2. Porting our MVC app to Azure – adding table storage. <—You are here!
  3. Adding a worker role
  4. Deploying the application to Azure
  5. Integrating this Azure application with SharePoint

In the previous article, I demonstrated writing a very simple MVC app. Now lets move that app into Azure, and start using concepts such as Azure Table storage etc.

Continuing with the previous application, let’s port this application to Azure.

Making our application “Azure friendly” is quite easy! This is quite easy! Right click on the “ComplaintBox” project, and choose “Add Windows Azure Deployment Project”. This will add a project called “ComplaintBox.Azure” and do everything you need to do, to deploy the project to atleast your local development fabric.

Now, running it is quite easy! Just press F5. You would see that the application is basically the same, except now it is running in Azure dev fabric, not in Cassini.

Note that you are running an Azure application now, locally, disconnected from the internet! Deploying this in real Azure needs just a couple of more steps – but before we do that, let’s enhance our application so it stores data in table storage.

In the “ComplaintBox” MVC project, add references to,

- Microsoft.WindowsAzure.ServiceRuntime

- Microsoft.WindowsAzure.StorageClient

- System.Data.Services.Client

Now, in the HomeController, enhance the HttpPost Index method to the following,

  1:         [HttpPost]
  2:         public ViewResult Index(Complaint complaint)
  3:         {
  4:             CloudStorageAccount storageAccount = CloudStorageAccount.FromConfigurationSetting("DataConnectionString");
  5:             CloudTableClient.CreateTablesFromModel(
  6:                 typeof(ComplaintContext),
  7:                 storageAccount.TableEndpoint.AbsoluteUri,
  8:                 storageAccount.Credentials);
 10:             ComplaintContext context = new ComplaintContext(storageAccount.TableEndpoint.AbsoluteUri, storageAccount.Credentials);
 11:             context.RetryPolicy = RetryPolicies.Retry(3, TimeSpan.FromSeconds(1));
 13:             context.AddObject("ComplaintEntry", complaint);
 14:             context.SaveChanges();
 16:             return View("Thanks", complaint);
 17:         }

What we are doing here is, on submit we are storing the data to an Azure table. You might notice that I am using some classes, ComplaintContext in particular. Lets get to that in a second. Lets examine the “Complaint” class first. I have modified the Complaint class as follows,

  1:     public class Complaint : Microsoft.WindowsAzure.StorageClient.TableServiceEntity
  2:     {
  3:         public Complaint()
  4:         {
  5:             PartitionKey = DateTime.UtcNow.ToString("MMddyyyy");
  6:             RowKey = string.Format("{0:10}_{1}", DateTime.MaxValue.Ticks - DateTime.Now.Ticks, Guid.NewGuid());
  7:         }
  9:         public string Title { get; set; }
 10:         public string Description { get; set; }
 11:         public bool IsProcessed { get; set; }
 12:     }

I have inherited from the TableServiceEntity class because anything put inside of an Azure table must have RowKey, PartitionKey and TimeStamp, and up to 252 more properties.

Next is ComplaintContext, which is shown below,

  1: using System;
  2: using System.Collections.Generic;
  3: using System.Linq;
  4: using System.Web;
  5: using Microsoft.WindowsAzure.StorageClient;
  7: namespace ComplaintBox
  8: {
  9:     public class ComplaintContext : TableServiceContext
 10:     {
 11:         public ComplaintContext(string baseAddress, Microsoft.WindowsAzure.StorageCredentials credentials) : base(baseAddress, credentials)
 12:         { }
 14:         public IQueryable<Models.Complaint> ComplaintEntry
 15:         {
 16:             get
 17:             {
 18:                 return this.CreateQuery<Models.Complaint>("ComplaintEntry");
 19:             }
 20:         }
 21:     }
 22: }


This provides enough information to Azure to be able to create a table based on this context.

Finally, in Application_Start for global.asax, add the following code –

  1:         protected void Application_Start()
  2:         {
  3:             AreaRegistration.RegisterAllAreas();
  5:             RegisterGlobalFilters(GlobalFilters.Filters);
  6:             RegisterRoutes(RouteTable.Routes);
  8:             Microsoft.WindowsAzure.CloudStorageAccount.SetConfigurationSettingPublisher((configName, configSetter) =>
  9:             {
 10:                 configSetter(Microsoft.WindowsAzure.ServiceRuntime.RoleEnvironment.GetConfigurationSettingValue(configName));
 11:             });
 12:         }

With this in place, run your application again, and submit a complaint!

If you followed all steps correctly, you will see the following message,

How do we know if it worked? In visual studio, go to View -> Server Explorer, and look for Windows Azure Storage, and expand it till you find the “ComplaintEntry” Table. Right click on it, and choose “ViewTable” and you should see the entries as shown below.


Wow cool! Now you have a functional Azure application, albeit it’s still running on your local development machine! Now that you are accepting complaints, perhaps we should also process them! Well that’s a job for a worker role, which I will describe next.

Sound off but keep it civil:

Older comments..

On 4/10/2012 1:39:15 AM Neil Mackenzie said ..
FYI. The following is documented:

It's now recommended that you use the CreateTable or CreateTableIfNotExist method to create a table, rather than CreateTablesFromModel. It is not necessary to create a custom class that is derived from TableServiceContext in order to work with Table service data.