You can use the VaryByCustom
parameter for this.
In your user control you would have the following:
<%@ OutputCache Duration="1000" VaryByParam="None" VaryByCustom="MyKey" %>
Then you would override the GetVaryByCustomString
method in your Global.asax like so:
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);
}
Finally in MyPage.aspx
you would do this:
Application["MyGuid"] = Guid.NewGuid();
How does this work?
Whenever your control is cached, it is associated with a string (the string returned from the GetVaryByCustomString
method when your control's VaryByCustom
key is passed into it).
Whenever the control is subsequently used, GetVaryByCustomString
is called again. If the returned string matches a cached version of the control, then the cached version is used.
In our case, "MyKey" is passed into GetVaryByCustomString
and it returns whatever is stored in Application["MyGuid"]
.
Whenever MyPage.aspx
is called, it changes Application["MyGuid"]
to a new random value.
When your control is next used the GetVaryByCustomString
method will return the new value, and because there is no cached version of the control associated with that value, the control will be regenerated. (The control will then be cached and associated with the new value, to persist until the next call to MyPage.aspx
etc)
There's an overview here.
You can use HttpResponse.RemoveOutputCacheItem
or HttpResponse.AddCacheItemDependency
to invalidate output cache entries.
It's a bit of a sledgehammer to crack a nut sort of approach but it was the simplest and most effective way to completely clear/flush the cache of an application that I found find.
Simply call:
HttpRuntime.UnloadAppDomain();
This has the same impact as recycling the app pool. Not suitable in every situation but it will definitely get the job done.
Edit: If you have enabled kernel caching on II6+ then you will need to go with Luke's advice and use a VaryByCustom header, as clearing ASP.NET cache will not affect kernel cache.
OutputCache is stored in the ASP.NET Cache, so you can just call 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);
}
This will, however, remove ALL cache entries, including custom entries added by your code.
By taking inspiration on other post, the following snippet removes successfully every page cached by OutputCache
in asp.net by using reflection:
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);
}
}
Sinсe this answer no longer works, and this answer only clears custom cache items (not the pages/MVC-actions stored in cache), I digged through ASP.NET reference source codes and came up with this:
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);
}
}
More info in my blog post here
you can add HttpResponse.RemoveOutputCacheItem("/YourCachePageName.aspx"); line of code in the page load event of the page, loading of which you expect the cached page's cache to go off.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With