.NET Stopwatch meet IDisposable

You’re probably aware of the .NET Stopwatch class, a System.Diagnostics class that ‘Provides a set of methods and properties that you can use to accurately measure elapsed time’.

A code sample illustrates its typical usage:

Stopwatch stopWatch = new Stopwatch();
stopWatch.Start();
Thread.Sleep(10000);
stopWatch.Stop();
// Get the elapsed time as a TimeSpan value.
TimeSpan ts = stopWatch.Elapsed;

You get the idea – create, start, execute code (thanks Thread.Sleep(…)), stop and examine its Elapsed property.

There are a number of open source profilers such as Prof-It that provide comprehensive timing information, and there can be some discrepancies when timing code execution with a Stopwatch, as this excellent Code Project article explains, it’s often sufficient to temporarily put in a Stopwatch block to time a piece of code.

One thing to note from the code sample is that it is a little verbose.  The Thread.Sleep(…) call is trivial, for our example, but if we’re timing several lines, the various Stopwatch boilerplate lines rather get in the way.

Wouldn’t it be nice if we could write something like this:

using (new CleverTimer()))
{
	Thread.Sleep(10000);
}

We can, with this little ‘CleverTimer’ class, which uses a mix of a Stopwatch and IDisposable:

public class CleverTimer : IDisposable
{
	private readonly Stopwatch _stopwatch;
	private readonly Action<Stopwatch> _action;
	public CleverTimer(Action<Stopwatch> action = null)
	{
		_action = action ?? (s => Console.WriteLine(s.ElapsedMilliseconds));
		_stopwatch = new Stopwatch();
		_stopwatch.Start();
	}
	public void Dispose()
	{
		_stopwatch.Stop();
		_action(_stopwatch);
	}
	public Stopwatch Watch
	{
		get { return _stopwatch; }
	}
}

The class has a couple of members – the all important Stopwatch, as well as an Action of type Stopwatch.  The constructor can accept an Action, but defaults to writing out the Elapsed milliseconds of the stopwatch.   The constructor creates a the member Stopwatch and starts it.

The Dispose method, required for the implementation of the IDisposable interface, simple stops the Stopwatch member and invokes the _action code.

It’s all fairly simple stuff, but goes some way to simplifying timed code.

Resolving WordPress Twenty Thirteen Disqus Plugin placement issues

WordPress’ new 2013 theme is fantastic, but if you’re also using the Disqus plugin, it’s quite likely you’ve noticed an issue with its placement.

Rather than sitting nicely under the main content, it spreads out and occupies the space visually reserved for the sidebar.

WordPress.org forum thread details some fixes, but I found a quick CSS addition fixed the problem.  Simply add this to the bottom of the 2013 Theme’s stylesheet:

#disqus_thread {
    max-width: 1040px;
    padding: 0 376px 0 60px;
}

This should push the area under the left column and respond appropriately.

I also made a small change to the single.php file, because I feel the ‘post nav’ is better suited to being placed after the comments.  Simply modify the loop of that file to this:

<?php while ( have_posts() ) : the_post(); ?>
  <?php get_template_part( 'content', get_post_format() ); ?>
  <?php comments_template(); ?>
  <?php twentythirteen_post_nav(); ?>
<?php endwhile; ?>

I swapped the order of the comments_template() and twentythirteen_post_nav() function calls.

Hope this helps!

Orchard Module to Prevent (Indefinite) JS/CSS Caching

A couple of days ago, I saw this tweet

 

A few months ago, I wrote a ‘Resource Timestamper’ Orchard module to add a timestamp to invalidate cache on the client.

Browsers cache resources such as JavaScript and CSS. This is a good thing, but this caching prevents browsers from requesting updated versions of resources. Although doing a ‘hard refresh’ of a page can force a reload of scripts and styles, we can’t expect users to do that to circumvent the problem.

It turns out that resources can be updated using a query string parameter. A client browser considers these as two different requests for the same physical resource:

<link type="text/css" rel="stylesheet" href="somecss.css?1"/>
<link type="text/css" rel="stylesheet" href="somecss.css?2"/>

Using a different query string each time the file is served gets around the caching issue, but loses all benefits of caching.  Better yet, generate a new query string value only when the file has changed.

The Resource Timestamper module modifies resource URLs generated with Orchard’s standard Resource Manager class.  To add a timestamp, call the SetAttribute method with parameters of ‘data-timestamped’, and ‘true’.  Here’s an example from ‘The Theme Machine’s’ Layout.cshtml file:

Style.Include("site.css").SetAttribute("data-timestamped", "true");

On the client, a URL is generated:

http://localhost:30321/OrchardLocal/Themes/TheThemeMachine/styles/site.css?v=635151301095348769

