Общие сведения о состоянии представления ASP.NET

Visual Studio 2010

Обновлен: Ноябрь 2007

Состояние представления — это метод, который платформа веб-страниц ASP.NET использует для сохранения значений страницы и элемента управления между циклами обработки. При отображении разметки HTML страницы, текущее состояние страницы и значения должны сохраняться во время обратного запроса, сериализуясь в строки в кодировке base64. Затем данные сведения помещаются в скрытое поле или поля состояния представления.

В данном разделе рассматриваются следующие темы:

Состояние представления используется платформой веб-страниц ASP.NET для сохранения сведений, которые должны сохраняться между обратными передачами. К данным сведениям относятся любые нестандартные значения элементов управления.

Кроме того, состояние представления можно использовать для хранения данных приложения, относящихся к страницам.

К началу

Состояние представления — это хранилище в странице ASP.NET, которое может хранить значения, которые должны сохраняться во время обратной передачи. Платформа веб-страниц использует состояние представления для сохранения параметров элемента управления между обратными передачами.

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

  • Сохранения значений между обратными передачами, не сохраняя значения в состоянии сеанса или в профиле пользователя.

  • Хранения задаваемых значений страницы или свойств элемента управления.

  • Создания пользовательского поставщика состояния представления, который позволяет хранить сведения состояния представления в базе данных SQL Server или в другом хранилище данных.

Например, можно хранить сведения в состоянии представления, к которому созданный код имеет доступ во время события загрузки страницы следующего запроса, когда страница отправляется на сервер. Рекомендации по использованию см. в разделе Рекомендации по управлению состоянием ASP.NET.

К началу

Веб-приложение является приложением с неопределенным состоянием. Новый экземпляр класса веб-страницы создается при каждом запросе страницы у сервера. Как правило, это означает, что все данные на странице и в ее элементах управления будут потеряны при каждом цикле обработки. Например, по умолчанию, если пользователь вводит сведения в текстовое поле на веб-странице HTML, эти данные отправляются на сервер. Однако данные не возвращаются веб-обозревателю в ответе.

Чтобы преодолеть данное внутреннее ограничение веб-программирования, платформа веб-страниц ASP.NET включает несколько возможностей управления состоянием, позволяющих сохранять значения страницы и элемента управления между циклами обработки на веб-сервере. Одна из данных возможностей представляет собой состояние представления Общие сведения об управлении состоянием ASP.NET.

По умолчанию, платформа веб-страниц ASP.NET использует состояние представления для сохранения значений страницы и элементов управления между циклами обработки. При отображении HTML кода страницы, текущее состояние страницы и значения должны сохраняться во время обратной передачи, сериализуясь в строки в кодировке base64. Затем они помещаются в скрытое поле или поля в странице.

Доступ к состоянию представления можно получить в коде с помощью свойства страницы ViewState. ViewState свойство является словарем, содержащим пары ключ/значение, которые содержат данные состояния представления.

Bb386448.alert_security(ru-ru,VS.100).gifПримечание о безопасности.

Пользователь-злоумышленник может легко просмотреть и изменить содержимое скрытого поля. Дополнительные сведения о том, как защитить состояние представления данных, см. далее в подразделе Защита состояния представления.

Рекомендации о том, когда следует хранить данные в состоянии представления, см. в разделе Рекомендации по управлению состоянием ASP.NET.

Можно изменить поведение по умолчанию и сохранять состояние представления в другом месте, например, в базе данных SQL Server, путем реализации пользовательского класса PageStatePersister для хранения данных страницы. Пример сохранения состояния страницы в потоке, а не в скрытом поле см. в примере для класса PageStatePersister.

Вопросы по использованию состояния представления

Состояние представления предоставляет сведения о состоянии для конкретной страницы ASP.NET. Если требуется использовать данные по более чем одной странице, или, если требуется сохранить сведения при перемещении внутри веб-узла, необходимо использовать другой метод для сохранения сведений о состоянии. Например, можно использовать состояние приложения, состояние сеанса или профиль свойств.

Сведения состояния представления сериализуются в XML и затем кодируются с помощью кодировки base-64, которая может генерировать большой объем данных. Когда страница отправляется на сервер, содержимое состояния представления отправляется как часть сведений обратной передачи страницы. Если состояние представления содержит большой объем данных, то это может повлиять на производительность страницы. Проверьте производительность страниц с помощью обычных данных для приложения, чтобы определить, является ли причиной проблем производительности размер состояния представления. Альтернативные варианты использования состояния представления см. в разделе Рекомендации по управлению состоянием ASP.NET.

