Устранение проблем с недопустимым состоянием представления

В этой статье описаны методы отладки и устранения проблем с состоянием представления в приложениях Microsoft ASP.NET.

Исходная версия продукта: ASP.NET
Исходный номер базы знаний: 829743

Введение

Viewstate — это функция в ASP.NET, которая позволяет страницам автоматически сохранять состояние, не полагаясь на состояние сервера (например, состояние сеанса). Однако проблемы, связанные с состоянием просмотра, могут быть трудно отлаживать. В большинстве случаев при возникновении проблем с viewstate в веб-браузере появляется следующее сообщение об ошибке, которое не указывает на причину проблемы:

Состояние представления недопустимо для этой страницы и может быть повреждено.

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

Установка атрибута validationKey, если вы работаете в веб-ферме

В веб-ферме каждый клиентский запрос может отправляться на другой компьютер при каждой обратной отправке. Из-за этого нельзя оставить атрибуту validationKey значение AutoGenerate в файлеMachine.config . Вместо этого необходимо задать для атрибута validationKey фиксированную строку, которую совместно используют все компьютеры в веб-ферме.

Не храните динамически создаваемые типы в viewstate в веб-ферме

Когда ASP.NET динамически компилирует файлы, файлы встроены в сборки со случайными именами (например, имя файла может бытьjp395dun.dll). Если вы используете веб-ферму, одни и те же файлы компилируются в сборки с разными случайными именами. Как правило, это не проблема, так как никто не делает предположений об именах этих сборок. Но если динамически скомпилированный тип помещать в состояние представления с помощью двоичной сериализации, имя сборки будет включаться в данные viewstate. При последующей отправке этого значения представления на другой сервер в веб-ферме состояние представления невозможно десериализировать, так как в нем используются разные имена сборок.

Лучшее решение заключается в том, чтобы избежать использования двоичной сериализации. Двоичная сериализация использует много ресурсов, даже если эта проблема не возникает. Вместо этого ограничьте то, что вы помещаете в viewstate, сочетанием массивов, пар, триплетов и простых типов (например, строк, int и других типов). System.Web.UI.Pair и System.Web.UI.Triplet — это простые типы оболочки, которые подсистема viewstate может эффективно обрабатывать.

Альтернативным решением, чтобы избежать этой проблемы, является перемещение типов, которые вы храните в viewstate, в предварительно скомпилированную сборку либо в папке Bin , либо в Global Assembly кэше. Это исправление не влияет на производительность, но гарантирует, что у сборки одинаковые имена на всех компьютерах.

Примечание.

Если вы храните сложные типы данных в viewstate и испытываете эту проблему, сведения о стеке вызовов будут содержать стеки, аналогичные следующим:

[FileNotFoundException: Could not load file or assembly 'App_Web_fx--sar9, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null' or one of its dependencies. The system cannot find the file specified.]
 System.RuntimeTypeHandle._GetTypeByName(String name, Boolean throwOnError, Boolean ignoreCase, Boolean reflectionOnly, StackCrawlMark& stackMark, Boolean loadTypeFromPartialName) +0
System.RuntimeTypeHandle.GetTypeByName(String name, Boolean throwOnError, Boolean ignoreCase, Boolean reflectionOnly, StackCrawlMark& stackMark) +72
System.RuntimeType.PrivateGetType(String typeName, Boolean throwOnError, Boolean ignoreCase, Boolean reflectionOnly, StackCrawlMark& stackMark) +58
System.Type.GetType(String typeName, Boolean throwOnError) +57
System.Web.UI.ObjectStateFormatter.DeserializeType(SerializerBinaryReader reader) +192 
System.Web.UI.ObjectStateFormatter.DeserializeValue(SerializerBinaryReader reader) +943 
System.Web.UI.ObjectStateFormatter.DeserializeValue(SerializerBinaryReader reader) +384 
System.Web.UI.ObjectStateFormatter.DeserializeValue(SerializerBinaryReader reader) +198 
System.Web.UI.ObjectStateFormatter.DeserializeValue(SerializerBinaryReader reader) +210 
System.Web.UI.ObjectStateFormatter.DeserializeValue(SerializerBinaryReader reader) +198 
System.Web.UI.ObjectStateFormatter.Deserialize(Stream inputStream) +142

Функция кода проверки подлинности компьютера viewstate (MAC) предназначена для того, чтобы клиенты не отправляли запрос, содержащий вредоносное состояние представления. По умолчанию эта функция включена в следующем флаге в файлеMachine.config .

enableViewStateMac="true"

Самый простой способ определить, связана ли проблема с функцией MAC, — отключить эту функцию. Для этого измените флаг в файлеMachine.config на следующий код.

enableViewStateMac="false"

Если вы больше не получаете ошибки viewstate, проблема связана с функцией MAC.

Важно!

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

