james mckay dot net

because there are few things that are less logical than business logic

February 2009

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.

07
Feb

The case of the disappearing feeds

Now when you announce on your blog that you are starting work in an establishment such as Parliament, you naturally brace yourself for at least a modest increase in web traffic. After all, when your place of employment features prominently on the front page of almost every newspaper in the country several times a week, people do tend to take an interest, even if you are a serious INTJ blogger writing a serious INTJ blog about technology that is not work related. You certainly don’t expect your Feedburner subscriptions to drop overnight from 50 to fifteen.

However, that was what happened to me, and it had me scratching my head a bit. What kind of people would hit the “unsubscribe” button on reading that kind of news? I know that certain individuals in Westminster get a bit of a bad press from time to time, but surely there isn’t some kind of deep-seated prejudice out there that extends to those of us whose role is to spend the entire day looking at computer screens doing fancy things with XML?

It turns out that the cause was actually somewhat more mundane. The day after I posted that particular entry, I moved my blog off my shared hosting account onto a new virtual server, and while it mostly went smoothly, I inadvertently missed out the Feedburner plugin that had been redirecting my feeds. So anyone who had subscribed to the WordPress default http://jamesmckay.net/feed/ rather than the Feedburner version at http://feeds.feedburner.com/jamesmckay would not have been counted. Okay, download latest version of plugin, install, activate, and after 24 hours, the figure on my Feedburner widget is beginning to look a little bit more respectable again.

End of story? Not quite.

For the past couple of years or so, I’ve subscribed to my own blog in Google Reader. This is mainly a diagnostic thing — it shows how long it’s taking for my blog entries to show up (it frequently takes up to about three or four hours), and that everything is displaying correctly. Now Google Reader caches old blog entries, and for as long as I could remember, the oldest one that has appeared in my list was the entry, “Pastors, get blogging!” back in November 2006. This is what you will see if you have subscribed to http://feeds.feedburner.com/jamesmckay.

Anyway, I decided to unsubscribe from my feed and re-subscribe — only to find that Google Reader had lost track of all my blog entries except the last ten.

It turns out that this is because my Feedburner feeds are now being redirected to http://feeds2.feedburner.com/jamesmckay, which Google Reader treats as a completely separate feed.

A little bit of experimentation confirmed this. My blog’s feed URL can take several different forms — it works with a trailing slash or without, with a “www.” subdomain or without, and so on. By constructing it in different ways when you plug it into Google Reader, you can get different posting histories. The longest one seems to be http://www.jamesmckay.net/feed which goes back to February 2006.

This behaviour is only to be expected, of course. I’m sure that Google could identify when two different URLs point to the same feed, and could treat similar looking ones that give the same content as one and the same. I’m sure too that they could deliver a tighter integration between Feedburner and Google Reader in this particular respect. However, that could be an over-engineered solution capable of introducing all sorts of other problems. It would have been far better if they’d just left the feed at its original location rather than chopping and changing all over the place.