我正在尝试做一些应该非常简单的事情......我有一个带有下拉列表的网站,用户从中选择一个组。此后,用户使用菜单中的查询字符串参数浏览站点。所以我希望缓存依赖于查询字符串 - 这似乎有效。我还希望缓存依赖于他们选择的组。
但是当查询字符串为空时,缓存元素似乎都不起作用 - 页面就是最后一个选定组的版本。我的缓存指令如下所示:
<%@ 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);
我很困惑。任何想法都将不胜感激。
答案 0 :(得分:6)
我最终确定了问题 - 当输出缓存放在PAGE级别(而不是控件级别)时,会话不可用,并抛出异常。因为全局错误处理程序Global ABOVE中发生此异常,所以它会以静默方式失败。我最终通过在VaryByCustomString中包含缓存密钥生成代码的try-catch块和Response.Write-out来解决这个问题。
无论如何......无论如何,解决方案是在控制级别实现缓存,遗憾的是,由于页面的各个部分协同工作,所以工作量要大得多......但它比没有缓存更好。我希望这有助于为其他人节省一些时间。
底线:对于global.asax中的varyByCustomString - 在页面级别缓存时无法使用SESSION。