Web 表单中的对象是否持久保存在内存中?

问题描述 投票:0回答:1

我有丰富的 C# 经验,但我对 Web 表单还很陌生。

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

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

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

asp.net webforms garbage-collection viewstate
1个回答
3
投票

我的理解是,代表我的页面(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
    文件中声明的所有子控件实例,并调用所有控件上的
    Init
    Load
    事件,然后
    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
字典(代表 Viewstate(用 MVP/MVC 的说法,
.aspx
/HTML 是视图 - 因此将其状态与请求状态分开,根据定义,请求状态是短暂的)。

Control
Page
子类中,您需要使用 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 之类的东西。

© www.soinside.com 2019 - 2024. All rights reserved.