Tips for Publishing Multiple Sites in a Web Role

In November 2010, with SDK 1.3, Microsoft introduced the ability to deploy multiple web applications in a single Windows Azure web role.  This is a great cost savings benefit since you don’t need a new role – essentially a virtual machine – for each web application you want to deploy.

Creating a web role that contains multiple web sites is pretty easy.  Essentially, you need to add multiple <Site> elements to your web role’s ServiceDefinition.csdef file.  Each <Site> element would include a physicalDirectory element that references the location of the web site to be included.

  <Site name="WebRole1" physicalDirectory="..\..\..\WebRole1">
<Binding name="Endpoint1" endpointName="Endpoint1" />
<Site name="WebApplication1" physicalDirectory="..\..\..\WebApplication1\">
<Binding name="Endpoint1" endpointName="Endpoint2" />
<Site name="WebApplication2" physicalDirectory="..\..\..\WebApplication2\">
<Binding name="Endpoint1" endpointName="Endpoint3" />

For additional detailed information on creating a web role with multiple web sites, I suggest following the guidance provided at these excellent resources:

The above resources provide a great starting point.  However, there is a once piece of what I think is important information that is missing.  When Visual Studio and the Windows Azure SDK (via CSPACK) create the cloud deployment package (.cspkg), the content listed at the physicalDirectory location is simply copied into the deployment package.  Meaning, any web applications there are not compiled as part of the process, no .config transformations take place, and any code-behind (.cs) and project (.csproj) files are also copied.


What’s going on? CSPack is the part of the Windows Azure SDK that is responsible for creating the deployment package file (.cspkg).  As CSPack is part of the core Windows Azure SDK, it doesn’t know about Visual Studio projects.  Since it doesn’t know about the Visual Studio projects located at the physicalDirectory location, it can’t do any of the normal Visual Studio build and publish tasks – thus just copying the files from the source physicalDirectory to the destination deployment package.

However, when packaging a single-site web role, CSPack doesn’t rely on the physicalDirectory attribute.  With a single-site web role, the packaging process is able to build, publish, and create the deployment package.

The Workaround

Ideally, each web site should be published prior to packaging in the .cspkg.  Currently there is not a built-in way to do this.  Fortunately we can use MSBuild to automate the build and publish steps.

  1. Open the Windows Azure project’s project file (.ccproj) in an editor.  Since the .ccproj is a MSBuild file, additional data points and build targets can be added here.
  2. Add the following towards the bottom of the .ccproj file.
  <!-- Inject the publication of "secondary" sites into the Windows Azure build/project packaging process. -->
  <!-- This is the directory within the web application project directory to which the project will be "published" for later packaging by the Azure project. -->
<!-- These SecondarySite items represent the collection of sites (other than the web application associated with the role) that need special packaging. -->
  <SecondarySite Include="..\WebApplication1\WebApplication1.csproj" />
  <SecondarySite Include="..\WebApplication2\WebApplication2.csproj" />
<Target Name="CleanSecondarySites">
  <RemoveDir Directories="%(SecondarySite.RootDir)%(Directory)$(SecondarySitePublishDir)" />
<Target Name="PublishSecondarySites" Condition="'$(PackageForComputeEmulator)' == 'true'
                      Or '$(IsExecutingPublishTarget)' == 'true' ">
    Execute the Build (and more importantly the _WPPCopyWebApplication) target to "publish" each secondary web application project.
    Note the setting of the WebProjectOutputDir property; this is where the project will be published to be later picked up by CSPack.
  <MSBuild Projects="%(SecondarySite.Identity)" Targets="Build;_WPPCopyWebApplication" Properties="Configuration=$(Configuration);Platform=$(Platform);WebProjectOutputDir=$(SecondarySitePublishDir)" />

Finally, for each secondary site defined in the .csdef, update the the physicalDirectory attribute to reference the publishing directory, azure.publish\.

<Site name="WebApplication1" physicalDirectory="..\..\..\WebApplication1\azure.publish">
<Binding name="Endpoint1" endpointName="Endpoint2" />

How does this all work?  By adding the CleanSecondarySites and PublishSecondarySites targets to the <CoreBuildDependsOn> element, that is forcing CleanSecondarySites and PublishSecondarySites to happen before any of the default targets included in <CoreBuildDependsOn> (defined in the Microsoft.WindowsAzure.targets file). Thus, the secondary sites are built and published locally before any of the default Windows Azure build targets execute. The IsExecutingPublishTarget condition is needed to ensure PublishSecondarySites happens only when packaging the Windows Azure project (either from Visual Studio or via the command line with MSBuild).

UPDATE (1/15/2013): I’ve added a PackageForComputeEmulator condition to the PublishSecondarySites target. This should ensure the target is also executed when debugging locally via the compute emulator.

I like this approach because it seems like a fairly clean approach and I don’t have to modify build events (keep reading) for each secondary web site I want to include.  I can keep the above build configuration snippet handy and use it in future projects quickly.

Alternative Approach

The above approach relies on modifying the project file to help automate the build and publish of any secondary sites.  An alternative approach would be to leverage build events.  I first learned of this approach from “Joe” in the comments section of Wade Wegner’s blog post.

  1. Select your Windows Azure project, and select Project Dependencies.  Mark the other web apps as project dependencies.build_dependencies
  2. Open the project properties for each web application (not the one used as the Web Role).
  3. For the Build Events, you’ll need to add a pre-build and post-build event.


rmdir "$(ProjectDir)..\YOUR-AZURE-PROJECT\Sites\$(ProjectName)" /S /Q


