net mvc cache asp asp.net caching user-controls runtime loadcontrol

asp.net - asp - outputcache mvc 5



Cómo cargar un control que utiliza VaryByControl OutputCache, especificando valores para propiedades (3)

Creo que ha entendido mal la propiedad VarByControl, no le dice a la memoria caché que cambie sobre una propiedad en el control, sino en el ID de los controles en la página. Aquí está el texto de MSDN :

La propiedad VaryByControl se establece en identificadores de control totalmente calificados, donde el identificador es una concatenación de identificadores de control que comienza desde el control principal de nivel superior y se delimita con un carácter de signo de dólar ($).

En su caso, tal vez pueda establecer VaryByCustom en lugar de VaryByControl y generar una clave de caché desde Test-property-value y modificarla si cambia.

Tengo un control de usuario que debe usar el almacenamiento en caché, con VaryByControl . El archivo .ascx ve así:

<%@ Control Language="C#" AutoEventWireup="true" CodeBehind="TestControl.ascx.cs" Inherits="mynamespace.TestControl" %> <%@ OutputCache Duration="10" Shared="true" VaryByControl="Test" %> <p id="SomeText" runat="server">Nothing</p>

La clase TestControl en el archivo de código subyacente tiene una propiedad int Test {...} y un controlador de eventos Page_Load() que llena el párrafo SomeText con:

SomeText.InnerText = string.Format(@"Test={0} at {1}", Test, DateTime.Now)

Tengo un archivo .aspx que se ve así:

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="TestPage.aspx.cs" Inherits="mynamespace.TestPage" %> <%@ Register TagPrefix="xxx" TagName="TestControl" Src="Controls/TestControl.ascx" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head runat="server"> <title></title> </head> <body> <xxx:TestControl Test="6" runat="server" /> <xxx:TestControl Test="7" runat="server" /> <hr /> <asp:PlaceHolder ID="Suport" runat="server" /> </body> </html>

Las dos etiquetas <xxx:TestControl> cargan correctamente las instancias de TestControl con Test conjunto de Test en el valor esperado, puedo actualizar el navegador varias veces y puedo ver el caché correctamente haciendo su trabajo.

Ahora me gustaría completar el <asp:PlaceHolder ID="Suport" /> con algunas instancias de TestControl , utilizando diferentes valores de Test , que deberían beneficiarse del almacenamiento en caché adecuado. LoadControl usar el método LoadControl , pero no puedo encontrar la forma de especificar un valor para la propiedad Test . Espero que exista este método, después de que todo el código asp.net que carga la página .aspx logre encontrar el control en caché adecuado. Todo lo que obtengo es una instancia de PartialCachingControl sin CachedControl inicializado y en tiempo de ejecución el TestControl representado muestra que Test tiene el valor predeterminado de 0 .

Así es como se ve mi controlador de eventos .aspx Page_Load() :

protected void Page_Load(object sender, EventArgs e) { PartialCachingControl tc = (PartialCachingControl) LoadControl(@"Controls/TestControl.ascx"); if (tc.CachedControl != null) ((TestControl)tc.CachedControl).Test = 67; Suport.Controls.Add(tc); }

Editar

Podría solucionar el problema guardando en caché toda la página, pero parece extraño que no pueda encontrar la manera de hacerlo de esta manera . Especialmente desde que invocar el control a través del archivo ASPX funciona como se espera (probando que hay una manera).

Editar 2

Hmm, no hay respuestas hasta ahora. Empecé una recompensa, espero que reciba un poco más de atención.


Para obtener un control participar en el ciclo de vida de la página completa, se agregará en el evento Init o en el método CreateChildControls en lugar de agregarlo en Load. Como VaryByControl necesita identificadores de control totalmente calificados para funcionar, debe inicializarse antes de que comience el ciclo de la página.

Algo similar a esto:

protected override void OnInit(EventArgs e) { var testControl = LoadControl(@"TestControl.ascx"); testControl.ID = "TestControl"; Suport.Controls.Add(testControl); base.OnInit(e); } protected override void OnLoad(EventArgs e) { TestControl testControl = GetTestControl("TestControl"); if(testControl != null){ //If it is null it is cached and can not be changed testControl.Test = 242; } base.OnLoad(e); } private TestControl GetTestControl(string name) { var control = this.Suport.FindControl(name); var partialCachedControl = control as PartialCachingControl; if(partialCachedControl != null) { control = partialCachedControl.CachedControl; } return control as TestControl; }

Dado que la salida se almacena en caché por control, no puede cambiar el control hasta que se borre la caché. Si desea cambiar el valor y regenerar el contenido, debe obtener la caché borrada o crear un nuevo control (con una nueva ID). Una forma de borrar el caché es usar VaryByCustom en su lugar y genera una clave de caché que cambia si su valor de prueba está cambiando.

Recuerde también implementar la interfaz INamingContainer en su control de prueba para evitar conflictos de nombres entre los diferentes objetos. Para hacer esto, simplemente agregue la interfaz al control, así:

public class TestControl: WebControl, INamingContainer {}


Tienes que cambiar 2 líneas para hacer que tu código funcione:

PartialCachingControl tc = (PartialCachingControl) LoadControl(@"Controls/TestControl.ascx"); Suport.Controls.Add(tc); if (tc.CachedControl != null) ((TestControl)tc.CachedControl).Test = 67;

Tan pronto como agregue el control, el control en caché se inicializa.

P.EJ