Someone's having a firework party just down the road. Not sure why -- I know it's the Fourth of July, but this isn't America! 2 hrs ago

ASP.NET

11
May

Reinventing the wheel, badly

A few years ago, I inherited a VB.NET application in which every method (many of which were four hundred lines long, copied and pasted all over the place, and peppered with vague sounding variable names such as blnRunIf and blnRunElse) contained this boilerplate code:

Sub MyMethod()
    Try
        '
        ' ** snip ** '
        '
    Catch ex As Exception
        Throw New Exception ("MyClass.MyMethod::" + ex.Message)
    End Try
End Sub

Those who do not understand Exception.StackTrace are doomed to reinvent it, badly.

29
Apr

XsltArgumentList violates the Single Responsibility Principle

Can somebody please enlighten me as to why XsltMessageEncountered and AddExtensionObject are members of System.Xml.Xsl.XsltArgumentList?

It seems like a violation of the Single Responsibility Principle to me — neither of them are anything to do with the list of arguments that you pass into your transform. It would make more sense if they were members of XslCompiledTransform instead.

23
Feb

Sometimes, sweeteners can be a bit sour

There’s a gotcha with including scripts in your XSL stylesheets using the <msxsl:script> tag that I blogged about a couple of months ago.

Whenever you load in a stylesheet into an XslCompiledTransform object, it compiles the scripts into a new in-memory assembly using System.CodeDom. Every time you re-load the stylesheet, another assembly is created, and as assemblies are not garbage collected and can only be unloaded by unloading your entire application domain, this is a potentially pretty serious memory leak that can quickly bring your application to its knees.

According to Microsoft, this only affects ASP.NET 1.0, but people have reported problems with ASP.NET 1.1 and 2.0 through 3.5 as well.

There are two solutions to this. One is to use XSL extension objects instead of scripts. The other is to use a singleton design pattern, only creating your XslCompiledTransform once and caching it for future use. In fact, you should be doing this for performance reasons anyway, as parsing and compiling an XSL stylesheet takes time.

A class such as this should prove useful. It caches your XSL stylesheets so that each one will only be parsed into an XslCompiledTransform the first time:

using System;
using System.Collections.Generic;
using System.IO;
using System.Runtime.CompilerServices;
using System.Xml;
using System.Xml.Xsl;

public static class XslCache
{
    private static Dictionary<string, XslCompiledTransform> cache
        = new Dictionary<string, XslCompiledTransform>();

    [MethodImpl(MethodImplOptions.Synchronized)]
    public static XslCompiledTransform GetTransform(string xslFile)
    {
        // Normalise the path to the XSL file
        xslFile = new FileInfo(xslFile).FullName;
        
        // Return the cached transform if it exists.
        if (cache.ContainsKey(xslFile)) {
            return cache[xslFile];
        }
        
        // Otherwise, load the XSL stylesheet.
        var transform = new XslCompiledTransform();
        transform.Load(xslFile,
            new XsltSettings(true, true),
            new XmlUrlResolver()
        );
        
        cache.Add(xslFile, transform);
        return transform;
    }
}

XslCompiledTransform objects are threadsafe once they have been loaded.

24
Nov

Another XSLT sweetener

Update: There is a memory leak issue with using <msxsl:script> tags in your stylesheets. For details on the problem and how to mitigate it, see here.

XSLT can be pretty perplexing to newbies. It gives you a small number of string manipulation and other functions, but the selection at your disposal often seems very limiting. It also doesn’t have variables, so unless you’re familiar with recursion and other concepts of pure functional programming, it can seem very much like a language that doesn’t have nouns. It is easy to wonder how you could possibly do anything fancy with it.

