Automating Visual Studio 2010 builds and deployments with Nant.Builder

Part 2 in my Visual Studio 2010 Turbo series

  1. Visual Studio 2010 Workflow
  2. Automating Your Builds with Nant.Builder
  3. DIY AppHarbor – Deploying Your Builds onto Windows Azure

In this post I look at using Nant and my Nant.Builder nuget package to quickly get your builds automated, from here it should be simple for you to integrate with a CI tool of your choice.

Update (27/07/12) – Anoop Shetty has put together an awesome post on using Nant.Builder here.  Thanks Anoop 🙂

Nant and Nant.Builder

I’ve been using Nant for years now, it’s a great tool for scripting and automating tedious build and deployment tasks.  Some might say it’s getting a bit long in the tooth, and it’s not as hip as rake etc.  However, I find it perfectly usable, with a learning curve that’s not too steep, it’s very well documented and it’s updated usually once or twice a year.

I’ve recently been doing more and more with Nuget, and I’m increasingly finding it a very powerful way of quickly setting up new projects.  One task that always takes a bit of time is setting up a build script for the new project.  Usually I’d cut and paste an existing script and hack out the bits that needed changed.  This was painful, and I wanted to get rid of this boring step, so Nant.Builder was born.

Installing and Integrating Nant

Hopefully you’ve followed part 1 of this enthralling series, so if you haven’t get Nant installed, download the latest stable build and extract it c:\dev\tools\nant-0.91.  If like me you’re trying to do more from the command line, add the bin directory into your Path environment var, ie C:\dev\tools\nant-0.91\bin

Open powershell and type nant you should see something like this, don’t worry about the Failure message for now:

NAnt 0.91 (Build 0.91.4312.0; release; 22/10/2011)
Copyright (C) 2001-2011 Gerry Shaw
http://nant.sourceforge.net

Nant can also be launched from Visual Studio.  Go to the Tools | External Tools menu option, click Add and complete as per screenshot, ensure you tick the Use Output Option.   You can now launch Nant from VS.

Install Nant.Builder

If you followed the first installment of this series you should have your new Solution in your workspace.  Now lets setup Nant.Builder:

  • Add a new empty project and name it  <yoursolutionname>.Build, ensure you save it in the src directory.  We’ll use this project to hold our build scripts.

  • We don’t want the compiler to build this project so click Build | Configuration Manager.  Untick build on any configurations

  • Now we can install Nant.Builder from Nuget run the following command, from the package manager command line:
install-package nant.builder -projectname <yoursolutionname>.Build
  • We now have Nant.Builder installed into your .Build project 🙂

Configure Nant.Builder for your solution

I’ve tried to keep configuration to the bare minimum, as the whole point is to keep things fast.

  • Open the Nant.Build file.
  • Set the solution.name property to the name of your solution, in our example SampleSolution
  • If you’ve set up your workspace as described in the Workspace blog, you won’t need to edit solution.src.dir.  If you don’t save your projects in a source dir, and save them in the same directory as the .sln file, edit this property to blank, ie “”
  • Set the solution.projects property to a comma separated list (no spaces) of all the projects contained in your solution, in our example SampleSolution.Services,SampleSolution.Tests,SampleSolution.Web
  • Set the release.configuration property to the configuration you want the solution to be compiled under, default is Release
  • If you’re not using CI, you can manually set the version number.  Nant.Builder will then version all your dlls with the version number you specify.  If you are using CCNet, Nant.Builder will pick up the version number from CCNet
  • Set the company.name property to the name of your company, this will also be added to the Assembly.Info, so users can see who created the dll
  • So in our sample we have this:
<!--The name of your solution, please overwrite the default -->
<property name="solution.name" value="SampleSolution"/>

<-- If your projects reside in a different directory from the .sln file specify here, or leave empty if not -->
<property name="solution.src.dir" value="src" />

<!-- Comma seperated list of projects contained in your solution -->
<property name="solution.projects" value="SampleSolution.Services,SampleSolution.Tests,SampleSolution.Web" />

<!-- Set the configuration for compilation, typically release, but may be custom -->
<property name="release.configuration" value="Release" />

<!-- Manually set version, if using CCNet this will be overwritten later -->
<property name="version.tag" value="1.0.0.1"/>
<property name="company.name" value="iainhunter.wordpress.com" />

If you’ve followed the first tutorial you shouldn’t need to change anything in GlobalBuildSettings.xml.  However, if you have a different workspace, buildspace, or have msbuild4 located in a non-standard location, set the values appropriately or you’ll get errors.

Running Nant

We can now run Nant from the command line by opening powershell, navigate to your Build directory, eg C:\dev\work\SampleSolution\src\SampleSolution.Build  then type Nant.  Your solution should build, or throw errors if you have warnings etc.

