Versioned content in MVC

When you add a script or stylesheet to your HTML page, those requests can be cached by the browser, potentially providing outdated content to the browser.

If you’re not using a bundler or anything fancy like that, then the only way to prevent this problem is to create a brand new URL whenever your script file or stylesheet changes. This is easily accomplished with a querystring, so if your app was previously using app.js?v=1 and you change that to app.js?v=2, the browser will definitely not use the cached version, and will instead make a new request to the server, and pull the latest one.

Using the following technique, you can guarantee that you’ll always pull the latest script and stylesheet when working in dev, and when in production, you can define a “version key”, possibly in a config file or database, and if you ever update just the static content, you would only need to update that key, and it would force all browsers to pull new content.

public static class HtmlExtensions {
    private static string GetUniqueVersionKey() {
        #if DEBUG
        return Guid.NewGuid().ToString("N");
        #else
        // This needs to be somewhere you can get to it, like a web.config file or database
        return MvcApplication.GetUniqueVersionKey();
        #endif
    }
 
    public static MvcHtmlString Script(this HtmlHelper htmlHelper, string scriptFileName) {
        var urlHelper = new UrlHelper(htmlHelper.ViewContext.RequestContext);
        return new MvcHtmlString(string.Format("<script type=\"text/javascript\" src=\"{0}?uv={1}\"></script>",
            urlHelper.Content(scriptFileName), GetUniqueVersionKey()));
    }
 
    public static MvcHtmlString Style(this HtmlHelper htmlHelper, string styleFileName) {
        var urlHelper = new UrlHelper(htmlHelper.ViewContext.RequestContext);
        return new MvcHtmlString(string.Format("<link rel=\"stylesheet\" href=\"{0}?uv={1}\">",
            urlHelper.Content(styleFileName), GetUniqueVersionKey()));
    }
}

These will produce the appropriate link or script tag:

@Html.Style("app.css")
@Html.Script("app.js")

Comments

Popular posts from this blog

C# Record Serialization

Add timestamp to photo using ImageMagick

Read/write large blob to SQL Server from C#