开发者

Output Caching using BOTH varybyparam and varybycustom

I'm trying to do something which should be very simple...I have a site with a dropdown from which the user selects a group. Thereafter, the user navigates through the site using querystring arguments from menus. So I want the caching to be dependent on the querystring - this seems to work. I also want the cache to be dependent on the group that they selected.

But when the querystring is empty, neither cache element seems to work - the page is just whatever the version was for the last selected group. My cache directive looks like this:

<%@ OutputCache Duration="300" VaryByCustom="currentAtomId" VaryByParam="documentId;folderId;sectionId;renderMod开发者_开发百科e;typeId" %>

My varyByCustom code looks like this:

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));
    }
}

The call to CurrentAtomId boils down to this:

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;
}

Finally, the code which specifies the CurrentEntityId is this:

    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);

I'm baffled. Any thoughts would be appreciated.


I eventually determined the problem - when output caching is placed at a PAGE level (as opposed to a control level), the session is not available, and throws an exception. Because this exception is occurring in Global ABOVE the global error handler, it fails silently. I eventually figured this out by wrapping a try-catch block around the cache key generation code in VaryByCustomString and Response.Write-ing it out.

What a beatdown...at any rate, the solution is to implement caching at the control level, which unfortunately is a lot more work because the pieces of the page work together...but it's better than no caching. I hope this helps save somebody else some time.

Bottom Line: for varyByCustomString in global.asax - SESSION IS NOT AVAILABLE WHEN CACHING AT THE PAGE LEVEL.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