views:

21

answers:

2

I've recently been tasked with fixing a rather nasty bug resulting from the misuse of session state. We have an asp.net web application that runs on a single sever using inproc session state. The basic design is that a typed dataset is loaded from the database and stored in session state using a common session variable name like Session["dataset"] = dataset. After the data is stored in the session the user edits the data, dataset is retrieved from the session updated and sent to the database for updating. This type of data editing\storing is used across multiple webforms that basically do the same thing. All is good until a user tries to launch a second instance of the application and data stored within the session variable can get mixed up.

Here are the possible fixes that I've been able to find

  1. Set sessionState cookieless="false" (every new instance gets a unique session id) PROS - easiest solution, almost no code changes needed CONS - guid in url, user can edit guid, guid can be copied

  2. Use a custom session key for every instance (pass a session key around and combine it the "dataset" + session key name so that each instance has a unique session variable) PROS - no guid in url CONS - most amount of code changes, possibly fragile

  3. Remove the session variable (Load the dataset from the database a second time for editing) PROS- frees up server resources, no longer dependent upon session state CONS - performance hit, high amount of code changes

Anyone know of any other possible solutions? Thanks

A: 

Well, the only way to guarantee that two instances won't access the same sessionstate is to do something with the url/POST-data. That's what you have to play with.

Easiest is probably going to be to use cookieless=true, and hope that all url:s get rewritten correctly. Best will probably be to just access the database directly, most likely it won't affect as much as you think, and if it affects, you really shouldn't cache a lot of data per user, instead you should use a global cache.

Onkelborg
I agree, caching data per user is bad. That is why I'm trying to fix it. When you say use a "global cache" I'm not sure what you mean. I've used an application cache for application wide data, but how would that work for data that is loaded per user?
Eric
Global is relative, per application is what I thought :) If you really, really have to have per-user data, you can save that data with a key that's connected to the user. But again, I don't recommend a cache unless you really have performance problems
Onkelborg
A: 

You state that the third option would be a performance hit (remove the session object altogether), but have you tried it?

I ask, because serialising a standard dataset is notoriously resource intensive on the server side - the memory footprint can increase by an order of magnitude in many cases (a 1MB dataset can take 10-15MB to serialise), as well as processor time to do this.

I'd really recommend looking at trying 3 and testing to see if your concerns are well founded, or if you actually see a performance gain ;)

If you are set on storing datasets in session, then you should look at custom serialisation to minimise the amount of data stored.

Zhaph - Ben Duguid
I have not tried removing session object and reloading the data, I will give it a try.
Eric
Just as a side note it looks like the dataset is stored in session using Session["dataset"] = dataset.GetXml(). Not sure if that is any different than just direct serialization.
Eric
In proc session state doesn't serialize, but it appears that seralization is forced though..
Onkelborg
@Onkelborg - that's a good point that I missed. Although clearly my psychic powers were strong, as Eric admitted in his comment to calling .GetXML which will clearly serialise it ;).
Zhaph - Ben Duguid