11/02/2007

System.Web.Caching.Cache, HttpRuntime.Cache, and IIS Recycles

Recently I chimed in on a newsgroup thread to an OP (Original Poster) who was questioning why he was losing Cache items. This individual would load a dataset from the Cache object into a local object to use to perform processing. He had been using httpcontext.current.cache and noticed that sometimes he was not able to get the dataset out of the cache. He tried switching to HttpRuntime.Cache and it seemed to help.

The OP claimed that the application is under heavy hits, and once or twice every month he would see this error. He wanted to know why does the HttpContext.Current.Cache call work sometimes, while some other times does not.


A couple of posters replied, one of whom is a respected MVP who usually makes very astute, high-quality posts. He posted,"The cache is only valid during the life of the request. how is you[sic] code using the cache?"

Somebody else (also pretty astute, usually) responded, "Cache is valid during lifetime of application not request.....".

What's the answer?

Just to make sure, I posted some response information:

"ASP.NET applications recycle periodically, especially if there is a lot of memory pressure. When this happens, Cache goes away and is then resurrected.
While there could be other explanations, this is the most likely one. It should not matter whether you use HttpContext or HttpRuntime..."

I got a response:

"recycling doesn't effect [sic] HttpRuntime.Cache, which only exists for the request. during a recycle, currently running requests continue in the old
appdomain, so they still have this data."

That's only partially true. Yes, existing requests continue to finish up on the original AppDomain. However, that doesn't explain why the Cache item would be gone on any subsequent request, which is what the OP was really asking. So I responded in more detail:

"The System.Web.Caching.Cache class can be accessed either through the static property System.Web.HttpRuntime.Cache or through the helper instance properties System.Web.UI.Page and System.Web.HttpContext.Cache. (or HttpContext.Current.Cache) It is therefore available outside the context of a request. There is only one instance of this object throughout an entire application domain. Recycling an AppDomain (e.g. by touching web.config, or due to IIS causing the recycle due to memory pressure, etc.) will drop Application, Cache, and in-process Session information since that is stored in the AppDomain logical process. You can do this simple test:


protected void Page_Load(object sender, EventArgs e)
{
Cache["test"] = "Stuff in Cache";
System.Web.HttpRuntime.UnloadAppDomain(); // similar to an IIS AppDomain Recycle
Response.Redirect("Default2.aspx");
// Default2.aspx simply does: Response.Write((string) Cache["test"]); -- you should see nothing.
}

---"

The main point here is that if your Application is recycled either due to IIS health settings, the web tree contents being changed, or because your buggy code throws an unhandled exception, then your Session , Application, and Cache contents go "bye bye". There are no ifs, ands or buts about it. You are getting a new AppDomain, and it starts life with nothing in either Session, Application, or Cache.

The most efficient way to access the Cache is via the HttpRuntime.Cache object directly, the other methods involve extra parsing for the current HttpContext . It's a very minor optimization though. In point of fact, you can use the HttpRuntime.Cache class from Windows Forms or even a Windows Service, and it will work just fine. All you need is a reference to System.Web. It is very efficient and has neat Invalidation callbacks and other useful features that would be hard to duplicate. It's also much more lightweight than the Enterprise Library Caching framework and if you believe in traveling with "batteries included" as I do, this is the best way to go.

Politics: Her Hillarious Inner Self

Peggy Noonan, who I particularly admire, did a piece in the Wall Street Journal about Hillary Clinton revealing her "inner self". Rather than try to be a pundit, I'll just quote the pointillist paragraph:


"Giving illegal immigrants drivers licenses makes sense because it makes sense, but she may not be for it, but undocumented workers should come out of the shadows, and it makes sense. Maybe she will increase the payroll tax on Social Security beyond its current $97,500 limit, to $200,000. Maybe not. Everybody knows what the possibilities are. She may or may not back a 4% federal surcharge on singles making $150,000 a year and couples making $200,000. She suggested she backed it, said she didn't back it, she then called it a good start, or rather "I support and admire" the person proposing such a tax for his "willingness to take this on."

Noonan continues, "The problem for Mrs. Clinton is not that people sense she will raise taxes. It's that they don't think she'll raise them on the real and truly rich. The rich are her friends. They contribute to her, dine with her, have access to her. They have an army of accountants. They're protected even from her. But she can stick it to others, and in the way of modern liberalism for roughly half a century now, one suspects she'll define affluence down. That she would hike taxes on people who make $150,000 a year."

You know, I think it's too bad that this fellow Ron Paul is so extreme that he has deliberately made himself totally unelectable. He has great Libertarian ideas; it's just that you don't overtly put these into your platform and expect to become a Convention Nominee.

I think this is turning out to be one of the most unremarkable Presidential Campaigns in modern history. Really, on all three sides of the aisle.