Alternatively in Visual Studio open the Nant.Build file, then in Tools  run your new Nant tool you created above.

Now if you navigate to your builds directory C:\dev\builds\SampleSolution you should see your build, and if you look at one of the Dlls you should see it has been versioned according to your instructions

Next steps

Nant.Builder is available on github here, so feel free to fork or send me a patch if you think it can be improved.  I’m planning to add a few enhancements like a msdeploy task etc, we’ll see how time allows.

Next time

We alter Nant.Builder to automatically deploy your solution onto Windows Azure

Advertisement

Visual Studio 2010 Turbo – Workflow

Recently I’ve been attempting to streamline my workflow, to help me Get Things Done 🙂  So I thought I’d share some of that work, in a mini-series of blog posts:

  1. Visual Studio Workflow
  2. Automating Your Builds with Nant.Builder
  3. DIY AppHarbor – Deploying Your Builds onto Windows Azure

Tool Up

I won’t spend much time expounding on the tools that I use, as excellent guides are but a Google search away, but I’d recommend installing and using the following:

  • Powershell – Yeah it’s a bit clunkier than bash, but it’s extremely powerful and lets you easily automate your day to day life
  • Console2 – A nice way of working on the CommandLine and Powershell- read Hanselman’s excellent guide
  • Git – As a looooong time SVN user and aficionado I was reluctant to move to Git, but now I have I have to confess I’m enjoying the experience
  • PoshGit – Work with Git in Powershell, read Haack’s excelent guide to getting it set up here and here.
  • Nant – My build tool of choice, I’ll talk about it a bit more in follow up posts.
  • Nuget – Jump start your projects with this excellent package manager, and then upload some packages of your own 🙂

Configure your workspace

I’d encourage all dev teams to configure their workspace in the same way.  That way you can jump onto a colleague’s machine and you’ll know where to go to find the code if pairing etc.  Also it makes it easy to share buildscripts around the team.  I set up my workspace as follows:

C:\dev 
    \builds 
    \releases 
    \tools 
    \work

So all work is done in the C:\dev dir.  We then create 4 subdirs:

  • builds – used solely by your build tool to copy files into for compilation, running unit tests etc
  • releases – used by your build tool to copy your solution in a format that can be easily released, ideally any subfolders here would be dated or versioned
  • tools –  contains any tools you use to help with developing code, ie Nant, NUnit etc
  • work – the main event, contains all your various solutions

So for example we might have:

C:\dev 
	\builds 
		\DemoApp1 
	\releases 
		\DemoApp1-Build-120508-0915 
		\DemoApp1-Build-120508-1115 
		\DemoApp2-Build-120507-1506 
	\tools 
		\Nant-0.91 
		\Nunit-2.6 
	\work 
		\DemoApp1 
		\DemoApp2

Creating a new empty solution

A number of years ago I read the excellent Code Leader, the author advised using a tool called TreeSurgeon to set up a new solution.  This tool is slightly long in the tooth now and could do with being updated, but you can follow the guide below to quickly define a new solution in the same style:

  • Create a new blank solution in c:\dev\work and name it after your project  – eg SampleSolution

  • Your solution will open in Visual Studio and will contain only the solution file.  Now you can add projects to your solution you might want to add a Web project a Services project and a Tests project.
  • So right-click on the solution file and select Add | New Project
  • As per .Net convention you should call the various projects <solutionname>.<projecttype>.  So we’ll add SampleSolution.Web, SampleSolution.Tests, SampleSolution.Services.
  • When you add the project ensure you set the location of the project to the /src folder within your solution

  • Right-click on the solution file again and select Enable Nuget Package Restore.   Click Yes when you get the pop-up about wanting Nuget to manage packages restores for you.  A couple of nuget files will be added to the root of your solution.

We should now have a nice neat solution, with all projects saved in the src dir, eg:

Next Steps

Now to test if Nuget is working lets add a package to see if all is working as expected, lets add the awesome Twitter Bootstrap.  So if we run the command in the Package Manager console

install-package TwitterBootstrap

Twitter Bootstrap will be installed successfully, and if we now look at our Solution dir, you’ll see we now have a new packages dir, containing Bootstrap and its dependencies

Now that we’re happy you can add your solution to the source code management tool of your choice, I’d recommend checking out Git.  BTW with nuget installed, you do NOT add the Packages directory to Source Control.

Next time

I’ll look at using Nant, to quickly build our solution.

CRUD – Destroyer of Worlds

As web developers a large part of what we do is CRUD.  The average Service class in my project is at least 50% CRUD methods, and often a lot more.

If you’re anything like me, you’ve probably not given much thought to CRUD methods, you just write them as required.  However, I recently had a small epiphany, this approach to CRUD was making the code base sprawl, approaches to CRUD from the team were non-standard.  Which was leading to new CRUD methods being created, when not required, because of the difficulty of understanding what was there.

