Migrating the .Net Pet Shop to Windows #Azure

In a previous blog post I walked through a criteria for calculating migration complexity to Windows Azure. As an example I used Tom Hollander’s challenge of migrating the classic .Net Pet Shop. In this post I will walk through the steps I undertook to migrate the solution from scratch. Please refer to the previous post, at the bottom, for how the end result translated to the migration complexity criteria I put forward.

Not withstanding any mistakes, omissions (or further Windows Azure work) these three steps will migrate the project and give you an indication of the effort required to move a relatively old but not an un-complex solution to Windows Azure. This exercise should take you no more than 20 minutes (all going well!) if you are familiar and have an account setup with Windows Azure*.

* A quick live chat or phone call will get you a no-credit-card required Windows Azure platform free pass.

STEP 1 – Create a Cloud Solution

  1. Download and install the PetShop 4.0
  2. Copy the original Pet Shop 4.0 Project to your Projects directory
  3. Open the project in in Visual Studio and convert and update it to the latest framework
  4. Build and Compile the solution
  5. Add a new AzurePetShop Cloud Project as web role
  6. Rename Web Role to PetShopWebRole

STEP 2 – Change from a Web Site Project to a Web Application Project

Reading: Walkthrough: Converting a Web Site Project to a Web Application Project in Visual Studio

  1. Remove all files from the new web application project except the webrole.cs

  2. Add a project reference to every project in the solution

  3. Copy all file and folders from comm images from the web site project to the web application

  4. Add a trace listener back into the to the web config ofthe web

     1: <trace> 
     2:     <listeners> 
     3:         <add type="Microsoft.WindowsAzure.Diagnostics.DiagnosticMonitorTraceListener, Microsoft.WindowsAzure.Diagnostics, Version=, Culture=neutral, PublicKeyToken=31bf3856ad364e35" name="AzureDiagnostics"> 
     5:             <filter type="" /> 
     6:         </add> 
     7:     </listeners> 
     8: </trace>
  5. Copy the app_Code and app_themes from the web site project to the the web application project

  6. Rename the app_Code Directory to Old_app_Code

  7. Make sure all the file of the Old_app_Code have the content property set to compile

  8. Create a new CustomProfile Class and add it to the the project

  9. Insert the following code inside the CustomProfile class

     1: using System; 
     2: using System.Collections.Generic;
     3: using System.Linq; 
     4: using System.Web; 
     5: using System.Web.Profile;
     7: namespace PetShop.Web 
     8: { 
     9:     public class CustomProfile 
     10:     { 
     11:         private ProfileBase Profile 
     12:         { 
     13:             get { return HttpContext.Current.Profile; } 
     14:         } 
     17:         public virtual PetShop.BLL.Cart WishList 
     18:         { 
     19:             get 
     20:             { 
     21:                 return ((PetShop.BLL.Cart)(Profile.GetPropertyValue("WishList"))); 
     22:             } 
     23:             set 
     24:             { 
     25:                 Profile.SetPropertyValue("WishList", value); 
     26:             } 
     27:         } 
     29:         public virtual PetShop.BLL.Cart ShoppingCart 
     30:         { 
     31:             get 
     32:             { 
     33:                 if (Profile.GetPropertyValue("ShoppingCart") == null) 
     34:                     Profile.SetPropertyValue("ShoppingCart", new PetShop.BLL.Cart()); 
     35:                 return ((PetShop.BLL.Cart)(Profile.GetPropertyValue("ShoppingCart"))); 
     36:             } 
     37:             set 
     38:             { 
     39:                 Profile.SetPropertyValue("ShoppingCart", value); 
     40:             } 
     41:         } 
     43:         public virtual PetShop.Model.AddressInfo AccountInfo 
     44:         { 
     45:             get 
     46:             { 
     47:                 return ((PetShop.Model.AddressInfo)(Profile.GetPropertyValue("AccountInfo"))); 
     48:             } 
     49:             set 
     50:             { 
     51:                 Profile.SetPropertyValue("AccountInfo", value);
     52:             } 
     53:         } 
     55:         public void Save() 
     56:         { 
     57:             Profile.Save(); 
     58:         } 
     60:     } 
     61: }
  10. Click on the web application project and select Convert to a web application

  11. Overwrite the profile class to get values from the web.config by adding to each of the following classes this single constructor:

 private CustomProfile Profile = new CustomProfile(); 
  • CheckOut.aspx.cs(10)
  • ShoppingCartControl.ascx.cs(11):
  • WishListControl.ascx.cs(10):
  • ShoppingCart.aspx.cs(6):
  • UserProfile.aspx.cs(6):
  • WishList.aspx.cs(6):

STEP 3 – Migrate Data and Configure the Application

With the Pet shop installed you will have your SQL Server setup with multiple databases installed. Its worth run SQL management studio to have a look.

Warning you will want to upgrade to SQL 2008 R2 SP2 if you have not already. Make sure you install the full version as outlined in this post. If you do not the SQL Migration Wizard, and other features, will not work as expected and give some interesting error messages.

  1. Login to the Windows Azure Portal and sign in

  2. Select the SQL Azure Database option from the left power bar

  3. Create a new database from within an existing SQL Azure subscription

  4. Add in the appropriate firewall rules for access

  5. Copy the Connection String for the migrated database. It should look like this (replacing highlighted items):


  6. Install and run the SQL Migration Wizard for each of the four SQL Server databases, moving each to a single Azure database:

    • ASPState
    • PetShop
    • Orders
    • Profile
    • Services
  7. Update the Cache dependency: Invalidates the cache when data changes

    • With the web application comment out the

         protected TableDependency(string configKey) {..}

    • Note: AppFabric Cache doesn’t replace SQL Dependency
  8. Fix the Web Application to have a single (i.e.. not multiple) connection strings

      • First Remove encrypted connection strings from web.config
      • Then add new connection string to web.config
        1: <connectionStrings> 
        2:     <add name="PetShopConnectionString" connectionString="Server=tcp:yourServer.database.windows.net,1433;Database=petshopnew;user id=User@yourServer;password=Password;Trusted_Connection=false;Encrypt=true;MultipleActiveResultSets=True" providerName="System.Data.SqlClient"/>
        3: </connectionStrings>
  9. Open the project OrderProcessor projects app.config

  10. Comment out SQLConnString1 SQLConnString2 and SQLConnString3 connection strings in this app.config

  11. Comment out SQLMembershipConnString in this app.config

  12. Insert a new connection string to the app.config as below:

      <add name="PetShopConnectionString" connectionString="Server=tcp:yourServer.database.windows.net,1433;Database=petshopnew;user id=User@yourServer;password=Password;Trusted_Connection=false;Encrypt=true;MultipleActiveResultSets=True" providerName="System.Data.SqlClient"/>

    Note: make sure password is changed!

  13. Open DBUtility project

  14. Amend SQLHelper class connection strings to use the PetShopConnectionString

  15. Open the web application web.config

    • Amend Cache dependancy connection string to use PetShopConnectionString
    • Amend SQLMembershipProvider to PetShopConnectionString

Along the way I would encourage compiling and building in Visual Studio to check and when complete, test in local emulator before finally testing in Windows Azure proper.

Its not a difficult task, particularly given it is a full port, though I would certainly not encourage migrations without looking at the test scenarios in more detail to confirm expected behaviour as well as consider ways the application can be scaled, monitored and managed better.