Building Windows Azure Cloud Services App with Web Role, Worker Role, Table Storage and Service Bus

Windows Azure Cloud Services, provides a Platform as a Service (PaaS) offering for building multi-tier, highly scalable, reliable cloud applications on the Windows Azure Cloud platform. In this blog post, I will demonstrate how to build a multi-tier Windows Azure Cloud Services application using with Web Role, Worker Role, Table Storage and Service Bus Queue. This demo application will also demonstrates the usages of Service Bus Queue, Table Storage and how to communicate between the Web Role and Worker Role.

Source Code

The source code of the demo Windows Azure Cloud Services app available on GitHub at https://github.com/shijuvar/AzureCloudServices

About the Demo App

The Cloud Services app will have two roles: a Web Role and a Worker Role. Windows Azure Service Bus Queue will be used for communicating between the Web Role and a Worker Role. Table storage is used for the persistence of data. A user can a register a Customer entity from the Web Role where a message will be send to Windows Azure Service Bus Queue. The Worker Role will be polling the Queue messages, and finally persist the data into a Windows Azure Table storage.

The following Windows Azure services will be used for the demo app:

  • Web Role
  • Worker Role
  • Windows Azure Table
  • Windows Azure Service Bus

The Web Role app is built with ASP.NET MVC 4 web application and the Worker Role uses the Worker Role with Service Bus Queue template.

The following NuGet packages for Windows Azure, have been used in this app

image

Write Command of the App

The code block below provides the entity class which represents for creating a new customer entity

   1:  public class NewCustomerCommand
   2:  {
   3:      public string FirstName { get; set; }
   4:      public string LastName { get; set; }
   5:      public string Address { get; set; }
   6:      public string Phone { get; set; }
   7:      public string Email { get; set; }
   8:  }

Read Model of the App

The code block below provides the read model of the app

   1:  public class Customer : TableEntity
   2:  {
   3:      public string Id { get; set; }
   4:      public string FirstName { get; set; }
   5:      public string LastName { get; set; }
   6:      public string Address { get; set; }
   7:      public string Phone { get; set; }
   8:      public string Email { get; set; }
   9:  }

In this demo app, Windows Azure Table storage is used for persistence and read operations will be performed against the Table storage. The Customer class represents the Windows Azure Table entity so that it is inherited from the class TableEntity.

Building the Cloud Services App with Visual Studio

Let’s create a Windows Azure Cloud Services projects from Visual Studio 2012. The Windows Azure Cloud Service project available from the Cloud  template.

image

Let’s add ASP.NET MVC 4 Web Role and Worker Role with Service Bus Queue onto the Windows Cloud service as shown in the following picture.

image

The Windows Azure Cloud Service project has the two Roles: a Web Role and a Worker Role

image

Let’s add the necessary NuGet packages to the corresponding projects. In this demo app, we are using Windows Azure Storage and Windows Azure Service Bus so that we have to add the connection string for both Windows Azure Storage and Windows Azure Service Bus. To add the connection string, right click the corresponding Role from the Roles folder of the Cloud Service project, choose properties.

image

From the properties windows, choose the settings tab, add Settings. Let’s add names StorageConnectionString and Microsoft.ServiceBus.ConnectionString for Windows Azure Storage and Service Bus. If you want to use local Storage Emulator for the development cycle, you can give the value “UseDevelopmentStorage=true” for the connection string.

image

Helpers for Table Storage and Service Bus Queue

Let’s add helper classes for Windows Azure Table and Service Bus Queue in order to working these services.

AzureStorageHelper.cs

 
   1:  public static class AzureStorageHelper
   2:  {
   3:  public static void InitializeAzureTable(string tableName)
   4:  {
   5:      CloudTable table = GetAzureTable(tableName);
   6:      //Create table if it doesn't exists
   7:      table.CreateIfNotExists();        
   8:  }
   9:   
  10:  public static CloudTable GetAzureTable(string tableName)
  11:  {
  12:      var storageAccount = Microsoft.WindowsAzure.Storage
  13:          .CloudStorageAccount.Parse(
  14:          RoleEnvironment.GetConfigurationSettingValue
  15:          ("StorageConnectionString"));
  16:      // Get table for working with tables.
  17:      var tableClient = storageAccount.CreateCloudTableClient();
  18:      CloudTable table = tableClient.GetTableReference(tableName);
  19:      return table;
  20:  }       
  21:  }

