2014-08-27 6 views
4

У меня есть webusercontrol с общественностью int Недвижимость SelectedCatID. Я использую этот контроль на других страницах и в других элементах управления следующим образом:Получить выходной кеш для работы в ASP.net с помощью webusercontrol

<NewStore:LeftMenuLinks runat="server" SelectedCatID="<%#CatIDToSelect%>" /> 

Как кэш вывода я этот контроль основан на SelectedCatID? Все, что я пытался, терпит неудачу.

Ближайшее, что я получил, это его кеширование, но оно не меняется на SelectedCatID, оставляя тот же пункт меню выбранным до истечения срока действия кеша. Без кеширования управление работает так, как ожидалось.

+0

Атрибут 'VaryByControl' должен соответствовать идентификатору пользовательского элемента управления для кэширования, а не только для произвольного свойства элемента управления. Если вы проверите, что элемент управления существует в коде позади, а затем установите переменную, которая будет использоваться вашим пользовательским элементом 'NewStore: LeftMenuLinks', работает ли он? – Justin

+0

У вас есть версия SelectedCatID = "<% # SelectedCatID%>" в элементе управления с привязкой к базе данных или она просто привязана к свойству класса страницы? Какова связь между SelectedCatID и SelectedMenu? Или это просто опечатка? –

+0

@menno опечатка, крепление сейчас! –

ответ

0
<%@ OutputCache Duration="60" VaryByParam="SelectedCatID" %> 

Теперь хранить Youre <% # CatIDToSelect%> как параметр, ех? SelectedCatID = 12 Теперь вы Page или UserControl в зависимости от того, что вы хотите кэшировать вывод будет кэш в зависимости от того, что запрос. Параметр ["SelectedCatID"] равен.

Вы также можете сделать что-то вроде этого (хотя и не самый легкий путь)

Это идет на странице/UserControl вы хотите кэшированные:

<%@ OutputCache duration="120" varybyparam="None" varybycustom="SelectedCatID" %> 

Это идет в файл Gloabal.asax:

public override string GetVaryByCustomString(HttpContext context, string custom) 
{ 
    if(custom == "SelectedCatID") 
    { 
     return CatIDToSelect; 
    } 
    return String.Empty; 
} 
+0

Взгляните на этот pastebin: http://pastebin.com/NLmZkfP9 Он выдает ошибку 'CS0115: 'Controls_Blog_LatestEntries.GetVaryByCustomString (System.Web.HttpContext, string)': не найдено подходящего метода для переопределения'. Кэш, определенный как '<% @ OutputCache duration =" 120 "varybyparam =" None "varybycustom =" SelectedBlogID "%>' Я понимаю, что с помощью Google это предназначено для перехода на global.asax, но это не помогает мне , Мне нужен способ кэширования элемента управления, основанного на свойствах, переданных в iut –

+0

