Anyone Understand this?

I have been asking this question for some time but no one is responding.
Am I just and idiot?

-
-- First case
-
string var, var2;
var = "ABC";
var2 = var;

Session["myVarKey"] = var; // Out of Process - State Server "forces serialization"

var2 = "DEF";

var = Session["myVarKey"];

results:

var = "ABC" and var2 = "DEF"

I undersand this...strings are immutable.
But the foll0wing is just too wierd!

-- class def

[Serialziable]
public class Simple{
private string m_var;
public Name{
get{ return m_var;}
set{ m_var = value;}
}
}

-- Second case

Simple var, var2;

var = new Simple();
var.Name = "ABC";
Session["myVarKey"] = var; // Out of Process - State Server "forces serialization"
var2 = var;

var2.Name = "DEF"

var = (Simple)Session["myVarKey"] ;

results:

var.Name = "DEF" and var2.Name = "DEF"

Why? I mean this does the same thing with int or decimal etc...

Eric

[1114 byte] By [codefund.com] at [2007-12-16]
# 1
Well, I had to try it. This forum deals with Windows forms, so I crufted up a demo that uses serialization instead of the Session class to serialize the data. Guess what? I get the same response from both demonstrations. Here, try this form (with the same expert user interface for which I've become famous in these here parts <g>):

using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;
using System.Runtime.Serialization.Formatters.Binary;
using System.IO;

namespace WindowsApplication64
{
/// <summary>
/// Summary description for Form1.
/// </summary>
public class Form1 : System.Windows.Forms.Form
{
private System.Windows.Forms.Button button1;
private System.Windows.Forms.Button button2;
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.Container components = null;

public Form1()
{
//
// Required for Windows Form Designer support
//
InitializeComponent();

//
// TODO: Add any constructor code after InitializeComponent call
//
}

/// <summary>
/// Clean up any resources being used.
/// </summary>
protected override void Dispose( bool disposing )
{
if( disposing )
{
if (components != null)
{
components.Dispose();
}
}
base.Dispose( disposing );
}

#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.button1 = new System.Windows.Forms.Button();
this.button2 = new System.Windows.Forms.Button();
this.SuspendLayout();
//
// button1
//
this.button1.Location = new System.Drawing.Point(32, 24);
this.button1.Name = "button1";
this.button1.Size = new System.Drawing.Size(104, 32);
this.button1.TabIndex = 0;
this.button1.Text = "button1";
this.button1.Click += new System.EventHandler(this.button1_Click);
//
// button2
//
this.button2.Location = new System.Drawing.Point(32, 64);
this.button2.Name = "button2";
this.button2.Size = new System.Drawing.Size(104, 32);
this.button2.TabIndex = 1;
this.button2.Text = "button2";
this.button2.Click += new System.EventHandler(this.button2_Click);
//
// Form1
//
this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
this.ClientSize = new System.Drawing.Size(292, 273);
this.Controls.AddRange(new System.Windows.Forms.Control[] {
this.button2,
this.button1});
this.Name = "Form1";
this.Text = "Form1";
this.ResumeLayout(false);

}
#endregion

/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
Application.Run(new Form1());
}

private void button1_Click(object sender, System.EventArgs e)
{
String var1, var2;

var1 = "ABC";
var2 = var1;

Serialize(var1);

var2 = "DEF";

// Deserialize the value
var1 = (String)Deserialize();

MessageBox.Show(string .Format("var1 = {0} and var2 = {1}", var1, var2));

}

private void Serialize( object value)
{
BinaryFormatter bf = new BinaryFormatter();
FileStream fs = new FileStream("C:\\temp.dat", FileMode.Create);
bf.Serialize(fs, value);
fs.Close();
}

private object Deserialize()
{
BinaryFormatter bf = new BinaryFormatter();
object obj;
FileStream fs = new FileStream("C:\\temp.dat", FileMode.Open);
obj = bf.Deserialize(fs);
fs.Close();
return obj;
}

private void button2_Click(object sender, System.EventArgs e)
{
Simple var1, var2;
var1 = new Simple();

var1.Name = "ABC";
var2 = var1;

// Serialize the value.
Serialize(var1);

var2.Name = "DEF";

// Deserialize the value.
var1 = (Simple)Deserialize();

MessageBox.Show(string .Format("var1 = {0} and var2 = {1}", var1.Name, var2.Name));
}

}
[Serializable()]
class Simple
{
private string _name;
public string Name
{
get {return _name;}
set {_name = value;}
}
}
}

As you can see, running this gives the same results both times. That you're getting different results in your demonstration may be an artifact of something the Session class is doing, and is a question better suited for forums that focus on such things. It may also be an artifact of something else going on in your app, I suppose.

