Safe and Sound
The Project52 Challenge
January 2010
During the end of December last year I, along with many others, somehow got caught up by the #p52 hashtag and, in true 'resolutions that I probably won't be able to keep' stylé, I took on the challenge. The idea is as follows:
The goal is to write at least 1 new article per week for 1 year.
http://project52.info
I'm kicking that off with a new article about useful .net dev resources and how to keep up to date. I've also finally made some good use of my free basecamp account by making a list of potential articles so I should be on my way for at least a few months. It's finding the time that could be tricky.
The idea has already 'persuaded' me to get some more functionality up on to cargowire. The categorisation of my posts is now exposed through url routes (e.g. http://cargowire.net/articles/tagged/general) and I will be tagging all my Project52 posts appropriately at: /articles/tagged/project52.
Additionally I've begun to add 'table of contents' links to the upper right of articles. Thus allowing skipping down the article. Commenting functionality is coming soon... I promise.
I'm also going to try and run a commenting #p52 alongside the article writing, as Yaili proposed.
Looking forward to a fun and productive 2010!
Cargowire MVC Series begins...
December 2009
A new post has just gone up over in the articles section. Now that I've migrated the cargowire codebase to .NET MVC I intend to release a few articles in relation to the process. The first is with regard to routing, particularly extensionless routes that match my pre-existing urls but use the new Routing capabilities of .NET MVC.
Overengineering and a lack of testing, the pitfalls of personal projects
November 2009
On this weeks show 'Content Negotiation' and browser testing
Ok, so yesterday I jumped the gun somewhat with the rather over ambitious:
asp.net MVC version of http://cargowire.net up now - pretty much the same (hopefully) fleshed out notes and added link to thebarn page
http://twitter.com/cargowire/status/6182546830
Inevitably this was followed by:
@cargowire heads up for you this is what I see in Safari 4 for http://cargowire.net OK in FF3.5 http://yfrog.com/4imo3p
http://twitter.com/porkandpaws/status/6183712464
Clearly I'd made three (or at least three of my) classic 'personal project for self only' mistakes:
- Overengineering
- Lack of testing
- Eagerness to get it live
I had set out to merely replace the backend of my previous .NET WebForms project (that used XSL/XML for view separation) with an implementation of asp.net/MVC. A fairly trival task, that along the way I expanded by virtue of being my own client and wanting to try out random things.
Being effectively an engine swap (I was even using the same XSL as well as javascript/css) I neglected to worry too much about browser rendering. After all, it was the same CSS that I'd tested before... surely all would be well.
The problem: Content Negotiation
My original cargowire implementation had the ability to serve different content types baked in. You could call most pages in the following ways (you still can now, try it):
- http://cargowire.net/articles (rendered html)
- http://cargowire.net/articles.html
- http://cargowire.net/articles.xml
- http://cargowire.net/articles.rss
I wanted to keep this functionality with the new asp.NET MVC version, however somewhere along the way I decided it would be a good idea to not only expose these different formats through varying file extensions but also respond to the HTTP Accept header that get sent with the request. This behaviour, similar to the respond_to method from Ruby On Rails, would allow multiple versions of the content to be requested easily.
The implementation was simple and based on my brief reading of the Http Accept header description.
// Pseudocode of the algorithm
format = request.extension
if exists(format) and haveViewFor(format)
return content as format
else
read in list of values from Accept header
sort the list of accept headers by quality first and original request order second
return content as the first format in the list that matches an available view
if no appropriate view found
return content as html
By attempting to find any possible view it allowed me to later add any format I like (json for example) just by adding the relevant view and all the plumbing would wire up.
All seemed well in Firefox, and after forgetting about this code and finishing the rest of the backend off, browser testing was irrelevant.. right?... I'd not changed any css, html or JS... I pushed live.
Why did Safari looks so funny?
During testing I'd been working with firefox, which, if you request an extensionless url, appears to send the following accept header (according to the live headers plugin):
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
So in my algorithm you'd get:
- text/html (default q = 1) - sorted before xhtml because requested first
- application/xhtml+xml (default q = 1)
- application/xml;q=0.9
- */*;q=0.8
In this scenario the code looks for a template for html, finds one and returns (ignoring the rest of the list).
When I saw the output from porkandpaws tweet it was immediately clear that he was seeing the XML output instead of html. A quick run in debug mode gave the following accept header from Safari 4:
Accept: application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5
It would appear that if no extension is specified Safari will prioritise XML over XHTML. With application/xml requested before application/xhtml+xml and with both being assigned the default quality level 1 my algorithm assumed the client wanted the XML view and returned it!
The quick fix was to prioritise types containing 'html' before falling back to request order. This may not be a perfect solution, but lets be pragmatic, I'd only implemented this on a whim - no-one is actually using this site other than for the html or rss view.
Conclusion
To round up then, although overengineering and random play code is almost inevitable for the curious developer when working for themselves with no timescale, it doesn't excuse full testing and you can never rule out what any change, no matter how 'isolated', might effect.
New article posted! (Ubuntu gets inside Vista)
August 2009
Just posted a new article covering how to get a previously installed dual boot of Ubuntu and Vista to work seamlessly inside VirtualBox running on Vista (check it out over in the articles section). It's something I did a while back and have been meaning to finish the article on. It has definately increased my usage of Ubuntu.
I love the dev community for this reason:
July 2009
One of the reasons I've always enjoyed being part of the web is the fantastic people it attracts. Rarely have I met someone in the industry that I couldn't get on with on some level... and today that view was reinforced.
Anyways on with the story... as with many others, when I first left University I signed up to a bunch of recruitment sites, as well as applying to companies direct (in classic 'keep as many options open as possible stylé'). When doing so, I signed up to the unwritten law that I would thereafter receive more spam than actual e-mail - I was once even berated by some crazy recruiter for telling him I had a job (after he'd ran through a minute long rant about a job opportunity without stopping for breath).
Therefore I'm quite used to deleting a lot of e-mails from my inbox on a daily basis. So much so that I didn't stop to think about it until I saw that a couple of e-mails had the same subject line with 'RE:'...
It started with:
Good evening,
I specialise in placing IT Contractors across the UK and Europe and I have the following vacancy that you may be interested...
Addressed to a company address and copied to well over 500 possible applicants. This was then succinctly followed by the first reply...
"This e-mail is confidential and is intended solely for the use of the individual or entity to whom it is addressed"
so that's all fucking 640 of us then?
Marked as spam for sharing people's email addresses and possibly breaking some sort of data protection law, though how you got these email addresses is questionable to begin with as I have never given mine to you.
and this...
This amuses me.
Recruitment FAIL.
I’m sure if you’d like help developing a mail distribution system though Mr [.....], there’s 640 of us that could potentially help you.
and finally...
Dude - that was magnificent! I've never heard of [.....], [.....] and I've certainly never given anyone permission to give my email to them either.
Now it might just be me in a late Monday night computer stupor but that definately cheered up my day! I must then add (personal ad stylé) 'GSOH' as an extra point for Paul's recent post.
Cheers to the guys who I've quoted here!

http://twitter.com/porkandpaws/status/6183712464
