force browsers to get latest js and css files in asp.net application

kiev picture kiev · Feb 2, 2010 · Viewed 109.8k times · Source

Some browsers cache js and css files, failing to refresh them unless you force them to. What's the easiest way.

I just implemented this solution that seems to work.

Declare a version variable on your page

  public string version { get; set; }

Get the version number from web.config key

 version = ConfigurationManager.AppSettings["versionNumber"];

In your aspx page make the calls to javascript and stylesheets like so

<script src="scripts/myjavascript.js?v=<%=version %>" type="text/javascript"></script>
<link href="styles/mystyle.css?v=<%=version %>" rel="stylesheet" type="text/css" />

So if you set the version = 1.1 from 1.0 in your web.config your browser will download the latest files which will hopefully save you and your users some frustration.

Is there another solution that works better, or will this cause any unforeseen issues for a website?

Answer

Adam Tegen picture Adam Tegen · Nov 29, 2011

I solved this by tacking a last modified timestamp as a query parameter to the scripts.

I did this with an extension method, and using it in my CSHTML files. Note: this implementation caches the timestamp for 1 minute so we don't thrash the disk quite so much.

Here is the extension method:

public static class JavascriptExtension {
    public static MvcHtmlString IncludeVersionedJs(this HtmlHelper helper, string filename) {
        string version = GetVersion(helper, filename);
        return MvcHtmlString.Create("<script type='text/javascript' src='" + filename + version + "'></script>");
    }

    private static string GetVersion(this HtmlHelper helper, string filename)
    {
        var context = helper.ViewContext.RequestContext.HttpContext;

        if (context.Cache[filename] == null)
        {
            var physicalPath = context.Server.MapPath(filename);
            var version = $"?v={new System.IO.FileInfo(physicalPath).LastWriteTime.ToString("MMddHHmmss")}";
            context.Cache.Add(filename, version, null,
              DateTime.Now.AddMinutes(5), TimeSpan.Zero,
              CacheItemPriority.Normal, null);
            return version;
        }
        else
        {
            return context.Cache[filename] as string;
        }
    }
}

And then in the CSHTML page:

 @Html.IncludeVersionedJs("/MyJavascriptFile.js")

In the rendered HTML, this appears as:

 <script type='text/javascript' src='/MyJavascriptFile.js?20111129120000'></script>