Keeping the Viewstate persistent and retrieve it o

2019-08-12 05:24发布

I've got a page with several controls, such as Checkboxlists and two containers holding search results.

I've been told to make this site persistent, so the user can come back from anywhere while browsing our site and find it's settings restored (read: boxes stll checked; results still available)

So far I have tried to override SavePageStateToPersistenceMedium and LoadPageStateFromPersitenceMedium, but I am constantly running into a yellow screen of death as soon, as I click a button on the page.

protected override void SavePageStateToPersistenceMedium(object viewState)
{
    string str = "VIEWSTATE_" + Request.UserHostAddress;
    Cache.Add(str, viewState, null, DateTime.Now.AddMinutes(Session.Timeout), TimeSpan.Zero, CacheItemPriority.Default, null);
    ClientScript.RegisterHiddenField("__VIEWSTATE_KEY", str);
    ClientScript.RegisterHiddenField("__VIEWSTATE", "");
}
protected override object LoadPageStateFromPersistenceMedium()
{
    string str = Request.Form["__VIEWSTATE_KEY"];
    if (!str.StartsWith("VIEWSTATE_"))
    {
        throw new Exception("Invalid viewstate key:" + str);
    }
    return Cache[str];
}

Is there anything wrong with my code and what would I need to call to retrieve the Viewstate on Page_Load or Page_init to retrieve it?

edit: Here is the approach to solve it via session["xyz"]

List<ListItem> selectItems = new List<ListItem>();
        foreach (ListItem item in CheckBoxListLevel.Items)
        {
            if (item.Selected)
                selectItems.Add(item);
        }

        Session.Add("SavedLevelItems", selectItems);

//And then in Page_Load

   if (Session["SavedLevelItems"] != null)
    {
        List<ListItem> SessionList = (List<ListItem>)Session["SavedLevelItems"];
        foreach (var item in SessionList)
        {
            if (item.Selected)
            {
                CheckBoxListLevel.Items.FindByText(item.Text).Selected = item.Selected;
            }
        }
    }

However, if I view a searchresult and then just fire a GET to get back to the initial page, all stored items are not rendered correctly.

3条回答
我想做一个坏孩纸
2楼-- · 2019-08-12 06:06

According to this:

so the user can come back from anywhere while browsing our site and find it's settings restored (read: boxes stll checked; results still available)

The viewstate works only while you are on the same page. It is used to remember the page state across postbacks. If you navigate to another page, the previous page viewstate will be lost. You cannot change this behavior.

What you are looking for is ASP.Net profiles

I just answer a related question:

Save state of html to database

查看更多
够拽才男人
3楼-- · 2019-08-12 06:08

There are several difficulties with your approach.

The immediate problem is that you are manually adding a "__VIEWSTATE" hiddenfield in the SavePageStateToPersistenceMedium method. This causes two empty hiddenfields to be rendered in the html page sent to the browser. The page will send one empty such field automatically since you are overriding the method.

But a bigger problem with your approach is that the LoadPageStateFromPersistenceMedium method is only called by the page if it detects a post back.

Typically, if a user has been doing something else on your site (or some other site for that matter) and then returns to your page, your page will be loaded fresh (a regular GET so it's not a post back). Therefore whatever viewstate you have cached away for the page in question will not be loaded.

To solve you problem, I think you will have to store not the whole viewstate of the page, but instead just enough information to rebind/reinitialize the controls on the page. Then when the page is loaded and it's not a post back you can grab the saved state in Page_Load and reinitialize the page.

To store state you can use any of several possible state containers including:

  • Session
  • Cache
  • Sql server or other custom out of process store
  • Profile (like Jupaol suggested, this is at least with the "default" Asp.Net providers stored in a sql database)
查看更多
时光不老,我们不散
4楼-- · 2019-08-12 06:09

The solution was pretty simple in the end. I only needed the state of some controls and not the whole page, since the results could change anytime.

The problem was, that the datasources for the CheckBoxLists was defined in the aspx file. this resulted in no items being loaded when I tried to access the controls via Page_Load().

So i transferred the whole data access logic to the code behind file, wrapped in an if statement. If a fitting session object is available the datasource is the session object, else take it from the database.

 protected void fillEntrylevelList()
{
    using (OleDbConnection connection = new OleDbConnection(ConfigurationManager.ConnectionStrings["TestEnvironment"].ConnectionString))
    {
        string EntrylevelQuery = @"INSERT SQL STATEMENT HERE";
        OleDbCommand command = new OleDbCommand(EntrylevelQuery, connection);
        if (Session["SavedLevelItems"] != null)
            {
                CheckBoxListLevel.Items.Clear();
                List<ListItem> SessionList = (List<ListItem>)Session["SavedLevelItems"];
                foreach (var item in SessionList)
                {
                    try
                    {
                        CheckBoxListLevel.Items.Add(item);
                    }
                    catch { }

                }
            }
        else
        {
            connection.Open();
            CheckBoxListLevel.DataTextField = "bez_level";
            CheckBoxListLevel.DataValueField = "id_level";
            OleDbDataReader ListReader = command.ExecuteReader();
            CheckBoxListLevel.DataSource = ListReader;
            CheckBoxListLevel.DataBind();
            ListReader.Close(); ListReader.Dispose();
            GC.Collect();
        }
    }
}

kind regards

查看更多
登录 后发表回答