Web Deploy Parameterization

by Web Deploy Team

Introduction to Parameterization

Web application development most often involves deploying code in different environments: development, staging, or production servers. Each environment might use a different set of resources, like database connection information, and Web Deploy is built with features that help transform web applications as they are deployed into different environments. In order to transform an application during deployment, different parts of the applications can be "parameterized", and, at deployment time, Web Deploy takes a user's input to replace different pieces of information within the application.

Different Ways to Deploy Applications: Live Synchronization, Web Platform Installer, and Visual Studio

The Web Deploy tool can be used to deploy an application in a couple of different ways. A web application can be synchronized live, from one server (perhaps the development server) to another server (perhaps the server that hosts the application on the web). Web applications can also be packaged into a .zip file, to be downloaded and installed by a wider, more general audience of developers. This is a model commonly used by "platform"-like apps (for example, Wordpress), and the application can later be easily installed by using a guided UI, namely Microsoft Web Platform Installer. Finally, Web Deploy is used behind the scenes by Visual Studio when developing and deploying web application (WAP) projects. In this case, Visual Studio automatically parameterizes most of the necessary parts of the web applications, with the ability to create custom parameters if necessary.

Creating and Parameterizing an Application to be Deployed with Microsoft Web Platform Installer

Microsoft provides an easy way to install over 50 popular web applications, like Wordpress, Joomla, Drupal, and DotNetNuke. These applications can be installed relatively quickly and easily with a guided UI by using either the Microsoft Web Platform Installer or Microsoft WebMatrix. Behind the scene, these UIs use the Web Deploy tool to install the application from a .zip package. In order to create an application package so that it can be installed by using one of these tools, a number of steps must be taken, including parameterizing parts of the application.

The following steps are required to turn an application into a .zip package that can be deployed with the Web Platform Installer:

  1. Create an application.
  2. Create a "manifest" file. This file tells the Web Deploy tool the different actions that are required to install the application. This includes things like copying files and setting up a database.
  3. Create a parameter file. This is the "parameterization" file that Web Deploy uses to identify the parts of the application that need to be transformed at the time of installation based on user input.
  4. Create a .zip file that contains the application, the manifest file, and the parameter file.
  5. Create an XML file that the Web Platform Installer will use to display and install the application.

This article presents each of these steps in detail.

Step 1 - Create an Application

An easy way to create an application to experiment with web deploy parameterization is to use WebMatrix. WebMatrix can be installed using the Microsoft Web Platform Installer, which you can download here. After installing Web Platform Installer, search for "WebMatrix" and install it:

Screenshot shows the Web Platform Installer 3 point zero window highlighting the Microsoft Web Matrix option to install.

After WebMatrix finishes installing, run the program and at the start screen select Site From Template:

Screenshot shows the directory of Microsoft Web Matrix to select the Site from Template folder.

The Site from Template page appears.

Screenshot shows the Site from Template folder with its templates.

Since the photo gallery template application can use a Microsoft SQL Server database, it is a good choice for showing how Web Deploy parameterization can be used.

On the Site from Template page, select Photo Gallery. In the Site Name box, enter the name "Vacation Pictures". Next, click OK to install the Photo Gallery application.

Out of the box, the photo gallery application uses a file-based, SDF database. However, most real-world applications use a non-file based database, so you will convert (or "migrate") the SDF database into a Microsoft SQL Server database. If you don't have SQL Server, use Web Platform Installer to search for "SQL Server Express 2008 R2". Next, click Add, and then click Install to install it:

Screenshot shows database search results highlighting S Q L Server Express 2 zero zero 8 R 2.

During the application setup, remember the administrative username ("sa") and the password that you enter:

Screenshot shows the Web Platform Installation window choosing the Mixed Mode Authentication option and specifying the password.

Now that a SQL server instance is available, navigate back to WebMatrix. In the bottom left corner of WebMatrix, click the Databases tab to open the databases workspace.

Screenshot shows the Web Matrix dialogue box with navigation tabs to select Databases option.

