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

时间:2013-02-07 04:17:18

标签: 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");
    }
}

路径“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(在绘画中更改其颜色并重新保存)。
  3. 重复。
  4. 在间隔几秒钟的1到20次重复之后,返回的图像将是过时的副本。

    一旦感到不安,服务器只会在经过一段未知时间后(从10秒到几分钟)返回当前版本。如果我将步骤1中的网址替换为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。
    8. 修改 - 更多详情:

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

        我在IIS中启用了“失败的请求跟踪”(有趣的是,如果配置正确,这对于 - 失败的请求是如何工作的。管道是相同的,直到第17步请求返回过时版本清楚地显示了缓存命中。

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

        Good Request

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

        Bad Request

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

        在堆栈的下方,我们看到第一个请求:

        Good Request 2

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

        Bad Request 2

        另请注意,根据FileDirmoned="true",目录显然已被监控。

2 个答案:

答案 0 :(得分: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);
    }
}

答案 1 :(得分:0)

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

HttpContext.Current.Server.TransferRequest(newUrl);

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