программно управлять кешированием вывода - отключить или включить кеш в соответствии со значением параметра - PullRequest
20 голосов
/ 25 июня 2009

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

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

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

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

Гораздо проще, URL-это что-то вроде "/ ProductList? Category = что-то & Page = 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.

Ответы [ 5 ]

31 голосов
/ 31 декабря 2009

Вместо использования директивы 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, помеченного как «не должен вызываться». В конце концов, так или иначе будет работать, так что выбирайте.

5 голосов
/ 31 декабря 2009

edit: Мне больше нравится ответ Дэвида Эббо, чем мой.


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

<%@ 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);
}
4 голосов
/ 18 мая 2012

Я считаю, что лучший способ сделать это - использовать HttpCachePolicy.AddValidationCallback

См. http://www.hanselman.com/blog/AdvancedASPNETCachingAndAddValidationCallBack.aspx - есть полный пример, который отвечает именно на этот вопрос.

1 голос
/ 12 июня 2015

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

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

0 голосов
/ 25 июня 2009

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

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

...