In the above code block, the method GetAzureTable returns CloudTable and the InitializeAzureTable method creates the Azure Table if it does not exists.

The code block below provides the helper class for working with Windows Azure Service Bus

ServiceBusQueueHelper.cs

   1:  public static class ServiceBusQueueHelper
   2:  {
   3:  //// Recommended that you cache QueueClient       
   4:  //// rather than recreating it on every request.
   5:  public static public static QueueClient CustomersQueueClient;
   6:  // The name of the queue
   7:  public const string QueueName = "CustomerQueue";
   8:   
   9:  public static NamespaceManager CreateNamespaceManager()
  10:  {
  11:      string connectionString =
  12:      CloudConfigurationManager.GetSetting(
  13:      "Microsoft.ServiceBus.ConnectionString");
  14:      var namespaceManager = NamespaceManager.
  15:        CreateFromConnectionString(connectionString);
  16:      return namespaceManager;
  17:  }
  18:  public static void Initialize()
  19:  {
  20:      // Using Http to be friendly with outbound firewalls
  21:      ServiceBusEnvironment.SystemConnectivity.Mode =
  22:          ConnectivityMode.Http;
  23:      string connectionString =
  24:          CloudConfigurationManager.GetSetting
  25:          ("Microsoft.ServiceBus.ConnectionString");
  26:      NamespaceManager namespaceManager = CreateNamespaceManager();
  27:      if (!(namespaceManager.QueueExists(QueueName)))
  28:      {
  29:          namespaceManager.CreateQueue(QueueName);
  30:      }
  31:   
  32:      // Initialize the connection to Service Bus Queue
  33:      CustomersQueueClient = QueueClient.
  34:          CreateFromConnectionString(connectionString, QueueName);
  35:  }
  36:  }

The code block below calls from Global.asax.cs for creating Table and initializing the Service Bus Queue.

   1:  //Create Azure Table
   2:  AzureStorageHelper.InitializeAzureTable("Customer");
   3:  //Initialize Service Bus Queue
   4:  ServiceBusQueueHelper.Initialize();

Sending Messages to Service Bus Queue in Web Role App

The web role app lets the users to create Customer entity, where a message will be send to Windows Azure Service Bus Queue and the worker role will be polling the queue messages.

The code bock below provides to send customer message to Windows Azure Service Bus Queue, from Create action method of CustomerController

   1:  [HttpPost]
   2:  public ActionResult Create(CustomerFormModel form)
   3:  {
   4:  if (ModelState.IsValid)
   5:  {
   6:      //maps to domain object from view model
   7:      var command = Mapper.Map<CustomerFormModel,
   8:          NewCustomerCommand>(form);
   9:      var message = new BrokeredMessage(command);
  10:      // Send customer message to Service Bus Queue          
  11:      ServiceBusQueueHelper.CustomersQueueClient.
  12:                       Send(message);
  13:      return RedirectToAction("Index");
  14:  }
  15:  return View(form);
  16:  }

We create the object of BrokeredMessage with the NewCustomerCommand object and send the message to Windows Azure Queue. BrokeredMessage  represents the unit of communication between Service Bus clients.

The screen shot below provides the UI for creating a new Customer

image

Receiving Messages from Service Bus Queue in Worker Role App

The Worker Role app will be polling on the Windows Azure Service Bus Queue and persist data into Table storage.

