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.)

CacheVisualizer - File CacheDependency

Cache entry with file dependencies.

CacheVisualizer - Sql CacheDependency

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)

28 Responses to “Visual Studio 2005 Cache Visualizer”

  1. Mark Petersen Says:

    How do I use / install it?

  2. hunter Says:

    how to use it in vs 2005,it only contain dll,i don’t know how to use it in vs 2005

  3. Gar Maguire Says:

    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.

  4. Brett Says:

    Gar, thanks for the tip! I’ll definately take a look at doing what you suggest.

  5. Brett Says:

    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!

  6. David Williams Says:

    I don’t seem to be able to download this. The link to the Visualizer code is coming up 404.

  7. Brett Says:

    Link fixed

  8. David Williams Says:

    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?

  9. Andrej Gaevskij Says:

    Great tool! Thanks!

  10. Kenny’s Weblog » Blog Archive » Collection of Visualizers for Visual Studio 2005 Says:

    […] Visual Studio 2005 Cache Visualizer […]

  11. Will Fawthrop Says:

    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

  12. Jeff Says:

    it errors, something about _entries in multiple mode.

    any ideas?

  13. TJ Says:

    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

  14. Hill Xie Says:

    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

  15. Hill Xie Says:

    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

  16. Hill Xie Says:

    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

  17. Marc Says:

    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.

  18. Boris Modylevsky Says:

    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)

  19. brucenan Says:

    Well Done!

    BTW:
    ha ha. You can cut the image better. Using Alt+PrintScrn, you can get the active form screenshot image.

  20. Dirc Says:

    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?

  21. matt Says:

    I get an access denied error when trying to use the visualizer. Any suggestions? Am I missing something obvious?

  22. Ricky Wang Says:

    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

  23. Michael Freidgeim Says:

    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:

  24. Mohammad Azam Says:

    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);

  25. Charles Rex Says:

    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;

  26. 小狐狸DM » Blog Archive » Scott Hanselman’s 2007 Ultimate Developer and Power Users Tool List for Windows Says:

    […] Cache Visualizer - What’s in the ASP.NET cache? Find out with this VS2005 Visualizer. […]

  27. Jesse Says:

    Any plans for a VS 2008 version?

  28. Shahed Khan (MVP C#) : The Big Ten Life and Work Changing Utilities from Scott Hanselmans BLOG Says:

    […] Cache Visualizer - What’s in the ASP.NET cache? Find out with this VS2005 Visualizer. […]

Leave a Reply