Home » none » Modifying Copies of a Session Object

Modifying Copies of a Session Object

spider This morning I woke up to the following question in my inbox:

I am storing an object into session. Then in one of my functions I am copying that session object into a local object and doing some modifications to the local object. But I can see all those changes made into session object also. How to avoid this?

There is so much here to unpack in this question that I don’t think I can deal with it all in one post.  Fortunately, I’ve already dealt with many of the issues.  So as a prerequisite, you should read these articles that I’ve already written about session variables and objects:

The difference between Objects and Values

To fully understand the answer to the question above, you must first understand exactly what is happening under the hood when you assign one variable to another.  Actually, to be an excellent programmer, you really need to understand what is happening under the hood as much as possible.

.NET has two fundamental types of variables.  There are Objects and Value Types.  Value Types are types like int, double, decimal, boolean, and char, to name a few.  It also includes all enumeration types and all structures.  They all derive from the class, ValueType in our object hierarch.  Whenever you assign a variable that is a type of ValueType, you are creating a copy of that variable automatically.

int i;
i = 5;
int j;
j = i;

In the code above int i, and int j both create areas in memory large enough to hold an integer.  When we declare the variable, .NET initializes that area to zero.  However, you can tell the compiler to treat an uninitialized variable as a zero as undefined.  When we do the assignment we are basically saying, “Take whatever is on the right side of the assignment and put it in the space allocated to the variable on the left side.  So all Value Type variable assignments are copies by definition.

What trips up new programmers is that they expect Object types to work the same way.

When I create an object, what I am really doing is creating a variable that points to memory to hold the object.  You might think this sounds the same, but there is a very subtle difference.  A Value IS the memory location.  A pointer only points to the memory location.  The variable is the name we’ve given to the memory location.

The reason this distinction is important is because of what happens when we assign one Object variable to another.

object i;
i = new object();
object j;
j = i;

In the code above object i and object j both create an area in memory large enough to hold a pointer to an object.  It isn’t until we say, “new object()” that memory for the object is allocated.

The line:

i = new object();

1) creates memory for the object and assigns the pointer to that object to i.  Two entirely different memory areas.

The line:

j = i;

Copies the pointer that we’ve labeled “i” to the pointer we’ve labeled “j”, so that anything we do to j will be reflected in i because they are both referring to the same object.

What’s this got to do with Session variables?

Session variables are object pointers.  When you say,

object i;
i = new object();
Session["varname"] = i;
object j;
j = Session["varname"];

What you are saying is, create an object and make i point to it.  Copy the pointer in “i” to the pointer Session[“varname”].  And then ultimately, copy the pointer in Session[“varname”] and put it in the variable “j”.  But at the end of the code, Session[“varname”], i and j are all pointing at the same object so that anything you do with one variable is reflected in all of the other variables because they are all pointing to the same object.

So what is the answer?

To work with a copy of a session variable, or any other variable that is pointing to an object, what you really want to do is to create a copy of the object first and then work with that.  The standard way of doing this in .NET is to create a method called Clone().

The clone method will:

  1. Create a new object using the same type that the object is in.
  2. Initialize all of the member variables to the same state as the object the Clone method is being called from.
  3. Return the new object.

So assuming we are working with the good ole’ Person object:

public class Person
{
    public string First { get; set; }
    public string Last { get; set; }
    public string Address { get; set; }
    public string City { get; set; }
    public string State { get; set; }
    public string Zip { get; set; }
}

our Clone() method would look like this:

public Person Clone()
{
    Person p = new Person();
    p.First = this.First;
    p.Last = this.Last;
    p.Address = this.Address;
    p.City = this.City;
    p.State = this.State;
    p.Zip = this.Zip;
    return p;
}

The Exception to the Rule

The observant reader will notice that I’m using Strings, which ARE object types and doing the very thing that I’ve already said we shouldn’t be able to do.  This is because String classes are immutable.  That is, any change we make to a string creates a new object by definition.  When our clone code above finishes we will have a new Person object, but the properties will all point to the same First, Last, Address, etc.. string.  If these strings had been any other type of object, we would have needed to clone those objects prior to assigning the pointer to the new object’s properties.

The impact of Session Servers on copies

To be honest, I don’t know if a session variable that is stored in a Session Server of some sort works exactly the same way as in-proc in that any object modifications made to an object in a session variable that was not cloned gets replicated back to the session server or we have to make an explicit call back up.  One hopes that .NET is smart enough to automatically store the state of the session object back to the session storage, regardless of where it is, right before it sends the page back to the client.  But I have no personal experience one way or the other.

Maybe someone can verify this for me in the comments.

Related Post

  • Multi-Step Processing in ASP.NETMulti-Step Processing in ASP.NET I received the following question a few days ago but I’ve been so busy with billable work that I just haven’t had a chance to answer it until now.  Actually, I’m still busy, but I […]
  • When Session Objects Get Created With No Session VariablesWhen Session Objects Get Created With No Session Variables I thought about calling this  Session Object Madness, but it really isn’t that crazy once you think through what’s happening. Here’s the issue.  I have a client who does work […]
  • HttpContext.Items[] vs Session[]HttpContext.Items[] vs Session[] Since .NET first became available, passing data around during a request has become a lot easier.  The ability to set a property has made that so.  Still, there are times when […]
  • Serializable attribute vs Serializable InterfaceSerializable attribute vs Serializable Interface Judging from the comments I received yesterday, it looks like we need to review  serialization in .NET.The Easy Way There are two ways of making an object serializable.  The […]
  • The case of the disappearing session variablesThe case of the disappearing session variables Way back in ASP.NET version 1.1, I wrote one of my first asp.net web sites for a client that depended pretty heavily on session variables.  Without getting into the arguments about the […]

About Dave Bush

Dave Bush is a Full Stack ASP.NET developer focusing on ASP.NET, C#, Node.js, JavaScript, HTML, CSS, BootStrap, and Angular.JS.Does your team need additional help in any of the above? Contact Dave today.