Can't get viewstate to work

M

multiformity

The following page will not load the view state from the statebag
without throwing an exception. After we get this working, I will be
working on viewstate for some custom controls, but one thing at a time.


using System;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
/// <summary>
/// Simple test of view state, we are trying to persist the value for i
among multiple postbacks.
/// </summary>
/*
Use the following ASPX page to test this class:
**********************************************
<%@ Page language="c#" AutoEventWireup="false" Inherits="TestPostback"
CodeFile="TestPostback.aspx.cs" EnableViewState="true" %>
<HTML>
<body>
<form runat="server" id="GridForm">
<asp:placeHolder ID="_Content" Runat="server" />
<br />
<asp:Literal ID=_Literal runat=server />
</form>
</HTML>
***********************************************
*/
public partial class TestPostback : Page {

private int i;

override protected void OnInit(EventArgs e) {
this.EnableViewState = true;
this.Load += new EventHandler(Page_Load);
base.OnInit(e);
_Content.EnableViewState = true;
}

protected override void LoadViewState(object savedState) {
try {
//This line throws an exception,
//and the viewstate collection is empty
i = (int)ViewState["index"];
_Literal.Text = (string)ViewState["text"];
base.LoadViewState(savedState);
} catch { }
}

protected override object SaveViewState() {
ViewState["index"] = i;
ViewState["text"] = _Literal.Text;
return base.SaveViewState();
}

protected void Page_Load(object sender, System.EventArgs e) {
++i;
Button button = new Button();
button.Click += new EventHandler(button_Click);
button.Text = "Click";
_Content.Controls.Add(button);
}

void button_Click(object sender, EventArgs e){
//We will note here that the _Literal controls state
//has persisted, but the index has not incremented.
_Literal.Text += i.ToString() + "<br />";
}
}
 
W

Will Asrari

i = (int)ViewState["index"];

try...

i = Int.Parse(ViewState["index"].ToString());
 
M

multiformity

After looking into it further I found that the ViewState colletion's
count is 0 every time that the LoadViewState method is called.

I also verified the order that the methods are firing

(open page)
Page Load, SaveViewState

(button click)
LoadViewState, Page Load, button Click, SaveViewState

(button click)
LoadViewState, Page Load, button Click, SaveViewState

(repeat)

I commented all of this and have a modified program that should just
spit out the current location of the progress in the Literals text
property, but it doesn't seem to be working, you can see it all at:

http://rafb.net/paste/results/RdHSXo56.html

I know it's a long program now, but a lot of that is just commenting
and stuff


AB
 
V

vMike

The following page will not load the view state from the statebag
without throwing an exception. After we get this working, I will be
working on viewstate for some custom controls, but one thing at a time.
*/
public partial class TestPostback : Page {

private int i;

override protected void OnInit(EventArgs e) {
this.EnableViewState = true;
this.Load += new EventHandler(Page_Load);
base.OnInit(e);
_Content.EnableViewState = true;
}


I think it is b/c your are looking for something in viewstate before your
have loaded it.
The LoadViewState is load from the page when it is posted back as I
understand it.
Also you should check the saveState before loading in as follows.

protected override void LoadViewState(object savedState)
{
if (savedState != null)
{
// Load State from the array of objects that was saved at ;
// SavedViewState.
object[] myState = (object[])savedState;
if (myState[0] != null)
base.LoadViewState(myState[0]);
if (myState[1] != null)
UserText = (string)myState[1];
if (myState[2] != null)
PasswordText = (string)myState[2];
}
}


The saveview state is what is saved to the page in the response.
protected override void LoadViewState(object savedState) {
try {
//This line throws an exception,
//and the viewstate collection is empty
i = (int)ViewState["index"];
_Literal.Text = (string)ViewState["text"];
base.LoadViewState(savedState);
} catch { }
}

protected override object SaveViewState() {
ViewState["index"] = i;
ViewState["text"] = _Literal.Text;
return base.SaveViewState();
}

protected void Page_Load(object sender, System.EventArgs e) {
++i;
Button button = new Button();
button.Click += new EventHandler(button_Click);
button.Text = "Click";
_Content.Controls.Add(button);
}

void button_Click(object sender, EventArgs e){
//We will note here that the _Literal controls state
//has persisted, but the index has not incremented.
_Literal.Text += i.ToString() + "<br />";
}
}
 
