One of the common workarounds for this situation that I've found quite effective is to append some value to the query string of the external file. So instead of the typical link (to a CSS file) in the Head section of your document,
<link href="styles.css" type="text/css" rel="stylesheet" />
You instead use a link with an arbitrary value following the actual file name:
<link href="styles.css?v=1" type="text/css" rel="stylesheet" />
Browsers cache the CSS file with an Id of "styles.css?v=1". If you update your CSS file, you can change the "v=1" to "v=2" in your HTML page and the browser treats styles.css?v=2 as a different file than styles.css?v=1. Since styles.css?v=2 isn't already cached, the browser will fetch the latest copy of styles.css from your web server. Constantly modifying (and trying to remember to modify) the query string value when I make changes to CSS and JS files has always been a manual task for me. Recently, however, I created a mechanism to automate this process.
The automated process appends the timestamp of the external file (CSS of JS) to the query string following the file's name that is sent to the browser. The file timestamp is stored in the .NET cache with a cache dependency to the actual file on the web server. Whenever I update the CSS or JS file, the timestamp is automatically removed from the cache and the next time a visitor arrives at the page and the timestamp is needed, the timestamp is retrieved and stored in cache. The purpose of the cache is to obviously reduce the amount of file I/O and overall time required in getting the page to the browser. I've fallen in love with this process as it's made my life easier!
The download link at the bottom of this post contains the code for a static GetFileWithVersion() function. The same function can be used for any external file that you want to prevent browsers from mistakenly hanging onto a copy of after you may have updated the file. At present, GetFileWithVersion returns a string value containing the filename and appended query string value. It's the caller's responsibility to add the necessary link or script tag to the head section of the page.
Example usage of the GetFileWithVersion() function with a CSS file:
string CssFileWithVersion = utils.GetFileWithVersion("MainCss", "~/styles.css");
System.Web.UI.HtmlControls.HtmlLink cssLink = new System.Web.UI.HtmlControls.HtmlLink();
cssLink.Href = CssFileWithVersion;
string JsKey = "MainJs";
if (!ClientScript.IsClientScriptIncludeRegistered(this.GetType(), JsKey))
string JsFileWithVersion = utils.GetFileWithVersion(JsKey, "~/tools.js");
ClientScript.RegisterClientScriptInclude(this.GetType(), JsKey, ResolveClientUrl(JsFileWithVersion));
Code Download (1.74 kb)