Windows Azure has been capable of running multiple websites in a single web role for some time now, but I found myself recently in a situation with 2 separate Azure solutions and was looking to combine them to create a single deployment. Just like in IIS, this is most often done via host headers, so requests coming in can be forwarded to the correct site.
Options to consolidate included folding the code into the Worldmaps site, which would involve actual work, or converting the site to use IIS instead of the hostable web core (HWC), which was, originally, the only way to host Azure deployments prior to version 1.3 of the SDK. Under IIS, host headers can be used to direct traffic to desired correct site.
Inside the ServiceDefinition file, the <sites> section is used to define the websites and virtual directories, like so:
<Site name="Web" physicalDirectory="..\WorldmapsSite">
<Binding name="HttpIn" endpointName="HttpIn" />
<Site name="Reporting" physicalDirectory="..\..\igWorldmaps\WorldmapsDemo.Web">
<Binding name="HttpIn" endpointName="HttpIn" hostHeader="reporting.myworldmaps.net" />
Nothing too crazy in there, but I’ll talk about the paths later.
The first problem is that I was using webrole.cs file in the Worldmaps application, overriding the Run method to do some background work:
public class WebRole : RoleEntryPoint
public override void Run()
// I'm doing stuff!
The Run method is called from a different thread, and it did a lot of background processing for the site (logging data, drawing maps, etc.). This is a great technique, by the way, to add “workers” to your website. This is, by itself, not a problem to do under IIS or HWC, except, under the HWC version, the thread runs in the same process. I could write to an in-memory queue via the website, and process that queue in the webrole.cs without problem, provided the usual thread safety rules are obeyed. Likewise, the worker could read/write to an in memory cache used by the website. Under IIS, though, the site and role are in a separate process, so it wasn’t possible to do this without re-engineering things a bit. You don’t need to worry about this if you aren’t doing anything “shared” in your webrole.cs file.
Add the Project
In my existing Worldmaps solution, I added the infragistics “WorldmapsRporting” project by adding the project to the solution (right click the solution, and choose Add Existing Project):
Hook it Up
The <sites> tag (seen above) is pretty self-explanatory as it defines each site in the deployment. For the first and main site, I didn’t provide a host header because I want it respond to pretty much anything (www, etc.). For the second site, I give it the reporting.myworldmaps.net host header.
Here’s the tricky part, which in retrospect seems so straightforward. The physicalDirectory path is the path to the web project, relative to the Cloud project’s directory. When I first created the Worldmaps solution (WorldmapsCloudApp4 is when I converted it .NET 4), I had the cloud project, the website itself, and a library project in the same directory, like so, with the cloud project highlighted:
So, the path the WorldmapsSite is up one level. To get to the infragistics website, it’s up to levels, the into the igWorldmaps folder and into the WorldmapsDemo.Web folder. We can ignore the other folders.
The project in Windows Azure is hosted at myworldmaps.cloudapp.net, as seen from the Azure dashboard:
…but I own the myworldmaps.net domain. In my DNS, I add the CNAMEs for both www and reporting, both pointing to the Azure myworldmaps.cloudapp.net URL (picture from my DNS dashboard, which will vary depending on who your DNS provider is):
To test host headers on a local machine, you’d need to add the DNS names to your hosts file (C:\Windows\System32\drivers\etc\hosts) , like so:
Overall, a fairly straightforward and easy way to add existing websites to a single deployment. It can save money and/or increase reliability by running multiple instances of the deployment.