Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

HttpContext.Current.Cache item null after page refresh

Tags:

c#

caching

web

I've a C# web page in which I'm storing a List<> object in the server cache, using HttpContext.Current.Cache. The object is saved in the cache after the first page load. When I refresh the page though, the cache object is null. Any thoughts?

Also, I'd like to set up a "job" to recreate the object every 30 minutes. I'd like to serve up the cached version until the new one is created, and then replace the old with the new. How do I do that?

In my Global.asax, in Application_Start, I've got the following:

HttpRuntime.Cache.Insert("MainADList", Uf.GetUsers(), null, Cache.NoAbsoluteExpiration, TimeSpan.FromMinutes(30));

When I need it, I do the following:

 MainADList = (Users)HttpRuntime.Cache["MainADList"];

Which is for the most part null. Not always, but almost always.

like image 679
user948060 Avatar asked Jan 20 '13 04:01

user948060


2 Answers

Even if you populate your cache using Cache.NoAbsoluteExpiration + Cache.NoSlidingExpiration, ASP.NET can remove items from the cache (i.e.: when the free system memory is low).

Pass CacheItemPriority.NotRemovable to Cache.Insert() to prevent that from happening. Lookup CachéItemPriority on MSDN.

An IIS application pool restart by long idle time, web.config/binary change, etc. will also wipe your cache. Check this other SO post, HttpRuntime.Cache.Insert() Not holding cached value

About creating a job to refresh the cache; I don't think there is a rule of thumb for the best Cache strategy. It will heavily depend on how your users interact with your web page, how often, how concurrent, and specially, how much time does it take to generate that data when the cache is not hit.

If the time it takes to generate the data is unacceptable for any user, you can set up a job that refreshes the cache, but it's interval should be less than the sum of the cache TTL + time that the generation/retrieval takes. For example, if your cache is 30m and it takes 2m to generate the data, your refresh interval must be 28m or less, to avoid any user to hit an empty cache.

like image 146
istepaniuk Avatar answered Oct 24 '22 13:10

istepaniuk


Can you use the System.Runtime.Caching instead. That way you're not dependent on the HttpRuntime namespace.

I suspect you're getting null because .Net is clearing it due to web-server restarts. Would it be better to do something along the lines of

    public List<User> GetUsers()
    {
        var cache = System.Runtime.Caching.MemoryCache.Default;
        if (cache["MainADList"] == null)
        {
            // Rebuild cache. Perhaps for Multithreading, you can do object locking
            var cachePolicy = new System.Runtime.Caching.CacheItemPolicy() { AbsoluteExpiration = DateTime.Now + TimeSpan.FromMinutes(30) };
            var users = Uf.GetUsers();
            cache.Add(new System.Runtime.Caching.CacheItem("MainADList", users), cachePolicy);

            return users;
        }

        return cache["MainADList"] as List<User>; 
    }
like image 34
Jason Jong Avatar answered Oct 24 '22 11:10

Jason Jong