Если отключить функцию MAC viewstate, а затем использовать viewstate для элементов управления, которые не кодируют HTML (например, элемент управления Label), злоумышленники могут изменить данные viewstate и поместить произвольные данные в состояние представления. Эти произвольные данные декодируются и затем используются элементами управления при отрисовке размещенной страницы. В результате злоумышленники могут внедрить скрипт в приложение, если вы не работаете над предотвращением атаки. Например, злоумышленник может декодировать данные, внедрять скрипт в данные, где находится элемент управления Label, а затем ссылаться на него с веб-сайта. Любой, кто щелкает ссылку, станет жертвой атаки путем внедрения скрипта, которая может потенциально украсть файлы cookie проверки подлинности или идентификатор сеанса. Скрипт также может позволить злоумышленнику изменять данные о состоянии для элементов управления, использующих viewstate, и в результате могут произойти атаки, относящиеся к приложению.

Как правило, корпорация Майкрософт рекомендует не отключать функцию MAC состояния представления, если вы не уверены, что вы отключили состояние просмотра для всех элементов управления, которые не кодируют их выходные данные (например, элементы управления DataGrid, элементы управления DataList, элементы управления Label и другие элементы управления) в формате HTML или что вы всегда явно задаете их значения в каждом запросе, чтобы они были безопасными.

Определите, какое именно исключение возникает при получении сообщения об ошибке

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

С помощью отладчика можно определить исходное исключение. Для этого необходимо подключить отладчик к процессу ASP.NET (Aspnet_wp.exe или W3wp.exe), а затем настроить его для перехвата всех исключений. Отладчик, вероятно, остановится на нескольких исключениях, которые не являются актуальными, но в конечном итоге он достигнет исключения viewstate и предоставит полезные сведения для устранения неполадок.

Ниже приведен пример использования отладчика среды выполнения (Cordbg.exe).

  1. В командной строке iisreset выполните команду, чтобы убедиться, что у вас есть хорошая отправная точка, а затем перейдите на страницу сайта.

  2. Запустите cordbg.exe.

  3. Введите <pro>, а затем нажмите клавишу ВВОД. Появится список управляемых процессов. Вы должны увидеть Aspnet_wp.exe или процессW3wp.exe . Запишите его PID.

  4. <PID>Введите .

    Примечание.

    Замените PID на PID, который был отмечен на шаге 3.

  5. Введите ca e , чтобы указатьCordbg.exe прервать выполнение всех исключений, а затем выполните <gto> процесс.

  6. При возникновении исключения введите <w> , чтобы просмотреть стек. Если стек является исключением viewstate (ищите LoadPageStateFromPersistenceMedium в стеке), скопируйте все исключения и сведения о стеке из командного окна, а затем сохраните сведения. Эти сведения помогут вам понять проблему. Если исключение не связано, введите <g>.

Попробуйте сохранить состояние представления в сеансе

По умолчанию состояние представления округляется с полем <input type=hidden> , которое отправляется в браузер. Затем браузер отправляет поле обратно на сервер при следующем запросе. В некоторых случаях это состояние представления может быть большим и может стать источником проблем. Некоторые браузеры не могут обрабатывать такое большое скрытое поле (и результирующий большой запрос), и браузеры могут усекать состояние представления. Усечение состояния представления вызывает сообщение об ошибке "состояние представления повреждено". Это поведение, скорее всего, будет происходить в более простых браузерах. Например, такое поведение может происходить в браузере на КПК.

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

<%@ language=c# debug=true %> 

<script runat=server> 
protected override object LoadPageStateFromPersistenceMedium() 
{ 
    return Session["_ViewState"]; 
}

protected override void SavePageStateToPersistenceMedium(object viewState) 
{ 
    Session["_ViewState"] = viewState; 
}

void TextChanged(object o, EventArgs e) 
{ 
    Response.Write("TextChanged"); 
} 
</script> 
<form runat=server> 
<asp:button text=Test runat=server/> 
<asp:textbox ontextchanged=TextChanged runat=server/> 
<input type=hidden name=__VIEWSTATE> 
</form> 

Определите, вызвана ли проблема перезапуском рабочего процесса

Рассмотрим следующий сценарий.

  • Вы используете ASP.NET в Microsoft IIS (IIS) 6.0.
  • Пул приложений работает под удостоверением, отличном от учетной записи локальной системы, учетной записи сетевой службы или учетной записи уровня администратора.
  • Атрибут validationKey<machineKey> элемента имеет значение AutoGenerate в файле конфигурации.

В этом сценарии следующая процедура вызывает ошибку viewstate:

  1. Пользователь просматривает страницу.
  2. Рабочий процесс, в котором размещается ASP.NET приложение, перезапускает.
  3. Пользователь публикует страницу.

В качестве обходного решения для этого сценария используйте явный validationKey атрибут в файле конфигурации.

Ссылки