Fortunately, the .NET framework allows you to extend XSLT, using the Microsoft-specific <msxsl:script> extension. So, for a simple example, here is a stylesheet that will give you a comma-separated list of the titles of all the items in an RSS feed, converted to uppercase:

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" 
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:msxsl="urn:schemas-microsoft-com:xslt"
  xmlns:my="http://example.com/my-stuff"
  exclude-result-prefixes="msxsl">

  <msxsl:script language="c#" implements-prefix="my">
    <![CDATA[
      public string join(string separator, XPathNodeIterator nodes)
      {
        StringBuilder sb = new StringBuilder();
        foreach (XPathNavigator node in nodes) {
          if (sb.Length > 0) {
            sb.Append(separator);
          }
          sb.Append(node.Value.ToUpper());
        }
        return sb.ToString();
      }
    ]]>
  </msxsl:script>

  <xsl:template match="/">
    <xsl:value-of select="my:join(', ', rss/channel/item/title)"/>
  </xsl:template>
</xsl:stylesheet>

In order to use this, however, you need to specifically enable it when you are performing your transform. To do this, you need to pass a XsltSettings object in the call to your XmlCompiledTransform’s Load method:

var transform = new XslCompiledTransform();
transform.Load("test.xsl", new XsltSettings(true, true), 
    new XmlUrlResolver());
transform.Transform("test.rss", new XmlTextWriter(Console.Out));

An alternative, cleaner approach is to use an extension object, which has the added advantage that you can use Linq and other C# 3.0 goodies as well:

var transform = new XslCompiledTransform();
var transformArgs = new XsltArgumentList();
transformArgs.AddExtensionObject
	("http://example.com/my-stuff", new MyExtensions());
transform.Load(@"test.xsl");
transform.Transform(@"test.rss", 
	transformArgs, new XmlTextWriter(Console.Out));

where your extension object might look like this:

using System;
using System.Linq;
using System.Xml.XPath;

namespace ConsoleApplication1
{
  public class MyExtensions
  {
    public string join(string separator, XPathNodeIterator iterator)
    {
      return String.Join(separator,
        (from XPathNavigator i in iterator 
         select i.Value.ToUpper()).ToArray()
      );
    }
  }
}

and your stylesheet might look like this:

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:msxsl="urn:schemas-microsoft-com:xslt"
    xmlns:my="http://example.com/my-stuff"
    exclude-result-prefixes="msxsl">

  <xsl:template match="/">
    <xsl:value-of select="my:join(', ', rss/channel/item/title)"/>
  </xsl:template>
</xsl:stylesheet>

Your code needs to be executing under full trust in order to use XSLT extension objects.

27
Oct

Unit testing URL generation and Html.ActionLink in ASP.NET MVC

As I’ve been working with ASP.NET MVC lately on a couple of websites, the one thing I’ve found the hardest to get used to is the routing engine. Getting it set up to parse your URL to give you a route is straightforward enough — the hard, and often confusing, part is the helper functions such as Html.ActionLink that generate URLs from route data. Sometimes the URLs look different to what you expect, but they work nonetheless; at other times, they are just plain wrong, especially if you have a complex routing table set up.

The logic behind constructing the URLs is fairly complex, and depends not only on the route data that you pass into the ActionLink method, but also on the route data that comes from the original URL that you used to access the page in the first place. If you have routes that are any more complex than the fairly trivial examples that come in the out of the box application templates, it can quickly get pretty confusing. Furthermore, chopping and changing the order in which you register your routes can get things totally out of kilter, so you really need a comprehensive suite of unit tests to be able to tackle it with any hope of retaining your sanity whatsoever.

The subject of unit testing your routes to make sure that you are getting the correct route data out of them has been covered by Phil Haack and Stephen Walther, so I won’t go into any further detail about that aspect here. However, I’m going to expand a bit on Phil’s methods to show how to test things the other way round: making sure that when you pass some route data in to Html.ActionLink, it gives you the URL that you expect.

As with Phil’s sample code, I’ve used Moq to mock the context, request and response, and I’m using Eilon Lipton’s technique of using an anonymous class as a dictionary literal. You can download the code as a Visual Studio solution if you want to get up and running with it straight away. Here’s a quick look at the methods that do all the work:

