MSBuild – the voyage of the noob

I’ve been determined to have a play with build automation/continuous integration for a while now and just have always found something more fun to play with (ORM, MVC, etc.), though I know as the team where I work move forward, there needs to be some control and some vision on how all of our work should hang together.  With that in mind, this weekend I started to read up on MSBuild (yup, I know there are other build managers out there, but I thought I’d start with that as my learning platform and move on from there).

Why do I need to modify the default build?

Why does anyone really I suppose, but I like what we get from it.  As we move forward, the following I think will be useful to us:

  • automating unit test runs on successful builds
  • auto-deploying to our development server
  • minifying and concating javascript and css
  • ensuring coding style rules are followed (once I setup a set of company rules for us)
  • other things I haven’t imagined… there will be lots!

So where do I learn?

This was my first stumbling block.  There are a lot of resources on MSBuild, and trudging through them to find the one that was right for my learning style and approach was a nightmare.  I though to start out with the task that was at the forefront of my mind (concat/minify JS/CSS), but I just didn’t find any resources that were straightforward (my failing more than the resources available I’m sure!)

I’ve grabbed a few useful ones on my delicious bookmarks, and in particular, a significant thanks must go to the Hashimi brothers for their fantastic series on dnrTV and finishing up with some Stack Overflow discussion.

So what did I learn?

Firstly, a quick look at a post by Roy Osherove highlighted to me some of the tools available.  I found two other visual build tools: MS Build Sidekick and MSBuild Explorer, both of which I found very useful in actually *seeing* the build process, but after a watch through those dnrTV vids, I though I’d try something straight forward – concating CSS files into a ‘deploy’ css.

Get into the .csproj file

Unload your project, right click on it, and select ‘edit <projectname.csproj>’

image

MSBuild projects seem to be broken down quite succinctly into Targets, Tasks, Items, and Properties.  For my particular need, I needed to look at Items and Targets.

The schema in MSBuild is incredibly rich – you get intellisense for the most part, but because you can define your own schema elements, you are never going to get 100% intellisense.

You have a number of different ‘DependsOn’ items (mostly defined in Microsoft.CSharp.targets file), so you can create tasks that hang onto some of these like so:


    
			ConcatenateCSS;
			$(BuildDependsOn);
		
  

This is telling the build process that I have a target called ‘ConcatenateCSS’ that should happen before the ‘BuildDependsOn’ target (roughly speaking!)

I then created that target with the following:


	  
		  
	  
    
    
    
      
    
    

Which to me, looks bloody complex! I had to find some help on this one naturally.  But essentially, we have created a target called ‘ConcatenateCSS’ which is going to execute before the build.  We create an ItemGroup (and this is where the intellisense falls over) called ‘InFiles’, and we tell it to include everything ending in .css under the _assets\css folder (it seems the **\\*.css is the wildcard for recursion too, though I may be wrong on this!), and we want to exclude _assets\css\site.css (more on this in a sec).

