[Okta Webinar] Learn how to a build a cloud-first strategyRegister Now

x
?
Solved

ViewState

Posted on 2009-04-20
10
Medium Priority
?
757 Views
Last Modified: 2012-05-06
Hi,
I have a site with a couple of pages. On one of them there is a bunch of data the visitor shall supply. If he leaves this page and then comes back all his work is gone. Which is the easiest way to persist the data as a whole. I have been looking at using VIEWSTATE but I can't figure out how to do. I would not like to save the individual controls but everything on the page.
Best regards
RTSol
0
Comment
Question by:RTSol
  • 4
  • 3
  • 2
  • +1
10 Comments
 
LVL 6

Expert Comment

by:DanielWillmott
ID: 24183968
I found this nice set of code to do what you are looking for. It saves the ViewState in cache and then will call it back up if the user goes back to the page and the current ViewState is empty. It overrides the 'SavePageStateToPersistenceMedium' and
'LoadPageStateFromPersistenceMedium' methods of the page. (C#)
protected override void SavePageStateToPersistenceMedium(Object viewState)
{
string _vskey;
_vskey = "VIEWSTATE_" + base.Session.SessionID + "_" + Request.RawUrl + 
"_" + System.DateTime.Now.Ticks.ToString();
 
Cache.Add(_vskey, viewState, null, 
System.DateTime.Now.AddMinutes(Session.Timeout), Cache.NoSlidingExpiration, 
CacheItemPriority.Default, null);
 
RegisterHiddenField("_VIEWSTATE_KEY", _vskey);
}
 
protected override object LoadPageStateFromPersistenceMedium()
{
string _vskey = Request.Form["_VIEWSTATE_KEY"];
 
if (_vskey == null)
{
return null; 
}
else
{
return Cache[_vskey];
}
}

Open in new window

0
 

Author Comment

by:RTSol
ID: 24184636
Hi,
I tried the code but I am not sure how to use it. I made a small site with two pages containing a textbox and a drop down. I have attached the code in one of the pages. When I first call the page SavePageStateToPersistenceMedium is fired. When I change the drop down (Which has postpack enabled) first LoadPageStateFromPersistenceMedium() is fired and then  SavePageStateToPersistenceMedium is fired. When I leave the page neither of the mehtods are fired. Cab you help me out?
-RTSol
Page 1
 
<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Test1.aspx.cs" Inherits="Test1" %>
 
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
 
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title></title>
</head>
<body>
    <form id="form1" runat="server">
    <div>
        <asp:HyperLink ID="HyperLink1" runat="server" NavigateUrl="~/Test1.aspx">Test1</asp:HyperLink>&nbsp;
        <asp:HyperLink ID="HyperLink2" runat="server" NavigateUrl="~/Test2.aspx">Test2</asp:HyperLink>
    </div>
    </form>
</body>
</html>
 
Page 2
 
<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Test2.aspx.cs" Inherits="Test2" %>
 
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
 
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title></title>
</head>
<body>
    <form id="form1" runat="server">
    <div>
        <asp:HyperLink ID="HyperLink1" runat="server" NavigateUrl="~/Test1.aspx">Test1</asp:HyperLink>&nbsp;
        <asp:HyperLink ID="HyperLink2" runat="server" NavigateUrl="~/Test2.aspx">Test2</asp:HyperLink>
        <br /><br /><asp:TextBox ID="TextBox1" runat="server"></asp:TextBox>
        <br /><br />
        <asp:DropDownList ID="DropDownList1" runat="server" AutoPostBack="True">
            <asp:ListItem>first value</asp:ListItem>
            <asp:ListItem>second value</asp:ListItem>
        </asp:DropDownList>
    </div>
    </form>
</body>
</html>
 
Code in page 2
 
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.Caching;
 
public partial class Test2 : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {
 
    }
    protected override void SavePageStateToPersistenceMedium(Object viewState)
    {
        string _vskey;
        _vskey = "VIEWSTATE_" + base.Session.SessionID + "_" + Request.RawUrl +
        "_" + System.DateTime.Now.Ticks.ToString();
 
        Cache.Add(_vskey, viewState, null,
        System.DateTime.Now.AddMinutes(Session.Timeout), Cache.NoSlidingExpiration,
        CacheItemPriority.Default, null);
 
        RegisterHiddenField("_VIEWSTATE_KEY", _vskey);
    }
 
    protected override object LoadPageStateFromPersistenceMedium()
    {
        string _vskey = Request.Form["_VIEWSTATE_KEY"];
 
        if (_vskey == null)
        {
            return null;
        }
        else
        {
            return Cache[_vskey];
        }
    }
}