%WinDir%\Microsoft.NET\Framework\v4.0.30319\MSBuild.exe "$(ProjectPath)"
/T:PipelinePreDeployCopyAllFilesToOneFolder /P:Configuration=$(ConfigurationName);PreBuildEvent="";PostBuildEvent="";

The pre-build event cleans up any files left around from a previous build.  The post-build event will trigger a local file system Publish action via MSBuild.  The resulting published files going to the “Sites” subdirectory.

Finally, be sure to update the physicalDirectory element in ServiceDefinition.csdef to reference the local publishing subdirectory (notice the ‘Sites’ directory in the updated snippet below).

<Site name="WebApplication1" physicalDirectory="..\..\Sites\WebApplication1\">
<Binding name="Endpoint1" endpointName="Endpoint2" />

When you “Publish” the Windows Azure project, all your web sites will build and publish to a local directory.  All the web sites will have the files you would expect.

Final Helpful Info

When deployed to Windows Azure, the secondary sites referenced in the physicalDirectory attribute are placed in the sitesroot folder of your E or F drive.  The site that is the web role is actually compiled, published and deployed to the approot folder on the E or F drive.  If you want to see this layout locally, first unzip the .cspkg and then unzip the .cssx file (in the extracted .cspkg).  This is the layout that is deployed to Windows Azure.

Special thanks to Paul Yuknewicz and Phil Hoff for their insightful feedback and assistance on this post.


31 thoughts on “Tips for Publishing Multiple Sites in a Web Role

  1. Howdy! It looks as though we both have a interest for the same thing.
    Your blog, “Tips for Publishing Multiple Sites in a Web Role Michael S. Collier’s Blog” and mine are very
    similar. Have you ever thought about authoring a guest post for a
    similar blog? It will unquestionably help gain publicity to your website (my site recieves a lot of targeted traffic).
    If you’re interested, email me at: Thank you so much

  2. Excellent article. This addresses an issue I was having with Azure randomly reverting any website publishings (as opposed to azure cloud service publishings). Hopefully the folks over at Microsoft will develop better support around this feature. Hosting multiple websites on a single role is very common.

  3. Super helpful, thanks Michael. One thing I would add is that when copying/pasting the Post-Build event above (and replacing YOUR-AZURE-PROJECT with your Azure project name), you might get an error when building “Project file not found.”

    This was occurring, because the copy/paste ommitted a crucial space in the MSBUILD.EXE arguments, and it looked like this:


    Ensure you add a space between “$(ProjectPath)” and /T

  4. One quick question – how do we test this from a staging site?

    Let’s say I’m hosting two sites, called “” and “”.

    Once I deploy my cloud project to Azure, I get a url like:

    How do I test the two sites, “” and “”?

    I’ve tried adding the IP of to my HOSTS file, along with entries for and, but the request eventually times out in IE and I get the “Internet Explorer cannot display the webpage”.

    I’ve even tried it from remote desktoping to the Server 2012 instance in Azure, and changed the host files there, opened IE, and tried to access the sites. Still no luck.

    I’ve confirmed my hosts file matches the hostHeader entries in ServiceDefinition.

    Any thoughts?


      1. You should be able to specify the host header ( in the ServiceDefinition.csdef file. Once you do that, and update your local host file to have the correct IP mapping (e.g., you should be good to go.

        One thing I’ve noticed though is that once you do this, you can’t use the Visual Studio debugger. You have to start without debugging.

  5. Michael – any thoughts as to why this solution does not work with TFS builds? The solution works great locally, but when I run it through TFS build, the secondary sites don’t appear to be building and/or the paths are all jacked up. C:\a\bin\ServiceDefinition.csdef (0): Cannot find the physical directory ‘C:\Web\MyApp.Web\azure.publish’ for virtual path MyApp.Web/.

  6. Thank you for the post.

    I change the project file a little bit, so the compile output file will be under WebRole folder like below:






  7. The config was not formatted correctly above. Try this one:

    I change the project file a little bit, so the compile output file will be under WebRole folder like below:






  8. @wjchristenson2

    It looks like the compile process is a bit different in TFS build. This probably has to do with the configuration of the Azure Publish Build Definition.

    I was able to get my secondary site to build by creating a dependency from the first site to the second.

    During the TFS build process, the service config file is put in bin, and compiled web projects are put into the directory _PublishedWebsites.

    So you need to update the ServiceDefenition file to to have your physical path be similar to this….

    I’m currently trying to figure out a way to update the servicedefenition file on the fly or update the build process to put the compiled project in the correct location.

  9. As a refinement to the selection of project configuration for the secondary site, consider using:

    With this I found that my secondary site was published using the project configuration configured in the solution-level project configuration map.

      1. Sorry for blatantly spreading lies on the internet, but I misdiagnosed my solution and the above msbuild xml is entirely without effect.

        However, I was able to get some of the way by getting hold of the name of the solution configuration used for packaging:

  10. I developed to one one solution with 2 projects like one website and one wcf service,
    After that i am hosted to azure cloud its working only one project remaing projects not running,
    EX:This is my defauly cloud url

    1) first website working

    remaning WCF service project And remaning Sub project not working?
    What is the reason for this?
    How can i host One solution with multiple projects to azure cloud?
    please help me

    my solution screenshot

  11. This is great and we are using this in our deployment now. One problem we have found is that we use the “Package” menu option from VS 2013 to create the Azure deployment package and then select a build configuration from the next prompt. The selected build configuration does not seem to flow through to the $(Configuration) variable in the MSBuild task for the secondary sites though. Do you know how to get that working?

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.