string FindUrlToRoute(string currentPage, object routeData)
{
	var mockContext = new Mock<HttpContextBase>();
	var mockRequest = new Mock<HttpRequestBase>();
	var mockResponse = new Mock<HttpResponseBase>();

	mockContext.Expect(c => c.Request).Returns(mockRequest.Object);
	mockContext.Expect(c => c.Response).Returns(mockResponse.Object);
	mockRequest.Expect(c => c.AppRelativeCurrentExecutionFilePath)
		.Returns(currentPage);
	mockResponse
		.Expect(c => c.ApplyAppPathModifier(It.IsAny<string>()))
		.Returns((string s) => s);

	var route = routes.GetRouteData(mockContext.Object);

	var requestContext 
		= new RequestContext(mockContext.Object, route);
	var url = new UrlHelper(requestContext);
	var dict = new RouteValueDictionary();

	foreach (PropertyValue property in GetProperties(routeData)) {
		dict[property.Name] = property.Value;
	}

	var path = routes.GetVirtualPath(requestContext, dict);
	return (path != null ? path.VirtualPath : null);
}

protected void AssertRouteUrl(string currentPage, string expectedUrl, 
	object routeData)
{
	var str = FindUrlToRoute(currentPage, routeData);
	Assert.AreEqual(expectedUrl, str, "URL was wrong!");
}

The sharp eyed among you will note that I am not actually calling Html.ActionLink() itself, but a different method, routes.GetVirtualPath. When you construct an action link, or when you use Url.Action(...) in your views, ASP.NET MVC ends up one way or another running your data through the GetVirtualPath method of your route table. You have to mock the Response.ApplyAppPathModifier method — a fact that wasn’t immediately obvious, and it took a bit of digging around in the System.Web.Routing assembly with Reflector to find out exactly what needed to be done.

You can then check to see whether you are getting the correct URL out by calling in to the AssertRouteUrl method as follows:

[Test]
public void TestBlogPath()
{
	AssertRouteUrl(
		/*
		 * currentPage is an app-relative URL, so it must be
		 * prefixed with a tilde (~). Note that this is required
		 * and must point to a valid route.
		 */
		"~/blog/2008/10/25",
		/*
		 * expectedUrl, on the other hand, is an absolute path,
		 * so it shouldn't.
		 */
		"/blog/2008/10/10",
		/*
		 * The route data. Note that you specify your controller and
		 * action here as the controller and action properties 
		 * respectively.
		 */
		new { 
			controller = "blog",
			action = "index",
			year = "2008",
			month = "10",
			day = "10"
		}
	);
}

Download: Unit testing route URL generation – Visual Studio solution

01
Oct

ASP.NET MVC + jQuery – can things get any better for web developers?

Microsoft’s recent decision to include jQuery in the ASP.NET development stack is pretty exciting news. I’ve been using jQuery for a while now, and all I can say about it is that it makes JavaScript fun. You can use it to add some pretty impressive effects to your web pages with only a couple of lines of code, and you have less to worry about as far as the idiosyncrasies of cross-browser detection are concerned. In the past year or so it’s become pretty popular and even something of a de facto standard in many ways, probably best described as JavaScript’s answer to Linq. If you’re a web developer and you haven’t yet come across it, I really would encourage you to check it out — you’ll love it, even if you hate JavaScript.

Hopefully this will attract some more talent back to the .NET platform. It’s been the case for a while now that the best, most passionate web developers — the ones who come up with the all-singing, all-dancing Ajax-y websites and eye candy — have generally been shunning the Microsoft stack in favour of PHP, Django and Ruby on Rails. You can easily understand why — the web forms postback model may be good for simple, fairly generic things, but if you really want to make your website sing, it has restrictions and leaky abstractions that get in the way a lot, such as the limitation of one server-side form per page, or the convoluted id attributes that it sticks in all over the place making CSS and DOM manipulation a major headache, or the monster that is view state.

However, with the ASP.NET MVC framework on the go, we have finally got back the control over our HTML that we need, and now with jQuery forming an official part of it, ASP.NET is becoming an even more exciting prospect again. It’s especially so since in many ways you can really push the boundaries with .NET a lot further than with most other frameworks. Languages such as PHP or Ruby are good in themselves, but they do have their limitations, and it’s not a good idea to try to use them for image manipulation, or genetic algorithms, or Bayesian spam filtering, for instance — they are just too slow for computationally intensive stuff such as that, and in those cases you would need to drop down to C++. On the other hand, in C#, you can do it all in one integrated end-to-end framework, and with Visual Studio, you have what is probably the best IDE on the market to help you on your way.