При отсутствии управляющей информации для хранения отдельных элементов управления, можно отключить состояние представления для элемента управления. Если элемент управления на странице обновляется из хранилища данных при каждом обратном запросе, можно отключить состояние представления для этого элемента управления, чтобы уменьшить его размер. Например, можно отключить состояние представления для элемента управления такого как GridView.

Bb386448.alert_note(ru-ru,VS.100).gifПримечание.

Даже если явно отключить состояние представления, скрытое поле по-прежнему отправляется в веб-обозреватель, чтобы указать, что происходит обратная передача для страницы.

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

Некоторые мобильные устройства вообще не предоставляют скрытых полей. Следовательно, состояние представления не будет работать для этих устройств. Дополнительные сведения и альтернативные методы см. в разделе Общие сведения о веб-разработке ASP.NET для мобильных устройств.

Состояние элемента управления

В дополнении к состоянию представления ASP.NET поддерживает состояние элемента управления. Страница использует состояние элемента управления для сохранения управляющей информации, которая должна сохраняться между обратными передачами, даже если состояние представления для страницы или элемента управления отключено. Подобно состоянию представления, состояние элемента управления хранится в одном или нескольких скрытых полей.

Сохранение значений в состоянии представления

Сведения состояния представления доступны с помощью свойства страницы ViewState, которое предоставляет объект словаря. Данный словарь можно использовать для хранения пользовательских значений. Обычно словарь используется для хранения значения настраиваемых свойств, которые определены для страницы.

Поскольку состояние представления отправляется в виде скрытого поля, вносить изменения для состояния представления можно до возникновения события страницы PreRenderComplete. После отображения страницы в веб-обозревателе, изменения состояния представления не будут сохранены.

Сведения в скрытом поле состояния представления могут просматриваться пользователями, если они просматривают источник веб-страницы и смогут декодировать строки в кодировке base-64. Это создает потенциальную уязвимость. Дополнительные сведения о проблемах безопасности состояния представления см. далее в подразделе Защита состояния представления.

Bb386448.alert_note(ru-ru,VS.100).gifПримечание.

Чтобы использовать свойство ViewState, веб-страница ASP.NET должна иметь элемент, имеющий атрибут form runat="server".

Для сохранения значений в состоянии представления создайте новый элемент, содержащий значение для сохранения и добавления элемента в словарь состояния представления. В следующем примере показана веб-страница ASP.NET с кодом, который сохраняет строку и целое значение в состоянии представления.

<%@ Page Language="VB" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<script runat="server">
  ' Sample ArrayList for the page.
  Dim PageArrayList As ArrayList

  Function CreateArray() As ArrayList
    ' Create a sample ArrayList.
    Dim result As ArrayList
    result = New ArrayList(4)
    result.Add("item 1")
    result.Add("item 2")
    result.Add("item 3")
    result.Add("item 4")
    Return result
  End Function

  Sub Page_Load(ByVal sender As Object, ByVal e As EventArgs)
    If (Me.ViewState("arrayListInViewState") IsNot Nothing) Then
      PageArrayList = CType(Me.ViewState("arrayListInViewState"), ArrayList)
    Else
      ' ArrayList isn't in view state, so it must be created and populated.
      PageArrayList = CreateArray()
    End If
    ' Code that uses PageArrayList.
  End Sub

  Sub Page_PreRender(ByVal sender As Object, ByVal e As EventArgs)
    ' Save PageArrayList before the page is rendered.
    Me.ViewState.Add("arrayListInViewState", PageArrayList)
  End Sub
</script>

<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
    <title>View state sample</title>
</head>
<body>
    <form id="form1" runat="server">
    <div>
    </div>
    </form>
</body>
</html>

