JoeJoe87577
JoeJoe87577

Reputation: 522

C# MVC using MemoryCache to replace Session

I want to build an MVC application that replaces the session object with the caching mechanism of .net framework 4.0.

The application has to store some values in some kind of cache to keep the database traffic and the loading times low (e.g. settings, dropdown values, etc.). The users authenticate themselfs with a username and a password. The default FormsAuthentication is used here. My idea was to create a unique MemoryCache for each user and a general MemoryCache for the application.

My getter for the User MemoryCache looks like this

private MemoryCache _memCache
{
    get
    {
        if(HttpContext.Application[User.Identity.Name] == null)
        {
            HttpContext.Application[User.Identity.Name] = new MemoryCache(User.Identity.Name);
        }

        return HttpContext.Application[User.Identity.Name] as MemoryCache;
    }
}

If a user logs out the cache will be disposed.

This is the global MemoryCache for the application

private MemoryCache _appMemCache
{
    get
    {
        if(HttpContext.Application["ApplicationMemoryCache"] == null)
        {
            HttpContext.Application["ApplicationMemoryCache"] = new MemoryCache("ApplicationMemoryCache");
        }

        return HttpContext.Application["ApplicationMemoryCache"] as MemoryCache;
    }
}

The question is if the Application object is usable to store the MemoryCache. And if the CacheItemPolicy works without problems with this.

The reason for me not to use the session is the possible timeout and the blocking of parallel request.

Upvotes: 1

Views: 2595

Answers (1)

Chris Pratt
Chris Pratt

Reputation: 239240

This is a bad idea for a number of reasons. First and foremost, MemoryCache is both volatile and process-bound. Some attempt will be made to keep Session data around, even if it's being stored in proc, but cache is considered completely disposable. If memory runs short, it will be discarded almost immediately. Also, this will effectively kill any ability to scale your app out to multiple workers (processes) as each would have it's on version of the cache, meaning whether the user's "session" was restored or not would depend on the luck of the draw of which process they landed on with their next request.

Your reasons for not just using session don't make any sense. Yes, sessions have timeouts, but these are somewhat fixed, assuming you're not using in proc. Even with in proc, the session will timeout at a fixed interval, as long as something like an App Pool recycle or similar does not occur. On the contrary, MemoryCache could go away at any time. There are no guarantees about how long the data would persist or if it would even persist at all. Just because you set it to stick around for a year, doesn't mean it won't be discarded in five minutes depending on what else is going on in the system.

As far as "blocking parallel requests" go, I'm not sure what you're talking about with that. The session is thread-safe and theoretically should allow parallel requests. There's always going to be concurrency issues with any asynchronous process like writing to a session store, but those same issues would exist with MemoryCache as well.

All that said, the things you're talking about saving actually don't belong in a session, anyways, though. While you're reasons for using something like MemoryCache are completely invalid, you should actually being using a cache to store this type of stuff. In other words, just use the cache and don't try to somehow replace the session with cache.

Also, as I mentioned previously, there's serious issues with MemoryCache in multiprocess scenarios. If you're building an app that will ever serve more than a handful of users, you should avoid MemoryCache entirely and use something like Redis instead. Redis is used by Microsoft Azure, so it has good support from Microsoft and integration into ASP.NET, but you could chooose any NoSQL solution.

Upvotes: 2

Related Questions