I’m looking forward to seeing a lot more all-singing, all-dancing websites written in ASP.NET.

08
Sep

Paths and file locations in ASP.NET

There are loads of ways to find the path — either the URL or the physical path — to a page, user control or other file in an ASP.NET application. Unfortunately, however, the documentation doesn’t do a brilliant job of explaining them to you. There are also several different scenarios, depending on whether you are using conventional web forms, or URL rewriting, or Server.Transfer, or ASP.NET MVC. So I thought I’d better write down an overview of some of them for reference.

Scenario 1: direct request for a web form.

Just suppose for a minute that you have been contracted to rewrite Wikipedia in ASP.NET. So, for instance, you may end up with the page “What Wikipedia is Not” (aka “WP:NOT” or “Wikipedia’s attempt to get into the Guinness Book of Records for the most lies per kilobyte on a web page”) at http://en.wikipedia.org/wiki.aspx/WP:NOT.

In this case, you have several different properties of HttpContext.Current.Request containing different representations of it.

  • Request.RawUrl = "/wiki.aspx/WP:NOT" represents the path and query string parts of the URL. In this case, of course, there is no query string, but if there were, you might see it set to something like "/wiki.aspx/WP:NOT?mode=edit".
  • Request.Path = "/wiki.aspx/WP:NOT" represents the path part of the URL.
  • Request.FilePath = "/wiki.aspx" represents the part of the path to the file (in this case wiki.aspx) that is handling the request.
  • Request.PathInfo = "/WP:NOT" is a diff of Request.Path and Request.FilePath, giving the extraneous bit of the path that does not refer to a file in the file system.
  • Request.PhysicalPath = "c:\inetpub\wwwroot\wiki.aspx" is the physical path to the file that is servicing the request.

Case 2: Server.Transfer() and Server.Execute()

Sometimes, you may want to transfer control from one file to another. Let us suppose, for instance, that you decide to use several Web forms: one for articles, one for special pages, and one for article history. You do a few simple checks in wiki.aspx and decide to transfer control to another file, say, article.aspx, using Server.Transfer(). Then, another property of Request comes into play.

  • Request.CurrentExecutionFilePath = "/article.aspx" represents the path to the file that is currently handling the current part of the request.
  • Request.FilePath = "/wiki.aspx", however, remains unchanged.
  • Request.PhysicalPath = "c:\inetpub\wwwroot\wiki.aspx" also remains unchanged.
  • Request.AppRelativeCurrentExecutionFilePath = "~/article.aspx" is the same as Request.CurrentExecutionFilePath, but relative to the root of the web application, as defined in IIS. If your application were rooted at, say, "/wiki" then Request.CurrentExecutionFilePath would be "/wiki/article.aspx".
  • Everything else remains unchanged.

Note that Request.CurrentExecutionFilePath is always in use: if there has been no call to Server.Transfer it will be the same as Request.FilePath.

Case 3: URL rewriting

So you have this lovely new ASP.NET version of Wikipedia up and running, it works much more smoothly, has much less downtime, and runs on only a dozen or so servers rather than a hundred. Then, you start getting hate mail from irate Wikipedians, many of whom are open source zealots who are definitely not NPOV on Microsoft Windows. Jimbo and the Arbitration Committee get involved and demand you rewrite those URLs to cover up the fact that the Wikimedia Foundation has gone over to the Dark Side.

So, you take the original URL http://en.wikipedia.org/wiki/WP:NOT and transmogrify it into http://en.wikipedia.org/wiki.aspx?ns=Wikipedia&pg=What_Wikipedia_is_Not using a discreet call to Context.RewritePath.