Prior to the timestamp being applied, the URL is converted to an absolute URL.  Why? Well, when writing the module, I realised that trying to append a query string to a relative URL (such as /OrchardLocal/Themes/TheThemeMachine/styles/site.css) didn’t work; the query string was being removed.  I see I’m not the only one who’s noticed Style.Include stripping query strings.

Absolute and relative URLs are often a personal preference, but one issue with absolute URLs is that they must be changed when deploying to a production system, or to another domain.  The plugin uses details of the current request, so there is no need to update the code.

The code generates a timestamp for the resource, and only generates a new timestamp when the file changes in some way.  That way, you get the benefit of caching without the problem of updating the file.

Code Analysis

The single class , FcmResourceManager (Fcm is an abbreviation for my company, Fresh Click Media), derives from Orchard’s ResourceManager class.  To actually use this class, rather than the default ResourceManager, an OrchardSuppressDependency attribute is used:

[OrchardSuppressDependency("Orchard.UI.Resources.ResourceManager")]

The class has a number of Orchard dependencies to get its work done:

private readonly IClock _clock;
private readonly ICacheManager _cacheManager;
private readonly IWebSiteFolder _websiteFolder;
private readonly IHttpContextAccessor _httpContextAccessor;
private readonly Work<WorkContext> _workContext;

These members are assigned using constructor injection.

The crucial method override is called BuildRequiredResources:

public override IList<ResourceRequiredContext> BuildRequiredResources(string stringResourceType)
{
    var resources = new List<ResourceRequiredContext> base.BuildRequiredResources(stringResourceType));
    foreach (var resource in resources)
    {
        if (resource.Settings.Attributes == null)
            continue;
        if ((from a in resource.Settings.Attributes.ToList()
            where a.Key == "data-timestamped"
            select a).Any())
        {
            resource.Resource.SetUrl(GetCachedUrl(resource));
        }
    }
    return resources;
}

It is this method that is called, and gives us an opportunity to manually set the new URL for the given resource.  This is only done is the ‘data-timestamped’ attribute is found.  In this scenario, the GetCachedUrl method is called.

The GetCachedUrl is shown below:

private string GetCachedUrl(ResourceRequiredContext resource)
{
    if (resource.Resource.Url.StartsWith("http://") || resource.Resource.Url.StartsWith("https://"))
    {
        return resource.Resource.Url;
    }
    string path = GetResourcePath(resource);
    // it's a local file:
    return _cacheManager.Get("Fcm.ResourceCache." + path, ctx =>
    {
        ctx.Monitor(_websiteFolder.WhenPathChanges(path));
        return GetUpdatedUrl(path);
    });
}

The method ignores absolute URLs.  For relative URLs, the path of the file is ascertained.  Orchard’s ICacheManager returns the value of GetUpdatedUrl(…) for a cache key made up of a combination of ‘Fcm.ResourceCache’ and the file’s path.  The cache is invalidated when the path of the file changes.  In this situation the path changes when the file is updated.

The GetUpdatedUrl method takes the original path of the resource, and converts to an absolute URL.

Download and Install

Once you download the Resource Timestamper module, you can install in the usual way.  The usual way? Go here for more information about installing Orchard modules.

Once the module has been installed, you should see a reassuring message as shown below.  Enable the ‘Resource Timestamper’ feature.

resource timestamper install

One final thing

I hope you find the module useful.  It was written for Orchard 1.5, but has been tested on Orchard 1.7.1 (latest at the time of writing).  It shouldn’t cause you any issues, but you should test it fully on a local environment before deploying it to a production environment. Think that covers it.

Redis

Installing Redis on Windows

Getting started with Redis on Windows is easy:

1. Download the latest .exe package from https://github.com/rgl/redis/downloads (choose the appropriate latest 32 or 64 bit version).

2. Running the exe will install Redis as a service and install the Redis client.

Troubleshooting

I got an issue when installing the service through the setup.  I had to do so manually using this command (ensure that you run cmd as Administrator):

sc create redis binPath= "C:\Program Files\Redis\redis-service.exe redis conf/redis.conf"

Note that Windows is particularly fussy about the space after binPath=, and paths with spaces must be wrapped with quotes.

Have fun!

Moving over to Disqus

A quick post to say that I’ve just migrated my blog’s comments over to Disqus; the whole thing was a lot less painful than I imagined, and I wished I’d done it ages ago.

If you’ve been living in a cave for a while, you’ll not know that Disqus is an online discussion and commenting service for websites. It powers the comments systems for many popular blogs as well as CNN and The Daily Telegraph, so the only thing holding me back was the thought of problems.

I needed a couple of links to get what I needed:

The first was an idiot’s guide to the migration, whilst the second was a useful tip to get rid of those ads (that appear by default.)