2014-08-27 59 views
4

我有一個webusercontrol使用公共int屬性SelectedCatID。我用其他的頁面和其他控件這種控制如下:使用webusercontrol獲取輸出緩存以在ASP.net中工作

<NewStore:LeftMenuLinks runat="server" SelectedCatID="<%#CatIDToSelect%>" /> 

我如何輸出緩存基於SelectedCatID這個控制?我試過的一切都失敗了。

我得到的最接近的是將它緩存到緩存中,但它在SelectedCatID上沒有變化,所以選擇相同的菜單項直到緩存過期。沒有緩存,控制按預期工作。

+0

'VaryByControl'屬性應該與用戶控件的ID匹配緩存,而不僅僅是控件的任意屬性。如果你檢查後面的代碼中存在控件,然後設置你的'NewStore:LeftMenuLinks'用戶控件使用的變量,它是否工作? – Justin 2014-08-29 16:20:41

+0

您在數據綁定控件中是否具有SelectedCatID =「<%#SelectedCatID%>」版本,還是隻綁定到頁面類的屬性? SelectedCatID和SelectedMenu之間的關係是什麼?或者這只是一個錯字? – 2014-09-02 12:07:11

+0

@menno錯字,現在修復! – 2014-09-02 12:54:12

回答

0
<%@ OutputCache Duration="60" VaryByParam="SelectedCatID" %> 

現在存儲您選擇<%#CatIDToSelect%>作爲一個參數e?SelectedCatID = 12 現在,您就取決於你想要根據請求需要緩存的內容將輸出緩存的頁面或用戶控件。參數[「SelectedCatID」]等於。

你也可以做這樣的事情(雖然不是最簡單的方法)

這那張/用戶控件你想緩存頁面:

<%@ OutputCache duration="120" varybyparam="None" varybycustom="SelectedCatID" %> 

這進入Gloabal.asax文件:

public override string GetVaryByCustomString(HttpContext context, string custom) 
{ 
    if(custom == "SelectedCatID") 
    { 
     return CatIDToSelect; 
    } 
    return String.Empty; 
} 
+0

看看這個pastebin:http://pastebin.com/NLmZkfP9 它引發錯誤'CS0115:'Controls_Blog_LatestEntries.GetVaryByCustomString(System.Web.HttpContext,字符串)':找不到合適的方法來覆蓋'。 緩存定義爲'%@ OutputCache duration =「120」varybyparam =「None」varybycustom =「SelectedBlogID」%> 我明白從使用谷歌這是爲了去global.asax,但這不是幫助我。我需要一種方法來緩存基於傳遞給iut的屬性的控件 – 2014-09-02 15:30:57

+0

