Управление состоянием в ASP.NET
Страница 2. Клиентские методы. ViewState


 

Клиентские методы

ViewState

Контейнер ViewState представляет собой коллекцию типа ключ-значение, которая позволяет сохранять информацию, относящуюся к определенной странице. Перед отправкой клиенту эта коллекция сериализуются и записываются в hidden поле под названием __VIEWSTATE. В этом можно убедиться, посмотрев сгенерированный html код любой ASP.NET страницы. В результате вы увидите подобный код:


<form name="Form1" method="post" action="WebForm1.aspx" id="Form1">
...
<input type="hidden" name="__VIEWSTATE" value="dDwtMTI3OTMzNDM4NDs7PqSz2R6MBTQBd6YfrNqpkCkIceLd" />
...
</form>

После того, как пользователь выполнит какие-то действия на странице и инициирует постбек, сервер получит очередной запрос. Данное hidden поле распарситься и выполниться десериализация его значения. Этот процесс происходит сразу после обработки события OnInit страницы. В случае, если при десериализации возникает ошибка, тем самым указывая, что либо информация в поле была повреждена в процессе передачи, либо намеренно изменена на клиенте, система сгенерирует исключение
System.Web.HttpException: The viewstate is invalid for this page and might be corrupted
Убедиться в этом можно написав в браузере http://localhost/WebForm1.aspx?__VIEWSTATE=abc

Данный контейнер позволяет пользователю сохранять значения следующим образом:

// запись
ViewState["color"] = "red";
// чтение
string strColor =(string)ViewState["color"];

Этот способ применим на веб-страницах и пользовательских контролах (наследниках классов Page и UserControl соответственно). В коллекцию ViewState можно занести любой сериализуемый объект, либо имеющий TypeConverter для преобразования его в строку. Контейнер оптимизирован для хранения примитивных типов, а также String, ArrayList, HashTable. В случае сохранения других типов рекомендуется перегрузить методы LoadViewState и SaveViewState, в которых реализовать свою более эффективную методику. Кроме того, эти методы необходимо перегружать в custom контролах (наследниках класса WebControl). Предположим, что custom контрол сохраняет свое состояние во ViewState под ключом X. Этот контрол размещается на некоторой странице, которая также сохраняет свое состояние во ViewState под таким же ключом X. В результате одно из значений будет потеряно, что, вероятно, приведет к неправильной работе. Поэтому в custom контролах настоятельно рекомендуются пользоваться следующим способом:

// запись

protected override object SaveViewState()
{
 // сохранение состояния как массива объектов
 object[] allStates = new object[3];
 // сохранение состояния родителя
 allStates[0] = base.SaveViewState();
 // сохранение значения контрола
 allStates[1] = "Control Value 1";
 allStates[2] = "Control Value 2";
 return allStates;
}
// чтение
protected override void LoadViewState(object savedState) 
{
 if (savedState != null)
 {
 // восстановление состояния из массива, сформированного в методе SavedViewState.
 object[] myState = (object[])savedState;
 // восстановление состояния родителя
 if (myState[0] != null)
 base.LoadViewState(myState[0]);
 // восстановления значений, сохраненных контролом
 String ControlValue1, ControlValue2;
 if (myState[1] != null)
 ControlValue1 = (string)myState[1];
 if (myState[2] != null)
 ControlValue2 = (string)myState[2];
 }
}

На использование ViewState также влияют два атрибута директивы @Page, которая определяет любую aspx страницу. Первый из них EnableViewStateMac, установка которого в true сообщает системе о необходимости шифрования hidden поля _VIEWSTATE. Второй - EnableViewState, позволяющий отключить использование коллекции. Т.е. при EnableViewState=false выполнение вышеуказанного кода даст strColor=null. Однако, посмотрев html код страницы, для которой отключен ViewState, мы все равно увидим hidden поле __VIEWSTATE. Это связано с тем, что ViewState также хранит некоторую системную информацию, например id активной формы страницы.

Использование атрибута EnableViewState=false может повысить скорость обработки страницы, однако также может вызвать проблемы, в случае если используются контролы, сохраняющие свои внутренние данные с помощью ViewState (например, номер столбца, по которому сортируется DataGrid). Для преодоления этой проблемы в ASP.NET 2.0 был введен контейнер ControlState. Этот контейнер записывается в hidden поле вне зависимости от значения атрибута EnableViewState. Для доступа к ControlState необходимо использовать методы LoadControlState и SaveControlState.

Поскольку все данные будут храниться в одном hidden поле, то не рекомендуется использовать данный контейнер для больших объектов, поскольку это может существенно увеличить размер страницы и скорость ее загрузки. В определенной степени размер ViewState можно уменьшить за счет упаковки поля.

 
« Предыдущая статья   Следующая статья »