When the database workspace is open, click the database file , PhotoGallery.sdf, in the left pane:

Screenshot shows the files in Database workspace highlighting the PhotoGallery dot s d f file.

This should light up the Migrate button in the ribbon control at the top of the application. Click Migrate to begin the migration:

Screenshot shows the Microsoft Web Matrix window highlighting the Migrate navigation icon.

The Migrate Database dialog box appears:

Screenshot shows the Migrate Database dialog box with database authentication details.

Leave the default database name and SQL server name unchanged. Change the dropdown from Windows Authentication to Database Authentication. In Login and Password boxes, enter the database administrator's username and password (if you installed SQL Express, use the same values that you entered during installation.)

Click OK. The database migration begins.

After migration completes, you can verify that the application still works by running the application in a web browser. In the top control ribbon, click Run to launch the application in a web browser:

Screenshot shows a web browser window highlighting the Run navigation icon.

This should bring up an application that looks similar to this:

Screenshot shows that the application is launched successfully in a web browser.

Now you have an application that is ready to be packaged and parameterized so that other developers can download and install it by using Web Platform Installer. The next step is to set up a file that will tell Web Deploy the steps required to install the application.

Step 2 - Create a "manifest" file

The Web Deploy tool can perform a number of functions, including copying files, web server configuration settings, and databases. Each of these functions is made possible by a Web Deploy "provider". In order to install the application you just created, you'll use the iisApp provider, which helps copy files and create the application on the server; the setAcl provider, which sets necessary file permissions; and the dbFullSql provider, which sets up the database. In order to tell Web Deploy to use multiple providers during setup, you need to create a Manifest.xml file that declares these three providers in the following way (you can copy a sample from here):

Screenshot shows the manifest dot x m l icon.

<?xml version="1.0" encoding="utf-8" ?>
<msdeploy.iisApp>
  <iisApp path="Vacation Pictures" />
  <setAcl path="Vacation Pictures/App_Data" setAclAccess="Write, ReadAndExecute" />
  <dbFullSql path="CreateDBAndUser.sql" />
  <dbFullSql path="VacPicDBSchema.sql" />
</msdeploy.iisApp>

Let's have a closer look at each of these entries.

IISApp Provider

The iisApp entry points to the folder where the application content is located. For example:

<iisApp path="Vacation Pictures" />

The path value would be different if the application had a different name.

SetAcl Provider

The setAcl entry tells Web Deploy to grant read, write, and execute permissions to the "App_Data" directory when the application is installed. For example:

<setAcl path="Vacation Pictures/App_Data" setAclAccess="Write, ReadAndExecute" />

Different applications might require special permissions on other folders. In that case, you would create a different setAcl entry for each permission setting that was required.

DbFullSQL Provider

The dbFullSQL provider entries point to different SQL scripts that are used to create a database and user ("CreateDBAndUser.sql") and to set up the database tables ("VacPicDBSchema.sql") at installation time.

The CreateDBAndUser.sql script is a fairly simple script that can be copied from here:

Screenshot shows the Create D B And User dot s q l icon.

The VacPicDBSchema.sql is the script that creates all the tables in the database that the application uses. This file can created using the Web Deploy command line tool. From the command line, navigate to where Web Deploy is installed (typically %programfiles%\IIS\Microsoft Web Deploy <LatestVersion>) and enter the following command:

msdeploy -verb:sync -source:dbfullsql="data source=.\SQLExpress;initial catalog=PhotoGallery;user id=sa;password=<AdminPassword>" -dest:dbfullsql="c:\VacPicDBSchema.sql"

Make sure to replace <AdminPassword> with the appropriate SQL administrator password.

At a basic level, the above command uses the dbFullSql provider to copy data from a database using a database connection string ("-source:dbfullsql=…") and copies it to a database script file ("-dest:dbfullsql=…")

More Information About Providers and Manifext.xml

For more information about the above providers, and other providers that can be used in a manifest file, see the web application package reference page.

Step 3 - Create a parameter file

