Любой способ очистить / очистить / удалить OutputCache? - PullRequest
28 голосов
/ 19 февраля 2009

Я использую OutputCache на своем веб-элементе управления (.ascx)

<%@ OutputCache Duration="1000" VaryByParam="none" %>

Я хотел бы сохранить кеш на следующие 1000 секунд, но когда загружается определенная страница на моем сайте, я хотел бы удалить / очистить / обновить кеш. Мол, я хочу очистить кеш при загрузке MyPage.aspx. Можно ли программно очистить кеш?

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

Заранее спасибо за помощь.

Ответы [ 7 ]

33 голосов
/ 19 февраля 2009

Для этого можно использовать параметр VaryByCustom.

В вашем пользовательском контроле у ​​вас будет следующее:

<%@ OutputCache Duration="1000" VaryByParam="None" VaryByCustom="MyKey" %>

Тогда вы переопределите метод GetVaryByCustomString в вашем Global.asax следующим образом:

public override string GetVaryByCustomString(HttpContext context, string arg)
{
    if (arg == "MyKey")
    {
        object o = context.Current.Application["MyGuid"];
        if (o == null)
        {
            o = Guid.NewGuid();
            context.Current.Application["MyGuid"] = o;
        }
        return o.ToString();
    }
    return base.GetVaryByCustomString(context, arg);
}

Наконец, в MyPage.aspx вы бы сделали это:

Application["MyGuid"] = Guid.NewGuid();

Как это работает?

Всякий раз, когда ваш элемент управления кэшируется, он связывается со строкой (строка, возвращаемая методом GetVaryByCustomString, когда в него передается ключ VaryByCustom элемента управления).

При каждом последующем использовании элемента управления снова вызывается GetVaryByCustomString. Если возвращаемая строка соответствует кэшированной версии элемента управления, используется кэшированная версия.

В нашем случае «MyKey» передается в GetVaryByCustomString и возвращает то, что хранится в Application["MyGuid"].

Всякий раз, когда вызывается MyPage.aspx, он заменяет Application["MyGuid"] на новое случайное значение.

Когда ваш элемент управления будет в следующий раз использован, метод GetVaryByCustomString вернет новое значение, и поскольку кешированная версия элемента управления, связанного с этим значением, будет восстановлена. (Затем элемент управления будет кэширован и связан с новым значением, чтобы сохранить его до следующего вызова MyPage.aspx и т. Д.)

Здесь есть обзор здесь .

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

Вы можете использовать HttpResponse.RemoveOutputCacheItem или HttpResponse.AddCacheItemDependency для аннулирования записей выходного кэша.

8 голосов
/ 16 апреля 2013

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

Просто позвоните:

HttpRuntime.UnloadAppDomain();

Это имеет тот же эффект, что и переработка пула приложений. Не подходит в любой ситуации, но это определенно сделает работу.

4 голосов
/ 26 февраля 2015

Вдохновившись другим постом, следующий фрагмент успешно удаляет каждую страницу, кэшированную OutputCache в asp.net, используя отражение:

        public static void ClearOutputCache()
        {

            var runtimeType = typeof(HttpRuntime);

            var ci = runtimeType.GetProperty(
               "CacheInternal",
               BindingFlags.NonPublic | BindingFlags.Static);

            var cache = ci.GetValue(ci, new object[0]);

            var cachesInfo = cache.GetType().GetField(
                "_caches",
                BindingFlags.NonPublic | BindingFlags.Instance);
            var cacheEntries = cachesInfo.GetValue(cache);

            var outputCacheEntries = new List<object>();

            foreach (Object singleCache in cacheEntries as Array)
            {
                var singleCacheInfo =
                singleCache.GetType().GetField("_entries",
                   BindingFlags.NonPublic | BindingFlags.Instance);
                var entries = singleCacheInfo.GetValue(singleCache);

                foreach (DictionaryEntry cacheEntry in entries as Hashtable)
                {
                    var cacheEntryInfo = cacheEntry.Value.GetType().GetField("_value",
                       BindingFlags.NonPublic | BindingFlags.Instance);
                    var value = cacheEntryInfo.GetValue(cacheEntry.Value);
                    if (value.GetType().Name == "CachedRawResponse")
                    {
                        var key = (string)cacheEntry.Value.GetType().BaseType.GetField("_key", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(cacheEntry.Value);
                        key = key.Substring(key.IndexOf("/"));
                        outputCacheEntries.Add(key);
                    }
                }
            }
            foreach (string key in outputCacheEntries)
            {  
                HttpResponse.RemoveOutputCacheItem(key);
            }
        }
4 голосов
/ 19 февраля 2009

Редактировать: Если вы включили кеширование ядра на II6 +, то вам нужно будет следовать совету Люка и использовать заголовок VaryByCustom, поскольку очистка кэша ASP.NET не повлияет на кэш ядра.

OutputCache хранится в ASP.NET Cache, поэтому вы можете просто вызвать Cache.Remove:

List<string> keys = new List<string>();

foreach(string key in HttpRuntime.Cache)
{
    keys.Add(key);
}

foreach(string key in keys)
{
    Cache.Remove(key);
}

Это, однако, удалит ВСЕ записи кэша, включая пользовательские записи, добавленные вашим кодом.

2 голосов
/ 13 июля 2010

вы можете добавить HttpResponse.RemoveOutputCacheItem ("/ YourCachePageName.aspx"); строка кода в событии загрузки страницы, при загрузке которого вы ожидаете, что кэш кэшированной страницы отключится.

1 голос
/ 03 мая 2019

Sinсe этот ответ больше не работает, а этот ответ очищает только пользовательские элементы кэша (не страницы / MVC-действия, хранящиеся в кэше), я копался по ссылке ASP.NET Исходники и придумали это:

public static void ClearAllCache()
{
    var runtimeType = typeof(System.Web.Caching.Cache);

    var ci = runtimeType.GetProperty(
       "InternalCache",
       BindingFlags.Instance | BindingFlags.NonPublic);

    var cache = ci.GetValue(HttpRuntime.Cache) as System.Web.Caching.CacheStoreProvider;
    enumerator = cache.GetEnumerator();
    while (enumerator.MoveNext())
    {
        keys.Add(enumerator.Key.ToString());
    }
    foreach (string key in keys)
    {
        cache.Remove(key);
    }
}

Больше информации в моем блоге здесь

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...