Итак, я протестировал, кажется, вам не нужен ([OutputCache (CacheProfile = «CacheProfile»)]. И работает, как только вы обновляете страницу. который показывает точное время (включая секунды) после секунд второго обновления, больше не меняется, время остается постоянным до истечения срока действия. И просто следуйте за изменениями, внесенными мной на пост – Hillboy

+0

мой тестовый код для вашего просмотра (4 файла): http: // pastebin .com/6v10bSgg http://pastebin.com/QFNXE7Z1 http://pastebin.com/Jbfuwywf http://pastebin.com/AXC2vT95 – Hillboy

2

Я понял, почему подход VaryByControls, который вы использовали изначально, не работает. К сожалению, вы отредактировали его из своего вопроса, поэтому мои исследования для этого просто должны войти в сообщение в блоге. Обновление: сообщение в блоге: http://tabeokatech.blogspot.be/2014/09/outputcache-on-user-controls.html.

Длинное и короткое, хотя VaryByControls является сокращением для VaryByParams и ничего не делает для свойств: оно учитывает только значения POST. Тот факт, что он когда-либо работал для свойств со статическим значением, кажется, является ошибкой - любая строка в VaryByControls заставила бы эту часть работать. Принятый ответ на этот вопрос неверен: Vary by control properties using PartialCaching in ASP.NET.

Нет встроенного способа изменения значений параметров управления.

Это не имеет никакого смысла, поскольку пользовательские элементы управления должны быть созданы, чтобы иметь значения свойств, и вы хотите избежать их создания, вместо этого кэширование их рендеринговых полей с кэшированными пользовательскими элементами управления имеет нулевое значение в коде, если кэшируется для них подана разметка. Это работает, введя PartialCachingControl на страницу вместо фактического пользовательского элемента управления. Этот PartialCachingControl проверяет кеш и создает только элемент управления, если не существует кешированной версии.

Что касается заставить его работать, я вижу два варианта:

  1. Если у вас есть только 1 UserControl на каждой странице, вы можете использовать подход VaryByCustom. Для того, чтобы вещи легко можно написать интерфейс, который возвращает ваше значение свойства для этой страницы, и реализовать его на каждой странице, которая содержит пользовательский элемент управления, например .:

    interface INumberProvider 
    { 
        int GetNumber(); 
    } 
    
    // and the page: 
    public partial class _Default : Page, INumberProvider 
    { 
        public int GetNumber() 
        { 
         return this.SomeNumberPropertyOrWhatever; 
        } 
    ... 
    

    В вашем Global.asax разыгрывании текущий обработчик INumberProvider и получить номер:

    public override string GetVaryByCustomString(HttpContext context, string custom) 
        { 
         if (custom == "INumberProvider") 
         { 
          var page = context.CurrentHandler as INumberProvider; 
    
          if (page != null) 
          { 
           return page.GetNumber().ToString(); 
          } 
         } 
         return base.GetVaryByCustomString(context, custom); 
        } 
    

    И под вашим контролем вы, очевидно, добавить:

    OutputCache Продолжительность = "180" VaryByCustom = "INumberProvider" VaryByParam = "None" Общий = "true"

    Это если у вас есть только один пользовательский элемент управления на странице, и он должен быть довольно простым. Если вам нужно более одного пользовательского элемента управления на странице, вам не повезло:

  2. Создайте собственную оболочку вокруг своего пользовательского элемента управления, написав пользовательский WebControl. Добавьте необходимые свойства, запишите вывод обработанного пользовательского элемента управления и вставьте его в HttpContext.Current.Cache с ключом, который включает SelectedCatID. В основном напишите свой собственный PartialCachingControl. Там также вариант 3:
  3. Решают кэширование не так важно, ведь
+0

'Вот если бы у вас только один пользовательский элемент управления на странице, и он должен быть довольно простым. Если вам требуется более одного пользовательского элемента управления на одну страницу, вам не повезло: «Неправильно. Вы просто добавляете директиву в различные пользовательские элементы управления, а не сами страницы. Возможно кэширование отдельного пользовательского элемента управления. – Hillboy

+0

Вышеупомянутое относится к кешированию пользовательских элементов управления. Что я говорю: на основе информации, доступной в переопределении Global.asax, нет способа вывести значение свойства пользовательского элемента управления, к которому предполагается создать кеш, для изменения, если только один из них не существует пользователь контролирует каждую страницу. –

+0

Огромный ответ спасибо, именно то, что я получил после. Если вы это сделали, напишите ссылку на ваш блог. –

0

Я опоздал на вечеринку здесь, что с принятым ответ и 500 точки Баунти в присужденной. Все еще хотелось дать мои небольшие центы о том, как это можно достичь.

Это может быть сделано для работы в самом управлении. Вы можете иметь хранилище управления в собственном виде в кеше и использовать кешированную версию в методе , если он найден. Я сделал очень простой UserControl для тестирования. Разметка выглядит следующим образом:

<%@ Control Language="C#" AutoEventWireup="true" CodeBehind="TestUC.ascx.cs" 
    Inherits="Webforms_Test.UserControls.TestUC" %> 
<div> 
    <asp:Label ID="curTime" runat="server"></asp:Label> 
</div> 

Он содержит только метку, которая устанавливается в DateTime.Now при инициализации. Код позади выглядит следующим образом:

public partial class TestUC : System.Web.UI.UserControl 
{ 
    private string cachedOutput = null; 
    public bool RenderFromCache = true; // set to false in containing page if this control needs to be re-rendered 

    protected void Page_Load(object sender, EventArgs e) 
    { 
     cachedOutput = HttpContext.Current.Cache["key"] as string; 
     if (cachedOutput == null) 
     { 
      // not found in cache, do the heavy lifting here to setup the control 
      curTime.Text = "UC:" + DateTime.Now.ToString("yy-MM-dd hh:mm:ss"); 
     } 
    } 
    protected void Page_PreRender(object sender, EventArgs e) 
    { 
     if (cachedOutput == null || !RenderFromCache) 
     { 
      RenderFromCache = false; 
      StringBuilder b = new StringBuilder(); 
      HtmlTextWriter h = new HtmlTextWriter(new StringWriter(b)); 
      this.RenderControl(h); 
      cachedOutput = b.ToString(); 
      HttpContext.Current.Cache.Insert("key", cachedOutput, null, DateTime.UtcNow.AddSeconds(10), TimeSpan.Zero); 
      RenderFromCache = true; 
     } 
    } 
    protected override void Render(HtmlTextWriter writer) 
    { 
     if (!RenderFromCache) 
      base.Render(writer); 
     else 
      writer.Write(cachedOutput); 
    } 
} 

В этом примере, сам элемент управления проверяет, является ли его выход находится в кэше, и если да, то метод Render будет просто написать кэшированные выход. Если он не найден в кеше, метод PreRender будет нормально запускать метод Render и захватить вывод и сохранить его в кеше.

В вашем случае вам, разумеется, потребуется немного больше логики, которая проверила бы соответствующее свойство элемента управления и использовала бы это, чтобы проверить, существует ли кешированная версия.

Отказ от ответственности: Это чрезвычайно простой контрольный контроль. Я не пытался выяснить, как сделать всю эту работу с элементами управления, которые содержат обработчики событий и т. Д. Поэтому возьмите его за то, что он стоит ...

+0

Я понимаю, о чем вы говорите. Я не уверен, что это будет почти так же эффективно, как класс обертки. Ваш контроль будет по-прежнему строить все дерево управления, чтобы выбросить все это и обслуживать кешированный html. PartialCachingControl переопределяет метод InitRecursive, но он помечен как внутренний, поэтому мы не можем его использовать. Возможно, OnInit будет работать. –