March 2011 - Posts

One great benefit of having a Continuous Integration server like TeamCity (http://www.jetbrains.com/teamcity/) building your code is that you can hook into the build process to have it also handle tedious or time-consuming tasks for you, such as running all of your unit tests, code coverage analyses, etc.

Now that NuGet (http://nuget.org/) has arrived and simplified package management in .NET, wouldn’t it be nice to have your CI server build an updated NuGet package for you along with every build?  An why not go one step further and have your build process automatically push the newest version of your package to the central NuGet server (or even your own hosted NuGet server)?

It turns out this is actually very easy to do – let’s see how.

Super-Quick NuGet Package Introduction

If you would like to familiarize yourself with what NuGet is and how to use it, take a look at the project homepage at http://nuget.codeplex.com/

For this post it’s really only necessary to know that a NuGet package starts out as a specification file (*.nupec) and usually some deliverable content (Dlls, script files, etc).  Once you have a specification file, you use the NuGet.exe command line utility to turn it into a package (*.nupkg) that can then be uploaded to the masses via http://nuget.org/.  [Full details are available at http://nuget.codeplex.com/documentation?title=Creating%20a%20Package].

Building and Deploying Your Package

You’ll need to have your *.nuspec file checked into source control, and I also find it useful to check in the nuget.exe command-line utility as well (although this is not necessary as long as it is on your build server).  I tend to put my specifications in a /Build/NuGet folder, so it’s outside of the main /src/ folder.

Note: The following steps are TeamCity specific, but any build process with the ability to run a batch file should be able to do the same thing.

1. Open up your project’s build configuration and select #3, “Build Steps.”

image

2. Click “Add Build Step.”

3. Under Runner Type choose “Command Line,” and then under Run choose “Custom Script.”  You can optionally specify a working directory to have your script run in that directory, which I find to be quite helpful.

image

4.  Now you are ready to write your custom script, which should be able to perform the following steps: (1) cleanup old *.nupack files, (2) create your newest package with the correct version number, and (3) push that package up to nuget.org or another nuget server.

My script is as follows:

del *.nupkg
 
NuGet.exe pack Project\Project.nuspec -Version %system.build.number%
 
forfiles /m *.nupkg /c "cmd /c NuGet.exe push @FILE <your-key>"

5. That’s all there is to it, just replace <your-key> with your access key from nuget.org (look under MyAccount)

image

Script Breakdown:

On line two notice how I use TeamCity’s %system.build.number% to inject the build number into the generated package.  This is very important because NuGet pays close attention to your package version number (as David Ebbo describes in detail in his NuGet versioning blog series http://blog.davidebbo.com/2011/01/nuget-versioning-part-3-unification-via.html).

The third line is pretty fun—basically it is saying for every file that ends in *.nupkg, call ‘NuGet.exe push <filename> <your-key>’.  I really like this approach, and it could even be adapted to build and push multiple NuGet packages during every build run.

Wrap Up

Overall there wasn’t too much work to do, we just created a command line script build runner and added a few lines of code to automatically build and push versioned NuGet packages.

Now that I’m using NuGet a lot more, with one OSS project on nuget.org (http://dataannotationsextensions.org/) and several hosted on my own internal company NuGet server, I find this automatic build and deploy process the perfect way to keep my packages up to date. 

Enjoy!

I was writing conventions for FluentNHibernate the other day and I ran into the need to pluralize a given string and immediately thought of the ruby on rails Inflector.  It turns out there is a .NET library out there also capable of doing word inflection, originally written (I believe) by Andrew Peters, though the link I had no longer works.  The entire Inflector class is only a little over 200 lines long and can be easily included into any project, and contains the Pluralize() method along with a few other helpful methods (like Singularize(), Camelize(), Capitalize(), etc).

The Inflector class is available in its entirety from my github repository https://github.com/srkirkland/Inflector.  In addition to the Inflector.cs class I added tests for every single method available so you can gain an understanding of what each method does.  Also, if you are wondering about a specific test case feel free to fork my project and add your own test cases to ensure Inflector does what you expect.

Here is an example of some test cases for pluralize:

TestData.Add("quiz", "quizzes");
TestData.Add("perspective", "perspectives");
TestData.Add("ox", "oxen");
TestData.Add("buffalo", "buffaloes");
TestData.Add("tomato", "tomatoes");
TestData.Add("dwarf", "dwarves");
TestData.Add("elf", "elves");
TestData.Add("mouse", "mice");
 
TestData.Add("octopus", "octopi");
TestData.Add("vertex", "vertices");
TestData.Add("matrix", "matrices");
 
TestData.Add("rice", "rice");
TestData.Add("shoe", "shoes");

Pretty smart stuff.

ASP.NET MVC 3 includes a new unobtrusive validation strategy that utilizes HTML5 data-* attributes to decorate form elements.  Using a combination of jQuery validation and an unobtrusive validation adapter script that comes with MVC 3, those attributes are then turned into client side validation rules.

A Quick Introduction to Unobtrusive Validation

To quickly show how this works in practice, assume you have the following Order.cs class (think Northwind) [If you are familiar with unobtrusive validation in MVC 3 you can skip to the next section]:

public class Order : DomainObject
{
    [DataType(DataType.Date)]
    public virtual DateTime OrderDate { get; set; }
 
    [Required]
    [StringLength(12)]
    public virtual string ShipAddress { get; set; }
 
    [Required]
    public virtual Customer OrderedBy { get; set; }
}

Note the System.ComponentModel.DataAnnotations attributes, which provide the validation and metadata information used by ASP.NET MVC 3 to determine how to render out these properties.  Now let’s assume we have a form which can edit this Order class, specifically let’s look at the ShipAddress property:

@Html.LabelFor(x => x.Order.ShipAddress)
@Html.EditorFor(x => x.Order.ShipAddress)
@Html.ValidationMessageFor(x => x.Order.ShipAddress)

Now the Html.EditorFor() method is smart enough to look at the ShipAddress attributes and write out the necessary unobtrusive validation html attributes.  Note we could have used Html.TextBoxFor() or even Html.TextBox() and still retained the same results.

If we view source on the input box generated by the Html.EditorFor() call, we get the following:

<input type="text" value="Rua do Paço, 67" name="Order.ShipAddress" id="Order_ShipAddress" 
data-val-required="The ShipAddress field is required." data-val-length-max="12" 
data-val-length="The field ShipAddress must be a string with a maximum length of 12." 
data-val="true" class="text-box single-line input-validation-error">

As you can see, we have data-val-* attributes for both required and length, along with the proper error messages and additional data as necessary (in this case, we have the length-max=”12”).

And of course, if we try to submit the form with an invalid value, we get an error on the client:

image

Working with MvcContrib’s Fluent Html

The MvcContrib project offers a fluent interface for creating Html elements which I find very expressive and useful, especially when it comes to creating select lists.  Let’s look at a few quick examples:

@this.TextBox(x => x.FirstName).Class("required").Label("First Name:")
@this.MultiSelect(x => x.UserId).Options(ViewModel.Users)
@this.CheckBox("enabled").LabelAfter("Enabled").Title("Click to enable.").Styles(vertical_align => "middle")
 
@(this.Select("Order.OrderedBy").Options(Model.Customers, x => x.Id, x => x.CompanyName)
                    .Selected(Model.Order.OrderedBy != null ? Model.Order.OrderedBy.Id : "")
                    .FirstOption(null, "--Select A Company--")
                    .HideFirstOptionWhen(Model.Order.OrderedBy != null)
                    .Label("Ordered By:"))

These fluent html helpers create the normal html you would expect, and I think they make life a lot easier and more readable when dealing with complex markup or select list data models (look ma: no anonymous objects for creating class names!).

Of course, the problem we have now is that MvcContrib’s fluent html helpers don’t know about ASP.NET MVC 3’s unobtrusive validation attributes and thus don’t take part in client validation on your page.  This is not ideal, so I wrote a quick helper method to extend fluent html with the knowledge of what unobtrusive validation attributes to include when they are rendered.

Extending MvcContrib’s Fluent Html

Before posting the code, there are just a few things you need to know.  The first is that all Fluent Html elements implement the IElement interface (MvcContrib.FluentHtml.Elements.IElement), and the second is that the base System.Web.Mvc.HtmlHelper has been extended with a method called GetUnobtrusiveValidationAttributes which we can use to determine the necessary attributes to include.  With this knowledge we can make quick work of extending fluent html:

public static class FluentHtmlExtensions
{
    public static T IncludeUnobtrusiveValidationAttributes<T>(this T element, HtmlHelper htmlHelper) 
        where T : MvcContrib.FluentHtml.Elements.IElement
    {
        IDictionary<string, object> validationAttributes = htmlHelper
            .GetUnobtrusiveValidationAttributes(element.GetAttr("name"));
 
        foreach (var validationAttribute in validationAttributes)
        {
            element.SetAttr(validationAttribute.Key, validationAttribute.Value);
        }
 
        return element;
    }
}

The code is pretty straight forward – basically we use a passed HtmlHelper to get a list of validation attributes for the current element and then add each of the returned attributes to the element to be rendered.

The Extension In Action

Now let’s get back to the earlier ShipAddress example and see what we’ve accomplished.  First we will use a fluent html helper to render out the ship address text input (this is the ‘before’ case):

@this.TextBox("Order.ShipAddress").Label("Ship Address:").Class("class-name")

And the resulting HTML:

<label id="Order_ShipAddress_Label" for="Order_ShipAddress">Ship Address:</label>
<input type="text" value="Rua do Paço, 67" name="Order.ShipAddress"
 id="Order_ShipAddress" class="class-name">

Now let’s do the same thing except here we’ll use the newly written extension method:

@this.TextBox("Order.ShipAddress").Label("Ship Address:")
.Class("class-name").IncludeUnobtrusiveValidationAttributes(Html)

And the resulting HTML:

<label id="Order_ShipAddress_Label" for="Order_ShipAddress">Ship Address:</label>
<input type="text" value="Rua do Paço, 67" name="Order.ShipAddress"
 id="Order_ShipAddress" data-val-required="The ShipAddress field is required."
 data-val-length-max="12"
 data-val-length="The field ShipAddress must be a string with a maximum length of 12."
 data-val="true" class="class-name">

Excellent!  Now we can continue to use unobtrusive validation and have the flexibility to use ASP.NET MVC’s Html helpers or MvcContrib’s fluent html helpers interchangeably, and every element will participate in client side validation.

image

Wrap Up

Overall I’m happy with this solution, although in the best case scenario MvcContrib would know about unobtrusive validation attributes and include them automatically (of course if it is enabled in the web.config file).  I know that MvcContrib allows you to author global behaviors, but that requires changing the base class of your views, which I am not willing to do.

Enjoy!

More Posts