How do you deploy your .NET Web Application? (Recommendations, please!)

I would strongly recommend using Continuous Integration.

We use a combination of TeamCity for CI, Rake and Albacore for automating the build.

TeamCity will check the code out of your source code repository, then, using Rake, build the application, execute unit tests and even run your database scripts if you so desire. After a successful build you can package your source code in a zip file or copy it to a destination of your choice.

We use Git, although TeamCity works with all source control systems.

Using TeamCity and Rake would be similar to using CruiseControl and NANT, without the XML file editing. Of course, you can use TeamCity with NANT if you prefer.

A short sample pulled from a rakefile.rb which performs the build. IMHO, easier to read and debug than an XML file.

require 'albacore'
require 'rexml/document'
require 'find'

VERSION_NO = "1.0"

OUTPUT_PATH = "output"
WEBOUTPUT_PATH = "output/web"
ADMINOUTPUT_PATH = "output/admin"

CONFIG = "Release"

WEB_PATH = "app/Company.Website.Web"
ADMIN_PATH = "app/Company.Website.Admin"
PACKAGE_PATH = "build/package"
DB_SCRIPT_PATH = "Company.Website.DB"
SOLUTION = "Company.Website.sln"

ARTIFACTS_PATH = "d:/build/artifacts/"

DEPLOY_WEB_PATH = "d:/deploy/company/website/"
DEPLOY_ADMIN_PATH = "d:/deploy/company/admin/"

task :default => ['setuptest','assemblyinfo','config','msbuild','createdb','sqlcmd','deploy']


task :setuptest do |setup|
  if ENV['BuildNumber'].nil? then ENV['BuildNumber'] = "000" end

  VERSION_NO = VERSION_NO + '.' + ENV['BuildNumber']
  puts 'Version Number : ' + VERSION_NO

  ZIPFILE_WEB = 'Company.Website.Web.' + VERSION_NO
  ZIPFILE_ADMIN = 'Company.Website.Admin.' + VERSION_NO  

  DB_SERVER = "WEB2"
  DB_DATABASE = "Website"  
  CREATEDB_SCRIPT = "app/Company.Website.DB/00CreateDatabaseTEST.sql"
end

  assemblyinfotask do |asm|
    asm.version = VERSION_NO
    asm.company_name = "Company Name"
    asm.copyright = "Copyright 2010"
    asm.output_file = "CommonAssemblyInfo.cs"
  end

  task :config do
    FileUtils.cp 'NHibernate.test.config', 'NHibernate.config'
  end

  msbuildtask do |msb|
    msb.properties = { :configuration => :Debug }
    msb.targets [:Clean, :Build]
    msb.solution = "Company.Website.sln"
  end

  sqlcmdtask :createdb do |sql|
    puts "executing sql scripts..."
    sql.log_level = :verbose
    sql.path_to_command = "sqlcmd.exe"
    sql.server = DB_SERVER
    sql.database = "master"
    sql.scripts << CREATEDB_SCRIPT
  end

  sqlcmdtask do |sql|
    puts "executing sql scripts..."
    sql.log_level = :verbose
    sql.path_to_command = "sqlcmd.exe"
    sql.server = DB_SERVER
    sql.database = DB_DATABASE
    sql.scripts << "app/Company.Website.DB/01CreateTables.sql"
    sql.scripts << "app/Company.Website.DB/02InsertReferenceData.sql"
  end

  task :deployprep do

    FileUtils.remove_dir 'app/Company.Website.Web/obj'
    FileUtils.remove_dir 'app/Company.Website.Admin/obj'

  end

  ziptask :zipweb do |zip|
    puts "creating zip package in " + ZIPFILE_WEB
    zip.directories_to_zip = ["app/Company.Website.Web"]
    zip.output_file = ZIPFILE_WEB  + '.zip'
    zip.output_path = File.dirname(__FILE__)
  end

  ziptask :zipadmin do |zip|
      puts "creating zip package in " + ZIPFILE_ADMIN
    zip.directories_to_zip = ["app/Company.Website.Admin"]
    zip.output_file = ZIPFILE_ADMIN  + '.zip'
    zip.output_path = File.dirname(__FILE__)
  end  

Albacore is suite of Rake tasks specifically build for deploying .NET application.


On Linux, I've used fabric (fabfile.org) and capistrano (capify.org) which are automation tools to assist in remote SSH and SCP commands. If you have Cygwin installed on your windows hosts, you should be able to reuse these as deployment tools.


"Publishing" a web application in Visual Studio can be run from the commandline as msbuild "C:\proj\yourprojectpathandfilename.csproj" /deploydir:"C:\some\deploy\dir". The destination directory is a deployable web application.

The other answers covering your larger question are good. I'd also add that you should look at several open source web application projects and copy the build process you like most.


I agree with Scott that this can be very complicated and easily overlooked. Deployment strategy is very application specific as well. If your app is completely self contained in one folder it might be easier than an app that references the GAC. Which in turn might be easier still than a server that needs to maintain multiple versions of an app that references multiple versions of assemblies the GAC. We don't want to get started talking about policy files here :).

Having said all that combining the Microsoft Web Deployment Tool with Application Request Routing is one good option. In IIS7, it's possible to create install packages using the tool. It is also possible to point the tool to a web application and backup the entire app into an application archive folder. You can then deploy from this archive folder to an IIS6 or an IIS7 web server (IIS5 not supported). I would use application request routing like Scott suggested to separate live from test websites. Once you've verified the newly published website is good, you might set ARR to route to the new version.