Изменяйте по свойствам элемента управления, используя PartialCaching в ASP.NET
Я использую атрибут PartialCaching в базовом классе пользовательского элемента управления.
Я хотел бы, чтобы кэшированные элементы управления изменялись в зависимости от свойств, установленных в экземпляре элемента управления.
Например:
<mycontrols:control1 runat="server" param1="10" param2="20" />
... выходные данные будут кэшироваться отдельно от экземпляра элемента управления с различными свойствами:
<mycontrols:control1 runat="server" param1="15" param2="20" />
... и этот элемент управления также будет кэшироваться отдельно:
<mycontrols:control1 runat="server" param1="10" param2="25" />
Однако, если два экземпляра элемента управления на двух отдельных страницах имеют идентичные свойства param1 и param2, я бы хотел, чтобы они кэшировались как один объект (чтобы кэшированный элемент управления был общим).
Можно ли реализовать описанный выше вариант использования с помощью атрибута PartialCaching? Какие настройки я бы использовал? varyByControl?
Кроме того, возможно ли сделать переменную длительности кэша во время выполнения?
Благодарю.
3 ответа
Чтобы ответить на ваш первый вопрос, позвольте мне сначала сказать вам, что у вашего вопроса есть ответ;). "Shared"... да, это ключевое слово:) Чтобы иметь один экземпляр в кэше для пользовательского элемента управления на всех страницах, установите Shared='true' в директиве @OutputCache. Это должно быть установлено на уровне управления пользователем, то есть на странице ascx.
Чтобы кэшировать пользовательский элемент управления на основе свойств пользовательского элемента управления, необходимо указать полное имя свойств в разделе varByControls PartialCachingAttribute. Несколько свойств, если таковые имеются, должны быть разделены точками с запятой.
<%@ Control Language="C#" AutoEventWireup="true"
CodeFile="WebUserControl.ascx.cs"
Inherits="UC_WebUserControl" %>
<%@ OutputCache Duration="60"
VaryByControl="UC_WebUserControl.param1;UC_WebUserControl.param2"
VaryByParam="none" Shared="true" %>
или вы также можете включить атрибут PartialCache для пользовательского элемента управления:
[PartialCaching(60, null, "UC_WebUserControl.param1;UC_WebUserControl.param2", null, true)]
public partial class UC_WebUserControl : System.Web.UI.UserControl
{
public string param1 { get; set; }
public string param2 { get; set; }
}
ИЛИ еще один способ кэширования элемента управления сочетанием обоих значений:
[PartialCaching(60, null, "UC_WebUserControl.BothParams", null, true)]
public partial class UC_WebUserControl : System.Web.UI.UserControl
{
public string param1 { get; set; }
public string param2 { get; set; }
public string BothParams
{
get { return String.Concat(param1, param2); }
}
}
Последний параметр (true) указывает на общий доступ. Длительность указана как 60. См. Ссылку Как кэшировать несколько версий пользовательского элемента управления на основе параметров
Чтобы ответить на ваш второй вопрос, чтобы сделать длительность кэша для пользовательской управляющей переменной во время выполнения, вы можете сделать это двумя способами:
Назначьте его в пользовательском коде управления:
[PartialCaching(60, null, "UC_WebUserControl.BothParams", null, true)] public partial class WebUserControl1 : System.Web.UI.UserControl { ... protected void Page_Load(object sender, EventArgs e) { this.CachePolicy.Duration = new TimeSpan(0, 0, 60); } }
Вы можете назначить его в коде страницы, на которую ссылается пользовательский элемент управления, используя идентификатор пользовательского элемента управления.
Например, если пользовательский элемент управления aspx:
<mycontrols:control1 ID="ucControl1" runat="server" param1="15" param2="20" />
тогда в коде aspx вы должны написать:
this.ucControl1.CachePolicy.Duration = new TimeSpan(0, 0, 60);
К сведению, если и пользовательский элемент управления, и страница кэшированы: если длительность кэша вывода страницы меньше, чем у пользовательского элемента управления, пользовательский элемент управления будет кэшироваться до тех пор, пока не истечет его продолжительность, даже после того, как остальная часть страницы будет восстановлена для запрос. Например, если для кэширования вывода страницы установлено значение 50 секунд, а для кэширования вывода пользовательского элемента управления установлено значение 100 секунд, срок действия пользовательского элемента управления истекает один раз каждые два раза, когда истекает срок действия остальной части страницы.
Вам нужно кэшировать несколько версий пользовательского элемента управления с помощью декларативных атрибутов.
Я отправляю новый ответ на этот очень старый вопрос, потому что принятый ответ крайне неточно. Этот правильный ответ:
- Нет встроенного способа варьировать по значению свойства элемента управления. VaryByControl работает только для элементов управления.
- Когда кешированная версия обслуживается, ваше поле управления будет нулевым. Вы не можете изменить длительность кэша в коде - вы получите исключение NullReferenceException.
- Существует ошибка, которая изменяет кэш в зависимости от идентификатора элемента управления и идентификатора (ов) NamingContainer, если для VaryByControl установлено любое значение. Вот почему, кажется, иногда работает. Ошибка прямо здесь: http://referencesource.microsoft.com/#System.Web/xsp/system/Web/UI/PartialCachingControl.cs#530
Недавно я писал об этом прямо здесь: http://tabeokatech.blogspot.be/2014/09/outputcache-on-user-controls.html.
Вы могли бы выполнить эту работу, вызвав метод построителя для PartialCachingControl самостоятельно в коде и вставив значение свойства, которое вы хотите изменить, в параметре guid:
// PhControls is an asp:PlaceHolder
protected void Page_Init(object sender, EventArgs e)
{
for (int i = 0; i < 3; i++)
{
System.Web.UI.StaticPartialCachingControl.BuildCachedControl(PhControls, String.Format("Test{0}", i), String.Format("1234567{0}", i), 180, null, null, null, null, new System.Web.UI.BuildMethod(GetBuilderDelegate(i)), null);
}
}
public Func<Control> GetBuilderDelegate(int number)
{
return delegate()
{
var control = (UserControls.Test)LoadControl("~/UserControls/Test.ascx");
control.Number = number;
return control;
};
}
Это аккуратно заботится о различной длительности кэширования и в коде. Убедитесь, что вы удалили директиву OutputCache из разметки в ascx, хотя, когда вы делаете это. В противном случае LoadControl получает вам еще один PartialCachingControl, и приведение завершится неудачно.