After you create the manifest file that tells Web Deploy how to install the application, you need to create a parameter file that tells Web Deploy how to transform certain settings so that the application can be customized to work in a specific user's deployment environment.

The basic pieces that would be useful to transform are:

  • The application name: if the end user that is installing your application wants to change the application name, you'll need to parameterize the application name.
  • The database name: a user might need to configure your application to run on a database that uses a different name. If so, you'll need to parameterize the database connection information.

Web Deploy reads parameterization information from an XML file. In this case, you'll call the file Parameters.xml. For this demo, the parameters file can be copied from here and looks like this (on the website, this XML file can be expanded into a code box like is used on this page):

Screenshot shows the parameters dot x m l icon.

Next, you'll learn now to parameterize the application name and the database name.

Parameterizing the Application Name

Web Deploy parameterization can be used to transform different kinds of input. Normally this involves searching for text in an XML file or text file and replacing it with different text. In the case of the application name, the file copying and the creation of the web site on the destination computer is handled by a Web Deploy provider. So, in order to parameterize the application name, you will actually have to parameterize the provider that you previously declared in the Manifest.xml file.

The provider in the manifest file can be thought of as the Source provider, which will read information from the application package that a user downloads. In turn, when the application is installed, a Destination provider is used behind the scenes to copy the content and create a web site on the user's machine. The Manifest.xml file contains the Source provider information, so in order to allow a user to change the application name; you need to parameterize the provider that was defined in the Manifest.xml file.

In the Parameters.xml file linked to above, this parameterization is accomplished with the first XML entry:

<parameter 
  name="Application Path" 
  description="Full site path where you would like to install your application (i.e., Default Web Site/PhotoGallery)" 
  tags="iisapp">
  <parameterValidation kind="AllowEmpty" />
  <parameterEntry kind="ProviderPath" scope="iisapp" match="Vacation Pictures" />
</parameter>

The important XML tag to notice is parameterEntry. This tells Web Deploy a few things: one, that you are parameterizing a provider in the manifest (kind="ProviderPath"); two, that you are parameterizing an iisApp provider (scope="iisapp"); finally, that you only want to replace entries in the manifest file that have the value "Vacation Pictures."

The second entry in the parameter file ('name="SetAclParameter1"') just makes sure that the setAcl provider in our Manifest.xml file uses the same name entered by the user for the iisApp provider, which is accomplished with the line 'defaultValue="{Application Path}/App_Data"'. The value in the brackets, {Application Path}, references the name of the first parameter.

Parameterizing the Database Name

The rest of the entries in the Parameters.xml file deal with parameterizing the database connection information. The 2nd-6th entries in the parameters file gather information from the UI when a user is installing the application through Web Platform Installer. These entries prompt the user for the database server which will host the database for the application ("Database Server"), the name of the database to create ("Database Name"), the database user to associate with the database ("Database Username"), and the password for that user ("Database Password"). To create the database and user, Web Deploy also needs the database administrator user ("Database Administrator") and password ("Database Administrator Password").

Finally, all of the information entered by the user is used by Web Deploy to actually execute the scripts that create the database (CreateDBAndUser.sql) and setup the tables (VacPicDBSchema.sql). These are the 7th and 8th entries in Parameters.xml:

<parameter 
  name="Create DB and DB User Connection String" 
  description="Automatically sets the connection string for the connection request."
  defaultValue="Server={Database Server};Database={Database Name};uid={Database Administrator};Pwd={Database Administrator Password};"
  tags="Hidden,SQLConnectionString,Validate">
  <parameterEntry type="ProviderPath" scope="dbfullsql" match="CreateDBAndUser.sql" />
</parameter>
<parameter 
  name="Populate DB Connection String" 
  description="Automatically sets the connection string for the connection request." 
  defaultValue="Server={Database Server};Database={Database Name};uid={Database Administrator};Pwd={Database Administrator Password};" 
  tags="Hidden,SQLConnectionString,Validate">
  <parameterEntry type="ProviderPath" scope="dbfullsql" match="VacPicDBSchema.sql" />
</parameter>