Let me know if you get different behavior than I do. As a tip: you'll get better results from folks who volunteer their time if you have an example people can simply cut/paste and try out, as in the example I've posted here. That way, we can just try it out as is, without having to craft an example to play with. Thanks!

codefund.com at 2007-9-8 > top of Msdn Tech,Windows Forms,Windows Forms General...
# 2
Ok...here is the code I used....

Remember this was accomplished using ASP.NET and not WinForms. I used the state server and out of process...

have an ASP.NET web page that has two simple buttons;
I'm running StateServer out of process.

1) Button 1 - STRING TEST
private void Button1_Click(object sender, System.EventArgs e)
{
string var;
string var2;

var = "FISH";
txtVar.Text = var.ToString();
var2 = var;
txtVar2.Text = var2.ToString();

Session[NEW_VAR] = var;

var2 = "PIG";
txtVar2Post.Text = var2.ToString();

var = (string)Session[NEW_VAR];

txtVarPost.Text = var.ToString();

}

RESULTS:
txtVar = "FISH"
txtVar2 = "FISH"
txtVar2Post = "PIG"
txtVarPost = "FISH"

Expectation is that they will NOT be the same.

Now if peroform the exact same pattern but using a class I get the following;

//
//CLASS DEF:
//

[SerializableAttribute]
public class Simple
{
public Simple(string name, int age)
{
Age = age;
Name = name;
}

private String m_name;
private int m_age;

// Name Propety
public String Name
{
get{
return m_name;
}
set{
m_name = value;
}
}

// Age Property
public int Age
{
get{
return m_age;
}
set{
m_age = value;
}
}
}

//
// BUTTON 2 EVENT
//

public void Button2_Click(object sender, System.EventArgs e)
{
Simple _obj1 = new Simple("NAME",15);
Simple _obj2;

txtAgeObj1.Text = _obj1.Age.ToString();
txtNameObj1.Text = _obj1.Name;

_obj2 = _obj1;

txtNameObj2.Text = _obj2.Name;
txtAgeObj2.Text = _obj2.Age.ToString();

// Serialize the _obj1
Session[OBJECT_VAL] = _obj1;

// Mod the data in _obj2
_obj2.Name = "NEW NAME";
_obj2.Age = 50;

txtNameMod1.Text = _obj1.Name;
txtAgeMod1.Text = _obj1.Age.ToString();

txtNameMod2.Text = _obj2.Name;
txtAgeMod2.Text = _obj2.Age.ToString();

// Get Seralized data
_obj1 = (Simple)Session[OBJECT_VAL];

txtNamePost1.Text = _obj1.Name;
txtAgePost1.Text = _obj1.Age.ToString();

txtNamePost2.Text = _obj2.Name;
txtAgePost2.Text = _obj2.Age.ToString()
}

RESULTS:
txtAgeObj1.Text= "15"
txtNameObj1.Text = "NAME"

txtAgeObj2.Text= "15"
txtNameObj2.Text = "NAME"

txtNameMod1.Text = "NEW NAME";
txtAgeMod1.Text = "50';

txtNameMod2.Text = "NEW NAME";
txtAgeMod2.Text = "50';

txtNamePost1.Text = "NEW NAME"
txtAgePost1.Text = "50";

txtNamePost2.Text = "NEW NAME";
txtAgePost2.Text = "50";

PONDERY:

Why in the second case are both Name Values the same? I mean you can clearly see that I have put the first object (_obj1) into "out of process" session, and then modifed the object reference (_obj2) and spit out the text to the screen. But when I pull the serialized object out of session it looks like it's just "re-referencing" it's self to the current processes reference (_obj2).

codefund.com at 2007-9-8 > top of Msdn Tech,Windows Forms,Windows Forms General...
# 3
Ken,

I'm going to try and re-create this code in ASP.NET and post this..so you or someone else can try it. Unfortunatley, it requires a bit of configuration.

ala...

WebConfig - out of proc "StateServer"
StateServer running

I reproduced this on 2 different machines both running the StateServer and out of process.

Thanks,

Eric

codefund.com at 2007-9-8 > top of Msdn Tech,Windows Forms,Windows Forms General...
# 4
Ok...here is the web page

using System;
using System.Collections;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Web;
using System.Web.SessionState;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.HtmlControls;
using System.Runtime.Serialization;

