1

我有一个包含多个控件的页面,例如 Checkboxlists 和两个保存搜索结果的容器。

我被告知要使该站点持久化,因此用户可以在浏览我们的站点时从任何地方返回并找到它的设置已恢复(阅读:框已选中;结果仍然可用)

到目前为止,我已经尝试覆盖 SavePageStateToPersistenceMedium 和 LoadPageStateFromPersistenceMedium,但是当我单击页面上的一个按钮时,我经常会遇到黄屏死机。

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];
}

我的代码有什么问题吗?我需要调用什么来检索 Page_Load 或 Page_init 上的 Viewstate 来检索它?

编辑:这是通过 session["xyz"] 解决它的方法

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

        Session.Add("SavedLevelItems", selectItems);

//然后在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;
            }
        }
    }

但是,如果我查看搜索结果,然后只触发 GET 以返回初始页面,则所有存储的项目都不会正确呈现。

4

3 回答 3

2

根据这个:

因此用户可以在浏览我们的网站时从任何地方返回并发现它的设置已恢复(阅读:框已选中;结果仍然可用)

仅当您在同一页面上时,视图状态才有效。它用于记住跨回发的页面状态。如果您导航到另一个页面,之前的页面视图状态将丢失。您无法更改此行为。

您正在寻找的是ASP.Net 配置文件

我只是回答一个相关的问题:

将html的状态保存到数据库

于 2012-08-10T12:22:48.847 回答
1

你的方法有几个困难。

直接的问题是您__VIEWSTATE在方法中手动添加了“”隐藏字段SavePageStateToPersistenceMedium。这会导致在发送到浏览器的 html 页面中呈现两个空的隐藏字段。由于您正在覆盖该方法,因此该页面将自动发送一个空的此类字段。

但是您的方法的一个更大的问题是该LoadPageStateFromPersistenceMedium方法仅在页面检测到回发时才被页面调用。

通常,如果用户在您的站点(或其他站点)上执行其他操作,然后返回到您的页面,您的页面将重新加载(常规 GET,因此它不是回发)。因此,您为相关页面缓存的任何视图状态都不会被加载。

为了解决您的问题,我认为您不必存储页面的整个视图状态,而是只存储足够的信息来重新绑定/重新初始化页面上的控件。然后,当页面加载并且它不是回发时,您可以获取保存的状态Page_Load并重新初始化页面。

要存储状态,您可以使用几种可能的状态容器中的任何一种,包括:

  • 会议
  • 缓存
  • Sql server 或其他自定义进程外存储
  • 配置文件(就像 Jupaol 建议的那样,这至少是存储在 sql 数据库中的“默认”Asp.Net 提供程序)
于 2012-08-10T14:33:20.590 回答
0

最终解决方案非常简单。我只需要一些控件的状态而不是整个页面,因为结果可能随时改变。

问题是,CheckBoxLists 的数据源是在 aspx 文件中定义的。这导致当我尝试通过 Page_Load() 访问控件时没有加载任何项目。

所以我将整个数据访问逻辑转移到文件后面的代码中,包裹在一个 if 语句中。如果合适的会话对象可用,则数据源是会话对象,否则从数据库中获取。

 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();
        }
    }
}

亲切的问候

于 2012-08-13T08:22:55.250 回答