views:

29

answers:

1

Hi. I'm using Session variables inside a web service to maintain state between successive method calls by an external application called QBWC. I set this up by decorating my web service methods with this attribute:

[WebMethod(EnableSession = true)]

I'm using the Session variable to store an instance of a custom object called QueueManager. The QueueManager has a property called ChangeQueue which looks like this:

 [Serializable]
 public class QueueManager
 {
  ...
  public Queue<QBChange> ChangeQueue { get; set; }
  ...

where QBChange is a custom business object belonging to my web service.

Now, every time I get a call to a method in my web service, I use this code to retrieve my QueueManager object and access my queue:

QueueManager qm = (QueueManager)Session[ticket];

then I remove an object from the queue, using

qm.dequeue()

and then I save the modified query manager object (modified because it contains one less object in the queue) back to the Session variable, like so:

Session[ticket] = qm; 

ready for the next web service method call using the same ticket.

Now here's the thing: if I comment out this last line

//Session[ticket] = qm;

, then the web service behaves exactly the same way, reducing the size of the queue between method calls. Now why is that?

The web service seems to be updating a class contained in serialized form in a Session variable without being asked to. Why would it do that? When I deserialize my Queuemanager object, does the qm variable hold a reference to the serialized object inside the Session[ticket] variable?? This seems very unlikely.

A: 

All reference types (such as classes) are stored in memory as references and Session State is also (normally) stored in memory, but can also be stored to a file or a database. When storing reference types in Session, you should almost always ensure they are Serializable as well.

QueueManager is a reference type, so all the Session[ticket] is doing is holding a reference to it in memory. You do not need to re-assign to it as the Session variable itself IS the item that you're modifying.

This is just a simplified version of what you're doing:

Session["Foo"] = new Bar();
Bar rar = (Bar)Session["Foo"];
rar.Count = 1;

if (((Bar)Session["Foo"]).Count == 1)
{
    // Great success!
}
GenericTypeTea
I see. I was under the impression that the entire object was actually serialized when put into a Session variable. What about an object in ViewState, then? Is that fully serialized between page calls, or does the ViewState hold just a reference to the object? And assuming that what you say is correct, then why is the Serializable attribute required to place an object in Session, then?
draconis
It's not always required for the class to be serializable for it to be in session. It depends on how your Session management is configured on the server. I believe it works the same way through viewstate, however the class MUST be serializable as the ViewState (StateBag) actually serializes and deserializes the object. When you call and cast the class through the ViewState, it gets deserialized.
GenericTypeTea
Is your explanation only valid for in-process session state, or is it generic? If the session state were configured to Out-of-process mode or SqlServer mode, would it still be true that only a reference to an object is held in a session variable?
draconis