Visual Studio 2005 Cache Visualizer
Anyone who’s ever tried to look at ASP.NET’s cache in a Visual Studio Watch window has likely given up after experiencing light-headedness and a motion-sickness sensation. View the dependencies? Yeah right.
After I wrote Control Visualizer, I got a little more ambitious and decided to write Cache Visualizer. I knew it would be more challenging, just not HOW much more. Almost everything related to the cache is internal/private, so reflection is really the only way to get at the interesting information about cache entries. At any rate, after 1 ½ weeks of coding off-and-on, I can finally give you something that should come in handy if you’re using ASP.NET 2.0’s caching features.
Unlike the relatively simple Control Visualizer, this one comes with a few disclaimers:
- I’ve been hard-pressed to get this thing done so I can move on to other projects I’ve been neglecting, so the code isn’t near as well-written or commented as I’d like (I did try to include comments on all classes and important methods though).
- It uses a lot of reflection – much of it obtaining access to internal/private fields. Scary, but necessary.
- SqlCacheDependency info is only displayed for Sql Server 7/2000 dependencies at this point.
- I have no idea what the side effects may be if you remove a cache entry or touch a file with a file dependency on it if the cache entry has a remove callback set…you’ve been warned [but I’ve tried it and didn’t have any problems :o)]
- I haven’t fully tested it. I’ve tried it with standard CacheDependency, SqlCacheDependency, AggregateDependency, with multiple file dependencies, etc. But there’s still plenty that could go wrong.
- If it screws something up in your app….feel free to let me know, but don’t get pissed or cry to me about it :o).
Screenshots and code below….Enjoy! (The source code also includes Control Visualizer, which contains a few cosmetic UI changes since the first release.)
Cache entry with file dependencies.
Cache entry with Sql dependency.
UPDATE: Somehow I left the Value property of the list of cache info to display. The source now includes this.
Download here (47KB)
March 21st, 2006 at 11:59 am
How do I use / install it?
March 26th, 2006 at 6:48 am
how to use it in vs 2005,it only contain dll,i don’t know how to use it in vs 2005
March 28th, 2006 at 5:17 am
Hi Brett,
nice work
I am writing some code to test for SqlCacheDependency on items in the cache. i have uncovered something which you may find useful. For some reason, which i have yet to find the reason for, The _cacheInternal field of the Cache object can be set to one of 2 things, CacheMultiple object and CacheSingle object which both derive from CacheInternal class.
From looking at your code, i think you will suffer the same pitfall as myself.
In the GetCacheEntries() method of the CacheHelper class, your code retrieves the hash table from the _entries field of the _cacheInternal field. This entries field belogs to the CacheSingle class. So when the _cacheInternal field is set to an instance of the CacheMultiple class, the code will fail as the _entries field does not exist.
A better way is to call the DoGet method of the the base class (CacheInternal) which can return you the cache entry and will save you coping the hashtables.
So what i suggest is changes the GetCacheEntry() method to do something like the following
public CacheEntryWannabe GetCacheEntry(string key)
{
object cacheInternal = ReflectionUtility.GetFieldValue(_cache, “_cacheInternal”);
// Parameters: IsPublic, Key, CacheGetOptions (1 = ReturnCacheEntry)
Object[] doGetParameters = { true, key, 1 };
object entry = ReflectionUtility.InvokeMethod(cacheInternal, “DoGet”, doGetParameters);
return this.CreateCacheEntry(entry);
}
note: i haven’t compiled and run this code but i am sure you get the gist of what i an trying to do
Regards,
Gar.
April 7th, 2006 at 11:59 am
Gar, thanks for the tip! I’ll definately take a look at doing what you suggest.
April 7th, 2006 at 12:01 pm
Mark & Hunter, you can view the documentation for installing a visualizer here: http://msdn2.microsoft.com/en-us/library/sb2yca43(VS.80).aspx
Not much to it!
April 17th, 2006 at 12:42 pm
I don’t seem to be able to download this. The link to the Visualizer code is coming up 404.
April 18th, 2006 at 9:19 pm
Link fixed
April 19th, 2006 at 12:17 pm
Thanks, I was able to download it, this looks realy good. It would be great to know (roughly) how big these cached items are. Is it possible to determine this?
May 17th, 2006 at 1:13 am
Great tool! Thanks!
June 30th, 2006 at 3:07 am
[…] Visual Studio 2005 Cache Visualizer […]
July 7th, 2006 at 11:19 am
Here is a updated version that actually lets you peek inside the cache if its a datatable or dataset. I wish I had a little more time to create a xml deserializer extension that would allow you to deserialize and objects state so you could view a xml description of the objects data that is being stored in cache but I guess thats for a another day. And brett try and going easy on us MSN AdCenter guys.
http://rapidshare.de/files/25215063/Johnson.Visualizers.zip.html
August 11th, 2006 at 9:45 am
it errors, something about _entries in multiple mode.
any ideas?
September 8th, 2006 at 7:01 am
Brett,
I am trying to install build your application, and don’t have the full version of Visual Studio as I am only using the web developer express version. Do you have a copy of your code that is pre-built?
Thanks
TJ
January 8th, 2007 at 9:48 am
Hi Brett,
It is a great tool! Thanks. but as Gar said the code will fail if the cache instance is CacheMultiple type, which happened to me. In my case I have a Dual CPU pc which might be the reason why I get the CacheMultiple object instead of CacheSingle object. And I got an error “Field ‘_entries’ does not exist in type System.Web.Caching.CacheMultiple”. To fix that I have to call the property “_caches” of the CacheMultiple object first to get the collection of the CacheSingle object, then I loop in the collection of the CacheSingle object.
public Hashtable GetCacheEntries()
{
object cacheInternal = ReflectionUtility.GetFieldValue(_cache, “_cacheInternal”);
object[] caches = (object[])ReflectionUtility.GetFieldValue(cacheInternal, “_caches”);
Hashtable internalTable = null;
Hashtable entries = new Hashtable();
for (int i = 0; i
January 8th, 2007 at 9:51 am
Sorry, the blog cut off my message, here is the rest.
public Hashtable GetCacheEntries()
{
object cacheInternal = ReflectionUtility.GetFieldValue(_cache, “_cacheInternal”);
object[] caches = (object[])ReflectionUtility.GetFieldValue(cacheInternal, “_caches”);
Hashtable internalTable = null;
Hashtable entries = new Hashtable();
for (int i = 0; i
January 8th, 2007 at 9:55 am
Last try:
public Hashtable GetCacheEntries()
{
object cacheInternal = ReflectionUtility.GetFieldValue(_cache, “_cacheInternal”);
object[] caches = (object[])ReflectionUtility.GetFieldValue(cacheInternal, “_caches”);
Hashtable internalTable = null;
Hashtable entries = new Hashtable();
for (int i = 0; i < caches.Length; i++)
{
internalTable = (Hashtable)ReflectionUtility.GetFieldValue(caches[i], “_entries”);
foreach (object entryKey in internalTable.Keys)
{
string key = (string)ReflectionUtility.GetPropertyValue(entryKey, “Key”);
entries.Add(key, internalTable[entryKey]);
}
}
return entries;
}
Hope this can help!
Hill
January 8th, 2007 at 8:49 pm
Can I use Cache Visualizer in the production server? I’m having a hard time figuring out what are the cache objects in the production server.
January 23rd, 2007 at 8:07 am
Hi,
It seems that I did something wrong as it does not work for me.
This link does not work:
http://rapidshare.de/files/25215063/Johnson.Visualizers.zip.html
So I dowloaded source files from the following link:
http://blog.bretts.net/wp-content/uploads/2006/03/Johnson.Visualizers.zip
Built the project using VS 2005 and copied dll file into my
[InstallPath]\Microsoft Visual Studio 8\Common7\Packages\Debugger\Visualizers folder as described in http://msdn2.microsoft.com/en-us/library/sb2yca43
After restarting the VS 2005, tried to view cache during debug and received the following error:
************** Exception Text **************
Microsoft.VisualStudio.DebuggerVisualizers.DebugViewerShim.RemoteObjectSourceException: Field ‘_entries’ does not exist in type System.Web.Caching.CacheMultiple —> System.MissingFieldException: Field ‘_entries’ does not exist in type System.Web.Caching.CacheMultiple
at Johnson.Common.ReflectionUtility.GetFieldValue(Object obj, String fieldName) in D:\Shared\Utils\Visual Studio 2005 Add-In\CacheVisualizer\ReflectionUtility.cs:line 56
at Johnson.Visualizers.CacheVisualizer.CacheHelper.GetCacheEntries() in D:\Shared\Utils\Visual Studio 2005 Add-In\CacheVisualizer\CacheVisualizer\CacheHelper.cs:line 77
at Johnson.Visualizers.CacheVisualizer.CacheVisualizerSource.GetData(Object target, Stream outgoingData) in D:\Shared\Utils\Visual Studio 2005 Add-In\CacheVisualizer\CacheVisualizer\CacheVisualizerSource.cs:line 31
at Microsoft.VisualStudio.DebuggerVisualizers.DebugViewerShim.VisualizerObjectSourceHolder.GetData(Object target, Stream s)
at Microsoft.VisualStudio.DebuggerVisualizers.DebugViewerShim.DebugeeHost.GetInitialData(VisualizerObjectSourceHolder sourceHolder, Object input)
— End of inner exception stack trace —
at Johnson.Common.ReflectionUtility.GetFieldValue(Object obj, String fieldName) in D:\Shared\Utils\Visual Studio 2005 Add-In\CacheVisualizer\ReflectionUtility.cs:line 56
at Johnson.Visualizers.CacheVisualizer.CacheHelper.GetCacheEntries() in D:\Shared\Utils\Visual Studio 2005 Add-In\CacheVisualizer\CacheVisualizer\CacheHelper.cs:line 77
at Johnson.Visualizers.CacheVisualizer.CacheVisualizerSource.GetData(Object target, Stream outgoingData) in D:\Shared\Utils\Visual Studio 2005 Add-In\CacheVisualizer\CacheVisualizer\CacheVisualizerSource.cs:line 31
at Microsoft.VisualStudio.DebuggerVisualizers.DebugViewerShim.VisualizerObjectSourceHolder.GetData(Object target, Stream s)
at Microsoft.VisualStudio.DebuggerVisualizers.DebugViewerShim.DebugeeHost.GetInitialData(VisualizerObjectSourceHolder sourceHolder, Object input)
at Microsoft.VisualStudio.DebuggerVisualizers.DebugViewerShim.PrivateCallback.MaybeDeserializeAndThrowException(Byte[] data)
at Microsoft.VisualStudio.DebuggerVisualizers.DebugViewerShim.PrivateCallback.WriteDataToStreamAndThrowOnException(Byte[] data, Stream dataStream)
at Microsoft.VisualStudio.DebuggerVisualizers.DebugViewerShim.PrivateCallback.Microsoft.VisualStudio.DebuggerVisualizers.IVisualizerObjectProvider.GetData()
at Johnson.Visualizers.CacheVisualizer.CacheViewer.GetObjectData() in D:\Shared\Utils\Visual Studio 2005 Add-In\CacheVisualizer\CacheVisualizer\CacheViewer.cs:line 49
at Johnson.Visualizers.CacheVisualizer.CacheViewer.SetObjectProvider(IVisualizerObjectProvider objectProvider) in D:\Shared\Utils\Visual Studio 2005 Add-In\CacheVisualizer\CacheVisualizer\CacheViewer.cs:line 32
at Johnson.Visualizers.CacheVisualizer.CacheVisualizer.Show(IDialogVisualizerService windowService, IVisualizerObjectProvider objectProvider) in D:\Shared\Utils\Visual Studio 2005 Add-In\CacheVisualizer\CacheVisualizer\CacheVisualizer.cs:line 21
at Microsoft.VisualStudio.DebuggerVisualizers.DebugViewerShim.ManagedShim.DelegatedHost.CreateViewer(IntPtr hwnd, HostServicesHelper hsh, SafeProxyWrapper proxy)
March 1st, 2007 at 6:36 pm
Well Done!
BTW:
ha ha. You can cut the image better. Using Alt+PrintScrn, you can get the active form screenshot image.
May 15th, 2007 at 3:52 am
I too get the _entries field error and cannot fire it up:
Microsoft.VisualStudio.DebuggerVisualizers.DebugViewerShim.RemoteObjectSourceException: Field ‘_entries’ does not exist in type System.Web.Caching.CacheMultiple —> System.MissingFieldException: Field ‘_entries’ does not exist in type System.Web.Caching.CacheMultiple
This is when using the ASP.NET dev web server.. not sure if this is any different to using IIS?
August 17th, 2007 at 7:46 am
I get an access denied error when trying to use the visualizer. Any suggestions? Am I missing something obvious?
August 26th, 2007 at 3:53 am
Hi, I also met the error
Microsoft.VisualStudio.DebuggerVisualizers.DebugViewerShim.RemoteObjectSourceException: Field ‘_entries’ does not exist in type System.Web.Caching.CacheMultiple —> System.MissingFieldException: Field ‘_entries’ does not exist in type System.Web.Caching.CacheMultiple
is there any setting I ignore?
Regards,
Ricky
September 25th, 2007 at 9:01 pm
Link to Control Visualizer, http://blog.bretts.net/PermaLink,guid,87d735a0-1592-4711-860f-8a1d29c9630f.aspx is not working:
Configuration Error
Line 8:
Line 9:
Line 10:
October 16th, 2007 at 1:27 pm
Hi,
How do you get the _entries from the _cacheInternal field. I checked the CacheInternal class and it does not expose the _entries collection.
I am using the following code:
System.Web.Caching.Cache _cache = Page.Cache;
FieldInfo f = _cache.GetType().GetField(”_cacheInternal”, BindingFlags.Instance |
BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.GetProperty);
object cacheInternal = f.GetValue(_cache);
FieldInfo c = cacheInternal.GetType().GetField(”_entries”,BindingFlags.Instance |
BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.GetProperty);
November 15th, 2007 at 7:55 am
Hello,
Can this code be used in a standalone ASP.NET application ?
I integrated your code in an ASP.NET application and at runtime
I get the following error:
“Field ‘_entries’ does not exist in type System.Web.Caching.CacheMultiple”
The function that fails is:
public Hashtable GetCacheEntries()
The failure is here:
Hashtable internalTable = (Hashtable)ReflectionUtility.GetFieldValue(cacheInternal, “_entries”);
}
where I previously initialised
Cache _cache = HttpContext.Current.Cache;
January 7th, 2008 at 12:16 pm
[…] Cache Visualizer - What’s in the ASP.NET cache? Find out with this VS2005 Visualizer. […]
January 10th, 2008 at 1:12 pm
Any plans for a VS 2008 version?
March 10th, 2008 at 10:50 pm
[…] Cache Visualizer - What’s in the ASP.NET cache? Find out with this VS2005 Visualizer. […]