I wouldn’t start from here…

So how did it come to this?  I use the Repository pattern for my DB layer and for whatever reason a lot of the documentation around this pattern have method signatures like this:

Customer GetCustomerById(int customerId)
Customer GetCustomerByAddress(Address address)

Thinking that this was the accepted pattern I just blindly started adding this style of methods into my code base, not only in the Repository but in the Service layer too.

Here’s an interface from out codebase for working with images, were you can see CRUD methods jumbled in with other methods to get PagedLists etc.  All in all not very obvious.

public interface IMediaItemsService
{
    PagedList<MediaItem> GetForUserId(int userId, MediaTypeEnum mediaType, int page, int pageSize);
    List<MediaItem> GetForUsername(string username, MediaTypeEnum? mediaType, int? numRecords);
    void Save(MediaItem mediaItem);
    void Delete(MediaItem mediaItem);
    void Delete(int mediaItemId);
    void Delete(int mediaItemId, int currentUserId);
    MediaItem GetByMediaItemId(int mediaItemId);
    MediaItem GetByUniqueId(Guid uniqueId);
    IPagedList<MediaItem> GetAll(int page, int pageSize);
    IPagedList<MediaItem> Search(MediaSearchParams mediaSearchParams, int page, int pageSize);
    MediaItem Update(MediaForm mediaModel);
    IEnumerable<MediaItem> GetAllMediaItemsForRequest(Guid uploadRequestId);
}

The Anti-Pattern

What I’ve come to realise is the Byxxxx is an anti-pattern and makes your interfaces far harder to work with.

Not only that but we had some non-standard approaches to Creates, sometimes called Save (does this do updates), Delete maybe called Remove etc.  The upshot being that when approaching adding some functionality you had to study the Service class to separate the CRUD methods from other methods.  It was at this point I realised there was a much better approach to dealing with CRUD (credit must go to @leegunn for planting the germ of the idea).

Convention over Configuration, Overloading and Areas

In my opinion, the most important message from Convention over Configuration (taken from the Wikipedia article) is:

“… a software design paradigm which seeks to decrease the number of decisions that developers need to make…”

So I came up with the following CRUD conventions for our project

  1. CRUD Methods will be added at the top of each method in a Region called CRUD
  2. All CRUD methods should be overloaded where-ever possible
  3. Overloads should ideally call down to one method containing all the business logic – (hopefully I’ll manage to expand on this in an additional post).
  4. CRUD methods should be entered in the order Create, Read, Update, Delete.
  5. Create Methods will be named Create, and should always return the object that was created
  6. Read Methods will be named Retrieve where they return a single object
  7. Read Methods will be named  RetrieveAll  where they return an IEnumerable<T> collection of objects
  8. Update Methods will be called Update and should always return the object that was updated
  9. Delete methods will be called Delete and return void, an exception may be thrown if an error occurs during the transaction.

The Results

By applying these rules to the interface above we get:

public interface IMediaItemsService
{
#region CRUD

MediaItem Create(MediaItem mediaItem);
MediaItem Retrieve(int mediaItemId);
MediaItem Retrieve(Guid uniqueId);
IEnumerable<MediaItem> RetrieveAll(Guid uploadRequestId);
IEnumerable<MediaItem> RetrieveAll (string username, int? numRecords);
MediaItem Update(MediaForm mediaModel);
MediaItem Update(MediaItem mediaItem);
void Delete(MediaItem mediaItem, int currentUserId);
void Delete(int mediaItemId, int currentUserId);
void Delete(MediaItem mediaItem, int currentUserId, bool isAdmin);
void Delete(int mediaItemId, int currentUserId, bool isAdmin);

#endregion

IPagedList<MediaItem> GetAll(int page, int pageSize);
PagedList<MediaItem> GetForUserId(int userId, MediaTypeEnum mediaType, int page, int pageSize);
IPagedList<MediaItem> Search(MediaSearchParams mediaSearchParams, int page, int pageSize);
}

By leveraging overloading where-ever possible we’ve got rid of Byxxx, which makes working with Reads a lot easier.  I can just do MediaItemsService.Retrieve and study the available overloads.  Same for Updates, Deletes etc.

Additionally by separating your interfaces into CRUD and Non-CRUD methods, it makes it easier to spot when a new class, factory etc might be appropriate.  In our case we can see that the non CRUD methods could do with being refactored, possibly rename to RetrieveAllPaged etc.  The point being the refactoring is now easy to spot.

So by conforming to CoC principles for CRUD methods, we’ve definitely decreased the number of decisions our devs needs to make.  Score! 🙂

Postscript