Suddenly, everything changes!

  • Request.RawUrl = "/wiki/WP:NOT" represents the original path and query string parts of the URL. In actual fact, Request.RawUrl always represents exactly what you typed into your browser.
  • Request.Path = "/wiki.aspx" represents the path part of the URL.
  • Request.FilePath = "/wiki.aspx" represents the part of the path to the file (in this case wiki.aspx) that is handling the request.
  • Request.PathInfo is blank. When you use URL rewriting you have to point to a real file: you can’t use a PathInfo — that’s why you need to use a query string instead.
  • Request.CurrentExecutionFilePath = "/wiki.aspx" until you call Server.Transfer, when it changes.
  • Request.QueryString = "ns=Wikipedia&amp;pg=What_Wikipedia_is_Not" is of course changed after the URL rewrite.
  • Request.PhysicalPath = "c:\inetpub\wwwroot\wiki.aspx" is, again, the physical path to the file that is servicing the request.

Case 4: ASP.NET MVC

So how on earth, you may be asking, does all this work with ASP.NET MVC? After all, it doesn’t use Web forms in the same way — URLs map to controllers, which then decide which views to render themselves.

Well here’s the skinny:

  • Request.RawUrl = "/wiki/WP:NOT" contains the raw URL (path and query string) as before.
  • Request.Path, Request.FilePath, and Request.CurrentExecutionFilePath, all contain the “path” part of the URL without the query string. They will all be set to "/wiki/WP:NOT"
  • Request.PathInfo is blank. ASP.NET MVC handles path info through the routing engine and passes it in the parameters for your controller.
  • Request.PhysicalPath = "c:\inetpub\wwwroot\wiki\WP:NOT" is NOT the physical path to the file that is servicing the request. Controllers may decide to render one of any number of views or other results, and they need not even be Web forms — they could be raw text content (from a ContentResult), or a redirect (from a RedirectResult or a RedirectToRouteResult) or a JSON string (from a JsonResult) and they aren’t associated with a physical file on the filesystem at all.

Case 5: ASP.NET MVC with URL rewriting and/or Server.Transfer

I shall leave this one as an exercise for the reader. No doubt there is someone, somewhere, who is doing this, for reasons that completely befuddle me. After all, I’d have thought that the whole MVC pattern renders URL rewriting and Server.Transfer pretty much redundant.

Case 6: Requests for a directory’s home page

This is much the same as the above, except that ASP.NET inserts the name of the home page — typically default.aspx — into Request.RawUrl, and, by extension, everything else. Obviously, this does not apply to ASP.NET MVC.

06
Jun

How to become a better .NET developer

If I can give one single piece of advice to ASP.NET developers anywhere, it will be this:

Learn another web development environment.

I really can not emphasise this strongly enough. From what I’ve observed, developers who only work with ASP.NET seem to have quite a bit of difficulty thinking outside of the Microsoft box. I am frequently confronted with indiscriminate and even inappropriate use of aspects of the .NET framework that don’t scale, such as DataSets, view state, or drag-and-drop programming. There’s nothing wrong with all these per se, but one of the most important things you need to know about how to use them is when not to use them. When all you have is a hammer, everything starts to look like a nail.

The ASP.NET Web Forms model in particular was originally designed to make web development look like Windows development, and ease the transition for VB6 developers from programming for rich Windows clients to the web. The result of this is that it has made the easy aspects of web development almost brain dead, while introducing a horrendously leaky abstraction layer that makes the hard things even harder, with masses of gotchas and pitfalls to trip you up if you venture outside it.

Languages such as PHP, Ruby on Rails or Python don’t have the same leaky abstractions, so developers tend to not only program “closer to the metal” but to think closer to the metal as well. This is why most of the cool sites, with stunning Ajax effects, tend to be written in these languages and target these platforms, while ASP.NET is largely languishing in the enterprisey world of Dilbert-esque cubicle farms.

I recommend you choose your alternative carefully, however. Rails and Python are the best choices. They will teach you patterns, practices, conventions, O/R mapping, MVC, and all round agile and pragmatic programming, and they tend to be taken up by smart and experienced developers who know what they’re doing. I have mixed feelings about Java: while you can learn a lot from it, like .NET it is very enterprisey, and at a time when everyone is getting excited about dynamic languages, Java is heading in completely the opposite direction. And I certainly don’t recommend PHP as a learning exercise: it is a beginners’ language — and a mind-bogglingly badly designed one at that — and while PHP guys are generally pretty enthusiastic and some of them are quite smart, and there are some decent PHP frameworks such as CakePHP and Symfony, the overwhelming majority of the PHP community simply don’t have what it takes to be programmers. Having said that, you need to know it, simply because it’s so pervasive.

