Viewstate Insanity

B

Big D

Hi all,

I have a web user control that I have turned into an abstract class that my
other controls will be inherriting from. The base class places 1 item in
the viewstate which is the controls current "edit mode" (to keep track of if
my control is in "edit mode" or "normal mode"). If I create a user control
that inherrits from this, and put it on a page, the control will display
properly (with the base classes 1 button). But clicking the button and
causing a postback generates an error... "Object reference not set to an
instance of an object", in refrence to the viewstate item. Here is what it
looks like:

protected enum editorModes{edit,normal}
protected editorModes CurrentMode
{
get { return (editorModes)ViewState["currentMode"];}
set
{
ViewState["currentMode"] = value;
setButtonText();
}
}

The set method of the current mode is DEFFINATELY being run during the base
classes Init. I have no idea how to tell if it's actually IN the viewstate
of the page or not, since it's just a bunch of "stuff". The error is during
postback, during the buttons "click" event, I attempt to retrieve the
currentMode, which calls "get { return
(editorModes)ViewState["currentMode"];}" and generates the error.

I had thought maybe you can't put an enumeration in the viewstate, and hav
tried the same approach with plain text, with the same result.

HELP!

Thanks!

-D
 
C

Cowboy \(Gregory A. Beamer\)

I do not think viewState is the best place for control state personally. I
would much rather make the control aware. The issue you are having may
relate to the order of events, which is generally where people get zapped.
Something is not getting set in the order you think it is.

--
Gregory A. Beamer
MVP; MCP: +I, SE, SD, DBA

**********************************************************************
Think Outside the Box!
**********************************************************************
 
T

Teemu Keiski

Hello,

Does the placing of the item happen on every request in the Init? I am just
tracking that everything you put to ViewState before TrackViewState is
called, is just initial value and won't actually be stored (Init happens
before view state tracking starts). Of course if this placing happens on
every request, (also at postback) the problem is elsewhere and then we would
need bit more information. Post bit more code or something

You might want to check this thread at ASP.NET Forums for reference:
http://www.asp.net/Forums/ShowPost.aspx?tabindex=1&PostID=293040

There's one long post where I've gathered things together and provided links
to another posts related to the same issues.

As another thing, in the getter of the property ,you might want to check
the ViewState("currentMode") for null reference before trying to cast it to
editorModes enum. If it is null return either value as default.

-
Teemu Keiski
MCP, Microsoft MVP (ASP.NET), AspInsiders member
ASP.NET Forum Moderator, AspAlliance Columnist
 
B

Big D

Well, here's the whole control. Sorry if it's a bit long, but I really
appreciate any help.

The viewstate's value is never requested prior to the button click event
which is well after init. Can you set the viewstate during init?

Here's the code:

public abstract class BaseFrontEndEditor : System.Web.UI.UserControl
{
#region " MEMBERS "

private Table tblMain = new Table();
private TableRow trButton = new TableRow();
private TableRow trContent = new TableRow();
private TableCell tcContent = new TableCell();
private TableCell tcButton = new TableCell();
protected Button btnEdit = new Button();
protected System.Web.UI.WebControls.PlaceHolder Output = new
PlaceHolder();
protected enum editorModes{edit,normal}
protected editorModes CurrentMode
{
get { return (editorModes)ViewState["currentMode"];}
set
{
ViewState["currentMode"] = value;
setButtonText();
}
}

internal bool showEditor
{
get
{
return true; }
}

#endregion


// FUNCTIONS //

public BaseFrontEndEditor()
{

//set properties of the table;
this.tblMain.CellPadding = 0; // new
System.Web.UI.WebControls.Unit("0px");
this.tblMain.CellSpacing = 0; //new
System.Web.UI.WebControls.Unit("0px");
this.tblMain.BorderWidth = 0; //new
System.Web.UI.WebControls.Unit("0px");
}

public void setButtonText()
{
switch (this.CurrentMode)
{
case(editorModes.edit) :
{btnEdit.Text = "Return"; break;}
case(editorModes.normal):
{btnEdit.Text = "EDIT"; break;}

}
}
private void Control_Init(object sender, System.EventArgs e)
{
if (! this.IsPostBack) this.CurrentMode = editorModes.normal;
//the edit button
this.EnableViewState = true;

btnEdit.ID = "btnEdit";
this.btnEdit.Click += new System.EventHandler(this.btnEdit_Click);
//check to see if the user is logged on, and if so, if they have edit
permissions
//if they have edit permissions, display the edit button.
if (this.showEditor)
{
//add the button to the table
this.tcButton.Controls.Add(btnEdit);
this.tcButton.HorizontalAlign = HorizontalAlign.Right;
this.trButton.Cells.Add(tcButton);
this.tblMain.Rows.Add(trButton);
this.tcContent.Controls.Add(this.Output);
this.trContent.Cells.Add(tcContent);
this.tblMain.Rows.Add(trContent);
this.Controls.Add(tblMain);
}
else
{
this.Controls.Add(this.Output);
}
}

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


#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);
}