好吧,所以我測試了它似乎你不需要([OutputCache(CacheProfile =「CacheProfile」)]。並且一旦你刷新頁面就工作了。它顯示第二次刷新後的確切時間(包括秒)不再改變一個時間是永久性的,直到持續時間到期爲止。只要按照我對測試代碼進行的更改 – Hillboy 2014-09-02 16:59:23

+0

進行查看(4個文件):http:// pastebin .com/6v10bSgg http://pastebin.com/QFNXE7Z1 http://pastebin.com/Jbfuwywf http://pastebin.com/AXC2vT95 – Hillboy 2014-09-02 17:10:06

2

我想出了爲什麼最初使用的VaryByControls方法不起作用。可悲的是,你將它編輯出了你的問題,所以我的研究只能進入博客文章。更新:有問題的博文:http://tabeokatech.blogspot.be/2014/09/outputcache-on-user-controls.html。但它的長短之處在於,VaryByControls對於VaryByParams來說有點簡單,並且對屬性不做任何事情:它只查看POST值。事實上,它曾經爲具有靜態值的屬性工作似乎是一個錯誤 - VaryByControls中的任何字符串都會使該部分工作。這個問題被接受的答案是錯誤的:Vary by control properties using PartialCaching in ASP.NET

沒有內置方法可以根據控件屬性值進行更改。

無論如何,這是沒有意義的,因爲用戶控件需要創建具有屬性值,並且您希望避免創建它們,而不是緩存它們的呈現標記 - 緩存的用戶控件字段在代碼隱藏中爲空(如果已緩存)標記是爲他們服務的。 這可以通過將PartialCachingControl注入頁面而不是實際的用戶控件來實現。此PartialCachingControl檢查緩存,並且只在沒有緩存版本存在的情況下創建控件。

至於使其工作,我看到兩個選項:

  1. 如果你只有每頁1個用戶控件,您可以使用VaryByCustom是辦法。爲方便起見,你可以寫一個返回你的屬性值,該頁面的界面,並實現它的每一頁承載用戶控件,例如:

    interface INumberProvider 
    { 
        int GetNumber(); 
    } 
    
    // and the page: 
    public partial class _Default : Page, INumberProvider 
    { 
        public int GetNumber() 
        { 
         return this.SomeNumberPropertyOrWhatever; 
        } 
    ... 
    

    在全局上。ASAX你投目前的處理程序INumberProvider並獲得數:

    public override string GetVaryByCustomString(HttpContext context, string custom) 
        { 
         if (custom == "INumberProvider") 
         { 
          var page = context.CurrentHandler as INumberProvider; 
    
          if (page != null) 
          { 
           return page.GetNumber().ToString(); 
          } 
         } 
         return base.GetVaryByCustomString(context, custom); 
        } 
    

    而在你的控制,你明顯增加:

    的OutputCache時間= 「180」 VaryByCustom是= 「INumberProvider」 的VaryByParam = 「無」 共享= 「true」

    這就是說,如果每個頁面只有一個用戶控件,並且應該非常簡單。如果每頁需要多個用戶控件,那麼您的運氣不好:

  2. 通過編寫自定義WebControl,在您的用戶控件周圍構建自己的包裝。添加您需要的屬性,捕獲呈現的用戶控件的輸出,並使用包含SelectedCatID的鍵將其插入到HttpContext.Current.Cache中。基本上寫你自己的自定義PartialCachingControl。 還有選項3:
  3. 決定緩存並不重要畢竟
+0

'這就是說,如果每頁只有一個用戶控件,並且應該非常簡單。如果每頁需要多個用戶控件,那麼你就不幸運了:'不正確,只需將該指令添加到各個用戶控件而不是頁面本身。緩存單個用戶控件是可能的。 – Hillboy 2014-09-02 18:56:25

+0

以上內容涉及到緩存的用戶控件具體。 我在說的是:基於Global.asax覆蓋中可用的信息,沒有辦法推斷緩存應該爲其創建變體的用戶控件的屬性值,除非只有一個用戶控制每頁。 – 2014-09-03 08:38:16

+0

很好的答案謝謝,正是我之後的那種信息。當你完成它的時候,請在這裏鏈接到你的博客文章! – 2014-09-03 11:12:22

0

,我遲到了這裏什麼與接受的答案和500點賞金獎勵。仍然想給我幾分錢如何實現這一目標。

它可以在控制本身工作。如果找到,您可以讓控件將其自己的輸出存儲在緩存中,並使用Render方法中的緩存版本。我做了一個非常簡單的UserControl來測試。該標記看起來是這樣的:

<%@ Control Language="C#" AutoEventWireup="true" CodeBehind="TestUC.ascx.cs" 
    Inherits="Webforms_Test.UserControls.TestUC" %> 
<div> 
    <asp:Label ID="curTime" runat="server"></asp:Label> 
</div> 

它只是包含初始化時被設置爲DateTime.Now的標籤。後面的代碼看起來是這樣的:

public partial class TestUC : System.Web.UI.UserControl 
{ 
    private string cachedOutput = null; 
    public bool RenderFromCache = true; // set to false in containing page if this control needs to be re-rendered 

    protected void Page_Load(object sender, EventArgs e) 
    { 
     cachedOutput = HttpContext.Current.Cache["key"] as string; 
     if (cachedOutput == null) 
     { 
      // not found in cache, do the heavy lifting here to setup the control 
      curTime.Text = "UC:" + DateTime.Now.ToString("yy-MM-dd hh:mm:ss"); 
     } 
    } 
    protected void Page_PreRender(object sender, EventArgs e) 
    { 
     if (cachedOutput == null || !RenderFromCache) 
     { 
      RenderFromCache = false; 
      StringBuilder b = new StringBuilder(); 
      HtmlTextWriter h = new HtmlTextWriter(new StringWriter(b)); 
      this.RenderControl(h); 
      cachedOutput = b.ToString(); 
      HttpContext.Current.Cache.Insert("key", cachedOutput, null, DateTime.UtcNow.AddSeconds(10), TimeSpan.Zero); 
      RenderFromCache = true; 
     } 
    } 
    protected override void Render(HtmlTextWriter writer) 
    { 
     if (!RenderFromCache) 
      base.Render(writer); 
     else 
      writer.Write(cachedOutput); 
    } 
} 

在此示例中,如果其輸出在高速緩存中找到該控件本身檢查,如果是這樣的Render方法只寫緩存的輸出。如果在緩存中找不到,則PreRender方法將正常運行Render方法,並捕獲輸出並將其存儲在緩存中。

在你的情況下,你當然需要更多的邏輯來檢查控件上的相關屬性,並使用它來檢查緩存版本是否存在。

免責聲明:這是一個非常簡單的測試控件。我還沒有試圖找出如何使用包含事件處理程序等的控件來完成所有這些工作。因此,請考慮它的價值...

+0

我明白你的意思了。我不相信它會像封裝類一樣有效。 您的控件仍然會構建整個控件樹,以便將其全部扔掉,並提供緩存的html。 PartialCachingControl重寫InitRecursive方法,但它的內部標記,所以我們不能使用它。也許OnInit會工作。 – 2014-09-05 20:17:15