<%@ Page Language="C#" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<script runat="server">
  // Sample ArrayList for the page.
  ArrayList PageArrayList;

  ArrayList CreateArray()
  {
    // Create a sample ArrayList.
    ArrayList result = new ArrayList(4);
    result.Add("item 1");
    result.Add("item 2");
    result.Add("item 3");
    result.Add("item 4");
    return result;
  }

  void Page_Load(object sender, EventArgs e)
  {
    if (ViewState["arrayListInViewState"] != null)
    {
      PageArrayList = (ArrayList)ViewState["arrayListInViewState"];
    }
    else
    {
      // ArrayList isn't in view state, so it must be created and populated.
      PageArrayList = CreateArray();
    }
    // Code that uses PageArrayList.
  }
    
  void Page_PreRender(object sender, EventArgs e)
  {
    // Save PageArrayList before the page is rendered.
    ViewState.Add("arrayListInViewState", PageArrayList);
  }
</script>

<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
    <title>View state sample</title>
</head>
<body>
    <form id="form1" runat="server">
    <div>
    </div>
    </form>
</body>
</html>

Типы данных, которые можно хранить в состоянии представления

В состоянии представления можно хранить объекты следующих типов:

  • Строки

  • Целые числа

  • Значения типа Boolean

  • Объекты Array

  • Объекты ArrayList

  • Хэш-таблицы

  • Собственные преобразователи типа (дополнительные сведения см. в описании класса TypeConverter).

Можно хранить и другие типы данных, но класс должен быть скомпилирован с атрибутом Serializable таким образом, чтобы его значения могли быть сериализованы для состояния представления.

Считывание значений из состояния представления

Чтобы прочитать значение из состояния представления, необходимо получить ViewState свойство страницы и затем прочитать значение из словаря состояния представления.

В следующем примере показано, как можно получить объект ArrayList с именем arrayListInViewState из состояния представления и затем привязать элемент управления GridView к объекту в качестве источника данных.

Dim arrayList As ArrayList
arrayList = CType(ViewState("arrayListInViewState"), ArrayList)

Me.GridView1.DataSource = arrayList
Me.GridView1.DataBind()

arrayList = new ArrayList();
arrayList = (ArrayList)ViewState["arrayListInViewState"];

this.GridView1.DataSource = arrayList;
this.GridView1.DataBind();

Значения в состоянии представления имеют тип String. Если в Visual Basic задано Option Strict On, необходимо привести значения состояния представления в соответствующий тип до начала работы со значениями, как показано в предыдущем примере. В C# при чтении состояния представления необходимо всегда приводить значения к соответствующему типу.

При попытке извлечь значение из несуществующего состояния представления, исключение не создается. Чтобы убедиться, что значение находится в состоянии представления, сперва проверьте, существует ли объект. Следующий пример показывает, как проверить наличие элемента в состоянии представления.

if (ViewState["color"] == null)
    // No such value in view state, take appropriate action.

При попытке использовать несуществующий элемент состояния представления каким-либо другим способом (например, выяснить его тип) будет создано исключение NullReferenceException.

К началу

Защита состояния представления

По умолчанию состояние представления данных хранится на странице в скрытом поле и кодируется с использованием кодировки base64. Кроме того, хэш состояния представления данных создается из данных с помощью ключа кода проверки подлинности компьютера (MAC). Хэш-значение добавляется в закодированное состояние представления данных и результирующая строка сохраняется на странице. Когда страница возвращается обратно на сервер, платформа веб-страниц ASP.NET заново вычисляет хэш-значение и сравнивает его со значением, которое хранится в состоянии представления. Если хэш-значения не совпадают, возникает исключение, которое указывает, что данные состояния представления могут быть недопустимыми.

Создавая хэш-значение, платформа веб-страниц ASP.NET может проверить являются ли данные состояния представления поврежденными или подделанными. Однако, даже если данные не подделаны, данные состояния представления могут быть перехвачены и прочитаны пользователями-злоумышленниками.

Использование кода проверки подлинности сообщения для вычисления хэш-значения состояния представления

MAC-ключ, используемый для вычисления хэш-значения состояния представления, либо генерируется автоматически, либо задается в файле Machine.config. Если ключ генерируется автоматически, то он создается на основе MAC-адреса компьютера, который является уникальным значением GUID сетевого адаптера компьютера.

Обратное вычисление MAC-ключа на основе хэш-значения в состоянии представления является очень трудной задачей для пользователей-злоумышленников. Таким образом, кодирование с помощью MAC адреса является достаточно надежным способом определения изменения данных состояния представления.