/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{

this.Load += new System.EventHandler(this.Page_Load);
this.Init += new System.EventHandler(this.Control_Init);
}

#endregion

public void btnEdit_Click(object sender, System.EventArgs e)
{
Response.Write("EVENT HANDLER FIRED!<BR>");
switch (this.CurrentMode)
{
case editorModes.normal :
{this.CurrentMode = editorModes.edit;Response.Write("Ran the normal
Procedure... turned it to edit.");break;}
case editorModes.edit :
{this.CurrentMode = editorModes.normal;Response.Write("Ran the edit
procuedure... turned it to normal.");break;}
}
}
}

Teemu Keiski said:
Hello,

Does the placing of the item happen on every request in the Init? I am just
tracking that everything you put to ViewState before TrackViewState is
called, is just initial value and won't actually be stored (Init happens
before view state tracking starts). Of course if this placing happens on
every request, (also at postback) the problem is elsewhere and then we would
need bit more information. Post bit more code or something

You might want to check this thread at ASP.NET Forums for reference:
http://www.asp.net/Forums/ShowPost.aspx?tabindex=1&PostID=293040

There's one long post where I've gathered things together and provided links
to another posts related to the same issues.

As another thing, in the getter of the property ,you might want to check
the ViewState("currentMode") for null reference before trying to cast it to
editorModes enum. If it is null return either value as default.

-
Teemu Keiski
MCP, Microsoft MVP (ASP.NET), AspInsiders member
ASP.NET Forum Moderator, AspAlliance Columnist



Big D said:
Hi all,

I have a web user control that I have turned into an abstract class that my
other controls will be inherriting from. The base class places 1 item in
the viewstate which is the controls current "edit mode" (to keep track
of
if
my control is in "edit mode" or "normal mode"). If I create a user control
that inherrits from this, and put it on a page, the control will display
properly (with the base classes 1 button). But clicking the button and
causing a postback generates an error... "Object reference not set to an
instance of an object", in refrence to the viewstate item. Here is what it
looks like:

protected enum editorModes{edit,normal}
protected editorModes CurrentMode
{
get { return (editorModes)ViewState["currentMode"];}
set
{
ViewState["currentMode"] = value;
setButtonText();
}
}

The set method of the current mode is DEFFINATELY being run during the base
classes Init. I have no idea how to tell if it's actually IN the viewstate
of the page or not, since it's just a bunch of "stuff". The error is during
postback, during the buttons "click" event, I attempt to retrieve the
currentMode, which calls "get { return
(editorModes)ViewState["currentMode"];}" and generates the error.

I had thought maybe you can't put an enumeration in the viewstate, and hav
tried the same approach with plain text, with the same result.

HELP!

Thanks!

-D
 
T

Teemu Keiski

Oh yes,

in the Control_Init change this line:

if (! this.IsPostBack) this.CurrentMode = editorModes.normal;

to

this.CurrentMode = editorModes.normal;

As I explained, values set before TrackViewState are not stored to
ViewState, so if you put something on initlal request to ViewState at Init,
it won't be there by the postback. That behavior can't be changed. Note that
loading the ViewState happens somewhat after TrackViewState (on postback) so
if you change something to ViewState property, it will be loaded by the time
you check for the proeprty and things works (i.e if you wonder why the
editorMode changes even if you set it to normal at Init on every request,
but after it is changed to the proeprty, LoadViewState will override the
initial value if there is something in ViewState for the property)

Just to give idea, here's the page/control lifecycle:

1. Instantiate
2. Initialize
3. TrackViewState
4. LoadViewState (postback)
5. Load postback data (postback, IPostBackDatahandler.LoadPostdata)
6. Load
7. Load postback data for dynamical controls added on Page_Load
8. Raise Changed Events (postback,
IPostBackDatahandler.RaisePostDataChanged)
9. Raise postback event (postback, IPostBackEventHandler.RaisePostBackEvent)
10.PreRender
11. SaveViewState
12. Render
13. Unload
14. Dispose

I still recommend you to read at least this:
http://www.asp.net/Forums/ShowPost.aspx?tabindex=1&PostID=148634 to
understand how it works.

--
Teemu Keiski
MCP, Microsoft MVP (ASP.NET), AspInsiders member
ASP.NET Forum Moderator, AspAlliance Columnist



Big D said:
Well, here's the whole control. Sorry if it's a bit long, but I really
appreciate any help.

The viewstate's value is never requested prior to the button click event
which is well after init. Can you set the viewstate during init?

Here's the code:

public abstract class BaseFrontEndEditor : System.Web.UI.UserControl
{
#region " MEMBERS "

private Table tblMain = new Table();
private TableRow trButton = new TableRow();
private TableRow trContent = new TableRow();
private TableCell tcContent = new TableCell();
private TableCell tcButton = new TableCell();
protected Button btnEdit = new Button();
protected System.Web.UI.WebControls.PlaceHolder Output = new
PlaceHolder();
protected enum editorModes{edit,normal}
protected editorModes CurrentMode
{
get { return (editorModes)ViewState["currentMode"];}
set
{
ViewState["currentMode"] = value;
setButtonText();
}
}

internal bool showEditor
{
get
{
return true; }
}

#endregion


// FUNCTIONS //

public BaseFrontEndEditor()
{

//set properties of the table;
this.tblMain.CellPadding = 0; // new
System.Web.UI.WebControls.Unit("0px");
this.tblMain.CellSpacing = 0; //new
System.Web.UI.WebControls.Unit("0px");
this.tblMain.BorderWidth = 0; //new
System.Web.UI.WebControls.Unit("0px");
}

public void setButtonText()
{
switch (this.CurrentMode)
{
case(editorModes.edit) :
{btnEdit.Text = "Return"; break;}
case(editorModes.normal):
{btnEdit.Text = "EDIT"; break;}

}
}
private void Control_Init(object sender, System.EventArgs e)
{
if (! this.IsPostBack) this.CurrentMode = editorModes.normal;
//the edit button
this.EnableViewState = true;

btnEdit.ID = "btnEdit";
this.btnEdit.Click += new System.EventHandler(this.btnEdit_Click);
//check to see if the user is logged on, and if so, if they have edit
permissions
//if they have edit permissions, display the edit button.
if (this.showEditor)
{
//add the button to the table
this.tcButton.Controls.Add(btnEdit);
this.tcButton.HorizontalAlign = HorizontalAlign.Right;
this.trButton.Cells.Add(tcButton);
this.tblMain.Rows.Add(trButton);
this.tcContent.Controls.Add(this.Output);
this.trContent.Cells.Add(tcContent);
this.tblMain.Rows.Add(trContent);
this.Controls.Add(tblMain);
}
else
{
this.Controls.Add(this.Output);
}
}

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


#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);
}

/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{

this.Load += new System.EventHandler(this.Page_Load);
this.Init += new System.EventHandler(this.Control_Init);
}

#endregion

public void btnEdit_Click(object sender, System.EventArgs e)
{
Response.Write("EVENT HANDLER FIRED!<BR>");
switch (this.CurrentMode)
{
case editorModes.normal :
{this.CurrentMode = editorModes.edit;Response.Write("Ran the normal
Procedure... turned it to edit.");break;}
case editorModes.edit :
{this.CurrentMode = editorModes.normal;Response.Write("Ran the edit
procuedure... turned it to normal.");break;}
}
}
}

Teemu Keiski said:
Hello,

Does the placing of the item happen on every request in the Init? I am just
tracking that everything you put to ViewState before TrackViewState is
called, is just initial value and won't actually be stored (Init happens
before view state tracking starts). Of course if this placing happens on
every request, (also at postback) the problem is elsewhere and then we would
need bit more information. Post bit more code or something

You might want to check this thread at ASP.NET Forums for reference:
http://www.asp.net/Forums/ShowPost.aspx?tabindex=1&PostID=293040

There's one long post where I've gathered things together and provided links
to another posts related to the same issues.

As another thing, in the getter of the property ,you might want to check
the ViewState("currentMode") for null reference before trying to cast it to
editorModes enum. If it is null return either value as default.

-
Teemu Keiski
MCP, Microsoft MVP (ASP.NET), AspInsiders member
ASP.NET Forum Moderator, AspAlliance Columnist



Big D said:
Hi all,

I have a web user control that I have turned into an abstract class
that
my
other controls will be inherriting from. The base class places 1 item in
the viewstate which is the controls current "edit mode" (to keep track
of
if
my control is in "edit mode" or "normal mode"). If I create a user control
that inherrits from this, and put it on a page, the control will display
properly (with the base classes 1 button). But clicking the button and
causing a postback generates an error... "Object reference not set to an
instance of an object", in refrence to the viewstate item. Here is
what
it
looks like:

protected enum editorModes{edit,normal}
protected editorModes CurrentMode
{
get { return (editorModes)ViewState["currentMode"];}
set
{
ViewState["currentMode"] = value;
setButtonText();
}
}

The set method of the current mode is DEFFINATELY being run during the base
classes Init. I have no idea how to tell if it's actually IN the viewstate
of the page or not, since it's just a bunch of "stuff". The error is during
postback, during the buttons "click" event, I attempt to retrieve the
currentMode, which calls "get { return
(editorModes)ViewState["currentMode"];}" and generates the error.

I had thought maybe you can't put an enumeration in the viewstate, and hav
tried the same approach with plain text, with the same result.

HELP!

Thanks!

-D
 
B

Big D

Thanks a million! I think execution order is one of the harder things about
web apps. ;-(

lol!

:)
Teemu Keiski said:
Oh yes,

in the Control_Init change this line:

if (! this.IsPostBack) this.CurrentMode = editorModes.normal;

to

this.CurrentMode = editorModes.normal;

As I explained, values set before TrackViewState are not stored to
ViewState, so if you put something on initlal request to ViewState at Init,
it won't be there by the postback. That behavior can't be changed. Note that
loading the ViewState happens somewhat after TrackViewState (on postback) so
if you change something to ViewState property, it will be loaded by the time
you check for the proeprty and things works (i.e if you wonder why the
editorMode changes even if you set it to normal at Init on every request,
but after it is changed to the proeprty, LoadViewState will override the
initial value if there is something in ViewState for the property)

Just to give idea, here's the page/control lifecycle:

1. Instantiate
2. Initialize
3. TrackViewState
4. LoadViewState (postback)
5. Load postback data (postback, IPostBackDatahandler.LoadPostdata)
6. Load
7. Load postback data for dynamical controls added on Page_Load
8. Raise Changed Events (postback,
IPostBackDatahandler.RaisePostDataChanged)
9. Raise postback event (postback, IPostBackEventHandler.RaisePostBackEvent)
10.PreRender
11. SaveViewState
12. Render
13. Unload
14. Dispose

I still recommend you to read at least this:
http://www.asp.net/Forums/ShowPost.aspx?tabindex=1&PostID=148634 to
understand how it works.

--
Teemu Keiski
MCP, Microsoft MVP (ASP.NET), AspInsiders member
ASP.NET Forum Moderator, AspAlliance Columnist



Big D said:
Well, here's the whole control. Sorry if it's a bit long, but I really
appreciate any help.

The viewstate's value is never requested prior to the button click event
which is well after init. Can you set the viewstate during init?

Here's the code:

public abstract class BaseFrontEndEditor : System.Web.UI.UserControl
{
#region " MEMBERS "

private Table tblMain = new Table();
private TableRow trButton = new TableRow();
private TableRow trContent = new TableRow();
private TableCell tcContent = new TableCell();
private TableCell tcButton = new TableCell();
protected Button btnEdit = new Button();
protected System.Web.UI.WebControls.PlaceHolder Output = new
PlaceHolder();
protected enum editorModes{edit,normal}
protected editorModes CurrentMode
{
get { return (editorModes)ViewState["currentMode"];}
set
{
ViewState["currentMode"] = value;
setButtonText();
}
}

internal bool showEditor
{
get
{
return true; }
}

#endregion


// FUNCTIONS //

public BaseFrontEndEditor()
{

//set properties of the table;
this.tblMain.CellPadding = 0; // new
System.Web.UI.WebControls.Unit("0px");
this.tblMain.CellSpacing = 0; //new
System.Web.UI.WebControls.Unit("0px");
this.tblMain.BorderWidth = 0; //new
System.Web.UI.WebControls.Unit("0px");
}

public void setButtonText()
{
switch (this.CurrentMode)
{
case(editorModes.edit) :
{btnEdit.Text = "Return"; break;}
case(editorModes.normal):
{btnEdit.Text = "EDIT"; break;}

}
}
private void Control_Init(object sender, System.EventArgs e)
{
if (! this.IsPostBack) this.CurrentMode = editorModes.normal;
//the edit button
this.EnableViewState = true;

btnEdit.ID = "btnEdit";
this.btnEdit.Click += new System.EventHandler(this.btnEdit_Click);
//check to see if the user is logged on, and if so, if they have edit
permissions
//if they have edit permissions, display the edit button.
if (this.showEditor)
{
//add the button to the table
this.tcButton.Controls.Add(btnEdit);
this.tcButton.HorizontalAlign = HorizontalAlign.Right;
this.trButton.Cells.Add(tcButton);
this.tblMain.Rows.Add(trButton);
this.tcContent.Controls.Add(this.Output);
this.trContent.Cells.Add(tcContent);
this.tblMain.Rows.Add(trContent);
this.Controls.Add(tblMain);
}
else
{
this.Controls.Add(this.Output);
}
}

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


#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);
}

/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{

this.Load += new System.EventHandler(this.Page_Load);
this.Init += new System.EventHandler(this.Control_Init);
}

#endregion

public void btnEdit_Click(object sender, System.EventArgs e)
{
Response.Write("EVENT HANDLER FIRED!<BR>");
switch (this.CurrentMode)
{
case editorModes.normal :
{this.CurrentMode = editorModes.edit;Response.Write("Ran the normal
Procedure... turned it to edit.");break;}
case editorModes.edit :
{this.CurrentMode = editorModes.normal;Response.Write("Ran the edit
procuedure... turned it to normal.");break;}
}
}
}

Teemu Keiski said:
Hello,

Does the placing of the item happen on every request in the Init? I am just
tracking that everything you put to ViewState before TrackViewState is
called, is just initial value and won't actually be stored (Init happens
before view state tracking starts). Of course if this placing happens on
every request, (also at postback) the problem is elsewhere and then we would
need bit more information. Post bit more code or something

You might want to check this thread at ASP.NET Forums for reference:
http://www.asp.net/Forums/ShowPost.aspx?tabindex=1&PostID=293040

There's one long post where I've gathered things together and provided links
to another posts related to the same issues.

As another thing, in the getter of the property ,you might want to check
the ViewState("currentMode") for null reference before trying to cast
it
to
editorModes enum. If it is null return either value as default.

-
Teemu Keiski
MCP, Microsoft MVP (ASP.NET), AspInsiders member
ASP.NET Forum Moderator, AspAlliance Columnist



Hi all,

I have a web user control that I have turned into an abstract class that
my
other controls will be inherriting from. The base class places 1
item
in
the viewstate which is the controls current "edit mode" (to keep
track
of
if
my control is in "edit mode" or "normal mode"). If I create a user
control
that inherrits from this, and put it on a page, the control will display
properly (with the base classes 1 button). But clicking the button and
causing a postback generates an error... "Object reference not set
to
an
instance of an object", in refrence to the viewstate item. Here is what
it
looks like:

protected enum editorModes{edit,normal}
protected editorModes CurrentMode
{
get { return (editorModes)ViewState["currentMode"];}
set
{
ViewState["currentMode"] = value;
setButtonText();
}
}

The set method of the current mode is DEFFINATELY being run during the
base
classes Init. I have no idea how to tell if it's actually IN the
viewstate
of the page or not, since it's just a bunch of "stuff". The error is
during
postback, during the buttons "click" event, I attempt to retrieve the
currentMode, which calls "get { return
(editorModes)ViewState["currentMode"];}" and generates the error.

I had thought maybe you can't put an enumeration in the viewstate,
and
hav
tried the same approach with plain text, with the same result.

HELP!

Thanks!

-D
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,014
Latest member
BiancaFix3

Latest Threads

Top