Подтвердить что ты не робот

Любой способ очистки/очистки/удаления OutputCache?

Я использую OutputCache для моего webuser-управления (.ascx)

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

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

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

Спасибо за вашу помощь заранее.

4b9b3361

Ответ 1

Для этого вы можете использовать параметр 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 и т.д.)

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

Ответ 3

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

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

HttpRuntime.UnloadAppDomain();

Это оказывает такое же влияние, как и на повторное использование пула приложений. Не подходит в любой ситуации, но это определенно сделает работу.

Ответ 4

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

OutputCache хранится в кэше ASP.NET, поэтому вы можете просто вызвать 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);
}

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

Ответ 5

Вдохновляясь другим сообщением, следующий фрагмент успешно удаляет каждую страницу, кэшированную 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);
            }
        }

Ответ 6

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

Ответ 7

Так как этот ответ больше не работает, и этот ответ очищает только пользовательские элементы кэша (не страницы/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);
    }
}

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