How can I force browsers to reload cached CSS files when using Asp.Net Themes?

18,247

Solution 1

I think I have a quick and dirty solution. The trick is to examine the controls within the page header (for example in the PreRender phase), find the links pointing to CSS-files under the App_Themes folder and make them dynamic (by adding some random information to the query-string). This will most likely tell the browser to invalidate the cached version of the file.

The code:

protected void Page_PreRender(object sender, EventArgs e)
{
    HtmlLink link = null;

    foreach (Control c in Header.Controls)
    {
        if (c is HtmlLink)
        {
            link = c as HtmlLink;

            if (link.Href.IndexOf("App_Themes/", StringComparison.InvariantCultureIgnoreCase) >= 0 &&
                link.Href.EndsWith(".css", StringComparison.InvariantCultureIgnoreCase))
            {
                link.Href += string.Format("?t={0}", DateTime.Now.Ticks.ToString());
            }
        }
    }
}

The output:

    <link href="App_Themes/MyTheme/MyTheme.css?t=634310637798128189" 
        type="text/css" rel="stylesheet" />

Note that you need to have a <head runat="server"> declared in your page's markup in order to be able to access the Header property (otherwise it will be null).

Solution 2

If you are asking how the SERVER side can force reloading... One way is to dynamically change the filename of the CSS/JS so that subsequent calls to the page require a different file.

<sarcasm> The other is to simply tell the user to press CTRL-F5 :) </sarcasm>

Solution 3

When finished doing changes to the site change the name of the css manually.

Solution 4

I've not found a way to version App_Themes files (yet), but you can set them to expire in a relatively short period of time (e.g., 10 seconds), which will minimize the cache problem while giving you some performance benefit of caching. Remember, if the file has not changed, the server will respond with 304-Not modified so traffic is reduced even if the browser requests the file.

Add this to the <configuration> section of the Web.Config

<location path="App_Themes">
    <system.webServer>
        <staticContent>
            <clientCache cacheControlMode="UseMaxAge" cacheControlMaxAge="00:00:10" />
        </staticContent>
    </system.webServer>
</location>
Share:
18,247
Homer
Author by

Homer

Updated on June 04, 2022

Comments

  • Homer
    Homer almost 2 years

    Possible Duplicate:
    CSS in App_Theme folder gets Cached in Browser

    I've seen "What is an elegant way to force browsers to reload cached CSS/JS files?" but the answer there uses PHP and it doesn't address the fact that the CSS is injected dynamically by an ASP.Net Theme.

  • Homer
    Homer over 13 years
    This method would definitely kill css browser caching since the filename would be different every time a user viewed the page. Anyway, I've read that browsers will not cache files with a querystring param.
  • volpav
    volpav over 13 years
    @Homer: They might cache such files, it depends on the implementation. Why not cache the file if its URI (not the URL) never changes?
  • Homer
    Homer about 13 years
    Any idea how to do that in ASP.Net (dynamically change the filename, not CTRL-F5)?
  • Dekker500
    Dekker500 about 13 years
    One method I've used is to have rewrite rules on the server, redirecting any request for a file of a particular pattern (/css/mycssfile.201104056554433.css) to the real file which does not have a timestamp. This way the browser treats each request as a request for a unique file, and your server can just blindly return a request for the file, regardless of the actual timestamp. You just need to remember in your asp page to dynamically change the css filename being requested on each request (easy, just insert the current timestamp on each request).
  • Jonathan Henson
    Jonathan Henson almost 13 years
    @Homer, this basic idea worked for me, I had to change a little however. Here is my change: protected override void OnPreRender(object sender, EventArgs e) also, you need to make sure you call the base method before the method is finished.
  • Joe Niland
    Joe Niland about 12 years
    You could do it by generating the Ticks from the lastmodified date on the file - would be slower of course, but would properly reflect the state of the file w.r.t. cache.
  • Roman Starkov
    Roman Starkov about 10 years
    Beware of the DateTime.Now.Ticks. You permanently disable all caching; this will make your site a lot slower. Use the file date/time, possibly with extra logic to stop retrieving it too often.