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:
Weird, huh?
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 :) )