J

Jeff Dillon

And it looks like i is always an unitialized variable

After looking into it further I found that the ViewState colletion's
count is 0 every time that the LoadViewState method is called.

I also verified the order that the methods are firing

(open page)
Page Load, SaveViewState

(button click)
LoadViewState, Page Load, button Click, SaveViewState

(button click)
LoadViewState, Page Load, button Click, SaveViewState

(repeat)

I commented all of this and have a modified program that should just
spit out the current location of the progress in the Literals text
property, but it doesn't seem to be working, you can see it all at:

http://rafb.net/paste/results/RdHSXo56.html

I know it's a long program now, but a lot of that is just commenting
and stuff


AB

Will said:
i = (int)ViewState["index"];

try...

i = Int.Parse(ViewState["index"].ToString());
 
M

multiformity

GRR

that was dumb, somethin is still wrong, but I got it working like so

override protected void OnInit(EventArgs e) {
this.EnableViewState = true;
//had to explicitly remove the enable view state for the label
_Literal.EnableViewState = false;
this.Load += new EventHandler(Page_Load);
base.OnInit(e);
_Content.EnableViewState = true;
}

protected override void LoadViewState(object savedState) {
//For some stupid reason I can access the saved state arraylist,
// but not the viewstate's collection
if (savedState != null) {
ArrayList list = (ArrayList)savedState;
try {
//I just happen to know that they are 1 and 3
//But why bother even haveing the viewstate then? I can
//write a specialized collection that does what the
//viewstate statebag does....
i = int.Parse(list[1].ToString());
_Literal.Text += list[3].ToString();
} catch (Exception ex) {
string junk = ex.Message;
_Literal.Text += ex.Message + "<br />";
}
}
base.LoadViewState(savedState);
}



complete listing here

http://rafb.net/paste/results/cGTR9O27.html

I am still interested in knowing why the viewstate doesn't work in the
load, is that supposed to be my job somehow?

AB
 
V

vMike

The following page will not load the view state from the statebag
without throwing an exception. After we get this working, I will be
working on viewstate for some custom controls, but one thing at a time.
I think it is because you can only use x = Viewstate("youritem") for things
that you put into view state. If you want to look at the rest of the view
state you have to do something like the following. (this is vb but you can
easily rewrite in c.

<%@ Page %>
<%@ import Namespace="System.Net" %>
<html>
<script language="vb" runat="server">

Protected Overrides Function SaveViewState() As Object
Return MyBase.SaveViewState()
End Function

Protected Overrides Sub LoadViewState(savedState As Object)
If Not (savedState Is Nothing) Then
MyBase.LoadViewState(savedState)
Response.write("<br>Viewstate as LoadViewState: " & Viewstate("Test"))
End If
End Sub

Sub Page_Load(sender as object, e as eventargs)
if not ispostback then
viewstate("Test") = "Not Postback"
response.write("<br>Viewstate at New: " & GetMruList())
else
dim strViewState as string = request.form("__Viewstate").tostring()
dim vdata as byte() = Convert.FromBase64String(strViewState)
dim strDecode as string = Encoding.ASCII.GetString(vdata)
response.write("<br>This is the coded viewstate " & strViewstate)
Response.write("<br>This is the decoded viewstate")
response.write(Server.HtmlEncode(strDecode))
end if
getdatactl()
end Sub

Function GetMruList() As String
Dim state As StateBag = ViewState
If state.Count > 0 Then
Dim upperBound As Integer = state.Count
Dim keys(upperBound) As String
Dim values(upperBound) As StateItem
state.Keys.CopyTo(keys, 0)
state.Values.CopyTo(values, 0)
Dim options As New StringBuilder()
Dim i As Integer
For i = 0 To upperBound - 1
options.append(keys(i) & " - " & values(i).value)
'options.AppendFormat("<option {0} value={1}>{2}",IIf(selectedValue
= keys(i), "selected", ""), keys(i), values(i).Value)
Next i
Return options.ToString()
End If
Return ""
End Function 'GetMruList

