views:

96

answers:

2

Just wondering if anyone knows definitively what the default serialization used by the ASP.net HttpRuntime.Cache is? Is it Binary, XML, something else?

I ask because I have a situation where I am populating a generic List with multiple objects of the same custom type. The custom type is a POCO, there is nothing special about it. All of its properties are public with { get; set; }, it is public, it has no inheritance, it has no interfaces. In fact it is much less complicated than many other objects which we are caching which work without issue. I have tried adding the [Serializable] attribute to the custom class and it has no effect.

I add the list to the cache with a unique key. The list has been verified as populated before it is inserted into the cache, the objects in the list have been verified as populated as well. But when the list is pulled back out of the cache it is an empty list (NOT NULL), it simply has no items in it. This means that the list is being added to the cache and is retrievable but for some reason the cache is having issues serializing the objects in the list.

I just find this freaky weird since I have another list of custom objects which are much more complicated (consisting of Inheritance, Interfaces, and also containing Properties which are generic lists of other complex objects) and the caching of those lists work without issue.

Both the working and non-working list are being managed in C# classes outside of the ASP.net user controls which consume the cached data. Both of these cache handling classes call the exact same Cache Manager class singleton instance which wraps the HttpRuntime.Cache to provide typed methods for pull and pushing objects into the cache.

Anyone have any ideas what could cause this to happen. The only thing I can thin of is that the 'Blurb' property of the Document object can potentially contain HTML, but if ASP.net uses binary serialization for the cache I don't see how this would do anything.

Here is the class

public class Document
{
    public string ContentTypeId { get; set; }
    public string ContentId { get; set; }
    public bool IsCustom { get; set; }
    public Language DocLanguage { get; set; }
    public string RegularTitle { get; set; }
    public string InvertedTitle { get; set; }
    public string Blurb { get; set; }
}  

Here is the subclass used in the Language Property

public class Language
{
    public string Name { get; set; }
    public string Code { get; set; }
}
+1  A: 

According to Reflector, HttpRuntime.Cache doesn't serialize data at all, it merely stores it in memory in a Hashtable.

You say you wrap calls to the cache inside your own singleton object. Why do you do this? HttpRuntime.Cache is a static property, and so your wrapper methods can be static too.

Christian Hayter
It is a company web application and was an architectural decision made by those with a lot more power than I :) .
Schleichermann
Unless you have evidence to the contrary, I would suspect the wrapper code before the ASP.NET runtime. I have written this kind of architectural code myself (including my own cache wrapper!), and I know how hard it is to get right. Perhaps you happen to be using it in a way that it wasn't designed to handle? I suggest taking the matter up with the authors of your wrapper class.
Christian Hayter
A: 

A little more detail regarding the environment in which this caching anomaly is taking place.

I have an ASP.net User Control which represents a Tabbed Container on the page. This control contains a list of topics selected by the user. For each topic the user has selected this control creates a new tab for that topic containing documents related to that topic.

The control creates the new tab by utilizing the ASP.net provided LoadControl method. It then assigns the newly created Tab Control a topic from its list. Each tab control knows how to locate documents for its assigned topic.

It is within this tab control where the caching was implemented. The cache key used to cache the lists of documents are completely unique to the Site+Topic+Gender+Age of the user viewing the topic. This allows the document lists to be cached and retrieved across the site by all users fitting that criteria.

Well when the lists of documents were passed to the cache they were passed by regular old object references (i.e. List documents = _documents). but when pulled from the cache the list were empty.

Although each tab control is its own instance of the same user control and all variables used within the tab control are private to that control and should be specific to that control. I hit the end of my rope and despite the fact that there is no way the individual tabs could be over-writing each others private lists I decided there had to be some sort of crazy reference bug going on and if that was the case I needed to stop using the referenced objects in the cache and only send the cache completely new copies of the lists I was trying to store.

I then used the following extension method for the List<> and cloned each list as they were passed to the cache. This made it so that all items passed to the cache were brand new objects with their own space in memory with their own unique references to that memory.

FIXED IT. THE CACHING NOW WORKS. The lists are now being returned exactly as they were added to the cache. I have no clue why this would make a difference, if anyone has any ideas I would love to hear them.

    /// <summary>
    /// Clones the specified list to clone.
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="listToClone">The list to clone.</param>
    /// <returns></returns>
    public static IList<T> Clone<T>(this IList<T> listToClone) where T : ICloneable
    {
        return listToClone.Select(item => (T)item.Clone()).ToList();
    }
Schleichermann