Open in new window

0
 
LVL 6

Expert Comment

by:DanielWillmott
ID: 24184661
When you go to a different page somewhere and then go to the page above, the LoadPageStateFromPersistenceMedium whould fire and load the page state from the Cache value. Did you try that?
0
VIDEO: THE CONCERTO CLOUD FOR HEALTHCARE

Modern healthcare requires a modern cloud. View this brief video to understand how the Concerto Cloud for Healthcare can help your organization.

 

Author Comment

by:RTSol
ID: 24184769
Yes - I tried that, but the first thing that fires when you enter the page is SavePageStateToPersistenceMedium which seems a bit backwards. The firing sequence is as I described in my previous post.
-RTSol
0
 
LVL 26

Assisted Solution

by:Anurag Thakur
Anurag Thakur earned 800 total points
ID: 24184977
0
 
LVL 7

Expert Comment

by:vbwizardry
ID: 24185230
The problem that I see in code is that if you live the page the next time you come back there will be no "_VIEWSTATE_KEY" since it has not been generated yt. (Unless you come back by using back button on web browser). So perhaps a better way to store you data in in the session. However what I think you want to do is this:

        public override PageStatePersister GetStatePersister() {
            return new CacheStatePersister(this.Page);
        }
 
 
        [System.Web.AspNetHostingPermission(System.Security.Permissions.SecurityAction.Demand, Level = System.Web.AspNetHostingPermissionLevel.Minimal)]
        private class CacheStatePersister : System.Web.UI.PageStatePersister
        {
 
            public CacheStatePersister(Page page)
                : base(page)
            { }
 
            private string CatchID
            {
                get
                {
                    return (Page.Session.SessionID + "_" + Page.Request.RawUrl + "_" + DateTime.Now.Date.Ticks);
                }
            }
 
            public override void Load()
            {
                var state = Page.Cache[CatchID] as Pair;
                if (state == null)
                {
                    base.ViewState = null;
                    return;
                }
                base.ViewState = state.First;
                base.ControlState = state.Second;
            }
 
            public override void Save()
            {
                if (ViewState != null || ControlState != null)
                {
                    if (Page.Cache == null)
                    { throw new InvalidOperationException("Caching is not enabled!"); }
                    Page.Cache.Remove(CatchID);
 
                    Page.Cache.Add(
                        CatchID,
                        new Pair(ViewState, ControlState),
                        null,
                        DateTime.Now.AddMinutes(Page.Session.Timeout),
                        TimeSpan.Zero,
                        System.Web.Caching.CacheItemPriority.Default,
                        null);
                }
            }
        }

Open in new window

0
 

Author Comment

by:RTSol
ID: 24191568
Hi vbwizardry,

I tried your piece of code but got the following error when building: Test2.GetStatePersister()': no suitable method found to override

Can you help me out? I attached the code.

Best regards
RTSol
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.Caching;
 
public partial class Test2 : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {
 
    }
    public override PageStatePersister GetStatePersister()
    {
        return new CacheStatePersister(this.Page);
    }
 
 
    [System.Web.AspNetHostingPermission(System.Security.Permissions.SecurityAction.Demand, Level = System.Web.AspNetHostingPermissionLevel.Minimal)]
    private class CacheStatePersister : System.Web.UI.PageStatePersister
    {
 
        public CacheStatePersister(Page page)
            : base(page)
        { }
 
        private string CatchID
        {
            get
            {
                return (Page.Session.SessionID + "_" + Page.Request.RawUrl + "_" + DateTime.Now.Date.Ticks);
            }
        }
 
        public override void Load()
        {
            var state = Page.Cache[CatchID] as Pair;
            if (state == null)
            {
                base.ViewState = null;
                return;
            }
            base.ViewState = state.First;
            base.ControlState = state.Second;
        }
 
        public override void Save()
        {
            if (ViewState != null || ControlState != null)
            {
                if (Page.Cache == null)
                { throw new InvalidOperationException("Caching is not enabled!"); }
                Page.Cache.Remove(CatchID);
 
                Page.Cache.Add(
                    CatchID,
                    new Pair(ViewState, ControlState),
                    null,
                    DateTime.Now.AddMinutes(Page.Session.Timeout),
                    TimeSpan.Zero,
                    System.Web.Caching.CacheItemPriority.Default,
                    null);
            }
        }
    }
}

