使用BOTH的输出缓存因参数而异,并且不同于自定义

时间:2011-07-21 18:51:28

标签: asp.net caching

我正在尝试做一些应该非常简单的事情......我有一个带有下拉列表的网站,用户从中选择一个组。此后,用户使用菜单中的查询字符串参数浏览站点。所以我希望缓存依赖于查询字符串 - 这似乎有效。我还希望缓存依赖于他们选择的组。

但是当查询字符串为空时,缓存元素似乎都不起作用 - 页面就是最后一个选定组的版本。我的缓存指令如下所示:

<%@ OutputCache Duration="300" VaryByCustom="currentAtomId" VaryByParam="documentId;folderId;sectionId;renderMode;typeId" %>

我的varyByCustom代码如下所示:

public override string GetVaryByCustomString(HttpContext context, string custom)
{
    switch (custom)
    {
        case "currentAtomId":
            var currentAtomId = SecurityManifold.Create().CurrentAtomId;

            var returnString = currentAtomId == null ? Guid.NewGuid().ToString() : currentAtomId.ToString();

            return returnString;

        default:
            throw new ArgumentException(string.Format("Argument '{0}' is not a valid cache argument.", custom));
    }
}

对CurrentAtomId的调用归结为:

public static int? GetCurrentAtomIdFromContext(HttpContext context)
{
    int entityId;

    if (context.Session == null)
    {
        throw new InvalidOperationException("Session is null");
    }

    var sessionEntityId = context.Session["CurrentEntityId"];

    if (sessionEntityId == null || string.IsNullOrEmpty(sessionEntityId.ToString()))
    {
        return null;
    }

    if (!int.TryParse(sessionEntityId.ToString(), out entityId))
    {
        return null;
    }

    return entityId;
}

最后,指定CurrentEntityId的代码是:

    var selectedEntityId = this.lstSecurityEntities.SelectedValue;

    if (string.IsNullOrEmpty(selectedEntityId))
    {
        return;
    }

    Session["CurrentEntityId"] = selectedEntityId;

    var possibleQueryString = Request.QueryString.ToString();

    if (!string.IsNullOrEmpty(possibleQueryString))
    {
        possibleQueryString = "?" + possibleQueryString;
    }

    Response.Redirect("default.aspx" + possibleQueryString);

我很困惑。任何想法都将不胜感激。

1 个答案:

答案 0 :(得分:6)

我最终确定了问题 - 当输出缓存放在PAGE级别(而不是控件级别)时,会话不可用,并抛出异常。因为全局错误处理程序Global ABOVE中发生此异常,所以它会以静默方式失败。我最终通过在VaryByCustomString中包含缓存密钥生成代码的try-catch块和Response.Write-out来解决这个问题。

无论如何......无论如何,解决方案是在控制级别实现缓存,遗憾的是,由于页面的各个部分协同工作,所以工作量要大得多......但它比没有缓存更好。我希望这有助于为其他人节省一些时间。

底线:对于global.asax中的varyByCustomString - 在页面级别缓存时无法使用SESSION。

相关问题