ASP.NET HttpModule RewritePath虚拟目录缓存没有刷新

Sni*_*tor 5 asp.net caching url-rewriting iis-7.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");
    }
}
Run Code Online (Sandbox Code Playgroud)

路径"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. 反复重新保存文件似乎没有效果.我想知道"文件修改"事件是否会丢失,但一旦卡住,我可以保存六个修改,而且我不会返回新的副本.
  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".

Cag*_*tay 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);
    }
}
Run Code Online (Sandbox Code Playgroud)