Как правило, чем больше MAC-ключ, используемый для создания хэш-значения, тем меньше вероятность того, что хэш-значения для различных строк будут совпадать. Если ключ генерируется автоматически, для создания большого ключа ASP.NET использует алгоритм кодирования SHA-1. Однако в среде веб-фермы ключ должен быть одинаковым для всех серверов. Если ключ не совпадает, страница отправляется обратно на сервер, который создал страницу, и платформа веб-страниц ASP.NET вызывает исключение. Поэтому в среде веб-фермы вместо автоматического создания ключа необходимо указать ключ в файле Machine.config. В этом случае убедитесь, что создается ключ, являющийся достаточно безопасным для хэшированного значения. Однако, чем больше ключ, тем больше времени необходимо для создания хэш-значения. Следовательно, необходимо сравнить требования безопасности и производительности.

Шифрование состояния представления

Хотя MAC-кодирование помогает избежать искажения данных состояния представления, оно не запрещает пользователям выполнять просмотр данных. Существует два способа предотвращения просмотра данных: передача страниц по протоколу SSL и шифрование данных в состоянии представления. Требование передачи страницы по протоколу SSL может помочь предотвратить перехват данных пакета и несанкционированный доступ к данным пользователями, которые не являются получателями страницы.

Однако пользователь, который запросил страницу, может по-прежнему просматривать данные состояния представления, так как протокол SSL расшифровывает страницу для отображения в веб-обозревателе. Это правильно, если не беспокоиться об авторизованных пользователях, имеющих доступ к данным состояния представления. Однако, в некоторых случаях элементы управления могут использовать состояние представления для хранения сведений, к которым пользователи должны иметь доступ. Например, страница может содержать элементы управления с привязкой к данным, в которых идентификаторы элементов (ключи данных) хранятся в состоянии представления. Если данные идентификаторы содержат конфиденциальные данные, например, коды клиентов, следует зашифровать данные состояния представления в дополнение или вместо отправки страницы по SSL.

Для шифрования данных присвойте свойству страницы ViewStateEncryptionMode значение true. Если сведения хранятся в режиме представления, можно использовать обычные методы чтения и записи. Страница сама выполнит шифрование и расшифровку данных. Шифрование данных состояния представления может повлиять на производительность приложения. Следовательно, не следует использовать шифрование без необходимости.

Шифрование состояния элемента управления

Элементам управления, использующим состояние элемента управления, может потребоваться шифрование состояния представления с помощью метода RegisterRequiresViewStateEncryption. Если любой элемент управления на странице требует, чтобы состояние представления было зашифровано, будут зашифрованы все состояния представления на странице.

Кодирование состояния представления для конкретного пользователя

Если веб-узел выполняет проверку подлинности пользователей, можно задать свойство ViewStateUserKey в обработчике событий Page_Init, чтобы связать состояние представления страницы с конкретным пользователем. Это помогает предотвратить мгновенные атаки, в которых пользователь-злоумышленник создает действительную и предварительно заполненную веб-страницу с состоянием представления из ранее созданной страницы. Затем атакующий заставляет жертву щелкнуть ссылку, которая отправляет страницу на сервер с помощью идентификации жертвы.

Если задано свойство ViewStateUserKey, идентификация атакующего используется для создания хэша состояния представления первичной страницы. Когда жертва завлечена для повторной отправки страницы, хэш-значения будут отличаться, поскольку отличаются ключи пользователя. Страница не пройдет проверку и возникнет исключение.

Свойство ViewStateUserKey необходимо связать с уникальным значением для каждого пользователя, например, именем пользователя или идентификатором.

Защита конфигурации в общей среде размещения

В общей среде размещения пользователи-злоумышленники потенциально могут изменить свойства управления представлением, что может повлиять на другие приложения на компьютере. Это можно сделать путем изменения файла Machine.config, изменения конфигурации классов и других средств администрирования и конфигурации. Поможет предотвратить изменение конфигурации приложения путем шифрования разделов файлов конфигурации. Дополнительные сведения см. в разделе Шифрование сведений о конфигурации с помощью функции защищенной конфигурации.

ViewState

Предоставляет объект словаря для сохранения значений между запросами для одной страницы.

PageStatePersister

Предоставляет средства для определения пользовательских механизмов для хранения сведений состояния представления, например, в базе данных SQL Server.

К началу

Показ: