【问题标题】:Keeping the Viewstate persistent and retrieve it on demand保持 Viewstate 持久化并按需检索
【发布时间】:2012-08-13 16:22:55
【问题描述】:

我有一个包含多个控件的页面,例如 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 以返回初始页面,则所有存储的项目都不会正确呈现。

【问题讨论】:

    标签: c# asp.net viewstate asp.net-4.0


    【解决方案1】:

    据此:

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

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

    你要找的是ASP.Net profiles

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

    Save state of html to database

    【讨论】:

      【解决方案2】:

      你的方法有几个困难。

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

      但是你的方法的一个更大的问题是 LoadPageStateFromPersistenceMedium 方法只有在页面检测到回发时才会被页面调用。

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

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

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

      • 会话
      • 缓存
      • Sql 服务器或其他自定义进程外存储
      • 配置文件(就像 Jupaol 建议的那样,这至少是存储在 sql 数据库中的“默认”Asp.Net 提供程序)

      【讨论】:

      • @user1249641 尝试存储每个选定 ListItem 的值,而不是实际的列表项。然后在重新绑定时,您可以检查每个复选框,如果该框的值存在于会话中的存储状态中。
      【解决方案3】:

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

      问题是,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();
              }
          }
      }
      

      亲切的问候

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2013-09-17
        • 1970-01-01
        • 1970-01-01
        • 2016-11-14
        • 2016-02-29
        • 1970-01-01
        • 2012-02-18
        • 1970-01-01
        相关资源
        最近更新 更多