代码之家  ›  专栏  ›  技术社区  ›  Andrew M

以编程方式控制输出缓存-根据参数值禁用或启用缓存

  •  20
  • Andrew M  · 技术社区  · 15 年前

    我们有一个相当标准的电子商务场景,其中包含类别内的产品页面列表。不管是好是坏,大约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。

    5 回复  |  直到 8 年前
        1
  •  31
  •   Dan Atkinson    13 年前

    不使用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。最后,任何一种方法都会奏效,所以你选吧。

        2
  •  5
  •   Josef Pfleger    15 年前

    编辑: 我比我自己更喜欢大卫·埃博的回答。


    你可以使用

    <%@ 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);
    }
    
        3
  •  4
  •   candrews    13 年前

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

    http://www.hanselman.com/blog/AdvancedASPNETCachingAndAddValidationCallBack.aspx -有一个完整的例子正好回答了这个问题。

        4
  •  1
  •   Iucounu    9 年前

    您仍然可以使用outputcache指令,在我看来,您最好使用一个基于global.asax中处理这一问题的可重用解决方案,而不是像您通常使用的任何varybycustom场景那样乱扔页面代码。

    因此,例如,如果您使用带有中继器的分页方法,那么您可能只是在搜索场景中希望从缓存中排除特定页面上的任何回发。 Here 就是这样一个代码示例。该方法只需要使用httpContext对象访问response.cache.setNoServerCache(),然后捕获您希望避免缓存的任何条件。我希望这有帮助。

        5
  •  0
  •   Ian Oxley    15 年前

    我想你应该能用 OutputCache directive 将varyByParam属性设置为分号分隔的字符串列表,这些字符串用于更改输出缓存。

    除非你只想缓存 只有 当Page=1时?