10

We've recently upgraded our ASP.NET Website to a Web Application and we're shocked by the sudden leap in difficulty when deploying it. Considering how common a task this must be, I was wondering what plug-ins/software people use to deploy a rapidly evolving, remotely stored, project (ie. a website)?

There must be a better way than just "Publishing" in Visual Studio and then having to manually FTP the files that have changed? Not least because the site goes down when we're uploading our .DLLs.

There are so many fiddly file exceptions that I'd must rather automate the process as much as possible, to prevent accidental uploads.

With our old solution (on our WebSite) we used Dispatch for ASP which totally rocked and made the entire process one click. Unfortunately it's not great for DLLs (as previously mentioned).

So how does your team do it?

Thanks for any advice.

PS - I've read that Visual Studio 2010 is supposed to address these shortcomings in VS2005/08, but until then...

Django Reinhardt
  • 2,256
  • 3
  • 38
  • 55

10 Answers10

5

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.

Jason Watts
  • 428
  • 1
  • 3
  • 10
  • dumb question: is there a similar solution as this for a Dreamweaver project? – djangofan Dec 23 '09 at 17:33
  • I don't know that you actually build dreamweaver projects, but you could still use continuous integration and file copying tasks built into rake. – Jason Watts Dec 23 '09 at 19:53
3

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.

user11094
  • 31
  • 1
3

"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.

Peter Seale
  • 141
  • 3
3

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.

Ameer Deen
  • 3,598
  • 4
  • 25
  • 27
2

PyroBatchFTP works great for this. It will push just the changes and you can script it so that you can push with a double-click of a batch file.

At Vaasnet we've setup the dream solution for ourselves, but it's fairly involved to setup but worth using some or all of these elements if you can. Here's what it is:

  • SVN on all of our dev machines
  • SVN on our build/deployment server
  • Cruisecontrol.net watches for changes to SVN and will build and stage just the necessary files to a staging folder
  • using PyroBatchFTP, we push to a staging site (triggered by Cruisecontrol so it happens automatically)
  • using IIS7 and Application Request Routing (ARR) and URL Rewrite, we have the following staging/production setup:
    • ARR up front will direct traffic to either instance 01 or 02, depending on which one is 'live' and which one is 'staging'
    • the FTP account is always bound to 'staging'
    • I have another mini admin site that will swap staging and live with a single click. It takes all of 1 second to switch with zero downtime and we can switch back again if we realize that something was wrong with that release (although it's rare since we can test it so easily before going live).

So the net result allows us to check into SVN and have it automatically build and push to production without any manual interaction. After we test on our staging URL and determine that it's ready to go live, we log into a simple site and with 1 click, it's live.

Scott Forsyth
  • 16,339
  • 3
  • 36
  • 55
  • i wish that product was free. it looks pretty cool. – djangofan Dec 21 '09 at 17:16
  • This sounds like precisely the type of thing we're looking for. I'll do a bit more research into it, but thanks for posting! – Django Reinhardt Dec 21 '09 at 19:38
  • Yeah, it's not free, but it pays for itself within the first hour of your time that it saves. That comes pretty quickly in a deployment situation like this. – Scott Forsyth Dec 21 '09 at 22:06
  • nice, one question though. You mention that instance 01 or 02 can be made live, and in case of issues, it can be switched back to other instance. What happens to user data in the database during that time? Half would be on instance 1 DB, and rest on other instance DB? – Saurabh Kumar Mar 16 '12 at 17:35
1

For another way that has not been suggested, I refer you to 'the Gu' and Web Setup Projects

This basically creates an MSI installer for your .NET application. This example is for VS2005, but I have VS2010 and the project type is still there. This can give you a lot of customization if you need it, or just the basic installation if you don't.

Personally where I work we just do an xcopy-style deployment, but I'd eventually like to just hand a package over to the server group, giving them the control in when and how it is deployed. (I think this might also makes it easier to do mass deploys using something like group-policy, but I'm not too familiar with that)

mpeterson
  • 255
  • 1
  • 11
0

There are lots of ways to skin this cat, really depends on how much access you can have on your server. My personal favorite method of late is to setup a build script within the project (typically using MSBUILD) that packages all deployment files, then use SVN to bridge those into production. And to version the production files.

Database-wise, best bet is to use some sort of migration framework. Again, a bunch of those running about and no real clear answer.

Wyatt Barnett
  • 725
  • 5
  • 14
0

Personally I just use a vbs script that i wrote myself to copy folders of specific filetypes to the dev server (i.e. leave out cs files, etc).

0

When I worked at a large .com company this is what we did with our .net deployments.

All of our source code and stored procedures were stored in SVN. Each night, a database job run and pull the production stored procs and slip them into a directory on SVN so that there was always a most current version in the source control.

On the day of deployment for a project, we would use an nAnt script to pull the projects from SVN, do a custom build of the projects and pulling any dependences that these projects needed. Once the nAnt script was run it was packaged into a self-extracting zip file. Stored procs that were associated with this deployment were checked into the source control and an excel spreed sheet was updated with the scripts to run and in which order.

When the deploymenet went off, the self-extracting zip file was transfered to the server where it was launched. All of the files were extracted into the correct directories and the DBA ran the stored procs on the prodcution database.

On a typical deployment using this system, we went from a five to six hour deployment to under an hour or less.

Good luck and hope this helps some in working out a way of deploying your application.

