Using a Page object within a Page object

Discussion in 'ASP .Net' started by Kevin Phifer, Jan 2, 2004.

  1. Kevin Phifer

    Kevin Phifer Guest

    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...
    Kevin Phifer, Jan 2, 2004
    #1
    1. Advertising

  2. Kevin Phifer

    MSFT Guest

    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.)
    MSFT, Jan 3, 2004
    #2
    1. Advertising

  3. 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.)
    Steven Cheng[MSFT], Jan 5, 2004
    #3
  4. Kevin Phifer

    Kevin Phifer Guest

    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
    >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.)
    >
    >.
    >
    Kevin Phifer, Jan 5, 2004
    #4
  5. 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.)
    Steven Cheng[MSFT], Jan 6, 2004
    #5
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. KatB
    Replies:
    0
    Views:
    430
  2. mark4asp
    Replies:
    2
    Views:
    2,196
    Harry Haller
    Nov 7, 2006
  3. Elmo Watson
    Replies:
    1
    Views:
    583
    Eliyahu Goldin
    May 8, 2007
  4. Ultrus
    Replies:
    3
    Views:
    361
    Stefan Behnel
    Jul 9, 2007
  5. Abe
    Replies:
    2
    Views:
    158
Loading...

Share This Page