Again, since Web Deploy uses a provider to synchronize database information (as declared in the Manifest.xml file), these two parameter entries are 'type="ProviderPath"'.

Our "Vacation Pictures" application also keeps track of the database connection in the Web.config file. This parameterization is handled by the final entry in Parameters.xml.

More Information about Creating the Parameters.xml File

For more information about creating the Parameters.xml file, including the meaning of various tags and the different kinds of parameter entries, see the web application package reference page.

Step 4 - Create a Zip File that Contains the Application, the Manifest File, and the Parameter File

You now have the basic building blocks needed to deploy the application using Web Platform Installer, so you can now package the application into the appropriate package format. The package just needs to contain the Parameters.xml file, the Manifest.xml file, and the database installation scripts at the top (root) level of the zip package, and the application content in a subfolder.

In the lower left corner of WebMatrix, click the Site tab to navigate to the site's content.

Screenshot shows the Web Matrix dialogue box highlighting the Site tab.

The site page has a link to where the application content lives:

Screenshot shows the URL and Path of the application content.

Click the link to navigate to the application content. Navigate up another level from this folder and create a new folder called "VacationPicsWPIInstaller". Copy the application content folder, the Manifest.xml and Parameters.xml files, and the database installation scripts into the newly created folder:

Screenshot shows the application content folder with files and database installation scripts.

With all of the files selected, right click->Send to->Compressed (zipped) folder:

Screenshot shows the files right selected highlighting the Send to and Compressed folder options.

This zipped file can be named anything, but to work better with the demo, name it "VacationPicsWPIInstaller.zip".

This package now contains everything that is needed to deploy it with Web Platform Installer.

Step 5 - Create an XML File that the Web Platform Installer Will Use to Display and Install the Application

The applications and products listed by Web Platform Installer are defined inside an XML file. In turn, to install our application by using the Web Platform Installer, we need to create an XML "feed" that Web Platform Installer will use to display and install our application.

Create a Custom Feed

A feed that works with the application created in this demo can be copied from here:

Screenshot shows the VacationFeed dot x m l icon.

Two values need to be modified in order for the feed to work properly. First, in the middle of the feed is the path to where the "VacationPicsWPIInstaller.zip" is located on disk. It should look like:

<installerURL>file://C:/Path/To/ApplicationInstaller/VacationPicsWPIInstaller.zip</installerURL>

Change this value to point to wherever your application zip file lives.

Second, the Web Platform Installer uses a hash to verify that the file the application hasn't been tampered with. To generate a hash for your zip package, download a tool called File Checksum Integrity Verifier, which can be found here (https://download.microsoft.com/download/c/f/4/cf454ae0-a4bb-4123-8333-a1b6737712f7/windows-kb841290-x86-enu.exe).

After unpacking the application, run this command from the command line to generate a hash for your application package:

<PathToExtractedUtility>\fciv.exe -sha1 <PathToAppliationPackage>\VacationPicsWPIInstaller.zip

This will output the hash of the file, which will look something like this:

Screenshot shows the hash output for the application package.

Copy the long number and use it to replace the value in the feed XML that looks like:

<sha1>8e53a4a0ca097470e906bc9c2d6c6b0125e20f27</sha1>
Add the Custom Feed to Web Platform Installer

Now that we have a custom feed, we need to tell Web Platform installer to load this feed. Inside Web Platform installer, click the options link at the bottom of the application:

Screenshot shows the Web Platform Installer page with the Options link and Install buttons.

Fill out the path to the custom application feed, and then click Add Feed:

Screenshot shows a text field to add custom application feed.

Finally, click OK to close the options dialog.

If everything works, a new entry will be displayed in the Web Platform Installer:

Screenshot shows the Web Platform Installer 3 point zero Sample Applications window highlighting Vacation Picture App.

Click Add to test installing your application. If everything is working, you will be presented with a page to enter the parameters that you previously declared in the Parameters.xml file:

Screenshot shows the Web Platform Installation window to enter application information.