sub GetDataCtl()
dim i as int32
dim strI as string
dim j as int32 = 10
for i = 0 to j
strI = i.tostring()
dim imgCtl as new imagebutton
imgctl.imageurl = "/someimage.jpg"
imgctl.id = "img" + strI
imgctl.commandargument = "Hello" & strI
addhandler imgctl.click, addressof ImageButton1_Click
plc1.controls.add(imgctl)

next i
End sub

sub ImageButton1_Click(sender as object, e as ImageClickEventArgs)
viewstate("Test") = "Postback"
response.write("<br>ViewState as Click: " & GetMruList())
End sub
</script>
<body>
<form runat="server">
<asp:placeholder id="plc1" runat="server"/>
</form>
</body>
 
V

vMike

This may even be a bit better example. Watch what happens when you change
the dropdownlist.


<%@ Page Trace=false %>
<%@ import Namespace="System.Net" %>
<html>
<script language="vb" runat="server">

Protected Overrides Function SaveViewState() As Object
Return MyBase.SaveViewState()
End Function

Protected Overrides Sub LoadViewState(savedState As Object)
If Not (savedState Is Nothing) Then
MyBase.LoadViewState(savedState)
Response.write("<br>Viewstate as LoadViewState: " & Viewstate("Test"))
End If
End Sub

Sub Page_Load(sender as object, e as eventargs)
if not ispostback then
viewstate("Test") = "Not Postback"
response.write("<br>Viewstate at New: " & GetMruList())
else
dim strViewState as string = request.form("__Viewstate").tostring()
dim vdata as byte() = Convert.FromBase64String(strViewState)
dim strDecode as string = Encoding.ASCII.GetString(vdata)
response.write("<br>This is the coded viewstate " & strViewstate)
Response.write("<br>This is the decoded viewstate")
response.write(Server.HtmlEncode(strDecode))
end if
getdatactl()
end Sub

Function GetMruList() As String
Dim state As StateBag = ViewState
If state.Count > 0 Then
Dim upperBound As Integer = state.Count
Dim keys(upperBound) As String
Dim values(upperBound) As StateItem
state.Keys.CopyTo(keys, 0)
state.Values.CopyTo(values, 0)
Dim options As New StringBuilder()
Dim i As Integer
For i = 0 To upperBound - 1
options.append(keys(i) & " - " & values(i).value)
'options.AppendFormat("<option {0} value={1}>{2}",IIf(selectedValue
= keys(i), "selected", ""), keys(i), values(i).Value)
Next i
Return options.ToString()
End If
Return ""
End Function 'GetMruList

sub GetDataCtl()
dim i as int32
dim strI as string
dim j as int32 = 10
dim drpCtl as new DropDownList
drpCtl.AutoPostBack="True"
for i = 0 to j
strI = i.tostring()
dim imgCtl as new imagebutton

dim lst as new listitem("hello" + strI, stri)
drpCtl.items.add(lst)
imgctl.imageurl = "/someimage.jpg"
imgctl.id = "img" + strI
imgctl.commandargument = "Hello" & strI
addhandler imgctl.click, addressof ImageButton1_Click
plc1.controls.add(imgctl)

next i
addhandler drpCtl.SelectedIndexChanged, addressof DropList_Change
plc1.controls.add(drpCtl)
End sub

sub ImageButton1_Click(sender as object, e as ImageClickEventArgs)
viewstate("Test") = "Postback"
response.write("<br>ViewState as Click: " & GetMruList())
End sub

Sub DropList_Change(sender as object, e as eventargs)
viewstate("Test") = "Postback"
response.write("<br>ViewState as DropListChange: " & GetMruList())
End Sub
</script>
<body>
<form runat="server">
<asp:placeholder id="plc1" runat="server"/>
</form>
</body>
 
M

multiformity

I figured it out about 10 minutes after my last post, just didn't post
my new code.

Basically in the loadview state I had to call

base.LoadViewState(sender) before I did anything...

Now onto the component viewstate, which is going to be a little more
complicated I am sure, so keep an eye out for that one guys!


AB
 

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

Top