You should also learn Linux if you can. It will teach you about modular design and the value of scripting everything that can be scripted. This is right at the heart of why Unix is Unix: a large part of its philosophy involves chaining text-based programs where the output of one can be passed as the input to another, to produce some fairly powerful command-based functionality, and scripting repetitive tasks so that their outcomes can be reliably reproduced. These are philosophies that seem largely lost in the world of Windows, which relies much more heavily on the visual, drag, drop and click approach of dialog boxes and wizards, even though they are every bit as essential if you want to have robust procedures and practices in place.

And whichever platform you take on board, you simply must familiarise yourself thoroughly with CSS, DHTML, JavaScript and Ajax, and at least one JavaScript framework such as Prototype or jQuery.

Personally, I still think that ASP.NET is technically the best platform on which to develop scalable, high performance, reliable web applications. However, in order to make the most of it, you need to have a good feel for what approaches you can import and learn from other platforms. Otherwise you will be stuck with the limitations and leaky abstractions of Web Forms.

30
May

What part of “no agencies” do you not understand?

Now if things carry on the way they are going, one of these days, we are probably going to get an application for our developer position from Zefram Cochrane. He’d be more than welcome — I’m sure that someone smart enough to invent the warp drive should have C# pretty much figured out by now even though he hasn’t been born yet, though I shudder to think what his penchant for loud heavy metal music would do to our score on the Joel Test.

Of course, Dr Cochrane is just trekkie fantasy, but even so, reality at the beginning of the 21st century does occasionally send us applications such as one (with no CV attached) from someone claiming “Ihave 34 year experience in asp.net c#” (sic). Given that in the absence of time travel and warp drives, no-one will have 34 years of experience of C# until 2035 at the earliest, I think we’ll wait until then before sending that guy the coding exercise we use as a screener. However, by that time, chances are that C# will be the new COBOL, having been replaced by something more esoteric.

It also sends us ones such as this e-mail the other day that was simultaneously funny, annoying and at the same time rather sad:

This Email is to introduce my company and to ask, if you can give us a chance to prove ourselves and provide our recruitment services to your company.

My name is ______, I represent a Recruitment consultancy called __________. I am attaching my company’s Terms of Business for your consideration and rates wise we are flexible like 12 – 15%.

We mainly work in IT sector e.g, (Web Developers / Designers; Software Developers, Testers, Business Analysts and Project Managers).

You have written that you wont accept calls from AGENCIES so thats why I am emailing you to try my luck.

Please consider and respond positively & if you have any questions please feel free to ask.

In other words, “I see you’ve said no agencies, so I thought I’d write to offer the services of my … agency.”

It boggles my mind to think what was going through this guy’s mind when he drafted this e-mail up. Did he think that because we aren’t taking calls from agencies that e-mails are fine? Sorry, we don’t say “no calls from agencies” — we say “Strictly NO AGENCIES please.” That means no phone calls, no e-mails, no letters, no carrier pigeons, no agencies, period.

Or does he think that because he’s called his company a “recruitment consultancy” that somehow exempts it from being an agency? Sorry, it doesn’t.

If you are a recruitment consultancy, whether you like it or not, you are an agency.

If you are a headhunter, you are an agency.

If you are enquiring on behalf of anyone other than yourself, you are an agency.

(Strictly speaking, that means that even if you are somebody’s girlfriend, calling on behalf of your better half, you are an agency, though that is admittedly probably stretching the point. Okay — strike that, if you are getting paid to enquire on behalf of anyone other than yourself, you are an agency.)

I’m not saying there’s anything wrong with agencies per se, other than that the quality of developers that they come up with can be pretty unpredictable, but as with all things such as these, we have a strict company policy in regard to these things of “don’t call us, we’ll call you.”

However, that aside, does someone who doesn’t understand that “no agencies” means “no agencies” really have the right stuff in his head to find us a competent developer? Methinks not, somehow…

