20

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

4

5 回答 5

31

除了使用 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。最后,无论哪种方式都可以,所以请选择。

于 2009-12-31T07:21:23.003 回答
5

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


你可以使用

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

并以返回第一页的固定密钥和所有其他页面的随机密钥的方式实现它。您可以(并且应该)让清理机制来处理内存,但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);
}
于 2009-12-30T22:21:23.903 回答
4

I believe the best way to do this is to use HttpCachePolicy.AddValidationCallback

See http://www.hanselman.com/blog/AdvancedASPNETCachingAndAddValidationCallBack.aspx - There's a full example that answers precisely this question.

于 2012-05-17T20:00:14.950 回答
1

您仍然可以使用 outputcache 指令,并且在我看来,与其在页面代码中乱扔一堆缓存螺母和螺栓,不如使用基于 Global.asax 中处理此问题的可重用解决方案。将任何 VaryByCustom 方案。

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

于 2015-06-12T19:55:54.313 回答
0

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

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

于 2009-06-25T12:45:44.057 回答