2011-07-21 6 views
5

Estoy intentando hacer algo que debería ser muy simple ... Tengo un sitio con un menú desplegable del que el usuario selecciona un grupo. A partir de entonces, el usuario navega por el sitio utilizando los argumentos de la cadena de consulta de los menús. Así que quiero que el almacenamiento en caché dependa de la cadena de consulta, esto parece funcionar. También quiero que el caché dependa del grupo que seleccionaron.Caché de salida utilizando tanto varybyparam como varybycustom

Pero cuando la cadena de consulta está vacía, ninguno de los elementos de caché parece funcionar: la página es cualquiera que sea la versión del último grupo seleccionado. Mi directiva de caché es el siguiente:

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

Mi código VaryByCustom se ve así:

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

La llamada a CurrentAtomId se reduce a esto:

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

Finalmente, el código que especifica el CurrentEntityId es este:

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

Estoy desconcertado. Cualquier pensamiento sería apreciado.

Respuesta

6

Finalmente determiné el problema: cuando el almacenamiento en caché de resultados se coloca en un nivel de PÁGINA (a diferencia de un nivel de control), la sesión no está disponible y arroja una excepción. Debido a que esta excepción se produce en Global ABOVE el controlador de error global, falla silenciosamente. Eventualmente descubrí esto al envolver un bloque try-catch alrededor del código de generación de la clave de caché en VaryByCustomString y Response.Write-iting out.

Qué paliza ... en cualquier caso, la solución es implementar el almacenamiento en caché en el nivel de control, que lamentablemente es mucho más trabajo porque las partes de la página funcionan juntas ... pero es mejor que no almacenar en caché. Espero que esto ayude a salvar a alguien más en algún momento.

Resultado final: para varyByCustomString en global.asax - LA SESIÓN NO ESTÁ DISPONIBLE CUANDO CACHE A NIVEL DE PÁGINA.

Cuestiones relacionadas