Developing ASP.NET web applications with IIS

When you File -> New Project an ASP.NET application in Visual Studio and then F5 by default it will spin up IIS Express and navigate to the site for you.

IIS Express is pretty cool – it runs under your user account so no need to mess around with elevated privileges, it has most of the power of IIS (think web.config) and it “just works” out of the box without extra configuration needed across all dev machines 🙂

For projects that I work on every day though, I really dislike using IIS Express as a development server for the following reasons:

  • It will randomly crash
  • When it crashes I have to F5 or Ctrl+F5 in Visual Studio to restart it – I can’t just go to the last url it was deployed to (e.g. http://localhost:port/)
  • If your code has an uncaught exception then a crash dialog pops up in your taskbar in a way that isn’t obvious and requires you to click a button until the code continues running (this can be very confusing)
  • Setting up a custom domain is tricky to do, is a tedious manual process and can’t run on port 80 side-by-side with proper IIS
    • Using a custom domain is often essential too – think sharing cookies between domains or performing something like integrating with third parties where you need to provide a URL other than localhost

Part of the reason IIS Express exists is because setting up IIS with a site is not a trivial process. However, when you do eventually get it set up I usually find it works great from then on:

  • It’s stable
  • The URL is always available – you don’t have to use Visual Studio at all
  • Uncaught exceptions behave as expected
  • Custom domains are easy in both the IIS Manager GUI and via a variety of commandline options

In order to reduce the pain involved with setting up IIS I do two things:

  • I modify my Visual Studio taskbar icon to always run as admin (necessary to open a project bound to IIS)
  • I add a Developer Setup script to the project that developers must run once when they first clone the repository that sets up everything up for them in a matter of seconds (hopefully giving the same Open Solution -> F5 and start developinging experience)
    • I’ve added an example of such a script to a Gist – the script also includes setting up the hosts file and a SQL Express database
    • I can’t claim full credit for the script – it’s been a collaborative effort over a number of projects by all of the Readifarians I’ve worked with 😀

Web Deploy Package Connection String Parameterisation Problem

I recently came across a problem using web deploy packages, and more specifically with connection string parameterisation. I was generating a web deploy package using the “Package” MSBuild command and then deploying to a remote server using MSDeploy. The problem I came across was that the parameterised connection strings weren’t being replaced.

That resulted in the deployed web.config file looking something like this:

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  ...
  <connectionStrings>
      <add name="SomeConnectionString" connectionString="$(ReplacableToken_SomeConnectionString-Web.config Connection String_0)" />
  </connectionStrings>
  ...
</configuration>

I used a variety of approaches – DeployOnBuild MSBuild command, Visual Studio GUI interface, the generated .cmd file and direct msdeploy call – to deploy the package to check whether the problem was simply that I was somehow deploying it incorrectly, but they all resulted in the same problem.

Most of the Google results that came up simply said to turn off parameterisation, but in this instance I wanted to use parameterisation. While I was using XDT transformations, I also wanted to use connection string parameterisation so I could substitute the connection strings for entries in a password safe as part of an automated deployment step.

The build output wasn’t terribly helpful, so I passed the verbose option to msdeploy and got the following interesting output:

...
[16:08:33][Step 2/2] Verbose: Parameter entry 'SomeConnectionString-Web.config Connection String/1' could not be applied anywhere.
[16:08:33][Step 2/2] Verbose: The dependency check 'DependencyCheckInUse' found no issues.
[16:08:33][Step 2/2] Verbose: The synchronization completed in 2 pass(es).
[16:08:33][Step 2/2] Total changes: 10 (0 added, 0 deleted, 10 updated, 0 parameters changed, 1004778 bytes copied)
[16:08:33][Step 2/2] Process exited with code 0

This didn’t really make a huge amount of sense and after some sanity checking to make sure parameterisation does actually work (created a new ASP.NET website and deployed it successfully) I started comparing all the differences in my .csproj configuration to a blank project. After some tedious trial and error I managed to narrow the errant configuration to the following (seemingly) innocuous line:

<BaseIntermediateOutputPath>$(ProjectDir)..obj</BaseIntermediateOutputPath>

You might be asking why I had that line in there in the first place? It is certainly a bit weird and you would normally expect it to be set to “obj”. In this case it was there so that when MvcBuildViews was next executed after building a package it didn’t choke with the following error (on the intermediate web.config files in the obj folder):

It is an error to use a section registered as allowDefinition='MachineToApplication' beyond application level.  This error can be caused by a virtual directory not being configured as an application in IIS.

When I initially came across that problem I changed the location of the obj folder since it seemed the best option compared to the other options such as running clean before all builds or deleting the obj folder, both of which would slow down the build and be tedious and annoying. Also, I didn’t want to turn MvcBuildViews off since I want assurance on the build server that the views all compiled fine.

Since this was no longer an option (up until this point all web deploys were done manually so we hadn’t actually come across this new problem!) I came up with the following configuration as a solution (props to my Senior Dev, Matt Davies, for finding the relevant StackOverflow post for the inspiration):

  <Target Name="CleanPackage" BeforeTargets="MvcBuildViews" Condition="'$(MvcBuildViews)'=='true'">
    <CallTarget Targets="CleanWebsitesPackage" />
    <CallTarget Targets="CleanWebsitesPackageTempDir" />
    <CallTarget Targets="CleanWebsitesTransformParametersFiles" />
  </Target>
  <Target Name="MvcBuildViews" AfterTargets="Build" Condition="'$(MvcBuildViews)'=='true'">
    <AspNetCompiler VirtualPath="temp" PhysicalPath="$(WebProjectOutputDir)" />
  </Target>

Basically, if you have MvcBuildViews set to true then it will run MvcBuildViews directly after the build and before running MvcBuildViews it will run the CleanWebsitesPackage, CleanWebsitesPackageTempDir and CleanWebsitesTransformParametersFiles targets which clean up the web deploy package files and thus the web.config files that mess with MvcBuildViews.

Update (17 Feb 2013)

If you are trying to use the above MSBuild with Visual Studio 2012 then it won’t work. I have blogged a solution that works in both Visual Studio 2012 and Visual Studio 2010 though.

Getting up and running with Database testing quickly in .NET

When I first started learning about how to do database code in .NET and in particular how to test your database code I came across a really useful post on the Code Project.

It basically goes through a tutorial on how to get a base class set up that sets up a brand new SQL Server CE database every test run and populates it from an NHibernate configuration.

This was great, but there were a number of issues that caused it to not work for me (including the fact I decided to use Fluent NHibernate rather than writing a heap of obscure XML). As well as this, there were a couple of fundamental flaws in the way the test worked and it didn’t work with the latest versions of SQL Server CE and NHibernate at the time.

Consequently, I fixed up the code so it worked and I wanted to outline those changes and the final result here in case anyone finds it useful.

Continue reading “Getting up and running with Database testing quickly in .NET”

Source Code Indentation

I hate using spaces for indentation. I’m just putting it out there. My work mates think it’s a bit silly to have such a strong opinion on such a minor (mostly invisible) thing, however the pedantic perfectionist in me feels strongly about this.

Why do I hate using spaces for indentation? I’ll let the comparative advantages (and disadvantages) speak for themselves.

Continue reading “Source Code Indentation”