2013-02-07 34 views
5

我有一個ASP.NET IHttpModule實現,旨在重寫服務文件的路徑。該模塊只處理一個事件,PostAuthenticateRequest,如下:ASP.NET HttpModule RewritePath虛擬目錄緩存不刷新

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. 重複。

在1到20次重複之間的任何地方間隔幾秒鐘後,返回的圖像將是過期的副本。

一旦失敗,服務器將只會在未知的時間(從10秒到幾分鐘)之後返回當前版本。如果我用http://myserver/iismodulecachetest/virtdir/image.png替換步驟1中的URL,則問題似乎不會出現。但奇怪的是,在使用「foobar」URL出現問題後,直接URL 開始返回過期的圖像副本。

相關細節:

  1. 的應用程序池的回收解決問題。
  2. 等待一段時間解決問題。
  3. 反覆重新保存文件似乎沒有效果。我想知道「文件修改」事件是否會丟失,但是一旦卡住,我可以保存六次修改,並且Iis stil不會返回新的副本。
  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. 向該網址添加擴展程序沒有任何區別http://myserver/iismodulecachetest/foobar.png
  3. 將調試器連接到IIS顯示每次都會觸發context_PostAuthenticateRequest事件處理程序,並且無論緩存是否卡住,其行爲都是相同的。 。

EDIT2 - IIS日誌:

在IIS(有趣的是如何,如果配置正確,這適用於 -failed請求還我啓用了「失敗請求跟蹤」的管道是相同的,直到步17,回訪的過時的版本要求清楚地表明高速緩存命中

的第一個請求看起來只有精細,與高速緩存未命中:

Good Request

但是,一旦它被卡住,它一再顯示了一個高速緩存命中:

Bad Request

緩存命中之後的事件是,可以理解,比高速緩存未命中的情況完全不同。它看起來很像IIS,它認爲它的文件緩存是最新的,當它絕對不是! :(

一點點進一步下跌的堆棧,我們看到第一個請求:

Good Request 2

然後後續的(故障)高速緩存命中請求:

Bad Request 2

還要注意的是,目錄是顯然監視,按FileDirmoned="true"

+0

你能否確認文件上的修改日期實際上發生了變化? –

+0

是的,只是現在測試。 Windows資源管理器清楚地顯示該文件的新修改日期,但IIS仍然返回舊版本。 Http標題「Last-Modified」也返回* old *修改日期。 – Snixtor

+1

我會打開一個支持票與微軟。這顯然是一個錯誤,所以它應該是100%免費的。 –

回答

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); 
    } 
} 
+0

原則上我想這會顛覆緩存,從而繞過問題,但實際上,「隨機」實例需要被視爲單例以避免重複值。 – Snixtor

+0

你是對的,我糾正了那部分。 – Cagatay

0

我在使用方法RewritePath來解決虛擬目錄中的靜態資源時遇到同樣的問題。 我沒有使用這種方法的解決方案,但最終我選擇使用方法Server.TransferRequest,這顯示沒有緩存問題。

HttpContext.Current.Server.TransferRequest(newUrl); 

請求傳送由IHttpModule再次處理,所以你必須要小心,不會產生循環。