I then send a message (which will be seen on ‘output’ during build which tells us it’s happening, and then use the combination of ‘ReadLinesFromFile’ and ‘WriteLinesToFile’.  The %(InFiles.Identity) in the ReadLinesFromFile essentially turns this into a foreach loop, and Identity is one of the MSBuild defaults.  So this is essentially, foreach of the files we’ve identified, output the contents to the ‘Lines’ variable/parameter.  We then Write the whole lot back to our file using the @(Lines) variable.

Now, on each build, we generate a single css file (site.css) that our site can reference, but all edits go in via the broken files.  Yes, there are more elegant ways to do this, and yes, I will likely do that in time, but I’ve made a start!

Where next?

I’d be lying if I said I could do the above without some solid examples and help, so the next steps for me are creating a solid understanding of the core concepts, playing with the tools, and looking to solve some of our core business issues as we move forward in order to take some of the human elements out of the build process.  Obviously I have to investigate continuous integration and see where that all fits in too, but I’m happy with the start I’ve made.

Follow up – Microsoft’s customer service shines through

well, what brilliant customer experience I’ve had as a developer supported by the team over the recent CDN issue.  Firstly, @ericnel has been tip top – contacting me via DM to try a few things to start with, but once the issue was resolved, phoning me to talk through the issue and the resolution, and highlighting why it shouldn’t happen again – fantastic!  Also had a message from @swalther from the ASP.NET letting me know the problem had been escalated and would give feedback once they knew more.

First real time I’ve needed feedback from Microsoft on an issue (I have to generate a business case on why we should use the CDN now) so to get that feedback quickly and with clarity is ace – cheers fellas!

Microsoft – Why do you make it so difficult to love you?

I was loving the performance/ping rates we were getting from testing the Microsoft Ajax CDN (jquery) over Google’s. 

Then at about 10:39am GMT today, I noticed as I was dev’ing a page that my jquery niceness had stopped functioning.  Didn’t take long to see that the jquery library had become a blank document (both http and https).  I wasn’t the only one to notice it, but oddly, there wasn’t as much of an outcry on twitter as I’d have expected – am I one of only a few using it?

It took me long enough to get work to switch over to the CDN from Google’s.  I had to roll back to googles while it was down (about 40-45mins), and it’s going to take a stupidly strong business case to convince them to trust it again 🙁

Damn you Microsoft, at times you make it so difficult to be a fanboy!

A better way to check for validity in emails?

I’ve had a method that I’ve used from time to time to validate email addresses, trying to cater for the common problems that have been seen with addresses.  This weekend I had cause to look at it and thought there must be a better way of representing it all.

Couple of thoughts crossed my mind:

  1. I’m not throwing exceptions anywhere, and although I know the method, so use it as I’d expect, perhaps I should be throwing a FormatException? or some others?
  2. It’d be easy to make this an extension method, but I guess it’d be an extension to System.String, and doesn’t really feel right as it serves such a focussed purpose.
  3. Should I be doing any other checks in the code that I’m not already?

I’ll have a read around and look at refactoring, but thought I’d post it here so that I have a record of the ‘before’ and ‘after’ views.

/// 
/// 
/// 
/// 
/// 
/// 
public static string ValidateEmail(string email, out string error)
{
	try
	{
		error = "";

		// Pre-formatting steps
		email 	= email.Trim().Replace(" ", "");
		email 	= email.Replace(",", ".");												// mostly, commas are full stops gone wrong
		email 	= (email.EndsWith(".")) ? email.Substring(0, email.Length-1) : email;	// kill any full stop at the end of an address
		email	= email.Replace(@"""", "");												// remove " in the email address
		email	= (email.StartsWith("'")) ? email.Substring(1) : email;					// remove ' at the start of the address
		email	= (email.EndsWith("'")) ? email.Substring(0, email.Length-1) : email;	// remove ' at the end of the address

		// STEP 1	- No '@' symbol in Email
		if (!email.Contains("@"))
		{
			error = "Email contains no '@' symbol.";
			return "";
		}

		// STEP 2	- More than 1 '@'symbol in Email
		if (email.Split('@').Length > 2)
		{
			error = "Email contains too many '@' symbols.";
			return "";
		}

		// STEP 3	- No .com, .co.uk at end of addresses
		//			- Invalid characters ()<>,?/\|^!"£$%^&* ??? in address
		Regex _regex = new Regex(@"^[-\w._%+'][email protected][-\w.]+\.[\w]{2,4}$", RegexOptions.IgnoreCase);
		if (!_regex.IsMatch(email))
		{
			error = "Email address appears invalid.";
			return "";
		}
		
		return email;
	}
	catch
	{
		error = "Unknown error with email address.";
		return "";
	}
}

Dependent objects in SQL Server

another of those ‘bloody hell, why did I not know this before’ moments, but one of the lads circulated this during the week as a means of checking dependencies on either stored procs or tables.

A simple

exec sp_depends [object name]

Will return a set of results that highlight which stored procs, views, tables, user-defined functions or triggers are dependent upon that object.  The full MSDN documentation is available here.

So handy when there are schema changes in legacy code/schema’s.

Orphaned SQL Server Users

Been blogged about all over the place, but I wanted a central place to remember it.

After restore of a database from another server, often the user account can become unassigned from an SQL server login.

The following sorts it:

sp_change_users_login 'update_one', 'orphaned_login', 'sql_username'

jobs a good un.

Now I never need hunt again – huzzah 🙂

jQuery, Validation, and asp.net

Well, new job, new challenges, and finally my brain can switch off at the end of a day!

This past week or so I’ve been playing with a new registration process for a website, and decided to wherever possible depart from the path of least resistance (classic asp.net, validation, telerik controls, asp.net ajax etc.) and try to focus on the user experience that can be gained from using jquery and any associated plugins.

I plumped for hand rolling my own accordion as I needed more flexibility than that available from the standard plugins.  The area I’ve been most enlightened with though is the jquery.validation plugin.  I love the flexibility in the tool, the customisation, and the improvements it can bring to a form.

a simple:

$(‘input:text:not(.skip_auto_validation),input:password,select:not(.skip_auto_validation)’).blur(

function() {
        validate_field(this);
});

has allowed me to validate fields on loss of focus, and the method targets a number of elements on fail and highlights them.

Before Validation

image

Blur on username – fail

image

which incorporates a $.ajax call to an .ashx handler, and after the call has occured, the user either gets a nice slide down message or a nice indicator that everything is well.

Blur on username – success

image

 

The function that handles the validation is:

/// 
/// field by field validation – we only want to validate fields that are
/// either already validated or have previously succeeded/failed validation
/// and now have a different value
/// 
function validate_field(field) {
    var prev_icon = $(field).prev(‘.icon_success,.icon_fail’);
    if ($(field).val().length > 0 || prev_icon.length > 0) {
        if (!$(field).valid()) {
            prev_icon.remove();
            $(field).addClass(‘field_error’).before(icon_fail).prev().prev().addClass(‘label_error’).parent().parent().addClass(’section_error’);
        }
        else {
            prev_icon.remove();
            $(field).removeClass(‘field_error’).before(icon_success).prev().prev().removeClass(‘label_error’).parent().parent().removeClass(’section_error’);
        }
    }
};

Obviously there are some specific .parent() and .before() .prev() etc. that’ll only work in this pages layout, but you get the idea.

Validating Server Side Fields

I had a mare initially with this until I realised that it was the UniqueID that I wanted of the control.  After that, jobs a good un.

$(‘#aspnetForm’).validate({
    errorElement: ‘div’,
    errorClass: "validate_error",
    // what rules do we have – remember this is page 1
    rules:    {
        "<%=txt_UserName.UniqueID %>": {
            required_6_20:                true,
            username_already_in_use:    true,
            minlength:                    6,
            maxlength:                    20
        },
        "<%=txt_Password1.UniqueID %>": {
            required_6_20:                true,
            minlength:                    6,
            maxlength:                    20
        }
        "<%=txt_Email1.UniqueID %>": {
            required:                    true,
            email_already_in_use:        true,
            email:                        true
        },
        "<%=txt_Email2.UniqueID %>": {
            email:                        true,
            equalTo:                    "#<%=txt_Email1.ClientID %>"
        }
    },
    messages: {
        "<%=txt_UserName.UniqueID %>": {
            required_6_20:        ‘Your username must be between 6 and 20 characters and can only contain letters, numbers and – ! _ . punctuation characters’,
            username_already_in_use:    ‘Your username is already in use – please select another’,
            minlength:            ‘Your u
sername is too short – please change it to be between 6 and 20 characters’,
            maxlength:            ‘Your username is too long – please change it to be between 6 and 20 characters’
        },
        "<%=txt_Password1.UniqueID %>": {
            required_6_20:        ‘Your password must be between 6 and 20 characters and can only contain letters, numbers and – ! _ . punctuation characters’,
            minlength:            ‘Your password is too short – please change it to be between 6 and 20 characters’,
            maxlength:            ‘Your password is too long – please change it to be between 6 and 20 characters’
        },

        "<%=txt_Email1.UniqueID %>": {
            required:            ‘You must enter an email address’,
            email:                ‘You must enter a valid email address’,
            email_already_in_use:        ‘Your email is already in use – please enter another or click the link shown’
        },
        "<%=txt_Email2.UniqueID %>": {
            email:                ‘You must enter a valid email address’,
            equalTo:            ‘\’Email\’ and \’Confirm email\’ must match – please double check them’
        }
    }
});

so with .net controls you have to specify the field by using quotes, and <%= field.UniqueID %> to really get the rules to work.

Custom Rules

Creating custom validation rules is a doddle – just ensure they’re called before .validate()

jQuery.validator.addMethod(
    "valid_postcode",
    function(value, element) {
        // uk postcode regex – all straight forward apart from that last bit – apparently
        // uk postocdes don’t have the letters [CIKMOV] in the last 2
        var regex = /^[A-Z]{1,2}[0-9R][0-9A-Z]? ?[0-9][ABD-HJLNP-UW-Z]{2}$/i;    //after – no need for space
        return regex.test(value);
    },
    "This field is required"
);

This one validates against a UK postcode (regex actually published by the uk government – I couldn’t believe it!).

You then just say:

rules: {
“<%= txtPostcode.UniqueID %>”:
valid_postcode: true
}

It’s really nice to see microsoft are including this .validation library in the 2010 release of visual studio (I’m not sure if that means it’s going to replace the existing method of validation or not, but the fact that it’s gotten that level of support from Microsoft is ace.

Also, the CDN from Microsoft seems to include this as one of the libraries, so definitely an indicator of good things for the plugin.

installutil, windows7, and Run as administrator…

Well, stupidity had the better of me for over an hour on this one!  Having not really worked on a windows service in a while, and certainly not in Windows 7, I was having a mare getting it to install.

I’d found any number of references out there facing the same issue as me:

An exception occurred during the Install phase.
System.InvalidOperationException: Cannot open Service Control Manager on computer ‘.’. This operation might require other privileges.
The inner exception System.ComponentModel.Win32Exception was thrown with the following error message: Access is denied.

and a more detailed review of the install log indicated it was falling over at “Creating EventLog source Time Server Service in log Application…”

I immediately thought enhanced security model, UAC, and suspected that the account that I was trying to run the service as (LocalSystem) was the culprit – I seemed to remember back in the day having to set registry entries against accounts for permission to write to the system logs.  Battled with this for a while to no avail, disabled logging in the hope that the error message would be more helpful, but it didn’t reveal much.

I then started to think back to UAC etc. and started up a command window as Administrator (shift+ctrl+enter when it’s highlighted in the start menu rather than just enter).

Hey presto, problem solved.  I can see I’ll need to investigate further to ensure that there are no other issues with regards the tightened security in win7 (and indeed vista) but as of now, all seems to be working as expected.

Enthusiasm – Who needs talent…

Just read a fantastic post by Jeff Atwood about Talent versus Enthusiasm, and it certainly made me look over both recent events and past with a grin on my face.

I’ve worked with some incredibly talented people in my time who, for whatever reason, seem to have lost their spark.  I’ve also worked with some fairly mediocre programmers who are so incredibly willing to learn, to advance, and to know as much as they can.  I’d like to think that enthusiasm assists talent which in turn assists enthusiasm, and the whole thing becomes very self referential – unfortunately not everyone has that enthusiasm, or for some reason it’s hiding behind the sofa.

I’ve recently been tasked with finding a senior developer/team lead for an organisation, and I’ve been overwhelmed at the quality (or lack thereof) of CVs that have come through – spelling and grammatical errors, no sense of enthusiasm in the covering letters, and a clear indication that some of them hadn’t read the detail in the advert at all.  Hopefully some of these people are indeed talented, because their enthusiasm hasn’t overwhelmed me.

I’m happy to sit on the enthusiastically talented fence, I suggest you try it – the perks are fantastic 🙂

Interesting times and justifying ones existence :)

Well, wasn’t yesterday an interesting day!  Had a conversation with a friend about what it is I actually do.  They didn’t feel that I was selling myself effectively enough via this blog, though thankfully this blog was never about that – it (I hope) shows that I’m keen to learn, keen to do more, and never content with knowing ‘enough’.  They asked in particular for me to clarify what work I had done whilst working on suite-e, and looking back over our work schedules, project documents, and just generally over the functionality in there, it turned out to be quite a list:

  • User Controls / Custom Server Controls
  • Using .net forms and role-based security with the membership and role providers
  • Use of Enterprise Library application blocks for Data Access, Exception Management and Logging
  • Extention methods
  • Significant Ajax use (both ASP.NET Ajax and Telerik Ajax wrappers)
  • Linq (minor)
  • Facade design pattern (5 tier solution, UI -> Business Facade -> Business -> Dal Facade -> Dal)
  • Significant use of inheritance throughout the data and UI layers
  • Interface use (minor, where necessary)
  • Custom/3rd Party Controls (Telerik)
  • Hand rolled URL routing for friendly URLs (sitting atop urlrewriting.net)
  • Use of Themes, Masterpages, including browsercaps useage to allow CSS targetting more effectively for cross browser
  • jQuery use (my input minor)
  • CSS
  • Xhtml
  • > 80 table relational data model, significantly more stored procs, cursors, temp tables
  • Web services to authenticate licensing of the product
  • Windows services to manage email send from the CRM module
  • Significant and ongoing refactoring, including fxcop use when readying the solution for microsoft testing
  • Upgrade from .net 1.1 through 2.0, and then incorporating 3.5 elements when applicable

Suite-e as a product has obviously had more than one developer work on it, though it felt good whilst writing this up to realise how far I’d come and what technologies I’d learned and put into practice during the implementation.  I essentially architected the vast majority of the product, both code and SQL schema from its early days through to the modular CMS, Product Catalogue, E-commerce, CRM and Events management solution that it is today, with over 170 files and 51k lines of code across 6 projects, over 80 tables, significantly more stored procedures… the list goes on 🙂

It’s incredibly understandable that a blog would give people a perception of who you are, indeed it’s a very personal blog, so it certainly should, though I hope this blog also gives folks a perception of the sort of developer I am, that will keep ploughing on and learning as much as I am able, because that is what is ‘fun’ to me.