Saturday 6 March 2010

Azure: Deploying ASP.net websites instead of web application projects as web roles

This post has moved to http://wishfulcode.com/2010/03/06/azure-deploying-asp-net-websites-instead-of-web-application-projects-as-web-roles/

The Azure tools for Visual Studio have great support for creating web roles out of Web Application projects, but no built-in support for simple websites (that is, asp.net sites that are compiled at runtime). There are many scenerios where not needing to have a Web Application project are going to be the right decision for development and production, and the good news is that any IIS-servable directory can be packaged/deployed using simple commands from the Azure SDK.

The process of taking projects / code / files from from local to cloud with Azure is to:
  1. Prepare a local directory with a ready-to-run output of the application's build.
  2. Prepare a service definiton file (describes the roles to package).
  3. Package into an Azure package file using CSPack.
  4. Upload to production or staging environments on Azure, alongside a service configuration file (determines how many instances and what kinds of storage are available to the roles).
The Visual Studio add-in can handle this for web roles using website application projects, but we have to do this manually for website projects.

Preparing the project

The best folder structure for working locally is to create a parent directory with each role as a subdirectory. The service definition/configuration and package files can then be stored in the parent. So here I've created a the default Web Site from Visual studio at TestWebsite1\WebRole1 and just to prove that we don't need to add/modify anything from this default set-up I haven't changed anything, except to add a hello-world default.aspx:
<h1>Hello World</h1>
    <p><b><%= Environment.MachineName %></b> running <i><%=Environment.OSVersion.VersionString %></i> on <i><%=DateTime.Now.ToString("s") %></i></p>

Packaging the project for Azure

First off, we need to create a service definiton file, which just describes which kind of roles are in our application, and what their requirements are. In this case, we only have a single WebRole (and we'll give it some storage for fun), and I've called the file ServiceDefinition.csdef:
<?xml version="1.0" encoding="utf-8"?>
<ServiceDefinition name="Azure1_umbraco" xmlns="http://schemas.microsoft.com/ServiceHosting/2008/10/ServiceDefinition">
  <WebRole name="WebRole1">
    <InputEndpoints>
      <InputEndpoint name="HttpIn" protocol="http" port="80" />
    </InputEndpoints>
    <ConfigurationSettings>
      <Setting name="DiagnosticsConnectionString" />
    </ConfigurationSettings>
    <LocalResources>
      <LocalStorage name="LocalStorage1" cleanOnRoleRecycle="false" sizeInMB="100" />
    </LocalResources>
  </WebRole>
</ServiceDefinition>

Next we use the CSPack tool to package up the site in to a single file (testwebsite1.cspkg) for upload to Azure. The tool will automatically look for the supporting files for each role under a directory with the role's name:
cspack ServiceDefinition.csdef /out:testwebsite1.cspkg

We'll also need to create a simple service configuration file (ServiceConfiguration.cscfg) which describes how many instances to give each role:
<?xml version="1.0"?>
<ServiceConfiguration serviceName="Azure1_umbraco" xmlns="http://schemas.microsoft.com/ServiceHosting/2008/10/ServiceConfiguration">
  <Role name="WebRole1">
    <Instances count="1" />
    <ConfigurationSettings>
      <Setting name="DiagnosticsConnectionString" value="UseDevelopmentStorage=true" />
    </ConfigurationSettings>
  </Role>
</ServiceConfiguration>

Deploying the website to Azure

Now that we've finished everything we need to do locally, we can move to the Azure online management tool, where we'll need to create a new Hosted Service. Once that's made, we select either the production or staging environment for the service and select Deploy.... All we need to do here is select the package and configuration files, and give the deployment a name:


Azure will spend some time uploading the package, after which your service will be in the Stopped state.

After clicking Run the site should be instantly available.

In a later post, you'll see why I wanted to make sure we could use a web deployment without requiring a Web Application project.