While writing this post I came across an intriguing idea mentioned at the bottom of this Stackoverflow question about using lambda expressions within your CRUD interface, to allow you to effectively pass a query through to the DB.  This would drastically cut down on overloads not to mention repository methods.

So interface would be

T Single<T>(Expression<Func<T, bool>> expression) where T : class, new();

Usage would be

var user = _dbService.Single<User>(user => user.ID == 12);

There are a few things that could make this tricky to work with, especially if you needed to enforce business rules etc.  However, as a starting place for working with CRUD it’s a really smart idea, and warrants more investigation.

Update 07/12/11

After comments from @alanjmburns I decided he was right and the Delete methods are better to return void rather than a status, and throw an exception if necessary.

Resharper – Going too var?

Since installing Resharper 5.1, about a year ago, I’ve found it to be an invaluable tool.  One of its more controversial tenets is that all variables should be implicitly typed, not strongly typed, ie:

string rockStatus = “Iain rocks the casbah!”;

Should be

var rockStatus = “Iain implicitly rocks the casbah!”;

The rationale for this is held to be two-fold:

  1. It makes your code more readable, ie:
    1. Dictionary<int, object> example = new Dictionary<int, object>(); is a pain to write and read, much better to just use var
  2. It encourages developers to give their variables a more meaningful name, since the type is not present to impart additional meaning.
Aside – Personally I think another reason is it makes C# a bit more like the dynamic languages that all the cool kids are running (hello Ruby).  “Dude, thinking about what types my variables will hold, gets in the way of discovering the conceptual model of what I’m building.  There is no spoon, maaaaan”

Having resisted the notion for a while, I came round to this way of thinking (re points 1 and 2, not about the spoon ;-)), and generally I think Resharper is correct.

However, refactoring some code today, I realised there are a couple of potential pitfalls, one that could be very common in Web programming with MVC, and a less common scenario.

1. Using an implicitly typed variable for variables that are set from an external method, and then returned to a view.

ie:

public ActionResult Index()
{
    var model = _activityStreamService.GetActivityStream("iain");
    return View(model);
}

Now if you, as I did, refactored the external method to return a different type.  The compiler doesn’t help you as your var is implicitly typed to the new return type, and the first you know about it is when the view blows up.  On a complex system this may go unnoticed for a while.

2. Using an implicitly typed variable that are set from an external method, and downcasted when being processed by another method.

ie (imagine Helpers is a different class, I just put them together for quickness),

public string ToJson(object serializeMe)
{
    var jSerializer = new JavaScriptSerializer();
    return jSerializer.Serialize(serializeMe);
}

public ActionResult Index()
{
    var activityStream = _activityStreamService.GetActivityStream("iain");
    var json = Helpers.ToJson(activityStream);

    return View(json);
}

In this example if we refactor the return type from activityStreamService you may be in even more serious trouble, you might completely miss that there’s a problem until your customers complain.

The counter arguments to this are that UnitTests would hopefully catch this scenario (although interestingly if you’re using implicit variables in your unit tests, they might not, plus who honestly has 100% coverage).  Also return types are rarely refactored, you might change the body of the method, but if it started off returning a string it probably always will.

But I think the more important point is that there are cases where using implicit typing is a bad choice, and may store up trouble for you, especially in large projects.

SEO Friendly Strings, with a simple ToSeo() extension

In web development, you’ll spend a lot of time converting blog titles, image titles, page titles into SEO friendly format, ie:

iains-blogs-rock-my-world

In the past I would have written a static helper utility method to do this, eg

string convertMe = "Iain’s Blogs Rock My World";
string seoString = Utils.ConvertToSeo(convertMe);

However C# 3 gave us the awesome power of extension methods, which in the formal words of MSDN are:

Extension methods enable you to “add” methods to existing types without creating a new derived type, recompiling, or otherwise modifying the original type.

Or to put it another way, you can add methods to classes you didn’t write, be they classes in the framework or classes written by charlatans like my good self.

So we want to add a ToSeo() method onto the string object. To perform this black magic you must ensure the following is true:

  1. Your extension method must be static
  2. The first parameter specifies which type the method operates on, and the parameter must be preceded the this keyword
  3. The extension method must live in a public static class

So in our case we have

namespace HuzuSocial.Web.Helpers
{
    public static class Extensions
    {
        public static string ToSeo(this string str)
        {
            if (str == null)
                return null;
            else
            {
                // Remove any punctuation
                var sb = new StringBuilder();
                foreach (char c in str)
                {
                    if (!char.IsPunctuation(c))
                        sb.Append(c);
                }

                // Replace spaces with dashs and return
                return sb.ToString().ToLower().Replace(" ", "-");
            }
        }
    }
}

And now our new ToSeo() extension is available on all strings, as long as we have a reference to our extensions class

I think this is a definite improvement over the old utils class approach, and gives us a more flexible and natural way of adding functionality.