How to migrate your ASP.NET site to the Azure cloud

Cloud computing is one of the hot topics of 2011 with those willing to make the jump to a cloud-based solution finding financial savings in this new approach as well as, in many cases, better fault tolerance and a more responsive service turnaround in many cases. However, what many developers may not realise is just how straightforward it can be to migrate a web site from a local or hosted server into the cloud.

To demonstrate, this article will show you how to upgrade and deploy an existing ASP.NET 3.5 or 4.0 web application to the Windows Azure cloud platform.

We will cover:

  • The SDKs and tools to be installed on your machine before you can continue
  • How to set up your Windows Azure instance in preparation for the application
  • How to alter the application so that it will function in the cloud
  • How to deploy the application to Windows Azure

I’m going to assume that you’re already familiar with the .NET framework, that you know what the Windows Azure platform is, and that you’re comfortable with Visual Studio 2010. If you’ve not looked into Windows Azure before, have a look as Neil Mackenzie’s article “An Introduction to Windows Azure – What You Should Know” before continuing.

Pre-requisites

Before we begin, let’s get our development environment in order:

  • Back-up all your existing application code and data before you take another step! You can never be too careful.
  • Download and install the Windows Azure SDK
  • Download and install the Windows Azure Tools for Visual Studio 2010.
  • If you intend to implement session state in your application, then I’d recommend evaluating the Azure AppFabric Caching provider and for this you’ll need the Windows Azure AppFabric SDK.

You’ll need to make sure you have a Windows Azure services account. If you haven’t set one up already, sign up for a free trial. Windows Azure is a pay-as-you-go service but the free trial should more than suffice for you to experiment and try out Azure before you’ll need to start paying. If you’re a Microsoft BizSpark programme member or have an MSDN subscription, log in to your respective programme portal for information on the free offers available to you.

Modifying Your Existing ASP.NET Web Application

For the most part, modifying your existing ASP.NET application to run on the Windows Azure platform is a three step process:

  1. Create a new Windows Azure project into which code from your existing web application will be migrated.
  2. Alter the code in the new project to work in the cloud rather than on a ‘local’ web server. In particular, we’ll look at a. Moving configuration settings from web.config to the Azure RoleEnvironment b. Setting the number of instances of the site to be running in the cloud c. Options for handling session state in the cloud. In this article, we’ll see how to use Azure AppFabric for this purpose.

  3. Deploy your newly cloud-enabled application to the cloud.

So let’s start. Launch your copy of Visual Studio 2010, or Visual Web Developer Express and proceed to step 1.

Create A New Windows Azure Project

To begin migrating your web application to the cloud, you’ll need to create a new Windows Azure project to house your code. With Visual Studio running and in focus, you’ll need to:

  1. Click File > New Project.
  2. In the New Project dialog, select Visual C# > Cloud > Windows Azure Project, as shown below. New Windows Azure Project
  3. Name your project, set its location, choose a solution name and click OK.
  4. In the New Windows Azure Project dialog box, as shown below, do not select any roles to add. Just click OK to have Visual Studio generate a blank Windows Azure project. New Windows Azure Project template
  5. When Visual Studio has finished generating your new project, click File > Add > Existing Project, browse to and select the .csproj file for the web application project you want to migrate and click Open. This will add your existing project to the new solution.
  6. Now right-click the Roles folder under the cloud project you added earlier, and choose Add > Web Role Project in solution as shown below. New Windows Azure Project Adding Roles
  7. In the Associate with Role Project dialog, choose your web application project and click OK. Choosing your web application project You’ll see that it now appears under the Roles folder in Solution Explorer.
  8. Finally, you’ll need to add a reference to the Windows Azure service runtime to your Web Application project (not the Cloud project). Right click the References folder in that project and select Add > Reference.
  9. When the Add Reference dialog appears, switch to the .NET tab, find and select Microsoft.WindowsAzure.ServiceRuntime as shown below. Click OK. Choosing your web application project

Your projects are now set up. The next step is to alter your web application’s code to run within and take advantage of the cloud.

Alter The Web Application To Run On Azure

For the most part, modifying your existing ASP.NET application to run on the Windows Azure platform will be a very simple process. However, you may run into some minor challenges depending on how your existing application is coded and there are some special considerations to make because your application can easily be scaled-up (and down, for that matter) to run multiple instances at the same time.

Move Configuration Settings Into The Cloud Project

The first thing that’s likely to trip you up is that calls to the ConfigurationManager class to get your application settings do not work in the Azure environment. You’ll need to redefine those settings within the cloud project in the solution and then use the Azure RoleEnvironment class to access them instead.

If you have a look at the cloud project in Solution Explorer, you’ll see it contains two files, ServiceConfiguration.cscfg and ServiceDefinition.csdef, as shown below. These two files are incredibly important. They store the configuration settings for your application, just like web.config does, as well as other important settings like how many roles you have in your solution, what type they are, and how many instances of them need to run.