The code block below provides the implementation of Worker Role

   1:  public class WorkerRole : RoleEntryPoint
   2:  {
   3:  // The name of your queue
   4:  const string QueueName = "CustomerQueue";
   5:  public static QueueClient Client;
   6:  bool IsStopped;
   7:   
   8:  public override void Run()
   9:  {
  10:   
  11:  var storageAccount = CloudStorageAccount.Parse
  12:     (RoleEnvironment.GetConfigurationSettingValue
  13:     ("StorageConnectionString"));       
  14:   
  15:      while (!IsStopped)
  16:      {
  17:      try
  18:      {
  19:      // Receive the message
  20:      BrokeredMessage receivedMessage = null;
  21:      receivedMessage = Client.Receive();
  22:   
  23:      if (receivedMessage != null)
  24:      {
  25:      // Process the message
  26:      Trace.WriteLine("Processing", 
  27:          receivedMessage.SequenceNumber.ToString());
  28:      NewCustomerCommand command = receivedMessage.
  29:          GetBody<NewCustomerCommand>();
  30:     // Create the table client.
  31:     CloudTableClient tableClient = storageAccount.
  32:         CreateCloudTableClient();
  33:   
  34:      // Create the CloudTable object for "Customer" table.
  35:      CloudTable table = tableClient.GetTableReference("Customer");
  36:   
  37:      // Create a new customer entity.
  38:      Customer customer=new Customer{
  39:          Id=Guid.NewGuid().ToString(),
  40:          PartitionKey = command.LastName,
  41:          RowKey = command.FirstName,
  42:          FirstName=command.FirstName,
  43:          LastName=command.LastName,
  44:          Address=command.Address,
  45:          Email=command.Email,
  46:          Phone=command.Phone                                
  47:      };
  48:   
  49:      // Create the TableOperation that inserts the customer entity.
  50:      TableOperation insertOperation = TableOperation.Insert(customer);
  51:   
  52:      // Execute the insert operation.
  53:      table.Execute(insertOperation);
  54:      receivedMessage.Complete();
  55:      }
  56:    }
  57:          catch (MessagingException e)
  58:          {
  59:              if (!e.IsTransient)
  60:              {
  61:                  Trace.WriteLine(e.Message);
  62:                  throw;
  63:              }
  64:   
  65:              Thread.Sleep(10000);
  66:          }
  67:          catch (OperationCanceledException e)
  68:          {
  69:              if (!IsStopped)
  70:              {
  71:                  Trace.WriteLine(e.Message);
  72:                  throw;
  73:              }
  74:          }
  75:      }
  76:  }
  77:   
  78:  public override bool OnStart()
  79:  {
  80:      // Set the maximum number of concurrent connections 
  81:      ServicePointManager.DefaultConnectionLimit = 12;
  82:   
  83:      // Create the queue if it does not exist already
  84:      string connectionString = CloudConfigurationManager.
  85:          GetSetting("Microsoft.ServiceBus.ConnectionString");
  86:      var namespaceManager = NamespaceManager.
  87:          CreateFromConnectionString(connectionString);
  88:      if (!namespaceManager.QueueExists(QueueName))
  89:      {
  90:          namespaceManager.CreateQueue(QueueName);
  91:      }
  92:   
  93:      // Initialize the connection to Service Bus Queue
  94:      Client = QueueClient.CreateFromConnectionString
  95:          (connectionString, QueueName);
  96:      IsStopped = false;
  97:      return base.OnStart();
  98:  }
  99:   
 100:  public override void OnStop()
 101:  {
 102:      // Close the connection to Service Bus Queue
 103:      IsStopped = true;
 104:      Client.Close();
 105:      base.OnStop();
 106:  }
 107:  }

Receives Messages from Queue 

The code block below receives message from Service Bus Queue

   1:  BrokeredMessage receivedMessage = null;
   2:      receivedMessage = Client.Receive();

Process Queue Message and Insert Data to Windows Azure Table 

The code block below processes the queue message and insert data to Windows Azure Table

   1:  if (receivedMessage != null)
   2:  {
   3:  // Process the message
   4:  Trace.WriteLine("Processing", 
   5:      receivedMessage.SequenceNumber.ToString());
   6:  NewCustomerCommand command = receivedMessage.
   7:      GetBody<NewCustomerCommand>();
   8:  // Create the table client.
   9:  CloudTableClient tableClient = storageAccount.
  10:      CreateCloudTableClient();
  11:   
  12:  // Create the CloudTable object for "Customer" table.
  13:  CloudTable table = tableClient.
  14:      GetTableReference("Customer");
  15:   
  16:      // Create a new customer entity.
  17:      Customer customer=new Customer{
  18:          Id=Guid.NewGuid().ToString(),
  19:          PartitionKey = command.LastName,
  20:          RowKey = command.FirstName,
  21:          FirstName=command.FirstName,
  22:          LastName=command.LastName,
  23:          Address=command.Address,
  24:          Email=command.Email,
  25:          Phone=command.Phone                                
  26:      };
  27:   
  28:  // Create the TableOperation that inserts the customer entity.
  29:TableOperation insertOperation = TableOperation.Insert(customer);
  30:   
  31:  // Execute the insert operation.
  32:  table.Execute(insertOperation);
  33:  receivedMessage.Complete();
  34:  }

