2010-02-11 46 views
2

我有一個奇怪的問題發生在outputcache上。我在頁面上有多個用戶控件,其中一個是登錄控件。頁面和登錄控件不被緩存,但其他用戶控件使用VaryByParam緩存。現在,當我點擊不同的頁面時,所有這些都與緩存一起工作。但只要我登錄,該頁面上的其他用戶控件就會顯示舊的緩存版本。如果我刷新頁面,我會得到所有用戶控件的正確緩存版本。問題是隻有當回發發生時。出於某種原因在回發中,返回的緩存版本不考慮VaryByParam字符串。當在網上搜索時,我確實在asp.net上看到了類似的問題,它有一個解釋這個問題的代碼。OutputCache通過PostBack返回無效版本

回發爲什麼會導致緩存返回無效版本?

Default.aspx 

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="WebApplication1._Default" %> 
<%@ Register src="WebUserControl1.ascx" tagname="WebUserControl1" tagprefix="uc1" %> 
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 
<html xmlns="http://www.w3.org/1999/xhtml" > 
<head runat="server"> 
    <title>Untitled Page</title> 
</head> 
<body> 
    <form id="form1" runat="server">  
     <uc1:WebUserControl1 ID="WebUserControl11" runat="server" EnableViewState="false" />   
    </form> 
</body> 
</html> 

WebUserControl1.ascx 

<%@ Control Language="C#" AutoEventWireup="true" CodeBehind="WebUserControl1.ascx.cs" Inherits="WebApplication1.WebUserControl1" %> 
<%@ OutputCache Duration="3600" VaryByParam="MenuID" %> 
<asp:LinkButton ID="test" runat="server" Text="PostBack"></asp:LinkButton> 
<br /><br /> 
<a href="Default.aspx?menuid=1">1</a> - <a href="Default.aspx?menuid=2">2</a> - <a href="Default.aspx?menuid=3">3</a> 
<br /><br /> 
MenuID: <%= Request.QueryString["MenuID"] != null ? Request.QueryString["MenuID"].ToString() : "null" %> 

運行演示,你會看到頁面之間點擊獲取正確的緩存版本。但是玩弄點擊頁面並導致回發,然後你會看到你有時會得到錯誤的緩存版本。

回答

2

我認爲這是ASP.Net中的一個錯誤,並且直到它解決爲止,這裏是一個解決方法。

對於每個回發,我想要一個新版本而不是緩存版本。但除此之外,我想要緩存版本。所以我可以看看這是什麼樣的要求。如果這是'POST',我將得到一個新版本,如果這是'GET',我將從緩存中獲取版本。爲此,我在usercontrol上設置了VaryByCustom緩存設置。而在我的Global.asax這樣做:

public override string GetVaryByCustomString(HttpContext context, string arg) 
{ 
    if (arg.Trim().ToLower() == "getorpost") 
    { 
      //for a POST request (postback) force to return back a non cached output 
      if (context.Request.RequestType.Equals("POST")) 
      { 
       return "post" + DateTime.Now.Ticks; 
      } 
      return "get"; 
    } 
    return base.GetVaryByCustomString(context, arg); 
} 
+0

如果實施正確,這將肯定會返回新版本的頁面,但似乎存在使用不再使用的頁面版本混淆高速緩存的缺點。人們可以接受這個缺點,並使用短時間的高速緩存持續時間作爲折衷,但它仍然不是最好的。 – Iucounu

0

從裏面有人MS:

最初是爲控制輸出緩存行爲(現在仍然是書面)或者關閉的查詢字符串集合來鍵入或表單值集合。內部邏輯根據請求是GET還是POST來確定要查看哪個集合。我同意這種行爲並不明顯,但這顯然是控制輸出緩存行爲的最初意圖。

的兩種解決方法包括查詢字符串值的輸出緩存決策的一部分是:

  1. 鏡查詢字符串值到 隱藏表單變量,如果這是 可能。
  2. 或者使用已發現的替代方法 - 即使用 VaryByCustom和 GetVaryByCustomString。自定義 實施 GetVaryByCustomString可以返回含有的Request.QueryString爲 POST請求,以獲得所需 效果讀取一個或多個值 一個 字符串。
0

我同意加菲貓的原因,並認爲使用VaryByCustom的建議也是一個聰明的想法。爲了做到這一點,你可以簡單地在Global.asax中使用Response.Cache.SetNoServerCaching(),它只需要在Global.asax中感知頁面是否回傳。 Here是一個代碼示例。