5

我有一个 ASP.NET IHttpModule 实现,旨在重写服务文件的路径。该模块只处理一个事件,PostAuthenticateRequest,如下:

void context_PostAuthenticateRequest(object sender, EventArgs e)
{
    if (HttpContext.Current.Request.Path.ToLower().Contains("foobar"))
    {
        HttpContext.Current.RewritePath("virtdir/image.png");
    }
}

路径“virtdir”是应用程序的虚拟目录子目录。应用程序本身运行在一个典型位置:C:\inetpub\wwwroot\IisModuleCacheTest\ 虚拟目录“virtdir”映射到 C:\TestVirtDir\

正如预期的那样,请求http://myserver/iismodulecachetest/foobar将从虚拟目录返回 image.png。同样,请求http://myserver/iismodulecachetest/virtdir/image.png将返回相同的图像文件。

然后我执行以下操作:

  1. 要求http://myserver/iismodulecachetest/foobar
  2. 直接修改 C:\testvirtdir\image.png (在paint中改变它的颜色并重新保存)。
  3. 重复。

在间隔几秒钟重复 1 到 20 次后,返回的图像将是过期的副本。

一旦不高兴,服务器只会在经过未知的时间(从 10 秒到几分钟)后返回当前版本。如果我将步骤 1 中的 URL 替换为http://myserver/iismodulecachetest/virtdir/image.png,则似乎不会出现问题。但奇怪的是,在使用“foobar” URL 出现问题后,直接 URL开始返回图像的过期副本。

相关细节:

  1. 应用程序池的回收解决了该问题。
  2. 稍等片刻即可解决问题。
  3. 反复重新保存文件似乎没有效果。我想知道“文件修改”事件是否丢失了,但是一旦卡住,我可以保存六次修改并且 Iis 仍然不会返回新副本。
  4. 在 web.config 中禁用缓存没有任何区别。<caching enabled="false" enableKernelCache="false" />
  5. 这是一个虚拟目录这一事实似乎很重要,我无法复制 image.png 作为应用程序本身内容的一部分的问题。
  6. 不是客户端缓存,它肯定是服务器返回一个过时的版本。我已经通过检查请求标头、Ctrl+F5 刷新,甚至使用单独的浏览器来验证这一点。
  7. 我已经在两台机器上复制了这个问题。Win7 Pro 6.1.7601 SP1 + IIS 7.5.7600.16385 和 Server 2008 R2 6.1.7601 SP1 + IIS 7.5.7600.16385。

编辑 - 更多细节:

  1. 在服务器级别禁用缓存和内核缓存没有区别。
  2. 向 URL 添加扩展名没有任何区别http://myserver/iismodulecachetest/foobar.png
  3. 将调试器附加到 IIS 表明context_PostAuthenticateRequest事件处理程序每​​次都被触发,并且无论缓存是否被卡住,其行为方式都相同。

Edit2 - IIS 日志:

我在 IIS 中启用了“失败的请求跟踪”(有趣的是,如果配置得当,这对于非失败请求也是如何工作的。在步骤 17 之前,管道是相同的,其中返回过期版本的请求清楚地显示了缓存命中。

第一个请求看起来很好,但缓存未命中:

好的请求

但是一旦卡住,它就会反复显示缓存命中:

错误的请求

可以理解,缓存命中后的事件与缓存未命中情况完全不同。看起来 IIS 完全满足于认为它的文件缓存是最新的,但它绝对不是!:(

再往下一点,我们看到第一个请求:

好的请求 2

然后是后续的(错误的)缓存命中请求:

错误请求 2

另请注意根据FileDirmoned="true".

4

2 回答 2

1

您可以执行以下操作。

void context_PostAuthenticateRequest(object sender, EventArgs e)
{
    if (HttpContext.Current.Request.Path.ToLower().Contains("foobar"))
    {
        Random rnd = new Random();
        int randomNumber = rnd.Next(int.MinValue, int.MaxValue);
        HttpContext.Current.RewritePath("virtdir/image.png?"+randomNumber);
    }
}
于 2013-04-08T19:37:41.263 回答
0

RewritePath使用该方法处理虚拟目录中的静态资源时,我遇到了同样的问题。我没有使用此方法的解决方案,但最后我选择使用该方法Server.TransferRequest,这表明没有缓存问题。

HttpContext.Current.Server.TransferRequest(newUrl);

请求传输由 再次处理,IHttpModule因此您需要小心不要产生循环。

于 2013-08-22T09:56:24.787 回答