Using a Page object within a Page object

K

Kevin Phifer

Ok, before anyone freaks out, I have a solution I need to
create that gathers content from maybe different places.
Each one can return a <form> in the html, so its the
classic can't have more than one runat=server form on a
asp.net page. However, I still want developers to be able
to use asp.net controls to create some apps that are
created on the page. So I need multiple forms on a
asp.net page(doesn't everyone). I purchased the Wilson
Webform deal that got me started, but not quite all the
way there. My basic problems is when I tell the seperate
page to render it does, but the viewstate calls return
nothing....here comes some code:

the Page Class I created as follows, some comments inline

public class MyPage:System.Web.UI.Page
{
StringBuilder _myStringBuilder;
public MyPage():base()
{
_myStringBuilder = new
StringBuilder();
}

public StringBuilder myStringBuilder
{
get{return _myStringBuilder;}
}

protected override object
LoadPageStateFromPersistenceMedium()
{
return Session["ViewState" +
this.ID];
}
protected override void
SavePageStateToPersistenceMedium(object viewState)
{
//here is where my problem begins, when called
//viewstate == null
Session["ViewState" + this.ID] =
viewState;
}

protected override void Render
(System.Web.UI.HtmlTextWriter writer)
{
//I "steal" the html because if i don't it
//shows up on my main page
_myStringBuilder = new
StringBuilder();
System.IO.StringWriter sw = new
System.IO.StringWriter(_myStringBuilder);
System.Web.UI.HtmlTextWriter htw =
new System.Web.UI.HtmlTextWriter(sw);
base.Render (htw);
}

protected override void OnInit(EventArgs e)
{
//wilson form says I have to do this not sure
base.OnInit (e);
this.RegisterViewStateHandler();
}






-=-=-=-=-
Ok that being the Page class I create my page and execute
it with the following:

in the code behind page.....

private void Page_Load(object sender, System.EventArgs e)
{
// Put user code to initialize the
page here
MyPage myPage = new MyPage();
myPage.ID = "word";
myPage.EnableViewState=true;
myPage.Load+=new EventHandler
(myPage_Load);

System.Web.UI.HtmlControls.HtmlForm myForm = new
System.Web.UI.HtmlControls.HtmlForm();
myForm.ID = "myForm";
myPage.Controls.Add(myForm);
((IHttpHandler)
myPage).ProcessRequest(Context);

Literal1.Text =
myPage.myStringBuilder.ToString();
}


private void myPage_Load(object sender,
EventArgs e)
{
TextBox t1 = new TextBox();
t1.AutoPostBack=true;
t1.ID = "myTextBox";

((System.Web.UI.HtmlControls.HtmlForm)
((System.Web.UI.Page)sender).FindControl
("myForm")).Controls.Add(t1);

}

}

This all works great, textbox gets the postback info and
everything, the only thing is that viewstate object
in "protected override void
SavePageStateToPersistenceMedium(object viewState)" comes
back as null.

Anyone have any idea, I assume I'm not calling the Page
object correctly, or somehow need to instantiate the
viewstate or something. I've been fighting this for a
week now. Any suggestions would be greatly appreciated....

Thanx in advance...
 
M

MSFT

Hi Kevin,

Thank you for posting in MS Newsgroup. I am trying to find proper resource
to assist you on this issue and will update you as soon as posible.

Regards,

Luke
Microsoft Online Support

Get Secure! www.microsoft.com/security
(This posting is provided "AS IS", with no warranties, and confers no
rights.)
 
S

Steven Cheng[MSFT]

Hi Kevin,


Thank you for using Microsoft Newsgroup Service. Based on your description,
you created a custom page class which override the Method when Loading and
saving the page's viewstate. Also, you use this class to render another
form tag in a asp.net page which have a original form tag. However, when
you run the page and fire the textbox's change event , there occured the
"The viewstate is invalid for this page and might be corrupted" exception.
And you thought it caused by the ViewState which is not correctly loaded
from "session" where you manually stored the viewstate of the custom page
in. Please correct me if my understanding of your problem is not quite
exact.

I've read the code you provided and also had some tests on my side. Yes, I
also encountered the problem you mentioned. However, I don't think it is
because the viewstated not correctly retrieved from "session". I've add
some break points in the "LoadPageStateFromPersistenceMedium()" method, in
fact, when the exception occured, the runtime even hasn't entered this
function. That is said, the exception occured before retrieving data from
viewstate. I think the exception is likely caused by the ASP.NET runtime's
validation for the viewstate:

When an ASP.NET page receives a post, it checks for a field called
__VIEWSTATE (that's 2 underscore symbols) in the post. ASP.NET is using
this field for many reasons, most outside the scope of this article. But,
one thing the __VIEWSTATE field does contain is internal validation for
ASP.NET. If you simply post the __VIEWSTATE field to a different ASP.NET
page, than the page that filled the __VIEWSTATE field, ASP.NET will throw
an exception:

"The viewstate is invalid for this page and might be corrupted."

Since in the test page, we after rendering and view its html source in IE,
you could find that there will be two form tags in it and both has the
postback client script functions but only the original page's form tag has
the _VIEWSTATE hidden area. Thus, when the page is post back via those
postback client functions(not submit). That'll cause the ASP.NET runtime to
check the viewstate and found that the _VIEWSTATE doesn't match the
"page"(in fact, the two form tags will be processed using two different
page class) , so the "The viewstate is invalid for this page and might be
corrupted." came out.

I think you may try remove the "_VIEWSTATE" hidden area ( just change its
name) using client side script before the post back event and also add
break points to trace the custom page class's viewstate opeations to see
whether the problem remain.

If you have any questions on it or if you have any new findings, please let
me know.


Steven Cheng
Microsoft Online Support

Get Secure! www.microsoft.com/security
(This posting is provided "AS IS", with no warranties, and confers no
rights.)
 
K

Kevin Phifer

Hi Steven,
thanx for the reply. I did leave out one part that the
page I was basing the main page on was a modified one too,
that got me past the corrupt viewstate error it is as
follows:

public class NVSPage:System.Web.UI.Page
{
public NVSPage():base()
{
}
protected override object
LoadPageStateFromPersistenceMedium()
{

return null;

}
protected override void
SavePageStateToPersistenceMedium(object viewState)
{


}


}


this is ok, because on the main page I don't care about
the viewstate....

now here comes the funny part, after many hours looking at
the base page class with Anakrino I finally relized
something, that the page was working correctly, but ran
across something wierd. That the textbox class isn't
holding state in my page class. If i replace my textbox
controls with calendars it works great. ie....

private void myPage_Load(object sender, EventArgs e)
{

//System.Web.UI.WebControls.TextBox t1 = new
System.Web.UI.WebControls.TextBox();
MyTextBox t1 = new MyTextBox();
t1.ID = "myTextBox";
t1.EnableViewState=true;
Calendar c1 = new Calendar();
c1.ID = "myCalender1";
Button b1 = new Button();
b1.ID="myButton1";

((System.Web.UI.HtmlControls.HtmlForm)
((System.Web.UI.Page)sender).FindControl
("myForm")).Controls.Add(t1);

((System.Web.UI.HtmlControls.HtmlForm)
((System.Web.UI.Page)sender).FindControl
("myForm")).Controls.Add(c1);

((System.Web.UI.HtmlControls.HtmlForm)
((System.Web.UI.Page)sender).FindControl
("myForm")).Controls.Add(b1);

}

but you may have noticed something else that I found out.
In this senerio everything works great with everything
else, but to get the textbox to work I had to create my
own textbox class, inherited from it. You may be
wondering why this works. I have no idea, because all I
did was create an inherited control, but added nothing to
it:

public class MyTextBox:System.Web.UI.WebControls.TextBox
{
public MyTextBox():base()
{

}


}

Thats it. This has to be a bug or something. It makes no
sense. Of course textboxes work great in pages create the
normal asp.net way, but for some reason, to create pages
the way I did it would not hold viewstate until i did
this. Why is this? Is there something else I'm not doing.

So In the end, I can do what I want which is to create
multiple page objects adding controls to them and
processing them, holding state correctly etc, except on
this case with the TextBox control. Wierd huh? Anyway
I'll go ahead and post almost all the code for you to look
at:


public class MyPage:System.Web.UI.Page
{
StringBuilder _myStringBuilder;
public MyPage():base()
{
_myStringBuilder = new
StringBuilder();
}

public StringBuilder myStringBuilder
{
get{return _myStringBuilder;}
}

protected override object
LoadPageStateFromPersistenceMedium()
{
Triplet thisisit = (Triplet)Session
["ViewState" + this.ID];
return Session["ViewState" +
this.ID];
}
protected override void
SavePageStateToPersistenceMedium(object viewState)
{
Triplet thisisit = (Triplet)
viewState;
Session["ViewState" + this.ID] =
viewState;
}

protected override void Render
(System.Web.UI.HtmlTextWriter writer)
{
_myStringBuilder = new
StringBuilder();
System.IO.StringWriter sw = new
System.IO.StringWriter(_myStringBuilder);
System.Web.UI.HtmlTextWriter htw =
new System.Web.UI.HtmlTextWriter(sw);
base.Render (htw);
_myStringBuilder.Replace
("__doPostBack","__doPostBack" + this.ID);
}

protected override void OnInit(EventArgs e)
{
base.OnInit (e);
this.RegisterViewStateHandler();
}

protected override void AddParsedSubObject
(object obj)
{
base.AddParsedSubObject (obj);
}





}
public class NVSPage:System.Web.UI.Page
{
public NVSPage():base()
{
}
protected override object
LoadPageStateFromPersistenceMedium()
{

return null;

}
protected override void
SavePageStateToPersistenceMedium(object viewState)
{


}


}

public class WebForm1 : Anothersomething.NVSPage
{
protected
System.Web.UI.WebControls.Literal Literal1;

private void Page_Load(object sender,
System.EventArgs e)
{
// Put user code to initialize the
page here
MyPage myPage = new MyPage();
myPage.ID = "word";
myPage.EnableViewState=true;
myPage.Load+=new EventHandler
(myPage_Load);

System.Web.UI.HtmlControls.HtmlForm myForm = new
System.Web.UI.HtmlControls.HtmlForm();
myForm.ID = "myForm";
myPage.Controls.Add(myForm);
((IHttpHandler)
myPage).ProcessRequest(Context);

Literal1.Text =
myPage.myStringBuilder.ToString();


myPage = new MyPage();
myPage.ID = "word2";
myPage.EnableViewState=true;
myPage.Load+=new EventHandler
(myPage2_Load);
myForm = new
System.Web.UI.HtmlControls.HtmlForm();
myForm.ID = "myForm2";
myPage.Controls.Add(myForm);
((IHttpHandler)
myPage).ProcessRequest(Context);

Literal1.Text +=
myPage.myStringBuilder.ToString();


}

#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.Load += new
System.EventHandler(this.Page_Load);

}
#endregion

private void myPage_Load(object sender,
EventArgs e)
{

//System.Web.UI.WebControls.TextBox t1 = new
System.Web.UI.WebControls.TextBox();
MyTextBox t1 = new MyTextBox();
t1.ID = "myTextBox";
t1.EnableViewState=true;
Calendar c1 = new Calendar();
c1.ID = "myCalender1";
Button b1 = new Button();
b1.ID="myButton1";



((System.Web.UI.HtmlControls.HtmlForm)
((System.Web.UI.Page)sender).FindControl
("myForm")).Controls.Add(t1);

((System.Web.UI.HtmlControls.HtmlForm)
((System.Web.UI.Page)sender).FindControl
("myForm")).Controls.Add(c1);

((System.Web.UI.HtmlControls.HtmlForm)
((System.Web.UI.Page)sender).FindControl
("myForm")).Controls.Add(b1);

}
private void myPage2_Load(object sender,
EventArgs e)
{

//System.Web.UI.WebControls.TextBox t1 = new
System.Web.UI.WebControls.TextBox();
MyTextBox t1 = new MyTextBox();
t1.ID = "myTextBox2";
t1.EnableViewState=true;
Calendar c1 = new Calendar();
c1.ID = "myCalender2";
Button b1 = new Button();
b1.ID="myButton2";

((System.Web.UI.HtmlControls.HtmlForm)
((System.Web.UI.Page)sender).FindControl
("myForm2")).Controls.Add(t1);

((System.Web.UI.HtmlControls.HtmlForm)
((System.Web.UI.Page)sender).FindControl
("myForm2")).Controls.Add(c1);

((System.Web.UI.HtmlControls.HtmlForm)
((System.Web.UI.Page)sender).FindControl
("myForm2")).Controls.Add(b1);

}
}

public class MyTextBox:System.Web.UI.WebControls.TextBox
{
public MyTextBox():base()
{

}


}
-----Original Message-----
Hi Kevin,


Thank you for using Microsoft Newsgroup Service. Based on your description,
you created a custom page class which override the Method when Loading and
saving the page's viewstate. Also, you use this class to render another
form tag in a asp.net page which have a original form tag. However, when
you run the page and fire the textbox's change event , there occured the
"The viewstate is invalid for this page and might be corrupted" exception.
And you thought it caused by the ViewState which is not correctly loaded
from "session" where you manually stored the viewstate of the custom page
in. Please correct me if my understanding of your problem is not quite
exact.

I've read the code you provided and also had some tests on my side. Yes, I
also encountered the problem you mentioned. However, I don't think it is
because the viewstated not correctly retrieved from "session". I've add
some break points in
the "LoadPageStateFromPersistenceMedium()" method, in
 
S

Steven Cheng[MSFT]

Hi Kevin,


Thank you for the prompt response. I'm glad that you've found the main
problem in our issue. Yes, I did found that something strange with the
TextBox since I've add a Button correctly in the former test. And as you
said that you got it work correctly when using a custom TextBox just
inherit from the dotnet buildin class, I'm also a bit puzzled with this
situation. Maybe this is really an issue of the ASP.NET since we seldom use
a page object like this, hehe. Any way, I'll keep this issue in mind.
Thanks again for the information you provided.


Steven Cheng
Microsoft Online Support

Get Secure! www.microsoft.com/security
(This posting is provided "AS IS", with no warranties, and confers no
rights.)
 

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

Staff online

Members online

Forum statistics

Threads
473,995
Messages
2,570,230
Members
46,816
Latest member
SapanaCarpetStudio

Latest Threads

Top