In order to really push the efficiency of your ASP.NET application, I recommend using the HttpContext.Cache object for data that rarely changes. One thing I was experiencing with a high volume site was seemingly random errors to do with accessing cached objects. Consider the following simple example:
if (HttpContext.Current.Cache[“myObject”] != null) Control ctrl = (Control) HttpContext.Current.Cache[“myObject”];
This seems foolproof: first you check if the object is in the cache, and only retrieve it if it is. The problem is that the Cache is accessed in a multi-threaded environment, and so there could be potentially thousands of separate web requests happening at once for this object, with some of them perhaps clearing the cache and re-adding a new copy. It’s entirely possible for the cache to become null in the microsecond between checking for existence and actually retrieving from it. To make this matter worse, it’s a bug that will likely not be caught until on production with heavy traffic, and is very hard to duplicate effectively. So the simple way to handle this (without messing with locks) would be to first retrieve into an object, check that object for null, and then cast it:
object cachedCtrl = HttpContext.Current.Cache[“myObject”]; if (cachedCtrl != null) Control ctrl = (Control) cachedCtrl;
Always Set an Expiration on a Cache
In order to avoid the dreaded OutofMemoryException, you should make sure you are not loading too much into the cache. One way of doing this is to place a rolling timeout on your cached object. That way if it’s not being used frequently it will automatically be discarded to free up memory for other activities:
HttpContext.Current.Cache.Insert(“MyObject”, myObject, null, System.Web.Caching.Cache.NoAbsoluteExpiration, TimeSpan.FromHours(1));
If you are experiencing OutOfMemoryExceptions because of this sort of situation, a quick fix would be to clear the Application Pool for that application in IIS. You can then configure the app pool to automatically recycle the working process after it has consumed too much memory. Open up IIS Manager and right click the associated Application Pool:
Obviously this should be considered a temporary fix until you are able to test and push out a new version of code with more long term fixes.
On HttpContext and NUnit
Working directly with HttpContext makes writing Unit Tests difficult. When NUnit runs, it doesn’t have the same ASP.NET HttpContext to work with, and thus will throw an error when you try to access it in your code. Instead of accessing HttpContext directly, lately I’ve used a facade-type object that mimics the interface of HttpContext. If the context is available, it returns that, and if not, it returns simple collections for storing cache etc. I just found an excellent implementation by Phillip J Haack that does this better than my code, so I will direct you there instead of posting my version: Simulating Http Context For Unit Tests Without Using Cassinni nor IIS.



How does retrieving into an object avoid the issue?
Well, when you retrieve into an object, you aren’t going back a second time to the cache to actually work with the cached item. This avoids a race condition in that rare time that the value of the cache changes in the microsecond between checking if it is null and actually using it.
This pattern is also explained here:
http://scottcate.mykb.com/Article_5CB26.aspx
I actually second guessed myself about this after your comment, thinking that maybe retrieving into an object would be only a reference. But no, when you retrieve the cached item into an object, if the cache changes after that, it won’t affect the value of the object. So you know for sure that if you check that the object is not null, then it isn’t going to change on you a second later.