Изменение свойств управления с помощью 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?

Кроме того, возможно ли сделать переменную времени кэширования во время выполнения?

Спасибо.

Ответ 1

Чтобы ответить на ваш первый вопрос Q, позвольте мне сначала сказать вам, что ваш вопрос сам имеет ответ;). "Общий"... да, что ключевое слово:) Чтобы иметь один экземпляр в кеше для пользовательского элемента управления на всех страницах, установите Shared = 'true' в директиве @OutputCache. Это должно быть установлено на уровне пользовательского управления, то есть на странице ascx.

Чтобы кэшировать пользовательский элемент управления на основе свойств пользовательского управления, вы должны указать полное имя свойств в разделе varyByControls атрибута 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. См. Ссылку Как: Кэш нескольких версий пользовательского элемента управления на основе параметров

Чтобы ответить на второй Q, чтобы сделать продолжительность кэша для пользовательской переменной управления во время выполнения, вы можете сделать это двумя способами:

  • Назначьте его в коде управления пользователя позади:

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

FYI, если кэшируются как пользовательский элемент управления, так и страница: если продолжительность кэша вывода страницы меньше, чем у пользовательского элемента управления, пользовательский элемент управления будет кэшироваться до истечения его продолжительности, даже после того, как остальная часть страницы будет регенерированный для запроса. Например, если кеширование вывода страницы установлено на 50 секунд, а кэширование выходных данных управления пользователя установлено на 100 секунд, пользовательское управление истекает один раз на каждые два раза, оставшееся до конца страницы.

Ответ 3

Я отправляю новый ответ на этот очень старый вопрос, потому что принятый ответ горько неточен. Этот правильный ответ:

  • Нет встроенного способа изменения значения свойства управления. 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, и приведение не выполняется.