【问题标题】:Saving webControls in the Session object将 webControls 保存在 Session 对象中
【发布时间】:2012-03-02 03:33:45
【问题描述】:

我有一个面板 (pnlPanel),其中包含许多控件,例如 Textboxes and DropDownLists。我希望它们在用户返回页面时保持不变,所以我尝试了这个:

/*i have saved the panel like this 
  Session["testPanel"] = pnlTest;
*/

protected void Page_Load(object sender, EventArgs e)
{       
    if (Session["testPanel"] != null)
    {
        panel = Session["testPanel"] as Panel;
    }
}

但它不起作用。可能吗?我之所以要这样做是因为开销不是问题,并且我想减少编码时间。

【问题讨论】:

  • 你试过panel = (Panel)Session["testPanel"];吗?另外,你的表达方式是Session["panel"],这会导致错误。
  • 您可能需要考虑 ASP.NET 用户控件缓存。如果将面板代码移动到用户控件中,则可以轻松缓存呈现的内容。 stackoverflow.com/questions/880937/…
  • 面板包含文本框和下拉列表。

标签: c# asp.net session


【解决方案1】:

我自己从未尝试过,但在我看来这是一个非常糟糕的主意。如果不对其进行测试,我的猜测是这会产生大量的 ViewState 问题。即使您可以维护 ViewState,尝试保持对多个页面加载的这种控制充其量也是危险的。

我的建议是使用一个通用对象来保存所需面板的属性,然后在早期事件之一中构建一个方法,以使用这些属性预填充新面板。

【讨论】:

    【解决方案2】:

    在不知道这样做的全部原因的情况下,您应该看看输出缓存指令。最好将内容从面板中拉出并放入用户控件中。然后在控件上设置输出缓存,使用 VaryByCustom 以便您可以使用用户名或其他一些唯一标识符来按用户分隔。

    http://msdn.microsoft.com/en-us/library/hdxfb6cy.aspxhttp://msdn.microsoft.com/en-us/library/system.web.httpapplication.getvarybycustomstring.aspx

    如果您在 webfarm 场景中,使用会话和/或缓存将会有问题。缓存的范围是应用程序实例,因此网络场中的另一台服务器将无法访问它。

    类似情况的其他一些副作用包括视图状态问题。

    【讨论】:

      【解决方案3】:

      您在这里尝试做的是缓存面板,但这不是方法。保存时的面板是内存中的运行对象,不能按原样保存。您需要将其转换为 html 字符串并保存并缓存此字符串。因此,在 Panel 附近放置一个文字,然后渲染 Panel 并将其保存在会话中,然后实际显示此渲染中的文本。

      if(Session["testPanel"] == null)
      {
          TextWriter stringWriter = new StringWriter();
          HtmlTextWriter renderOnMe = new HtmlTextWriter(stringWriter);
          // render and get the actually html of this dom tree
          testPanel.RenderControl(renderOnMe);
          // save it as cache
          Session["testPanel"] = stringWriter.ToString();     
      }
      // render the result on a literal 
      cLiteralID.Text = Session["testPanel"];
      // hide the panel because I have render it on literal.
      testPanel.Visible = false;
      

      需要一些测试。我为自定义控件和自定义缓存使用了一些类似的代码,从不在会话中保存这么多数据。

      【讨论】:

        【解决方案4】:

        第一种方法


        protected void Page_Load(object sender, EventArgs e)
        {       
            if (ViewState["panel"] != null)
            {
                panel = ViewState["panel"] as Panel;
            }
        }
        

        在这种方法中,您的 ViewState 对象是不同的。一旦 ViewState["panel"] 被赋予控制内存并且对象被访问时,您可能会得到一些空值,而印象是 Session 是 Session["panel"]


        第二种方法


        完整面板 HTML 保存在数据库中,并在 表单加载 时访问它,方法是将函数保留在 IsPostBack 下。

        现在使用方法的连续性 - 2 将值分配给您的会话对象。

        this.Controls.Add(new LiteralControl("Your HTML"));
        

        第三种方法


        您可以使用文件系统。将 div 保存在您的文件中并在运行时访问该文件。

        希望对您有所帮助。


        EDIT - 1 => 为第二种方法添加了代码

        【讨论】:

        • 它不工作。我得到:在程序集“System.Web,Version=2.0.0.0,Culture=neutral,PublicKeyToken=b03f5f7f11d50a3a”中键入“System.Web.UI.WebControls.Panel”未标记为可序列化。
        • protected void Page_Load(object sender, EventArgs e) { if (ViewState["testPanel"] != null) { pnlTest = (Panel)ViewState["testPanel"]; } } protected void button_Click(object sender, EventArgs e) { ViewState["testPanel"] = pnlTest; label.Text = "已保存:" + ViewState["testPanel"].ToString(); }
        • this.Controls.Add(new LiteralControl("Your HTML"));
        【解决方案5】:

        我遇到了类似的问题。我试图将一个对象保存到存储面板的视图状态中,但我收到一条错误消息,告诉我面板不可序列化。您可以尝试使用 SerializationSurrogate。 https://msdn.microsoft.com/en-us/library/system.runtime.serialization.iserializationsurrogate(v=vs.110).aspx

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2013-11-19
          • 1970-01-01
          • 2017-11-02
          • 2021-04-24
          • 2017-09-24
          • 2016-11-08
          • 1970-01-01
          • 2011-02-22
          相关资源
          最近更新 更多