当使用Asp.Net主题时,我该如何强制浏览器重新加载缓存的CSS文件?

8

嗨,霍默,我不知道这个理论是否可行。我猜测浏览器会缓存CSS文件,并在发现有更改时获取新版本。我的想法是在CSS文件中添加一个未使用且每个主题都不同的类。如果这个类在每个CSS文件的顶部,则浏览器会读取它,看到不同的类名并重新下载CSS文件。当然,这一切都是基于假设,对于Internet Explorer如何缓存CSS没有任何了解。如果有其他人能够权威地发言,我也很感兴趣! - WraithNath
我有点困惑- 当您使用不同的主题时,样式表位于另一个文件夹中,例如/App_Themes/blue/stylesheet.css与/App_Themes/red/stylesheet.css。这个目录更改足以导致它无法被缓存。现在,当然red / stylesheet.css仍将被缓存,但是如果您切换到蓝色主题,则会加载蓝色主题(可能会被缓存)。 - Prescott
我不是在交换主题,只是修改CSS文件。 - Homer
4个回答

14
我认为我有一个简单而快速的解决方案。关键在于检查页面头部中的控件(例如在PreRender阶段),找到指向App_Themes文件夹下CSS文件的链接,并使它们动态化(通过向查询字符串添加一些随机信息)。这很可能会告诉浏览器使缓存版本失效。
代码如下:
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());
            }
        }
    }
}

输出结果:
    <link href="App_Themes/MyTheme/MyTheme.css?t=634310637798128189" 
        type="text/css" rel="stylesheet" />

请注意,在您的页面标记中必须声明一个<head runat="server">,才能访问Header属性(否则它将为null)。

这种方法肯定会杀死CSS浏览器缓存,因为每次用户查看页面时文件名都会不同。无论如何,我已经阅读过浏览器不会缓存带有查询字符串参数的文件。 - Homer
@Homer:它们可能会缓存这些文件,这取决于实现方式。如果文件的 URI(而不是 URL)从未更改,为什么不缓存该文件呢? - volpav
@Homer,这个基本思路对我有用,但是我需要做一些改变。这是我的更改:protected override void OnPreRender(object sender, EventArgs e)此外,您需要确保在方法完成之前调用基础方法。 - Jonathan Henson
4
可以通过根据文件的最后修改日期生成Ticks来完成此操作——当然速度会慢一些,但这样可以正确反映文件在缓存方面的状态。 - Joe Niland
小心 DateTime.Now.Ticks。你会永久性地禁用所有缓存;这 使你的网站变得更慢。使用文件日期/时间,可能加入额外的逻辑来防止过于频繁地检索它。 - Roman Starkov

1
我目前还没有找到一种版本化App_Themes文件的方法,但你可以将它们设置为在相对较短的时间内过期(例如10秒),这样可以最大程度地减少缓存问题,同时仍然能够获得一些缓存带来的性能优势。请记住,如果文件没有更改,服务器将响应304-未修改,因此即使浏览器请求文件,流量也会减少。

将以下内容添加到Web.Config的<configuration>部分中

<location path="App_Themes">
    <system.webServer>
        <staticContent>
            <clientCache cacheControlMode="UseMaxAge" cacheControlMaxAge="00:00:10" />
        </staticContent>
    </system.webServer>
</location>

1
如果您想知道服务器端如何强制重新加载...一种方法是动态更改CSS/JS文件的文件名,以便对页面的后续调用需要不同的文件。
另一种方法是简单地告诉用户按CTRL-F5键 :)

有没有想法如何在ASP.Net中实现动态更改文件名(而不是CTRL-F5)? - Homer
2
我使用的一种方法是在服务器上设置重写规则,将任何对特定模式文件(/css/mycssfile.201104056554433.css)的请求重定向到没有时间戳的真实文件。这样浏览器会将每个请求视为对唯一文件的请求,您的服务器可以盲目地返回文件请求,而不考虑实际时间戳。您只需要记住在ASP页面中动态更改每个请求中请求的CSS文件名(很容易,在每个请求中插入当前时间戳即可)。 - Dekker500

1

当完成对网站的更改后,请手动更改CSS的名称。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接