使用varybyparam和varybycustom的输出缓存

5
我正在尝试做一些非常简单的事情...我有一个带有下拉框的网站,用户从中选择一个组。此后,用户使用菜单中的查询字符串参数浏览站点。因此,我希望缓存依赖于查询字符串 - 这似乎有效。我还希望缓存依赖于他们选择的组。
但是当查询字符串为空时,两个缓存元素都无法工作 - 页面只是上次选择的组的版本。我的缓存指令如下:
<%@ 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个回答

6
我最终确定了问题所在 - 当输出缓存放置在页面级别(而不是控件级别)时,会话不可用,并抛出异常。由于此异常发生在全局错误处理程序之上的全局范围内,因此它会悄悄地失败。我最终通过在 VaryByCustomString 中包装 try-catch 块并将其 Response.Write 出来来解决这个问题。

真是一场痛苦的经历...无论如何,解决方案是在控件级别实现缓存,但这需要更多的工作,因为页面的各个部分需要协同工作...但这比没有缓存要好。我希望这能帮助其他人节省时间。

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


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接