Thursday, December 10, 2009

Web Site Project vs. Web Application Project

My organization has decided to migrate an existing Web Site Application (WSP) to a Web Application Project (WAP).  This is a quick post to share the decision-making process highlights and to consolidate some of the references we consulted.

I found an MSDN article Introduction to Web Application Projects that gave a nice WAP overview with a simple decision matrix for choosing between WSP and WAP.

I found these blog posts to be particularly helpful on how to make a decision, especially Vishal Joshi’s thorough and knowledgeable comparison:

My broad impression after reading these various resources is that the WSP is best suited for demo or small web sites, or if there is a strong case for granular deployment (e.g., deploy an individual web page).  WAP is the clear favorite for enterprise production web sites.

Our decision to switch to WAP came down to these four key factors that favor WAP:

  • Better support for unit testing
  • Better support for continuous integration
  • Upcoming Web Deployment features (VS 2010) only support WAP
  • Better control over application development (e.g., Namespace control)

Conversion assistance from WSP to WAP is available as an online tutorial and as an MSDN article.

Wednesday, December 2, 2009

Continuous Integration Server Setup – Part 2

This is the second part of my process for setting up a prototype Continuous Integration server using CruiseControl.NET.  I describe the server setup in Part 1.  This post describes how I configured my projects and unit tests using the ccnet.config file.

I decided to use a Visual Studio 2008 console application solution as the test for my prototype CI server.  There were some steps required to set up that solution to build and test properly in a CI environment.  I detailed the solution configuration steps in a separate blog post.

I then edited the ccnet.config file to build and run my projects and unit tests.  I extensively followed the advice of Geoff Lane from his DRY your CruiseControl.NET Configuration post.

  • I defined reusable variables and blocks
  • I split my ccnet.config file into multiple parts.
    • The ccnet.config file itself contains the variable and block definitions that are shared by all projects.  It imports the user information and all project information from external files.  The ccnet.config file is managed in source control.
    • Individual project files config contain variable and block definitions specific to the projects.  All project files are managed in source control.
    • The user information is stored in a separate config file and contains the plain text UID and PWD for connecting to the SubVersion server.  The user config file is not managed in source control as a security precaution.

Download sample CruiseControl.NET ccnet.config and other config files

Here are some other Key Points:

  • The <artifactDirectory> and <workingDirectory> values should exactly mimic the folder structure in the Visual Studio solution so that all references are valid when the projects are checked out to the CI server.
  • Set the <webURL> value to use the actual host name (rather than localhost) so that CI email notifications contain a valid clickable link.
  • I configured my NUnit tests to run using the <nunit> task block, but I could have configured the unit tests to run as part of the MSBuild process in the .csproj file.
  • I configured the email publisher so that details are not included (<email includeDetails=”false” … />).  Including the details is a handy feature, but I discovered that anytime there was an exception when trying to connect to the SubVersion server, the cruisecontrol UID and password were included in the email details.
  • I manage the ccnet.config file itself in source control and added a CCNET project to the top of the ccnet.config file to check out the ccnet.config file.  In other words, set up CCNET so that when any developer makes a change to the ccnet.config file, the updated file is immediately checked out to the CI server by the previous version of the ccnet.config file.

Next steps to take the prototype to prime time on a production CI server:

  1. Resolve errors I am still seeing in the build logs – there are four occasional error messages:  “Source control operation failed: svn: OPTIONS of 'project name': Could not read status line: An existing connection was forcibly closed by the remote host” or “Source control operation failed: svn: Server sent unexpected return value (401 Authorization Required) in response to PROPFIND request for 'project name'” or “Source control operation failed: svn: OPTIONS of 'project name': SSL negotiation failed: An existing connection was forcibly closed by the remote host” or “Source control operation failed: svn: Server sent unexpected return value (401 Authorization Required) in response to REPORT request for 'project name'.”  I can think of several possible causes for these errors:
    1. These errors might go away when the CI server is set up as a true production server instead of as a VM virtual server.
    2. The CI server has a newer version of svn.exe than the version of SVN on the source control server.
    3. The self-signed certificate used by the source control server might have to be replaced with a commercial certificate.
  2. Consider changing my strategy so that NUnit tests are run after the build by MSBuild (rather than as a task in the ccnet.config file).  Using MSBuild is the recommended strategy suggested by the CCNET documentation and by Craig Berntson’s Continuous Integration for .NET Development white paper.
  3. Most of my projects are developed against the ESRI ArcGIS Server framework, which loads all of its assemblies to the GAC.  Despite best efforts to use local Lib copies (with Browse references) of the ESRI assemblies, it looks like the CI server will need to install ArcGIS Server to avoid build or test errors.

Continuous Integration Server Setup – Part 1

I just finished setting up a prototype Continuous Integration server with CruiseControl.NET with a lot of help from Jeff McWherter and by following many of the suggestions in a white paper by Craig Berntson.  Here are the steps and lessons learned from this experience.

I built the prototype server in VMWare using Windows Server 2003 with a C: and E: drives, and created an administrator account.  Here are the next steps:

  1. Installed CruiseControl.NET 1.4.4 SP1 accepting all defaults
  2. Created an E:\Tools folder to contain all of the necessary utility applications (e.g., E:\Tools\nUnit\bin\net-2.0\nunit-console.exe and E:\Tools\svn\svn.exe)
  3. Created a cruisecontrol user in my organization’s ActiveDirectory and then added a local Windows account for this user.  This user has read-only privileges to the SubVersion repository.
  4. Configured the CruiseControl.NET service to start automatically and to Log On using the cruisecontrol account: Selected the service, opened the Properties, Log On tab, This account radio button, browsed to the cruisecontrol account, entered the password, applied, then restarted the service. 

I then did a little fine-tuning of the CC.NET configuration files:

  • I did not change ccnet.exe.config
  • I edited ccservice.exe.config
    • In <appSettings>, I inserted the key <add key=”ccnet.config” value=”config\ccnet.config” />
    • I did this so that my config files are cleanly grouped into the C:\Program Files\CruiseControl.NET\server\config folder.
  • I edited dashboard.config
    • I commented out all unwanted <xslFileNames> entries from the <buildReportBuildPlugin> block
    • I commented out all unwanted <xslReportBuildPlugin> entries from the <buildPlugins> block
    • I did this to remove unused tests and builds from my dashboard.

The final step was to resolve a problem due to our SubVersion server using a self-signed certificate, which would cause an error when CruiseControl.NET tried to check out any of the projects (error message = “Server certificate verification failed: issuer is not trusted”).

  1. I tried various ways to accept the SubVersion server certificate without success by following the suggestions in the CruiseControl.NET documentation.
  2. I finally resolved the problem by importing the certificate using IE:  browsed to the SubVersion server, continued past the certificate error warning, entered my credentials, clicked the IE Certificate Error button (to the right of the URL), clicked the View Certificates link, clicked the Install Certificate button, and accepted all defaults.

That’s it for the overall setup steps on the CI prototype server.  In Part 2 I will describe how I configured my ccnet.config file to build and test my projects automatically.