【问题标题】:programmatically control output caching - disable or enable cache according to parameter value以编程方式控制输出缓存 - 根据参数值禁用或启用缓存
【发布时间】:2023-03-08 10:13:01
【问题描述】:

我们有一个相当标准的电子商务场景,其中包含分类中的产品分页列表。无论好坏,大约 80% 的访问者从未浏览过第一页,根据类别的不同,可能会有 5 到 10 多页的结果被查看的频率要低得多。 (是的,我们确实优化了第一页上显示的内容并进行了良好的搜索 - 但这是一个不同的讨论)

我们不能缓存每一页结果,因为我们受到内存的限制,但是只缓存每个类别的第一页结果的好处是巨大的。

我知道我可以使用对象缓存来存储有问题的数据集来做类似的事情,但这是否可以使用输出缓存,也许通过使用 response.Cache 对象?

这可以在页面生命周期的哪个位置完成?预渲染?

非常简化,URL 类似于“/ProductList?Category=something&Page=1” 我想要类似(伪代码)的逻辑:

If paramater "Page" equals 1
   Use output caching: vary by param = "categoryName; page"
else
   Don't use caching at all, just render the page from scratch.

我们在 IIS 6/win2003 上使用 ASP.NET 2.0。

【问题讨论】:

  • 查看this 帖子上的最后一个答案。我希望这会有所帮助。

标签: asp.net iis-6 outputcache


【解决方案1】:

您仍然可以使用 outputcache 指令,在我看来,与其在页面代码中乱扔一堆缓存细节,不如使用基于 Global.asax 中处理此问题的可重用解决方案您通常会采用任何 VaryByCustom 场景的方式。

因此,例如,如果您使用带有转发器的分页方法,您可能只是在搜索场景中希望从缓存中排除特定页面上的任何回发。 Here 是一个这样做的代码示例。该方法只需要在捕获您希望避免缓存的任何标准之后使用 HttpContext 对象来访问 Response.Cache.SetNoServerCaching()。我希望这会有所帮助。

【讨论】:

    【解决方案2】:

    我相信最好的方法是使用HttpCachePolicy.AddValidationCallback

    http://www.hanselman.com/blog/AdvancedASPNETCachingAndAddValidationCallBack.aspx - 有一个完整的例子可以准确回答这个问题。

    【讨论】:

      【解决方案3】:

      除了使用 OutputCache 指令,您还可以通过编程执行相同的操作,如下所示:

      if (yourArbitraryCondition) {
        OutputCacheParameters outputCacheSettings = new OutputCacheParameters();
        outputCacheSettings.Duration = 60;
        InitOutputCache(outputCacheSettings);
      }
      

      从 OnInit 执行此操作应该可以正常工作。显然,您可以通过设置 OutputCacheParameter 上的各种属性来调整缓存行为,它与指令具有所有相同的旋钮(实际上,这就是我们在使用指令时生成的)。

      关键是你只是有条件地执行这个逻辑,而指令使它成为无条件的。

      更新:

      作为替代方案,您可以使用构建上述代码的低级缓存 API。例如

      HttpCachePolicy cache = Response.Cache;
      cache.SetCacheability(HttpCacheability.Public);
      cache.SetExpires(Context.Timestamp.AddSeconds(60));
      cache.VaryByParams["categoryName"] = true;
      

      基本上,这是做同样事情的另一种方式,不使用任何标记为“不应调用”的 API。最后,任何一种方式都行得通,所以选择吧。

      【讨论】:

      • 有效。知道为什么InitOutputCacheEditorBrowsableState.Never 并且不应该根据msdn.microsoft.com/en-us/library/ms153473.aspx 直接调用吗?
      • 嗯,这主要是因为我们最初设计它时缺乏前瞻性思维。页面上有许多以这种方式标记的公共/受保护的 API。它们都是由于使用各种语法而被生成的代码调用的东西,我们认为用户没有任何充分的理由直接调用它们。但现实情况是,自己调用它们并没有错,事实上,有时像这里一样,它可以让你做一些你不能用页面语法做的事情。我将提交一个错误以删除这些标志,尽管对于 VS2010 来说已经太晚了。
      • 还有一件事:您实际上可以通过直接调用低级缓存 API 来做同样的事情(并避免 InitOutputCache)。它的工作原理相同,但代码会更复杂。如果您需要替代解决方案,请告诉我。
      • 这可以与片段缓存一起使用以缓存动态生成的单个控件吗?换句话说,如果一个动态控件随一个参数变化,另一个动态控件随另一个参数变化呢?
      • 如果不包含 outputCacheSettings.VaryByParam = "none";
      【解决方案4】:

      编辑: 我更喜欢 David Ebbo 的回答。


      你可以使用

      <%@ OutputCache Duration="60"  VaryByParam="none" VaryByCustom="pageOne" %>
      

      并以返回第一页的固定键和所有其他页面的随机键的方式实现它。您可以(并且应该)让scavenging 机制处理内存,但如果必须,您可以使用HttpResponse.RemoveOutputCacheItem 删除缓存项。

      public override string GetVaryByCustomString(HttpContext ctx, string custom)
      {
          if(custom == "pageOne")
          {
              if(ctx.Request["page"] == "1")
              {
                  return "1";
              }
      
              HttpResponse.RemoveOutputCacheItem("/Default.aspx");
              return Guid.NewGuid().ToString();
          }
          return base.GetVaryByCustomString(ctx, custom);
      }
      

      【讨论】:

        【解决方案5】:

        我认为您应该能够使用 OutputCache directive 并将 VaryByParam 属性设置为用于改变输出缓存的分号分隔的字符串列表。

        除非您只想在 Page == 1 时缓存?

        【讨论】:

        • 不幸的是,这正是我想要的(仅当 page == 1 时)。如果我想缓存每一页很容易的结果,就像你说的那样使用varybyparam。抱歉,我认为我没有很清楚地表达这个问题,但我所追求的只是与每个人习惯的正常情况略有不同(但显着)。
        猜你喜欢
        • 2011-03-30
        • 2013-02-28
        • 2015-08-10
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多