namespace ProcTester
{
/// <summary>
/// Summary description for WebForm1.
/// </summary>
public class WebForm1 : System.Web.UI.Page
{
protected System.Web.UI.WebControls.Button Button1;
protected System.Web.UI.WebControls.Button Button2;

private string var;
private string var2;

private void Page_Load(object sender, System.EventArgs e)
{
// Put user code to initialize the page here
}

#region Web Form Designer generated code
override protected void OnInit(EventArgs e)
{
//
// CODEGEN: This call is required by the ASP.NET Web Form Designer.
//
InitializeComponent();
base.OnInit(e);
}

/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.Button1.Click += new System.EventHandler(this.Button1_Click);
this.Button2.Click += new System.EventHandler(this.Button2_Click);
this.Load += new System.EventHandler(this.Page_Load);

}
#endregion

private void Button1_Click(object sender, System.EventArgs e)
{

this.Response.Clear();

///////////////////////////////////////////
/// Immutable strings
///////////////////////////////////////////
var = "ABC";
var2 = var;

Response.Write("- TEST 1 --<br>");
Response.Write("Var [ " + var + " ] - Var2 [ " + var2 + " ]<br>");
///////////////////////////////////////////
Session["myVarKey"] = var;
var2 = "DEF";

Response.Write("- STEP 2 --<br>");
Response.Write("Var [ " + var + " ] - Var2 [ " + var2 + " ]<br>");
///////////////////////////////////////////
var = (string)Session["myVarKey"];

Response.Write("- STEP 3 --<br>");
Response.Write("Var [ " + var + " ] - Var2 [ " + var2 + " ]<br>");

}

private void Button2_Click(object sender, System.EventArgs e)
{
this.Response.Clear();

Simple var, var2;

var = new Simple();
var.Name = "ABC";
var.Age = 12;

var2 = var;

Response.Write("- TEST 2 --<br>");
Response.Write("Var [ " + var.Name + " ] - Var2 [ " + var2.Name + " ]<br>");
Response.Write("Var [ " + var.Age + " ] - Var2 [ " + var2.Age + " ]<br>");
/////////////////////////////////////////////
Session["myVarKey"] = var;

var2.Name = "EFG";
var2.Age = 50;
/////////////////////////////////////////////
Response.Write("- STEP 1 --<br>");
Response.Write("Var [ " + var.Name + " ] - Var2 [ " + var2.Name + " ]<br>");
Response.Write("Var [ " + var.Age + " ] - Var2 [ " + var2.Age + " ]<br>");
/////////////////////////////////////////////
var = (Simple)Session["myVarKey"];

/////////////////////////////////////////////
Response.Write("- STEP 3 --<br>");
Response.Write("Var [ " + var.Name + " ] - Var2 [ " + var2.Name + " ]<br>");
Response.Write("Var [ " + var.Age + " ] - Var2 [ " + var2.Age + " ]<br>");

}

}

[Serializable]
public class Simple
{
private string m_name;
private int m_age;

public string Name
{
get{return m_name;}
set{m_name = value;}
}

public int Age
{
get{return m_age;}
set{m_age = value;}
}
}
}

You will need to add the following to your web.config

<sessionState mode="StateServer"
stateConnectionString="tcpip=127.0.0.1:42424"
sqlConnectionString="data source=127.0.0.1;user id=sa;password="
cookieless="true"
timeout="20"
/>

As well as insure the following services is running...
ASP.NET State Service - aspnet_state.exe

You can do this from the Services pannel.

Thanks!

And it is running out of process...you can comment out the serializable attribute and you will get and error...

Eric

codefund.com at 2007-9-8 > top of Msdn Tech,Windows Forms,Windows Forms General...
# 5
Ok...

Same results when using SQLServer as the out of process state server.

I'm really trying to understand why? So version of the Serializer would I be using in HTTP vrs WinForms?

I realize that the WinForm example that Ken most graciously supplied uses the BinaryFormatter. It's my understanding that the BinaryFormatter is very complete...the most...and then possibly the Formater that the Session services implement are not quite as complete.

The problem I have with it is that if I store a DataSet or a DataTable for that matter in Session - out of process again only....and then reassign it to a variable I'm using in code. "regardless if this is a good idea or not"...you will have problems.

Intersting....I will do a little work on examining the Serialization formatters.

eric

codefund.com at 2007-9-8 > top of Msdn Tech,Windows Forms,Windows Forms General...
# 6
Ok...I modified the Serializable implemenation on the Simple class by adding the cutsom ISerializable interface and the constructor and GetObject method. And sure enough the results are not what I had expected.

[Serializable]
public class Simple : ISerializable{

private string m_name;
private int m_age;

public Simple(){
}

public Simple(SerializationInfo info, StreamingContext context){
m_name = info.GetString("name");
m_age = info.GetInt16("age");
}

public virtual void GetObjectData(SerializationInfo info, StreamingContext context){
info.AddValue("name", m_name);
info.AddValue("age", m_age);
}

public string Name{
get{return m_name;}
set{m_name = value;}
}

public int Age{
get{return m_age;}
set{m_age = value;}
}
}

codefund.com at 2007-9-8 > top of Msdn Tech,Windows Forms,Windows Forms General...