1

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.

1
  • See Think twice about using session state - it specifically states that session state is not the place to store user profile data. But I agree with @ChrisPratt, you should aim eliminate or minimize the use of session state rather than come up with elaborate ways to replace it. Commented Jan 23, 2017 at 18:56

1 Answer 1

2

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.

Sign up to request clarification or add additional context in comments.

5 Comments

asp.net uses one thread per (writable) session limiting the users on one request at a time. this is something i would like to prevent. Could you specify why my data doesn't belong to the session (dropdown values for example).
That's simply not correct. I'm not sure where you got that information. As far as why you shouldn't use session for that data, well in general you should use sessions for very little, period. If data belongs to a particular user, you can simply get it from the user again later. Sessions should only be used for data specific to anonymous users that actually needs to be persisted between requests. Something like drop down choices checks none of those boxes. You may want to cache it, to avoid a roundtrip to the DB, but it doesn't belong in the session.
@ChrisPratt - It is not correct to say that using ObjectCache won't scale out to multiple processes - you could use a distributed ObjectCache to handle that. But is it worth the extra effort than using out-of-process Session State or something like Redis? Probably not.
@NightOwl888: I was careful to say MemoryCache, not memory cache, in general. MemoryCache/ObjectCache does not scale, period. You can use something like memcached as the linked answer suggests, but then you're not using MemoryCache/ObjectCache any more. There was technically AppFabric Caching, as well, but that has been deprecated.
@NightOwl888: Also, the "effort" involved in using Redis, at least, is ridiculously small. I switched out all my caching and even session state storage to Redis in like 5 minutes, and most of that was just fixing API access, where I really should have abstracted the caching destination to begin with, i.e. my own laziness.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.