force browsers to get latest js and css files in asp.net application
Solution 1
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>
Solution 2
In ASP.NET Core (MVC 6) this works out of the box via the asp-append-version
tag helper:
<script src="scripts/myjavascript.js" asp-append-version="true"></script>
<link href="styles/mystyle.css rel="stylesheet" asp-append-version="true" />
Solution 3
Your solution works. It is quite popular in fact.
Even Stack Overflow uses a similar method:
<link rel="stylesheet" href="http://sstatic.net/so/all.css?v=6184">
Where v=6184
is probably the SVN revision number.
Solution 4
ASP.NET MVC will handle this for you if you use bundles for your JS/CSS. It will automatically append a version number in the form of a GUID to your bundles and only update this GUID when the bundle is updated (aka any of the source files have changes).
This also helps if you have a ton of JS/CSS files as it can greatly improve content load times!
Solution 5
There are a built-in way in asp.net for this: bundling. Just use it. Each new version will have unique suffix "?v=XXXXXXX". In debug mode bundling is off, for switching on make setting in web.config:
<system.web>
<compilation debug="false" />
</system.web>
Or add to the method RegisterBundles(BundleCollection bundles) :
BundleTable.EnableOptimizations = true;
For example:
BundleConfig.cs :
bundles.Add(new ScriptBundle("~/Scripts/myjavascript.js")
.Include("~/Scripts/myjavascript.js"));
bundles.Add(new StyleBundle("~/Content/mystyle.css")
.Include("~/Content/mystyle.css"));
_Layout.cshtml :
@Scripts.Render("~/Scripts/myjavascript.js")
@Styles.Render("~/Content/mystyle.css")
Related videos on Youtube
kiev
Updated on July 08, 2022Comments
-
kiev almost 2 years
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?
-
Brett Allen over 14 yearsInteresting question, I had the same issue recently, but was only an issue during development testing. Didn't care to much about it as we do not intend to change those file after launch. Would love to know a solution though for future reference!
-
monty over 10 yearsThe only issue I can see is that changes to the web.config will, in the background, call an application restart: msdn.microsoft.com/en-us/library/aa478432.aspx
-
BetterLateThanNever almost 7 yearsThank you for the question. This helped me in solving a big issue.
-
-
Darren Kopp over 14 yearsand uses copious amounts of bandwidth too.
-
kingdango over 10 yearsRight, you don't want a new version of the JS at each page load... you just want the browser to look for a new version each time you actually have an updated version.
-
kiev over 10 yearsyes, the issue is with bandwidth - like in the comments above stackoverflow.com/a/2185918/59508
-
kiev over 10 yearsthis is great for mvc, I wonder if the latest mvc 5 framework handle this issue? The approach that bundling uses with -{version} wildcard is also a way to solve this problem, however it requires the files to be renamed after each new build...
-
Colbs almost 10 yearsThis is perfectly acceptable for a temp solution on a 50KB css file while in development. +1
-
Bryan about 9 yearsI'm using the basics of your MVC example in a webforms website, and it's working great, so thank you for sharing!
-
Bryan about 9 yearsShould there be any reason to be concerned about displaying the last modified date/time stamp for resource files? If a file being used had a date/time stamp a few years past, could be information that a company might not want to be public to their users?
-
Tarun almost 9 yearsIt's the standard way, mostly applications follows. But that time stamp should change only when you deploy or built your application. Otherwise every time user refresh page or switch to other pages in your application. Browser will download your all stylesheets and javascript again, which is not good
-
Flavia Obreja over 8 yearsHey! Your example is working, but you should either remove the caching references or fix the code to use the cache because it can be confusing why you are using it. To use the cache you should add the version of the file to the cache using context.Cache.Add method in the case context.Cache[filename] == null . If the context.Cache[filename] != null then you should return the cached value (context.Cache[filename])
-
Bryan over 8 yearsFlavia, I think your explanation makes sense, and I think it's a simpler, more efficient implementation. Thanks for posting the helpful comments and feedback.
-
Jack about 8 yearsDo you mean that if we use bundles in an MVC application, there is no need any of the methods in posted answer here? If so, bundling is really much more important I have ever thought. Could you please clarify us about these issue? Thanks.
-
metalheart almost 8 yearsthis behavior is actually supported out of the box, see my answer
-
jonesy827 almost 8 yearsYes, exactly. As long as your scripts are included in a bundle, it will generate a version number automatically for each bundle when changes are detected in any of the bundle's source files.
-
Victor Zakharov over 7 yearsThis would be a much more taxing approach than the one described in the accepted answer. Checking SVN version of the file every time a page is served is a performance overhead, especially as number of users increases over time.
-
Salik over 7 yearsI have tried this method, but it adds the create date of the file, that's why it doesn't change version number on file overwrite.
-
dotnet-provoke over 7 yearsGreat solution. Im using it but i had to modify the code for the cache to work:
-
Ramazan Binarbasi about 7 yearsYou can get revision number during build, write it into a file (e.g. partial .cs file), include that file in your project, so you don't need to read it from svn at runtime. I've used this approach with msbuild to put revision numbers in my AssemblyInfo.cs files from svn.
-
Federico Navarrete almost 7 yearsMan! You're awesome. Seriously, it's the best and unique! Thanks a lot!
-
Federico Navarrete almost 7 yearsNice answer, but ASP MVC can a be a bit problematic if you don't consider what Adam explained because I tried it and the Bundle folder doesn't recognize it if you work with MVC 5. But thanks for the suggestion!
-
Federico Navarrete almost 7 yearsNice approach too!
-
Federico Navarrete almost 7 yearsThanks for letting us know! I didn't know it before!
-
VAAA over 6 yearsBut this will only work in release or production environments. What about development when debug mode is on? Does bundle still fix this issue?
-
VAAA over 6 yearsIm trying to use bundle, with the optimization property equals true works great but I want to know if in a dev environment (debug on) the bundle still force browser to refresh scripts?
-
Adam Tegen over 6 yearsUsing a global version / revision number has at least one drawback: publishing a website update invalidates browser caches for all .js and .css files, not just the ones that changed. This probably does not matter in the majority of applications, but I mention it for completeness.
-
Durgesh Sonawane over 6 yearsWhat is the impact on the performance of the page? How much delay can it cause to load the page?
-
kristianp about 6 yearsIf you update the version of your assemblyinfo.cs files automatically during a deployment or build, the minor version could be used for that number.
-
Tony Hinkle over 5 yearsBy far the easiest way to do this, and probably the lowest overhead.
-
Brad Mathews over 5 yearsPerfect solution. I also tested Chrome 70, Firefox 63 and IE 11 to make sure that caching was actually working. It is. This only busts caching on new versions of the file, at least on the latest versions of the browsers. I have heard mention elsewhere that some browsers reload every file with a querystring (?). Maybe that used be the case or maybe it is still true with Safari and Opera. DK.
-
SimplyInk over 5 yearsI like this, but am concerned why this solution has so little up votes...
-
JackArbiter over 5 years@SimplyInk I don't know, but there are 20 different answers, so that might have something do do with it. If it works and you like it, feel free to upvote it.
-
it3xl over 4 yearsYeah, bundlind doesn't make developers live easier. You have to press Ctrl-F5 after each script change. And if you have frames it will be even more funny.
-
it3xl over 4 yearsAnd don't forget that you still have headaches as a developer. The ASP.NET bundling helps nohow during debugging and development.
-
Thanasis Ioannidis almost 4 yearsthis wil force download in every page render, even if the files has not changed at all.
-
SantoshK almost 4 years@ThanasisIoannidis It can use where files are changes regularly. another option is add appVersion key in web.config and use with files name .. but you need to update when you release the application for prod.
-
sachin jaiswal about 3 years<caching enabled="true" enableKernelCache="true"> <profiles> <add extension=".html" policy="CacheUntilChange" kernelCachePolicy="CacheUntilChange"/> <add extension=".css" policy="CacheUntilChange" kernelCachePolicy="CacheUntilChange"/> <add extension=".js" policy="CacheUntilChange" kernelCachePolicy="CacheUntilChange"/> </profiles> </caching>
-
Mohammed Khurram about 2 yearsThis will get new version on every load and cause lot of data usage.