The messages in the Service Bus Queue contains the type NewCustomerCommand so that we are receiving the message from Queue as type NewCustomerCommand by using the generic type method GetBody of the BrokeredMessage class. The BrokeredMessage class represents the unit of communication between Service Bus clients. We create an instance of Customer object by copying the value of NewCustomerCommand object for insert a new Table entity. We create a TableOperation insert using the Insert method of TableOperation class and finally executes the insert operation using the execute method of CloudTable.

Reading Data from Windows Azure Table in Web Role App

The code block below provides the implementation of Index action method in the CustomerController of Web Role app.

   1:  public ActionResult Index()
   2:  {
   3:  CloudTable table = AzureStorageHelper.
   4:      GetAzureTable("Customer");         
   5:  TableQuery<Customer> query = new TableQuery<Customer>();
   6:  var customers = table.ExecuteQuery(query);
   7:  if (Request.IsAjaxRequest())
   8:  {
   9:      return PartialView("_List", customers);
  10:  }
  11:  return View(customers);
  12:  }

In the above code block, we are query the all customer data from the Windows Azure Table named Customer. We use the ExecuteQuery method of the CloudTable object for executing the query against the Table storage.

The code block below provides the complete implementation of ASP.NET MVC Controller class CustomerController, which is used for sending messages to Windows Azure Queue and reading data from Windows Azure Table Storage.

   1:  public class CustomerController : Controller
   2:  {  
   3:  public ActionResult Index()
   4:  {
   5:  CloudTable table = AzureStorageHelper.
   6:      GetAzureTable("Customer");         
   7:  TableQuery<Customer> query = new TableQuery<Customer>();
   8:  var customers = table.ExecuteQuery(query);
   9:  if (Request.IsAjaxRequest())
  10:  {
  11:      return PartialView("_List", customers);
  12:  }
  13:  return View(customers);
  14:  }
  15:  public ViewResult Create()
  16:  {
  17:      var viewModel = new CustomerFormModel();
  18:      return View(viewModel);
  19:  }
  20:  [HttpPost]
  21:  public ActionResult Create(CustomerFormModel form)
  22:  {
  23:  if (ModelState.IsValid)
  24:  {
  25:      //maps to domain object from view model
  26:      var command = Mapper.Map<CustomerFormModel,
  27:          NewCustomerCommand>(form);
  28:      var message = new BrokeredMessage(command);
  29:      // Send customer message to Service Bus Queue          
  30:      ServiceBusQueueHelper.CustomersQueueClient.Send(message);
  31:      return RedirectToAction("Index");
  32:  }
  33:  return View(form);
  34:  }
  35:  }

Source Code

The source code of the Windows Azure Cloud Service app available on GitHub at https://github.com/shijuvar/AzureCloudServices

Segregation of Command and Query Operations

We have segregated the Command and Read operations in this demo app. A Command operation from a Web Role application, sends messages to Service Bus Queue and the process of the command operations handles from a Worker Role app. The Worker Role application process the queue messages and finally persists on the Table storage for the Read operations. We use the Table storage for Read model of the app. We can use Table storage as the Read model for building CQRS applications on the Windows Azure.

Summary

In this blog post, we have discussed about how to build multi-tier Windows Azure Cloud Services application using  Web Role, Worker Role, Service Bus Queue and Table storage. Windows Azure Cloud Services is the Windows Azure offerings for Platform as a Service (PaaS) which lets the Cloud developers to build multi-tier highly scalable, reliable cloud applications on the Windows Azure Cloud platform. We can use Windows Azure Service Bus Queue or Storage Queue for communicating between Web Roles and Worker Roles. In this demo app, we have used Service Bus Queue for communicating between Web Roles and Worker Roles.

No Comments