20
May

Where are all the passionate .NET developers?

We’re looking to take on another developer.

The majority of our work is in C#/.NET, so obviously we’ve adjusted our skills requirement accordingly. However, what we are really looking for are smart people who get things done and have a real passion for what they are doing. If you’re smart and passionate, it isn’t a disaster if you don’t have two years of .NET experience, because smart, passionate developers can pick up pretty much anything very quickly, and besides, in this game you have to be learning very quickly all the time.

So, how can you identify the passionate ones?

For starters, I personally think that CVs tell you very little. When I see your average developer CV, my eyes tend to glaze over and all I see is white noise. They show that you have x years of experience in y platform, and that you know what all the current buzzwords are, but that is about it. They don’t tell me whether you spent those x years cutting and pasting code snippets out of those stupid PHP tutorials that teach you to write SQL injection vulnerabilities, or whether you were implementing recursive algorithms and Markov chains in your sleep.

No, the easiest way to get a decent first impression is to Google them and see what their online footprint looks like. You can typeset your CV in Comic Sans for all I care, but if we find you have a blog, we will sit up and take notice. Merely the fact that you are going beyond the 9-5 mentality and showcasing your skills to the world puts you head and shoulders above the crowd.

However, even then, there are blogs and there are blogs. Some developer blogs are very dry indeed — they consist of little more than a string of deadpan howtos and regurgitations of whatever SDK you are using. I’m not saying your blog shouldn’t contain any of those at all, but you need to convey some life with them. What’s the story behind the bug you’re blogging about? What’s your opinion on Hungarian notation? I don’t care if you say something I don’t agree with — the very fact that you actually have an opinion and aren’t being totally insipid is worth a tremendous amount.

Even better are contributions to an open source project. They don’t have to be in .NET — if all your publicly showcased code is in PHP, that’s fine. Rails is even better, simply because Rails developers seem to be the most passionate ones of the lot. One of the best conversations with another developer that I’ve had in a long time was with a Rails developer at MiniBar about a year ago. His enthusiasm was infectious.

And this is where my gripe is. Why don’t we see the same passion and enthusiasm in .NET land?

This is something I’ve noticed in general. PHP often has a reputation for producing a lot of bad code, but PHP developers are much more likely to blog, and their blogs frequently seem to have a lot more sparkle to them. The PHP guys that I know may not necessarily be brilliant coders, but they almost all have much more passion and drive than their .NET and Java counterparts. I think it’s fair to say that this exhibits itself in higher standards too, particularly visually: more often than not, PHP and Rails blogs are pure eye candy, and you certainly never see any of them producing anything as gross as purple and blue Lucida Sans.

You see it in the open source world too. My friend Sam McGeown recently lamented the fact that there are no real .NET WordPress killers. I don’t think it’s likely that there ever will be either: open source is generally acknowledged to be very much a second class citizen in the Microsoft ecosystem, and far too many open source .NET projects simply peter out and die completely after a year or two.

Some people think the problem is that Microsoft has been dragging its heels over open source for far too long. This is true to an extent, but apart from that, the problem is that the .NET (and to a lesser extent, Java) ecosystems are just too enterprisey for their own good. They tend to find their niche in large development teams in large companies, where developers are generally small fish in a huge pond. In the enterprise, you are spending all day every day implementing frustratingly crazy business rules, and you are not writing code for the end users but for their bosses, who often won’t sign off on an Ajax drop down search if it costs them an extra five hundred pounds. In an environment such as that, code gets written to the lowest common denominator and there can be little impetus to pull out all the stops and go the extra mile. The way up the career ladder is not to become a better developer, but to step off the coding ladder altogether and into project management, or enterprise architecture, or an MBA, and make way for another generation of mediocre programmers.

Unfortunately, nearly all the developers in the .NET ecosystem seem to have most of their commercial experience in that kind of setup. They can maybe offer us seven or eight years of experience as 9-5 developers, but the passion just isn’t there. Sure, there are people who buck the trend, but I can’t avoid the conclusion that the overwhelming majority of smart, passionate, enthusiastic developers work with PHP, Rails and Python.