Основы ASP.NET 2.0

       

ViewState


В лекции 3 упоминалось о скрытом поле ViewState, которое обычно есть у сгенерированных ASP .NET страниц. Говорилось, что там хранится информация о состоянии отображения страницы, которая передается на сервер и обратно, чтобы после перезагрузки на ней сохранялись ее динамические изменения. Там не хранятся введенные пользователем данные, они отправляются, как обычно, в теле запроса POST.

Понимание, что такое состояние отображения и как оно работает, очень важно, особенно для разработчиков, которые пишут собственные элементы управления.

В HTML было введено скрытое поле <input type=hidden> именно для того, чтобы передавать нужную для программиста, но не нужную или не интересную для пользователя информацию на сервер. ASP .NET пользуется этими полями, при этом шифруя информацию (хотя опытный пользователь сможет ее расшифровать). Состояние отображения хранится в скрытом поле формы с идентификатором __VIEWSTATE.

Каким же образом генерируется это поле, что в нем хранится и когда оно читается при возврате формы? Чтобы это понять, надо более подробно рассмотреть жизненный цикл страницы. Каждый раз, когда на сервере генерируется страница, в первый раз или после постбэка, заново создается объект Page и все его элементы. Если свойство элемента управления декларировано на странице или меняется во время события инициализации, оно будет таким всегда.


Рис. 15.2. 

Из картинки видно, что между событиями Init и Load при постбэке происходят еще два события: загрузка состояния отображения и загрузка данных постбэка.


И те, и другие читаются из тела запроса POST. Перед событием Render состояние отображения вновь записывается с помощью функции SaveViewState. Функция SaveViewState объекта рекурсивно вызывает ее же вложенных в нее элементов. При этом эта информация кодируется по алгоритму base-64. Во время отрисовки страницы создается скрытый элемент __VIEWSTATE. Следовательно, во время события Load или в обработчиках событий элементов управления можно изменять свойства страницы или любых ее элементов.

Свойство ViewState есть как у страницы, так и у всех элементов управления на ней.

Пусть у нас есть простая форма:

<form id="form1" runat="server"> <asp:Label ID="Label1" runat="server" ></asp:Label><br /> <asp:Button ID="Button1" runat="server" OnClick="Button1_Click" Text="Get Time" /><br /> <asp:Button ID="Button2" runat="server" Text="Button" /> </form>

Во время первой загрузки страницы ничего связанного с сохранением состояния не происходит.

При нажатии на первую кнопку динамически меняется текст метки. Кнопка вызывает отправку данных на сервер, и во время второго жизненного цикла выполняется функция RaisePostBackEvent, которая вызывает обработчик:

protected void Button1_Click(object sender, EventArgs e) { Label1.Text = DateTime.Now.ToLongTimeString(); }

Измененное состояние метки сохраняется в свойстве ViewState. Если теперь нажать на вторую кнопку, то сразу после инициализации страницы в текст метки будет загружаться текст, сохраненный в ViewState.



Если отключить возможность сохранения состояния, то текст метки вернется к своему пустому состоянию. То же самое произойдет и при нажатии на первую кнопку, но так как RaisePostBackEvent происходит после LoadPostBackData, значение, загруженное из ViewState, переписывается новым значением.

Состояние страницы доступно программисту, и в него можно добавлять дополнительные данные. Например, когда нужно было сортировать DataGrid, в переменную ViewState["sort"] записывалось выражение сортировки.

ViewState представляет собой коллекцию пар "ключ/значение", подобно объектам приложения и сессии. В него можно помещать только объекты с атрибутом Serializable. Свойство ViewState имеет тип System.Web.UI.StateBag, и синтаксис доступа к данным похож на доступ к значениям Hashtable.

Поле __VIEWSTATE может стать довольно большим (порядка десятков килобайт), например, когда в форме присутствует DataGrid или GridView. Эти элементы управления хранят в состоянии отображения все свое содержимое. И вся эта информация путешествует с клиента на сервер и обратно. Увеличивает это поле и элемент Wizard, и TreeView. В общем, чем больше возможностей и свойств, тем дороже приходится за это платить. Поэтому рассмотрим методы сокращения размера поля __VIEWSTATE. У каждого элемента управления есть свойство EnableViewState, которое по умолчанию равно True. Если установить его в False, то состояние данного элемента управления не будет записано в объект ViewState. Это свойство можно отключить и у всей страницы — с помощью атрибута EnableViewState директивы Page или программно:



Page.EnableViewState = false;

Такой же атрибут есть у директив MasterPage, Control.

Атрибут директивы Page EnableViewStateMac определяет, проводится ли машинный контроль аутентификации (MAC). Это контроль, гарантирующий, что состояние отображения не сфальсифицировано злонамеренными пользователями.

Хотя отключение EnableViewState позволяет уменьшить количество передаваемой информации, не всегда это можно делать безнаказанно. Если на странице есть DataGrid, который заполняется во время события Page_Load при условии if (!Page.IsPostBack), то есть при первой загрузке страницы, то после постбэка он просто исчезнет со страницы. Следовательно, при выключенном EnableViewState каждый раз необходимо читать данные из источника заново. Что выбрать, зависит от ситуации. В одних случаях бывает важнее сэкономить на времени загрузки страницы, в других — на соединении с базой данных.


Содержание раздела