kiev kiev - 4 months ago 120
Javascript Question

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

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

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 quiet 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("yyyyMMddHHmmss");
            context.Cache.Add(physicalPath, version, null,
              DateTime.Now.AddMinutes(1), TimeSpan.Zero,
              CacheItemPriority.Normal, null);
            context.Cache[filename] = version;
            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>