asp.netcachingwebconfigurationmanagerhttpruntime.cache

ASP.NET: HttpRuntime.Cache getting flushed when saving WebConfigurationManager -- Is this a bug?


Recently, I've been experimenting with caching objects with HttpRuntime.Cache and I was generally under the impression that if I "added" something to the cache like this:

HttpRuntime.Cache.Insert("Test", "This is a test!", null, 
     Cache.NoAbsoluteExpiration, Cache.NoSlidingExpiration, 
     CacheItemPriority.NotRemovable, new CacheItemRemovedCallback(FileChanged));

that the "NotRemovable" and "NoExpiration" flags would keep the object in-memory for the duration of the application. But was finding that at the end of certain page requests, the HttpRuntime.Cache would be completely empty!

Tracing thru and setting a breakpoint inside my Callback "FileChanged" I could see that indeed something was "removing" my object (and every other object in the cache), but I couldn't figure out why. So eventually, I started disabling other things that I thought might affect this subsystem.

Eventually, I commented out the line:

WebConfigurationManager.OpenWebConfiguration("~").Save;

I had been mostly retrieving data from "web.config" in the AppSettings region, but occasionally writing back to AppSettings and saving the changes using the above command. I knew from reading that the "web.config" is cached, but saving my changes back to it shouldn't flush all of HttpRuntime.Cache, right?

Is this a bug? Or are the two caches somehow linked in a way that I should be made aware of?

EDIT:

Ok, I've made this super reproducible if anyone wants to try this on their own machine. (I'm running VS2008 Pro w/ MVC2 targeting .NET 3.5) Just start up a new MVC2 project and paste the following into the HomeController over whatever is already there:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Configuration;
using System.Configuration;

namespace BackButtonTest.Controllers
{
    [HandleError]
    public class HomeController : Controller
    {
        private string MESSAGE = "Message";
        public ActionResult Index()
        {
            ViewData[MESSAGE] = HttpRuntime.Cache.Get(MESSAGE);
            Configuration Config = WebConfigurationManager.OpenWebConfiguration("~");
            Config.AppSettings.Settings.Add("SomeKey", "SomeValue");
            Config.Save();
            return View();
        }

        public ActionResult About()
        {
            HttpRuntime.Cache[MESSAGE] = "This is pulled from the HttpRuntime.Cache";
            return View();
        }
    }
}

Then follow these steps:

  1. Start-up the app in debug mode.
  2. Click on the "About" link. This loads a string into the Cache.
  3. Click on the "Home" link. String is pulled from the Cache and stuck in ViewMessage dictionary. Some key/value pair is written to web.config and saved. String from cache should appear on the Home page.
  4. Click on the "Home" link again. String should be pulled from the cache, but it's not.
  5. Stop program. Comment out the 3 lines that start with "Config". Restart the program.
  6. Try steps 1 thru 4 again. Notice how the HttpRuntime.Cache has not been emptied.

Weird, huh?


Solution

  • Writing to your web.config will force the application to restart, and, most likely, events for emptying the cache, in-proc sessionstate etc. will go off. Try and write down some log in global.asax Application_End (or whatever the name of the method is :) )