Fill out information for the application to finalize the installation. If everything is working, the application will launch inside WebMatrix after the installation completes. From there, you can click Run in the ribbon at the top of WebMatrix to view the application in a web browser.

For reference, you can download a copy of the original application used to create this demo from here:

Screenshot shows the VacationPics W P I Installer dot zip icon.

More Information about Creating Custom Application Feeds

The feed linked in this demo is missing a lot of information that Web Platform Installer will normally display to a user, like the date and time of the application's creation, a thumbnail image for the application icon, and the name of the author of the application. More information about creating custom feeds can be found on this blog post.

Scripts for this demo

CreateDBAndUser.sql

/**********************************************************************/
/* Install.SQL                                                        */
/* Creates a login and makes the user a member of db roles            */
/*                                                                    */
/**********************************************************************/

-- Declare variables for database name, username and password
DECLARE @dbName sysname,
      @dbUser sysname,
      @dbPwd nvarchar(max);

-- Set variables for database name, username and password
SET @dbName = 'PlaceHolderForDb';
SET @dbUser = 'PlaceHolderForUser';
SET @dbPwd = 'PlaceHolderForPassword';

DECLARE @cmd nvarchar(max)

-- Create login
IF( SUSER_SID(@dbUser) is null )
BEGIN
    print '-- Creating login '
    SET @cmd = N'CREATE LOGIN ' + quotename(@dbUser) + N' WITH PASSWORD ='''+ replace(@dbPwd, '''', '''''') + N''''
    EXEC(@cmd)
END

-- Create database user and map to login
-- and add user to the datareader, datawriter, ddladmin and securityadmin roles
--
SET @cmd = N'USE ' + quotename(@DBName) + N';
IF( NOT EXISTS (SELECT * FROM sys.database_principals WHERE name = ''' + replace(@dbUser, '''', '''''') + N'''))
BEGIN
    print ''-- Creating user'';
    CREATE USER ' + quotename(@dbUser) + N' FOR LOGIN ' + quotename(@dbUser) + N';
    print ''-- Adding user'';
    EXEC sp_addrolemember ''db_ddladmin'', ''' + replace(@dbUser, '''', '''''') + N''';
    print ''-- Adding user'';
    EXEC sp_addrolemember ''db_securityadmin'', ''' + replace(@dbUser, '''', '''''') + N''';
    print ''-- Adding user'';
    EXEC sp_addrolemember ''db_datareader'', ''' + replace(@dbUser, '''', '''''') + N''';
    print ''-- Adding user'';
    EXEC sp_addrolemember ''db_datawriter'', ''' + replace(@dbUser, '''', '''''') + N''';
END'
EXEC(@cmd)
GO

Manifest.xml

<?xml version="1.0" encoding="UTF-8"?>
<msdeploy.iisApp>
  <iisApp path="Vacation Pictures"/>
  <setAcl path="Vacation Pictures/App_Data" setAclAccess="Write, ReadAndExecute"/>
  <dbFullSql path="CreateDBAndUser.sql"/>
  <dbFullSql path="VacPicDBSchema.sql"/>
</msdeploy.iisApp>

Parameters.xml

<parameters>
  
  <parameter 
    name="Application Path" 
    description="Full site path where you would like to install your application (i.e., Default Web Site/PhotoGallery)" 
    tags="iisapp">
    <parameterValidation kind="AllowEmpty" />
    <parameterEntry kind="ProviderPath" scope="iisapp" match="Vacation Pictures" />
  </parameter>

  <parameter 
    name="SetAclParameter1" 
    description="Hidden - automatically sets write access for the app" 
    defaultValue="{Application Path}/App_Data" 
    tags="Hidden">
    <parameterValidation kind="AllowEmpty" />
    <parameterEntry kind="ProviderPath" scope="setAcl" match="Vacation Pictures/App_Data" />
  </parameter>

  <parameter 
    name="Database Server" 
    description="Location of your database server." 
    defaultValue=".\sqlexpress" 
    tags="DBServer, SQL">
  </parameter>

  <parameter 
    name="Database Name" 
    description="Name of the database for your application." 
    defaultValue="VacPicDB" tags="DBName, SQL">
    <parameterEntry type="TextFile" scope="CreateDBAndUser.sql" match="PlaceHolderForDb" />
  </parameter>

  <parameter 
    name="Database Username" 
    description="User name to access you application database." 
    defaultValue="VacPicDBUser" 
    tags="SQL, DbUsername">
    <parameterEntry type="TextFile" scope="CreateDBAndUser.sql" match="PlaceHolderForUser" />
  </parameter>

  <parameter 
    name="Database Password" 
    description="Password for the Database Username." 
    tags="New, Password, SQL, DbUserPassword">
    <parameterEntry type="TextFile" scope="CreateDBAndUser.sql" match="PlaceHolderForPassword" />
  </parameter>

  <parameter 
    name="Database Administrator" 
    description="Administrator username for your database." 
    defaultValue="sa" 
    tags="SQL, DbAdminUsername">
  </parameter>

  <parameter 
    name="Database Administrator Password" 
    description="Password that is associated with the database administrator account." 
    tags="Password, SQL, DbAdminPassword">
  </parameter>

  <parameter 
    name="Create DB and DB User Connection String" 
    description="Automatically sets the connection string for the connection request." 
    defaultValue="Server={Database Server};Database={Database Name};uid={Database Administrator};Pwd={Database Administrator Password};" 
    tags="Hidden,SQLConnectionString,Validate">
    <parameterEntry type="ProviderPath" scope="dbfullsql" match="CreateDBAndUser.sql" />
  </parameter>

  <parameter 
    name="Populate DB Connection String" 
    description="Automatically sets the connection string for the connection request." 
    defaultValue="Server={Database Server};Database={Database Name};uid={Database Administrator};Pwd={Database Administrator Password};" 
    tags="Hidden,SQLConnectionString,Validate">
    <parameterEntry type="ProviderPath" scope="dbfullsql" match="VacPicDBSchema.sql" />
  </parameter>

  <parameter 
    name="Connection String for Config" 
    description="Connection string to enter into config" 
    defaultValue="Data Source={Database Server};database={Database Name};user id={Database Username};password={Database Password}" 
    tags="Hidden, SQL">
    <parameterEntry kind="XmlFile" scope="\\web\.config$" match="//*[local-name()='connectionStrings']/*[local-name()='add'][@name='PhotoGallery']/@connectionString" tags="Sql, SqlConnectionString, Hidden" />
  </parameter>

</parameters>

VacationFeed.xml

<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <entry type="application">
    <productId>VactionPicApp</productId>
    <title>Vacation Picture App</title>
    <summary>App for posting vacation pictures</summary>
    <longSummary>Yet another app for posting pictures.</longSummary>
    <keywords>
      <keywordId>PicGalleryApp</keywordId>
      <keywordId>SQL</keywordId>
    </keywords>    
    <installers>
      <installer>
        <id>1</id>
        <installerFile>
          <!-- size of the package in KBs -->
          <fileSize>168</fileSize>
          <installerURL>file://C:/Path/To/ApplicationInstaller/VacationPicsWPIInstaller.zip</installerURL>
          <!-- SHA of the package file for signature verification -->
          <sha1>8e53a4a0ca097470e906bc9c2d6c6b0125e20f27</sha1>
        </installerFile>
        <msDeploy>
          <!-- Default page is a start page -->
          <startPage />
        </msDeploy>        
      </installer>
    </installers>
  </entry>
  <!-- Tab definition -->
  <tabs>
    <tab>
      <keywordTab>
        <id>SampleApplications</id>
        <name>Sample Applications</name>
        <description>Select from sample applications:</description>
        <!-- Subtabs definitions -->
        <keywords>
          <keywordId>PicGalleryApp</keywordId>
        </keywords>
      </keywordTab>
    </tab>
  </tabs>
  <!-- Keyword/titles of subtabs to group apps with those keywords under -->
  <keywords>
    <keyword id="PicGalleryApp">Picture Gallery Apps</keyword>
  </keywords>
</feed>