VS 2010 Azure Config Settings

If you open ServiceDefinition.csdef, you’ll see it is an XML file just like web.config. You need to insert a <ConfigurationSettings> element beneath <ServiceDefinition>\<WebRole> to describe any application settings that already exist in your existing ASP.NET web application. Edit your ServiceDefinition.csdef file so that it looks like this:

<?xml version="1.0" encoding="utf-8"?>
<ServiceDefinition name="MigratingToTheCloud" xmlns="http://schemas.microsoft.com/ServiceHosting/2008/10/ServiceDefinition">
  <WebRole name="LegacyWebApplication1">
    <ConfigurationSettings>
      <!-- Add your configuration settings here -->
    </ConfigurationSettings>
    <Sites>
      <Site name="Web">
        <Bindings>
          <Binding name="Endpoint1" endpointName="Endpoint1" />
        </Bindings>
      </Site>
    </Sites>
    <Endpoints>
      <InputEndpoint name="Endpoint1" protocol="http" port="80" />
    </Endpoints>
    <Imports>
      <Import moduleName="Diagnostics" />
    </Imports>
  </WebRole>
</ServiceDefinition>

Where I’ve placed the comment, you’ll insert one of the following lines for each of the settings present in your existing ASP.NET web application’s .config file:

 <Setting name="OldSettingName"/>

When you’re done, your <ConfigurationSettings> element in the ServiceDefinition.csdef file should look a little like this:

 <ConfigurationSettings>
      <Setting name="OldSettingName1"/>
      <Setting name="OldSettingName2"/>
      <Setting name="OldSettingName3"/>
      <Setting name="OldSettingName4"/>
      <Setting name="OldSettingName5"/>
</ConfigurationSettings>

Note how there are no value attributes. That’s because you define the values within ServiceConfiguration.cscfg, which is our next task.

Open ServiceConfiguration.csfg. It should already contain a <ConfigurationSettings> element. Go ahead and cut and paste each of the <Setting> elements you added to ServiceDefinition.csdef under the first <Setting> element within ServiceConfiguration.cscfg. Then, add the “value” attribute to each of the elements you’ve added accordingly. When you’re done, you should end up with a file that looks similar to this:

<?xml version="1.0" encoding="utf-8"?>
<ServiceConfiguration serviceName="MigratingToTheCloud" xmlns="http://schemas.microsoft.com/ServiceHosting/2008/10/ServiceConfiguration" osFamily="1" osVersion="*">
  <Role name="LegacyWebApplication1">
    <Instances count="1" />
    <ConfigurationSettings>
      <Setting name="Microsoft.WindowsAzure.Plugins.Diagnostics.ConnectionString" value="UseDevelopmentStorage=true" />
      <Setting name="OldSettingName1" value="foo"/>
      <Setting name="OldSettingName2" value="bar"/>
      <Setting name="OldSettingName3" value="abc"/>
      <Setting name="OldSettingName4" value="123"/>
      <Setting name="OldSettingName5" value="xyz"/>
    </ConfigurationSettings>
  </Role>
</ServiceConfiguration>

