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.

Comments (1)
  1. jiale says:

    profect! but maybe you have forgot to process the CustomProfile in the Global.axax.cs

Comments are closed.

Skip to main content