Bust a cache
Heads Up!
This article is several years old now, and much has happened since then, so please keep that in mind while reading it.
Client: "I just checked the website to see the changes you told me you'd deployed, but I can't see any. Are you sure you actually deployed it?"
You: "Are you looking at it in your browser now?"
Client: "Yes"
You: "Try holding down the Ctrl key and press F5"
Client: "Wait I'll put down my phone . . Ooooh there it is, what did you do?"
You: "Never mind".
Then you probably wished you've gotten around to implement some form of cache busting technique with the website you'd deployed.
Cache busting with a partial view
Here's how to do some cache busting using a partial view. To get ready: Log in to your favorite CMS go to the Settings
section, and create a new partial view.
In the view insert the following code.
@inherits Umbraco.Web.Mvc.UmbracoTemplatePage
@using File = System.IO.File
@{
Layout = null;
// Grab the url and find the file
var url = (string)ViewData["href"];
var path = Server.MapPath(url);
var exists = File.Exists(path);
// Determine file type
var fileType = Path.GetExtension(path);
if ("|.png|.gif|.jpg|.jpeg|".Contains(fileType))
{
fileType = "img";
}
// Check if the file exists
if (exists)
{
// Latest write time of the file
DateTime date = File.GetLastWriteTime(path);
// Build an url with a parameter that reflects last write time
url = string.Format("{0}?v={1}", url, date.Ticks);
}
else
{
fileType = string.Empty;
}
}
@switch (fileType)
{
case ".css":
<link rel="stylesheet" href="@url" />
break;
case ".js":
<script type="text/javascript" src="@url"></script>
break;
case "img":
<img src="@url" alt="@ViewData["altTxt"]" width="@ViewData["width"]" />
break;
default:
<!-- No versionable file found at @url -->
break;
}
With this partial view you are able to include CSS, JavaScript and image resources in your code, that'll automatically get versioned. Every time you save the file on the server, it will get a new version parameter on the query string causing your browsers to redownload the resource.
As you see in the partial it's possible to add strings for alt-, width- and height-attributes when using the partial for images, for this I'm using the possibility for adding a ViewDataDictionary as a parameter in the call to Html.Partial
. The ViewDataDictionary is a key/value dictionary made available in your Razor script as @ViewData
, and it is easily declared when using the Partial view with the Html-helper in a view. The Partial can be used in these ways:
// Stylesheet
@Html.Partial("FingerprintUrl", new ViewDataDictionary{{"href", "/css/site.css"}})
// Javascript file
@Html.Partial("FingerprintUrl", new ViewDataDictionary{{"href", "/scripts/frontpage.js"}})
// Image file
@Html.Partial("FingerprintUrl", new ViewDataDictionary{{"href", "/images/20130831-DSC_0030.jpg"}, {"altTxt", "Bulbs"}, {"width", "960px"}})
Bonusinfo
It's now possible to control the caching of your static resources, and you can put this is in your Umbraco project just by creating a partial view using the excellent Umbraco backend.
But you might like to know how you can set up a really, really long caching period for your static ressources since you're now able to force the client-browsers to download the newer version every time you update the file.
This cannot be done from the Umbraco backend, so you might have to ask the webserver administrator to set it for your IIS website, or if you have access to your website filesystem via FTP or RDP or something else, you could just put the following XML-snippet in place:
<system.webServer>
<staticContent>
<clientCache cacheControlMode="UseMaxAge" cacheControlMaxAge="365:00:00" />
</staticContent>
</system.webServer>
In an ordinary Umbraco website, the <staticContent>
node will already be in place, so you should just add the clientCache node to the existing node.
This setting will cache all your static content in the client browsers for 365 days. If you're trying to do cache busting while developing your site in Visual Studio, or just want to do this using a proper HtmlHelper function, you can read my take on cache busting with the HtmlHelper.
That's it
Have a nice holiday season, and while you're away from your computer why not Bust a Move instead.
Jesper Hauge
Jesper is on Twitter as @jhauge