输出缓存,VaryByParam / VaryByCustom

时间:2015-09-22 02:16:35

标签: c# asp.net caching outputcache

好的,赞美输出缓存的文章数量似乎没有尽头,以及它会加快你网站的速度。我现在已经阅读了数百篇文章和Q& As这个主题,但我似乎仍然无法使其发挥作用。 (我认为输出缓存可能会偷走我的灵魂)

我的要求非常简单,我想根据参数缓存3页:Home,Results和Details。我还有一小部分页面需要由用户改变。我还需要缓存到中央存储库,我选择了redis来保存我的数据。我还应该提一下,这仍然是一个旧的Web表单应用程序。

我最初的方法是尝试使用“VaryByCustom”选项提供我自己的自定义字符串。 Microsoft页面似乎使这看起来很简单:

https://msdn.microsoft.com/en-us/library/5ecf4420.aspx

这需要在global.asax文件中放置一个重写方法“GetVaryByCustomString”。问题是,大多数示例显示使用HttpContext中始终可用的变量(浏览器,浏览器版本等),即使Microsoft和其他人似乎建议将此作为首选“自定义字符串缓存”方法,我找不到任何允许页面定义字符串的工作示例。我已经看到一些人使用会话并声称它有效(会话对我来说是空的)和context.user(有人说用户为空)的例子但是我没有看到任何实用的方法来传递字符串,除了使用Response.Cache.SetVaryByCustom(“my_custom_string”)。在主项目实施了一天后,我决定建立一个独立的测试/概念验证项目。在这个项目中,只要我将它作为字符串传递给SetVaryByCustom,我就可以获得自定义字符串。问题是,这与我见过的任何例子都不匹配。示例显示GetVaryByCustomString返回“SomeKey”和“SomeValue”。对我有用的基本上是“SomeValue”和“SomeValue”。这是我的代码:

public override string GetVaryByCustomString(HttpContext context, string arg)
{
    if (arg != null)
    {
        return arg;
    }

    return base.GetVaryByCustomString(context, arg);
}

在设置创建回发的下拉列表的值之后,第一次在页面上工作,但从那以后就没有了。因此,“OnselectedItemChanged”触发一次并根据选择创建一组新的缓存条目,但它从未再次触发。我尝试修改几乎每个缓存参数以使其工作但无论我尝试了什么系列设置(在声明中设置缓存,在代码中设置缓存,尝试各种VaryByParams组合,添加位置等)我从未成功。<登记/> 在尝试了2天后,我决定采用不同的方法。我已经回到了更传统/更接受的方法。 我在web.config中创建了3个缓存配置文件:

<caching>
        <cache disableExpiration="false" />
        <outputCache defaultProvider="RedisOutputCacheProvider" enableOutputCache="true" enableFragmentCache="true" sendCacheControlHeader="true">
          <providers>
            <add name="RedisOutputCacheProvider"
                  type="LAC.OutputCacheProvider, LAC"
                  connectionString="192.168.XX.XX:6379,connectTimeout=10000"
                  dbNumber="5"
                  keyPrefix="LAC:OutputCache:" />
          </providers>
        </outputCache>
        <outputCacheSettings>
          <outputCacheProfiles>
            <add name="Home" varyByParam="*" varyByCustom="user" duration="86400"/>
            <add name="Results" varyByParam="*" varyByCustom="user" duration="7200" />
            <add name="Details" varyByParam="*" varyByCustom="user" duration="7200"/>
          </outputCacheProfiles>
        </outputCacheSettings>
    </caching>

因此每个页面都有一个自定义的用户字符串,可以帮助我为经过身份验证的用户和匿名用户缓存新页面。 然后我添加了一个看起来像的GetVaryByCustomString:

public override string GetVaryByCustomString(HttpContext context, string arg)
{
        switch (arg)
        {
            case "user":
                var identity = context.User.Identity.Name != "" ? context.User.Identity.Name : "Anonymous";

            return string.Format("IsAuthenticated={0},Identity={1}", context.Request.IsAuthenticated, identity);
        }

            return string.Empty;
}

我和以前一样接近这个工作,但它仍然不是100%。主页工作正常,详细信息页面工作正常,但结果页面永远不会缓存。结果页面包含一个包含12个不同下拉列表的过滤器。因此它需要根据选择存储页面版本。我在所有页面的顶部添加了一个时间戳,以便我可以看到该页面是否正在缓存。每次按下control-F5时,结果页面上的时间都会改变,而其他2页则不然。从未创建任何缓存条目,并且永远不会调用GetVaryByCustomString。我已经检查了某些“关闭可缓存性”设置的代码,但据我所知,页面中的任何地方都没有禁用缓存的代码。我的global.asax文件继承自正确的类,我的自定义ouputcache提供程序似乎为2个有效的页面添加了正确的条目。当然现在使用VaryByParam =“*”键可以和内容一样长,这要归功于viewstate(必须留下)BLECH!

所以基本上我在三个相似但一个不起作用的页面上设置了缓存。我不知道下一步该去哪儿。我希望像@kevinmontrose这样真正掌握这类东西的人会对我表示同情,并向我推动一个方向,这将引导我找到解决方案。

更新 我已经向微软公开了一个案例。

2 个答案:

答案 0 :(得分:0)

你有没有设置VaryByParam?我忘记了目前的细节,但我记得在发现它是强制性的之前卡住了。 (在每个情况下我认为。(?))我认为持续时间也是必需的。 (我指的是.aspx页面中的指令。)

答案 1 :(得分:0)

重新阅读您的问题我看到了这个问题:&#34;我找不到任何允许页面定义字符串的工作示例。&#34;我正在重读一些文章,我很确定这是错误的做法。

我还没有对所有这些进行过测试,但是对于前者,如果你采用标准的例子:

<%@ OutputCache Duration="10" VaryByParam="None" VaryByCustom="minorversion" %>

似乎正在发生的事情是你只是设置了要查找的字符串,而这就是它。

当请求进入时,您检查HTTP 请求标头 - Vary标头,这是您在页面中设置的标头 - 如果存在,您可以按照自己的意愿进行操作。

<%@ Application language="C#" %>
<script runat="server">
public override string GetVaryByCustomString(HttpContext context, 
    string arg)
{
    // arg is your custom 'Vary' header.
    if(arg == "minorversion")
    {
        return "Version=" +
            context.Request.Browser.MinorVersion.ToString();
    }
    return base.GetVaryByCustomString(context, arg);
}
</script>

我刚刚对基本示例进行了快速测试,并添加了一个标签,该标签在页面加载时使用当前时间进行更新。我多次刷新了实况页面,时间没有改变,直到10秒钟过去了。所以它绝对有效。我认为关键是你设定了价值并且你已经完成了,但如果你愿意,你可以使用它。

...第二个想法,我认为你在页面中创建标题,从global.asax返回值。哪里??我认为它被发送到缓存系统,它决定是否应该发送新的或缓存的页面。在上面的例子中,浏览器的次要版本被检查并设置,因为有一个缓存版本可用(在首次加载之后),它会发送,直到10秒为止。

VaryByCustom的文档位于“缓存页面的不同版本”的部分中。所以这就是这样做的。如果有人显示不同的浏览器,则会检查浏览器版本 - 然后缓存系统会检查该浏览器版本的页面版本是否可用。如果没有,创建一个新页面;如果是这样,请发送缓存版本。