Насколько я понимаю, объект, представляющий мою страницу (System.Web.UI.Page), является постоянным в течение всей жизни этой страницы
Это правильно, однако время жизни страницы только для одного запроса, после того, как HTML-код доставлен клиенту, экземпляр Page
уничтожается.
Рекомендую прочитать эту статью: https://msdn.microsoft.com/en-us/library/ms178472.aspx
Обратите внимание, что дизайн WebForms: абстракция web без состояния в псевдосохраняющую WinForms-подобную среду в значительной степени считается ошибкой, и поэтому ASP.NET MVC и ASP.NET Core имеют радикально другой дизайн (хотя Controller
экземпляры можно сравнить с Page
экземплярами, с похожей семантикой жизненного цикла, но значительно меньшими накладными расходами).
Может быть какая-то закулисная магия, когда идентификатор хранится во ViewState, но, реагируя на события на этой странице, могу ли я просто ссылаться на «это» и его свойства / методы?
Мне трудно это понять - но если вы считаете, что все члены экземпляра Page
, включая настраиваемые свойства, использующие только поле поддержки, автоматически сохраняются между запросами (включая запросы "обратной передачи"), то нет, то есть не правда. Волшебное постоянство для полей не требуется, необходимо использовать свойство Page.ViewState
в качестве резервного хранилища для этих свойств, и эти данные сохраняются только между специальными запросами POST "postback".
Позвольте мне попробовать собственное объяснение:
- Браузер делает запрос на
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 (на языке 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 или что-то в этом роде.