Open in new window

0
 
LVL 7

Expert Comment

by:vbwizardry
ID: 24195647
That because I used a PageAdapter. You need to override PageStatePersister in your page behind code.
        protected override System.Web.UI.PageStatePersister PageStatePersister
        {
            get
            {
                return new CacheStatePersister(this.Page);
            }
        }

Open in new window

0
 
LVL 7

Accepted Solution

by:
vbwizardry earned 1200 total points
ID: 24196346
Here is the full code.
    public partial class _Default : System.Web.UI.Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {
        }
 
        protected override PageStatePersister PageStatePersister
        {
            get
            {
                return new CacheStatePersister(this);
            }
        }
 
        protected override System.Collections.Specialized.NameValueCollection DeterminePostBackMode()
        {
            var id = CatchID;
            var value = base.DeterminePostBackMode();
            if (value == null)
            {
                var mode = Session[id] as System.Collections.Specialized.NameValueCollection;
                if (mode != null)
                {
                    Debug.Print("Load saved PostBack");
                    return mode;
                }
            }
            Debug.Print("Use existing PostBack");
            Session[id] = value;
            return value;
        }
 
        [System.Web.AspNetHostingPermission(System.Security.Permissions.SecurityAction.Demand, Level = System.Web.AspNetHostingPermissionLevel.Minimal)]
        private class CacheStatePersister : System.Web.UI.PageStatePersister
        {
 
            private string CatchID
            {
                get
                {
                    return (Page.Session.SessionID + "_" + Page.GetType().FullName + "_" + DateTime.Now.Date.Ticks).ToUpper();
                }
            }
 
            public CacheStatePersister(Page page)
                : base(page)
            { }
            
            public override void Load()
            {
                var id = CatchID;
                Debug.WriteLine("Persister load: " + id);
                var state = Page.Cache[id] as Pair;
                if (state == null)
                {
                    base.ViewState = null;
                    return;
                }
                base.ViewState = state.First;
                base.ControlState = state.Second;
            }
 
            public override void Save()
            {
                var id = CatchID;
                if (ViewState != null || ControlState != null)
                {
                    Debug.WriteLine("Persister save: " + id);
                    if (Page.Cache == null)
                    { throw new InvalidOperationException("Caching is not enabled!"); }
                    Page.Cache.Remove(id);
 
                    Page.Cache.Add(
                        id,
                        new Pair(ViewState, ControlState),
                        null,
                        DateTime.Now.AddMinutes(Page.Session.Timeout),
                        TimeSpan.Zero,
                        System.Web.Caching.CacheItemPriority.Default,
                        null);
                }
            }
        }
 
        private string CatchID
        {
            get
            {
                return (Page.Session.SessionID + "_" + Page.GetType().FullName + "_" + DateTime.Now.Date.Ticks).ToUpper();
            }
        }
 
    }

Open in new window

0
 

Author Closing Comment

by:RTSol
ID: 31572186
Thanks Guys,
I appreciate your effort and I am happy. I will use the solution provided by vbwizardry. The article in the codeproject given by ragi0017 was very enlightening.
Best regards
RTSol
0

Featured Post

Free Tool: IP Lookup

Get more info about an IP address or domain name, such as organization, abuse contacts and geolocation.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Entity Framework is a powerful tool to help you interact with the DataBase but still doesn't help much when we have a Stored Procedure that returns more than one resultset. The solution takes some of out-of-the-box thinking; read on!
It was really hard time for me to get the understanding of Delegates in C#. I went through many websites and articles but I found them very clumsy. After going through those sites, I noted down the points in a easy way so here I am sharing that unde…
In a question here at Experts Exchange (https://www.experts-exchange.com/questions/29062564/Adobe-acrobat-reader-DC.html), a member asked how to create a signature in Adobe Acrobat Reader DC (the free Reader product, not the paid, full Acrobat produ…
When cloud platforms entered the scene, users and companies jumped on board to take advantage of the many benefits, like the ability to work and connect with company information from various locations. What many didn't foresee was the increased risk…
Suggested Courses

834 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question