【问题标题】:Are objects in WebForms persistent in memory?WebForms 中的对象是否在内存中持久存在?
【发布时间】:2018-04-30 18:18:28
【问题描述】:

我在 c# 方面有很多经验,但我对 WebForms 还很陌生。

我正在做一个项目,其中大量数据存储在 ViewState 中,但我不明白为什么。

我的理解是,代表我的页面 (System.Web.UI.Page) 的对象在该页面的生命周期内是持久的。标识符存储在 ViewState 中可能存在一些幕后魔术,但是当对该页面上的事件做出反应时,我可以不简单地引用“this”及其属性/方法吗?

什么时候可以在 ViewState 中显式存储数据,而不是简单地使用当前对象(本例中为 Page)的属性?

--雅各布

【问题讨论】:

    标签: webforms viewstate


    【解决方案1】:

    我的理解是,代表我的页面的对象 (System.Web.UI.Page) 在该页面的生命周期内是持久的

    这是正确的,但是页面的生命周期仅针对单个请求,在 HTML 交付给客户端之后,Page 实例被销毁。

    我推荐阅读这篇文章:https://msdn.microsoft.com/en-us/library/ms178472.aspx

    请注意,WebForms 的设计:将 stateless-web 抽象为类似 WinForms 的伪状态环境在很大程度上被认为是错误的,这就是为什么 ASP.NET MVC 和 ASP.NET Core 具有完全不同的设计(尽管Controller 实例可以与Page 实例相比较,具有相似的生命周期语义但开销要少得多)。

    标识符存储在 ViewState 中可能有一些幕后的魔力,但是当对该页面上的事件做出反应时,我可以不简单地引用“this”及其属性/方法吗?

    我很难理解这一点 - 但如果您认为 Page 的所有实例成员(包括仅使用支持字段的自定义属性)在请求(包括“回发”请求)之间自动保留,那么不,那就是不对。字段没有神奇的持久性,您需要使用 Page.ViewState 属性作为这些属性的后备存储,并且该数据仅在特殊的“回发”POST 请求之间持久化。

    让我试试我自己的解释:

    1. 浏览器请求GET /MyForm.aspx
    2. ASP.NET 创建MyForm : System.Web.UI.Page 的新实例,创建在.aspx 文件中声明的所有子控件实例,并在所有控件上调用InitLoad 事件,然后Render生成输出 HTML,然后生成Unload。然后对请求的 MyForm 实例进行垃圾收集。

    如果MyForm.aspx 包含<form runat="server"> 并使用“回发”,那么当用户执行某些触发回发的操作时:

    1. 浏览器向POST /MyForm.aspx 发出请求,其中请求正文是来自<input > 元素的数据。在 HTML 的规则下,只有<input>(和<select><textarea> 等)的内容在 POST 请求中而不是整个 DOM 中提交 - 这是 ASP 的问题.NET WebForms 因为所有这些Controls 都有许多属性和设置(例如<asp:Label FontColor="">,它们不会通过它们自己的<input type="hidden" name="label123_FontColor"> 持久化,此外,即使它们有很多冗长的数据要发送回服务器。

    因此,ASP.NET 指示所有 Control 实例将其所有非 <input> 数据序列化到 ViewState 字典(表示 View 的 state (用 MVP/MVC 的说法,.aspx/HTML 是视图 - 因此将其状态与定义为短暂的请求状态分开保存)。

    ControlPage 子类中,您需要使用 ViewState,而不是支持字段:

    public String SomeName {
        get { return this.ViewState["SomeName"] as String; }
        set { this.ViewState["SomeName"] = value; }
    }
    

    ...然后ViewState被序列化和压缩并签名并呈现到<input name="__VIEWSTATE" type="hidden">中的页面)。

    __VIEWSTATE 中携带状态而不是简单地在每个页面请求上重新生成整个页面的数据的原因是因为有时最初生成页面可能涉及繁重的工作(例如数据库查询)。论点是,如果您有一个包含数据列表的页面,并且用户只是在将数据保存回数据库之前对其进行操作,那么您不需要从数据库重新加载,而是将该视图级数据存储在页面的__VIEWSTATE 好像它是某种超级cookie 或其他东西。

    【讨论】:

    • 谢谢。这与我认为它的工作方式非常不同。我总是被引导相信 WebForms 对象在 Web 服务器上保持状态。但是,您基本上是说所有状态信息都存储在浏览器的页面上。
    • 为什么有人会使用这种模式?
    • @Jacob 在受控环境中(您的用户从不使用浏览器的后退按钮!)它实际上运行良好,它为 WinForms 开发人员提供了一种快速构建 Web 应用程序的方法,以便他们可以复制并在项目之间粘贴代码。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-09-10
    • 2019-12-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多