The Daily Parker

Politics, Weather, Photography, and the Dog

Dual Microsoft Azure deployment, part 1

(This is cross-posted on the 10th Magnitude blog.)

In my last post, I talked about using Azure web sites to save beaucoup bucks over Azure Cloud Services web roles on nonessential, internal, and development web applications. In this post I'll go over a couple of things that bit me in the course of deploying a bunch of applications to Azure web sites in the last two weeks.

First, let me acknowledge that engineering a .NET application to support both types of deployment is a pain. Azure web sites can't use Cloud Storage, including tables, blobs, and queues. You'll need to architect (or refactor) your application to get its data from different sources based on whether it's running inside Cloud Services or not.

Once you've done all that (simple, right?), one line of code will let the application know where it is:

if (RoleEnvironment.IsAvailable) { DoCloudServicesStuff(); }

But here's the catch. Azure web sites don't have access to the RoleEnvironment class by default. The class lives in the Microsoft.WindowsAzure.ServiceRuntime assembly, which Cloud Services applications get through their VM's GAC and which website applications do not.

So even for your application to determine whether it's running in Cloud Services or not, you'll have to add two assemblies to the website project file: Microsoft.WindowsAzure.ServiceRuntime.dll and msshrtmi.dll. If you don't, you'll get one of these runtime errors:

Could not load file or assembly 'Microsoft.WindowsAzure.ServiceRuntime, Version=1.7.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35' or one of its dependencies. The system cannot find the file specified.

Could not load file or assembly 'msshrtmi, Version=1.7.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35' or one of its dependencies. The system cannot find the file specified.

(On my computer, the ServiceRuntime assembly is in "C:\Program Files\Microsoft SDKs\Windows Azure\.NET SDK\2012-06\ref" and msshrtmi is in "C:\...\2012-06\bin\runtimes\base\x86\".)

Once you have added those two references to your web project, find them in the References list under the project root, select both, right-click, and open the Properties tab. Then set both of them to Copy Local = true, like this:

Copy msshrtmi local image

This tells the Publisher to include them in the deployment to Azure web sites. Note that you'll have to include these in your web application if any of the satellite assemblies uses the RoleEnvironment class (like our time zone handler, for example).

But now you have a new problem if you have dual deployments: you need two web project files, because the Cloud Services deployment will crash when the web role starts if you have those two assemblies referenced explicitly. And if you have two different web application project files, you'll need two solution files as well.

Of course, it only takes about two minutes to:

  • Make a copy of the solution file (usually "MyApplication-WebRole.sln" or "MyApplication-Website.sln" for the new copy);
  • Make a copy of the Web project file (you don't need different versions of your other assembly projects);
  • Manually edit the new solution file to point to the new project file.

(You could, I suppose, accomplish the same thing with build scripts and lots of conditional compile regions, but I can't call that an improvement. Like I said, this approach has more PITA than a falafel stand.)

We also find it helpful to wait until late in the development cycle to create the second solution/project pair of files, because you'll need to keep the two project files identical except for the two assembly references.

You have to do one more thing, unfortunately. You need to build your website deployment for the x86 platform target:

Visual Studio 2010 example of building as x86

The msshrtmi assembly requires explicitly building the application for x86 or x64 deployments, depending on whether you grab it from "C:\Program Files\Microsoft SDKs\Windows Azure\.NET SDK\2012-06\bin\runtimes\base\x86\" or "...\x64\". But we've run into other problems trying to use the x64 version, so we don't recommend it.

Comments are closed