2009-06-25 4 views
20

У нас есть довольно стандартный сценарий электронной коммерции с выгружаемыми списками продуктов в категориях. К лучшему или худшему, около 80% посетителей никогда не перемещаются мимо первой страницы, в зависимости от категории может быть еще 5-10 страниц результатов, которые просматриваются гораздо реже. (Да, мы оптимизируем то, что появляется на первой странице и имеют хороший поиск, но это другое обсуждение)программно управляет выходным кэшированием - отключить или включить кеш в соответствии с значением параметра

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

Я знаю, что я мог бы сделать что-то подобное с помощью кэширования объектов для хранения данных, о которых идет речь, но возможно ли это с помощью кэширования вывода, возможно, с помощью объекта response.Cache?

Где на странице жизненного цикла это можно сделать? Pre-рендеринга?

Значительно упрощена, то URL что-то вроде "/ ProductList Категория = что-то & страница = 1?" И я хочу что-то вроде логики (псевдокод):

If paramater "Page" equals 1 
    Use output caching: vary by param = "categoryName; page" 
else 
    Don't use caching at all, just render the page from scratch. 

Мы используем ASP.NET 2.0, на IIS 6/win2003.

+0

Посмотрите на последний ответ на [this] (http://stackoverflow.com/questions/1122837/how-do-i-configure-asp-net-outputcache-to-vary-by-http-vs -https). Надеюсь, это поможет. – James

ответ

30

Вместо использования директивы OutputCache, вы можете сделать то же самое программно, следующим образом:

if (yourArbitraryCondition) { 
    OutputCacheParameters outputCacheSettings = new OutputCacheParameters(); 
    outputCacheSettings.Duration = 60; 
    InitOutputCache(outputCacheSettings); 
} 

Выполнение этого из OnInit должен работать нормально. И, очевидно, вы можете настроить поведение кэширования, установив различные свойства на OutputCacheParameter, который имеет все те же ручки, что и директива (фактически это то, что мы генерируем при использовании директивы).

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

UPDATE:

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

HttpCachePolicy cache = Response.Cache; 
cache.SetCacheability(HttpCacheability.Public); 
cache.SetExpires(Context.Timestamp.AddSeconds(60)); 
cache.VaryByParams["categoryName"] = true; 

В принципе, это еще один способ сделать то же самое, без использования каких-либо API, помеченный как «нельзя назвать». В конце концов, любой из них будет работать, так что сделайте выбор.

+0

Работы. Любая идея, почему 'InitOutputCache' является' EditorBrowsableState.Never' и не должна вызываться напрямую в соответствии с http://msdn.microsoft.com/en-us/library/ms153473.aspx? –

+1

Ну, это в основном из-за нехватки мышления, когда мы впервые это разработали. На странице есть несколько общедоступных/защищенных API, которые отмечены таким образом. Это все, что вызвано сгенерированным кодом в результате использования различного синтаксиса, и мы решили, что у пользователя нет веских причин для прямого вызова. Но на самом деле нет ничего плохого в том, чтобы называть их самих, и на самом деле есть такие моменты, как здесь, где он позволяет вам делать то, что вы не могли сделать с синтаксисом страницы. Я напишу ошибку, чтобы удалить эти флаги, хотя это путь к концу для VS2010. –

+0

Еще одна вещь: вы можете на самом деле сделать то же самое, обратившись непосредственно к API кеша низкого уровня (и избегайте InitOutputCache). Он будет работать одинаково, но код будет более сложным. Сообщите мне, хотите ли вы это альтернативное решение. –

0

Я думаю, вы должны иметь возможность использовать OutputCache directive с свойством VaryByParam, установленным в список разделенных запятыми строк, используемых для изменения выходного кэша.

Если вы не хотели просто кэшировать только когда Страница == 1?

+0

К сожалению, это именно то, что я хочу (Только при странице == 1). Если бы я хотел кэшировать каждую страницу результатов, которые были бы легкими, используя varibyparam, как вы говорите. Извините, я не думаю, что я сформулировал вопрос очень четко, но то, что мне нужно, является лишь незначительным (но значительно) отличным от обычного сценария, к которому все привыкли. –

5

Редактировать:Мне нравится ответ Дэвида Эббо намного лучше моего.


Вы можете использовать

<%@ OutputCache Duration="60" VaryByParam="none" VaryByCustom="pageOne" %> 

и реализовать таким образом, что возвращает фиксированный ключ для первой страницы и случайного ключа для всех остальных страниц. Вы можете (и должен), пусть механизм scavenging позаботится о памяти, но вы можете использовать HttpResponse.RemoveOutputCacheItem, чтобы удалить элементы кэша, если нужно.

public override string GetVaryByCustomString(HttpContext ctx, string custom) 
{ 
    if(custom == "pageOne") 
    { 
     if(ctx.Request["page"] == "1") 
     { 
      return "1"; 
     } 

     HttpResponse.RemoveOutputCacheItem("/Default.aspx"); 
     return Guid.NewGuid().ToString(); 
    } 
    return base.GetVaryByCustomString(ctx, custom); 
} 
1

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

Так, например, если вы используете подкастинг с ретранслятором, вы можете просто в своем сценарии поиска исключить любую обратную передачу на определенной странице из кеша. Here - пример кода, который делает именно это. Подход просто требует использования объекта HttpContext для доступа к Response.Cache.SetNoServerCaching() после захвата любых критериев, для которых вы хотите избежать кеширования. Надеюсь, это поможет.

 Смежные вопросы

  • Нет связанных вопросов^_^