This post is part of a series diving into the implementation of the @home With Windows Azure project, which formed the basis of a webcast series by Developer Evangelists Brian Hitney and Jim O’Neil.  Be sure to read the introductory post for the context of this and subsequent articles in the series.

It’s been about a month since my last post in which I finished the deep-dive into the implementation of the Azure@home client application, and it’s been an eventful month!  At PDC 2010 at the end of October, a host of upcoming features, betas, and Community Technology Previews (CTP) were announced, and just after Thanksgiving, the first wave of those hit with the release of Version 1.3 of the SDK and the new Silverlight Windows Azure Portal.  Given the updates, I thought it would be a good time to start looking at some of the new capabilities by revisiting our old friend, Azure@home

Over the next few posts, we’ll start looking at Remote Desktop capabilities, App Fabric Caching, and the VM Role, but before we get there, we’ll need to update the existing application to leverage the 1.3 SDK and the concomitant modifications in Windows Azure itself.

Step 1Download and install the SDK.

You know the drill!

Step 2 – “Migrate” the Azure@home solution.

Visual Studio Conversion WizardOnce you re-open the Azure@home solution after installing the 1.3 SDK, you’ll note the Conversion Wizard appears!  If you’re like me, your first reaction is to Cancel, close Visual Studio, and double-check you have the right project.  After all, this is just an SDK update, not a move from Visual Studio 2008 to 2010!

Despite it seeming a bit of overkill, I confirmed it’s a legit ‘feature’ of the upgrade.  Just be sure you read the fine print, which essentially says there ain’t no goin’ back.

So the next question is probably, what exactly happens during this conversion?  If you look at the conversion report (or simply do a before-and-after diff of the solution directory), you’ll find there were only two changes:

  • ProductVersion tag in azureathome.ccproj was updated to 1.3.0 from 1.0.0.  This isn’t typically a file you’d poke into anyway.
  • The Service Definition file (servicedefinition.csdef), specifically the section for the WebRole, goes from this
      <WebRole name="WebRole">
    
        <InputEndpoints>
    
          <InputEndpoint name="HttpIn" protocol="http" port="80" />
    
        </InputEndpoints>
    
        <ConfigurationSettings>
    
          <Setting name="DiagnosticsConnectionString" />
    
          <Setting name="DataConnectionString" />
    
        </ConfigurationSettings>
    
      </WebRole>


    to this
      <WebRole name="WebRole">
    
        <Sites>
    
          <Site name="Web">
    
            <Bindings>
    
              <Binding name="HttpIn" endpointName="HttpIn" />
    
            </Bindings>
    
          </Site>
    
        </Sites>
    
        <ConfigurationSettings>
    
          <Setting name="DiagnosticsConnectionString" />
    
          <Setting name="DataConnectionString" />
    
        </ConfigurationSettings>
    
        <Endpoints>
    
          <InputEndpoint name="HttpIn" protocol="http" port="80" />
    
        </Endpoints>
    
      </WebRole>

After a moment of two of comparison, the change you’ll note is that an entire new tag, Sites, has been added to the WebRole, and the InputEndpoint has been rearranged a bit, but is essentially still there.

As you might expect, Sites (plural), implies that there may be more than one web site within your role, and that’s indeed a new feature enabled 1.3.  Previously, when you deployed a Web Role to Windows Azure, your web application was actually served up by the Hosted Web Core (HWC), a subset of full IIS.  One of the restrictions of HWC is that it can only serve up a single Web application, which in turn means that a Web Role could only host one web application. 

That may not seem so awful until you realize that a Web Role (and Worker Role) correlates to a single VM instance running in Azure.  In many cases, a single web site may not be busy enough to really warrant the resources of a complete VM instance, so to save money on compute cycles, it’s reasonable to want to host multiple sites within the same VM instance – unfortunately, you couldn’t do that, until now.

With full IIS in your Azure Web Role, there are a number of other features you can take advantage of as well, including virtual directories, application warm-up, and installing HTTP handlers.

Step 3 – Run the application.

Modifying Specific Version propertyWhen your fire up the application, you’ll probably be met with a build error, the source of which is an incorrect reference to the Microsoft.WindowsAzure.StorageClient assembly within the AzureAtHomeEntities project.  The reference property, Specific Version, is set to true, and so it’s looking for the Azure SDK 1.2 version of that assembly, which is what was set up when the project was first created.  Switching that property from true to false will resolve the reference and take care of the problem.  A bit of foresight on my part when creating the original implementation would have made this step unnecessary.

Try executing again, and whoa, another problem

InvalidOperationException - SetConfigurationSettingPublisher needs to be called before FromConfigurationSetting can be used

right at the start of Page_Load for the default.aspx page:

My 'exceptional' code at work!

But this is the same code as before, and a quick look at the WebRole.cs file (which, by the way, was generated for us when we created the application under the 1.2 SDK), shows that indeed SetConfigurationSettingPublisher is called in the OnStart method:

public override bool OnStart()
{
    DiagnosticMonitor.Start("DiagnosticsConnectionString");
    // use Azure configuration as setting publisher
    CloudStorageAccount.SetConfigurationSettingPublisher(
        (configName, configSetter) =>
    {
        configSetter(RoleEnvironment.GetConfigurationSettingValue
             (configName));
    });
    // For information on handling configuration changes
    // see the MSDN topic at http://go.microsoft.com/fwlink/?LinkId=166357.
    RoleEnvironment.Changing += RoleEnvironmentChanging;
    return base.OnStart();
}

So what gives?  Well, with the move to full IIS from Hosted Web Core, the execution model of the web role code changes significantly (as covered in detail on the Windows Azure blog) .  In a nutshell, with HWC all of your web role code – your RoleEntryPoint code (in WebRole.cs) and the web site itself -  ran within the same process, WaWebHost.exe.  With full IIS, the RoleEntryPoint code runs under WaIISHost.exe, and the web site itself runs under w3wp.exe, as a regular IIS process, each in their own app domain.

Note that the FromConfigurationSetting method (as well as SetConfigurationSettingPublisher in OnStart) are static methods of CloudStorageAccount.  That worked before, because both methods were executed as part of the same process and the same app domain.  With the switch to full IIS, the methods are called in two different processes and two different app domains, the net effect of which is that SetConfigurationSettingPublisher (in WebRole.cs) and FromConfigurationSetting (in Default.aspx) aren’t dealing with the same object.  There’s a couple of different ways to handle this

  1. Make the call to SetConfigurationSettingPublisher within the web application itself.  A good place to set this up is in Application_Start.
  2. Use the Parse method on CloudStorageAccount in Default.aspx (and Status.aspx) instead:
        cloudStorageAccount = CloudStorageAccount.Parse
    
            (RoleEnvironment.GetConfigurationSettingValue("DataConnectionString"));
    

    Be aware though that this does not provide exactly the same functionality as before.  The configuration setting publisher mechanism is an abstraction that helps you more efficiently reuse code inside and outside of Windows Azure.  In Azure, the configuration would come from ServiceConfiguration.cscfg, and outside of Azure you might set it up to come from, say, the web.config file.  If you’re willing to forego that and are targeting Azure alone, then Parse will work just fine.  This, by the way, is the route we’ve taken with the updated code files on http://distributed.azure.com.