我的理解是,代表我的页面的对象 (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 请求之间持久化。
让我试试我自己的解释:
- 浏览器请求
GET /MyForm.aspx
- ASP.NET 创建
MyForm : System.Web.UI.Page 的新实例,创建在.aspx 文件中声明的所有子控件实例,并在所有控件上调用Init 和Load 事件,然后Render生成输出 HTML,然后生成Unload。然后对请求的 MyForm 实例进行垃圾收集。
如果MyForm.aspx 包含<form runat="server"> 并使用“回发”,那么当用户执行某些触发回发的操作时:
- 浏览器向
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 是视图 - 因此将其状态与定义为短暂的请求状态分开保存)。
在 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 或其他东西。