Chris
  • 810
  • 1
  • 7
  • 10
0

There must be a better way than just "Publishing" in Visual Studio and then having to manually FTP the files that have changed?

Occam's razor is typically the preferred approach: the simpler, the better. FTP is easy with little to no complications. Some people use XCOPY, Filezilla or WSFTP, others may use the MS Web Deployment Tool (which I'm not familiar with yet), but all-in-all, there is a better way of deploying ASP.NET web apps (and other apps in general). IMO, if deployment is taken into consideration from the beginning of development, deployment can be integrated with the web app which makes for a relatively pain-free and smooth deployment in the future.

As a .NET developer who has worked at several companies developing ASP.NET web apps ranging in size, complexity and number of users (from several hundred users to tens of thousands), IMO 'deployment' is often the most "fluid" topic. Some organizations take it too far in terms of bureaucracy while others don't address any issues with deployment at all. In my experience, issues with deployment tend to fall into 1 or more of 3 categories in terms of difficulties/failures:

  1. Deployment is ignored/forgotten in depth during the design phase: Most web apps tend to incorporate a web server and a database. Beyond application code, maybe some stored procedures and database tables, deployment doesn't need much thought. ASP.NET is more than capable of aiding in deployment but most often developers are distracted in terms of getting the actual application running and doing it's task while leaving the how of deployment as a separate issue.

  2. Deployment is complex across multiple systems and people at play: Complexity is a bitch. From MSMQ, T-SQL stored procedures and triggers, Reporting Services, SOAP/XML messaging, AD authentication, SSAS/SSIS, etc. etc. the number of technologies at play increase the number people involved. Worst of all, all these different components are typically managed by different entities within an organization. Unless everyone is in sync with one another, deployments can increase in complexity quickly leading to multiple points of failure.

  3. Laziness, apathy or lack of communication and/or management: From little to no documentation to lack of coordinated communication and protocol, it's easy to screw up a relatively simple process. Deployment should be a simple procedure with numerous checks in place all the while documenting what's done, but often it's never the case. Most people just want the damn site to be up an running. In my experience, people (non-programmers) don't really care until something goes really fubar. Responsibility seldom falls on just one person to actually do the deployment as no one really wants to be the reason for failure so accountability is usually dispersed.

There are so many fiddly file exceptions that I'd must rather automate the process as much as possible, to prevent accidental uploads. So how does your team do it?

I don't know of any vendors on hand to automate deployment although I wouldn't be surprised if there were a few. You could probably script a solution via VBScript/WMI or batch script a solution, but the reality is you need to tailor a solution together for more complex ASP.NET sites. Simple sites consisting of pages, database connectivity and nothing else, you don't need to do nearly as much so scale your deployment efforts in line with the complexity of the application itself.

So far, at my current work deployment is still done over FTP and moving a bunch of files. It's ugly, easy to screw up and there's no sense of an accurate history. Granted you could comb through FTP logs, no one really bothers to do so. Our apps are fairly simple without much need beyond FTP. How my team deploys our web apps is of really little to no use for you. Instead, I'd rather use this opportunity to suggest better practices.

  • Assume nothing. User accounts, R/W/X privileges, ACLs, firewalls, timing (when to deploy and how much time you have to do it), and if possible, test deployment to all environments before the final "launch date".
  • Before development actually begins, factor deployment into development. If it's a simple site, so be it. If there are numerous moving parts, factor all of it in and actually build a plan to which all the components (code, database, reports, queues, etc.) are all on the same plan.
  • Coordinate with other parities and communicate effectively and efficiently.
  • Document as much pertinent information if possible.
  • Environment: one web server vs. web farm; 32-bit vs. 64-bit; find a way to monitor logs/errors/rotate, etc.
  • Find (or build) tools that can aid in deployment.
  • If possible for programmable deployment, pick a paradigm and stick with it. For example, if you want to use a database server as the primary means for carrying out an application's state, deployment, access and such, bake it into the application and stick with it. If you prefer reading XML files (like web.config) by all means, just stick with a consistent paradigm of deploying the application. Another example: some organizations leave web.config as a static file in each environment that should not be deployed to other environments. Other's program web.config in such a way that it can be deployed across environments without error.

I realize that this post might be overkill for the question that was originally asked. Unfortunately, deployment just isn't a simple thing as applications can vary in complexity. I'd bet that most organizations that deploy complex ASP.NET apps have over time developed certain strategies the work (at the least) reliably.

osij2is
  • 3,875
  • 2
  • 23
  • 31
  • lol... i love how you quote parsimony but then you go on to give the most complex answer. lol. – djangofan Dec 21 '09 at 17:18
  • 1
    Yeah, I realize my answer is contradictory to itself. I've just encountered numerous deployments that go wrong that I'm *very* tired of it. Sorry for the rant! – osij2is Dec 21 '09 at 19:00
  • 1
    There is a newish tool from Red Gate: http://www.red-gate.com/supportcenter/Content/Deployment_Manager/help/1.0/dm_how_dm_works – Matt Evans Feb 04 '13 at 13:57
  • @Matthew Evans - NICE! I'm looking at the URL right now. Was this a new third party acquisition or their own product? – osij2is Feb 04 '13 at 15:35
  • I think its their own product. They developed and use it internally for all their own deployments - which sounds promising. Will update on my own evaulation when I get to it – Matt Evans Feb 05 '13 at 07:35