That takes care of our configuration files, now we just need to make sure that we replace the calls to ConfigurationManager in our existing code base to access the setting values from their new location if possible. To do this, we need to:

  1. Determine whether your application can ‘see’ the role environment by checking the value of RoleEnvironment.IsAvailable. This returns true if it is running on the compute platform (either for real, or locally on an emulator.
  2. If true, return the setting value needed by calling RoleEnvironment.GetConfigurationSettingValue(“configurationKey”).

  3. If false, try and retrieve the setting value from web.config with ConfigurationManager.AppSettings[“configurationKey”].

In effect, your code should now look like

String oldSettingValue = RoleEnvironment.IsAvailable ? 
   RoleEnvironment.GetConfigurationSettingValue("OldSettingName1") :                         
   ConfigurationManager.AppSettings["OldSettingName1"];

We’d recommend refactoring this into a helper class if you haven’t already done so to keep these changes and any new additions in a single, easy to locate place. You might want to implement them as either public properties or as methods, as demonstrated below.

using System.Configuration;
using Microsoft.WindowsAzure.ServiceRuntime;

namespace AzureWebApplication
{
    public class ConfigHelper
    {
        /// <summary>
        /// Returns the value of the configuration setting called "OldSettingName1" 
        /// from either web.config, or the Azure Role Environment.
        /// </summary>
        public static string OldSettingName1 
        {
            get 
            {
                return RoleEnvironment.IsAvailable ? 
                       RoleEnvironment.GetConfigurationSettingValue("OldSettingName1") : 
                      ConfigurationManager.AppSettings["OldSettingName1"];
             } 
        }

        /// <summary>
        /// Returns the value of the configuration setting called ”settingName”
        /// from either web.config, or the Azure Role Environment.
        /// </summary>
        public static string GetSettingAsString(string settingName)
        {
                return RoleEnvironment.IsAvailable ? 
                       RoleEnvironment.GetConfigurationSettingValue(settingName) : 
                      ConfigurationManager.AppSettings[settingName];
        }
    }
}

Using a simple ConfigHelper class such as this then, any existing calls to ConfigurationManager.AppSettings[“OldKey”] are replaced with calls to ConfigHelper.OldKey if you prefer using properties or ConfigHelper.GetSettingAsString(“OldKey”)` if you prefer methods so you can do a simple Find/Replace to update your code.

Set the Number of Site Instances to Run In the Cloud

The new cloud version of your web application can run on a number of instances. Think of instances as horizontal scaling for your application. You can control how many instances of your application are deployed by right-clicking the web role in the cloud project, and clicking “Properties”. You’ll see the following window appear in the main area of Visual Studio.

VS 2010 Cloud Project Properties

You’ll need to set the instance count to a number greater than one for the Azure SLA to apply to your web application.

Taking Care of Session State

If you are only planning to run one instance of your application (which is not recommended, by the way), or you don’t intend to make use of session state, then skip this section and go straight to deployment. If your application does make use of session state however, you will probably need to modify the way your application manages session state.

If your application currently uses “in-proc” session state and you intend to stick with only one instance running, again that’s fine. However - if you then ask Azure to scale-up and run it on two instances (which you should really consider if you want to avail of the Azure SLA), it will automatically load-balance between the two and suddenly session state will stop working as successive requests bounce from one instance to the other. This would be the same with two or more physical servers, too.

Your options for session state storage at this point are limited to three:

  • SQL Azure
  • Table Storage
  • Azure AppFabric Caching.

Which you choose depends on your circumstances and you are strongly encouraged you to learn more about the differences between these (or at least enough to be able to work out which will save you more money and be most appropriate for your deployment, since everything on Azure is chargeable!)

The Windows Azure Platform Training Kit contains sample code for both SQL Azure and Table Storage session providers which are both easily implemented but for the purposes of this article, we’ll look at using AppFabric Caching for session state.

AppFabric Caching is “the elastic memory that your application needs for increasing its performance and throughput by offloading the pressure from the data tier and the distributed state so that your application is able to easily scale out the compute tier”, according to MSDN magazine. In a nutshell then, it’s a bit like “in-proc” session state, but non-resident to any one instance of your application. This means that all your instances can collectively use the same cache by referencing that centralised ‘pool’.

To get a cache up and running for use by your web application, go to your Azure Portal at http://windows.azure.com and sign in. Once there:

  1. Click Service Bus, Access Control & Caching from the left-hand menu and then AppFabric > Cache from the submenu that appears.
  2. Click New Namespace from the top menu.
  3. When the Create a new Service Namespace dialog appears, check the Cache service on the left hand menu and then fill out the form on the right hand side. Don’t forget to check the availability of the namespace you want to use. Note also that 128MB should be plenty for this demonstration. New Service Namespace dialog
  4. Click Create Namespace when you are done.
  5. It will take a little while for your cache to be set up. Once its Status is marked as Active, select its entry and make a note of its Management Endpoint and Authentication Token from the right hand side Properties panel, as shown below. App Fabric Labs Properties

  6. Finally, click View Client Configuration in the portal’s top menu bar and copy the resulting XML (all of it) to Notepad as we will need that in a minute.

With the cache ready and waiting, we need to set up our existing ASP.NET web application to use it. Head back in to Visual Studio, and add a reference to all the assemblies that came with the AppFabric SDK within your web application:

  • Microsoft.ApplicationServer.Caching.Client
  • Microsoft.ApplicationServer.Caching.Core
  • Microsoft.Web.DistributedCache
  • Microsoft.WindowsFabric.Common
  • Microsoft.WindowsFabric.Data.Common

These assemblies are located in the %Program files%\Windows Azure AppFabric SDK\V2.0\Assemblies\Cache folder.

Note: Ensure that “Copy Local” is set to true on each of these assemblies.

Now we need to edit web.config:

  1. Go back to your Notepad document that contains your XML. There are actually two sections (defined by comments) in the XML you copied.
  2. Append the <configSections> element to your existing web.config. If you don’t already have a <configSections> element, add it to the top of the file, directly below the <configuration> element.
  3. Next, grab the <dataCacheClient> element from Notepad and add that directly below the <configSections> element (this is important – you’ll receive an error if <configSections> and <dataCacheClient> aren’t right at the top of the document).
  4. Now, create a <sessionState> element and add it to web.config. If you already have a <sessionState> element, delete it and replace it with the relevant section from the code you copied into Notepad.

When you’re done, you should end up with a web.config that looks a little like this:

<configuration>
  <configSections>
    <section name="dataCacheClient" type="Microsoft.ApplicationServer.Caching.DataCacheClientSection, Microsoft.ApplicationServer.Caching.Core"
             allowLocation="true" allowDefinition="Everywhere"/>
  </configSections>

  <dataCacheClient deployment="Simple">
    <hosts>
      <host name="LabsCacheDemo.cache.appfabriclabs.com" cachePort="22233"/>      
    </hosts>
    <securityProperties mode="Message">
      <messageSecurity authorizationInfo="--- YOUR APP FABRIC LABS AUTHORIZATION INFO HERE ----"/>
    </securityProperties>
  </dataCacheClient>

  <system.web>    
    <sessionState mode="Custom" customProvider="AppFabricCacheSessionStoreProvider">
      <providers>
        <add name="AppFabricCacheSessionStoreProvider" 
             type="Microsoft.Web.DistributedCache.DistributedCacheSessionStateStoreProvider, Microsoft.Web.DistributedCache"
             cacheName="MyApplicationCache1"
             sharedId="SharedApp" />
      </providers>
    </sessionState>
  </system.web>  
</configuration>

Your application is now configured to use distributed cache, which means you can scale your application up (or down) to as many or as few instances as you like, and session state will be maintained for you across all instances.

Deploying your Application to Windows Azure

Now, with all the preparation done, we’re ready to deploy our application out to the cloud. The first thing we need to do is create a package for our new deployment. To do this, right-click on the cloud project in your solution, and click “Publish” (make sure you select the cloud project, and not your existing ASP.NET project).

  1. Click “Create service package only”: Create service package only dialog
  2. In a few moments, Windows will open a folder that contains your new package. Copy the location to the clipboard as we’ll need that in a moment.

Now, open and sign in to the Windows Azure portal at http://windows.azure.com if you haven’t already done so:

  1. Click New Hosted Service from the top menu. You’ll see the Create a New Hosted Service dialog appear, as shown below. Create a new hosted service
  2. Ensure the correct subscription is selected (if you have only one, it is selected by default).
  3. Enter a name for your service, for example “Acme Website”.
  4. Choose a URL prefix for your application. This will, initially, be the only way you can access your cloud application but you can assign a CNAME to it later. For now, choose something unique to your deployment. The portal will let you know if you can use the name you’ve chosen.
  5. Now, choose a region. It is sensible to decide at this stage where you think most of your traffic will come from and locate your application within that region.
  6. Ensure that Deploy to stage environment is selected, and that the checkbox marked Start after successful deployment is checked.
  7. Enter a name for your deployment, for example, “Acme Website V1”.
  8. Now, click Browse Locally… next to the “Package location” box and browse to the location of your publish in Visual Studio (if you copied the location of the folder to the clipboard, CTRL+V to paste, press ENTER, and then your file will appear).
  9. Repeat this step for the “Configuration file” box underneath.
  10. Now, click “OK”.

The next step may take anywhere from 15 minutes to an hour to complete, but in general shouldn’t take longer. During this time, your package is being uploaded to Windows Azure and instances are being allocated within the region you chose to host your application.

The portal will keep you up to date with the progress, and when you see “Ready” in the status you’re good to go. Click on the instance and over to the right you’ll see your service URL where you can browse to verify everything’s working as expected. You’ll note at this time that your URL isn’t the one that you chose earlier.

That’s because Windows Azure is running your application in the stage environment, to give you a chance to test things out and rollback if necessary. When you’re satisfied everything is working as expected, just click “Swap VIP” (swap virtual IP) on your deployment and Windows Azure will migrate your application across to the production system and your new URL will become active.

Congratulations! You’ve now upgraded your very first existing ASP.NET application to run in the cloud and you’ve left your physical infrastructure behind forever!

Summary

In this article, we looked at the core steps required to update a web application project so that it works in the cloud. In particular, we saw how to configure the cloud for your application, a few of the basic coding issues you’ll need to resolve in order to base your application in the cloud, and finally how to deploy it.

You might also like...

Comments

About the author

Richard Parker

Richard Parker United Kingdom

In the beginning… I started my career as an intranet developer, writing some very bad code in ASP classic for a local council. Not long after that, the world was on the brink of the much-hyped M...

Interested in writing for us? Find out more.

Contribute

Why not write for us? Or you could submit an event or a user group in your area. Alternatively just tell us what you think!

Our tools

We've got automatic conversion tools to convert C# to VB.NET, VB.NET to C#. Also you can compress javascript and compress css and generate sql connection strings.

“It is practically impossible to teach good programming style to students that have had prior exposure to BASIC. As potential programmers, they are mentally mutilated beyond hope of regeneration.” - E. W. Dijkstra