Проблемы сжатия Viewstate - PullRequest
       34

Проблемы сжатия Viewstate

5 голосов
/ 06 апреля 2009

В настоящее время я борюсь с .NET Viewstate, и он начинает меня изматывать. Обнаружив, что некоторые страницы в одном из наших приложений состоят примерно из 80% просмотра, я попытался уменьшить это, где смогу.

Я смотрел (и доволен) отключением режима просмотра для элементов управления, которые ему не нужны (надписи, кнопки и т. Д.), И добился здесь небольшого выигрыша.

Сейчас я смотрю на сжатие состояния представления, и хотя я могу продемонстрировать уменьшение размера на 40-50%, оно не очень хорошо работает с моим приложением.

Сценарий: Страница содержит несколько выпадающих списков, кнопку и Grdiview (отсюда и необходимость иметь дело с ViewState!). Когда страница загружается, DDL заполняются и выбираются значения по умолчанию. Нажатие кнопки ОК приводит к тому, что Gridview заполняется, как и ожидалось.

Теперь проблема: с включенным Viewstate Compression, если пользователь изменяет выбранные элементы в DDL перед нажатием кнопки OK, он получит ошибку «Required Field Validator», указывающую, что выбор не был сделан в одном из DDL - Но это не так! Отключение кода сжатия устраняет проблему, и страница работает должным образом (то есть, как это было в течение нескольких месяцев!).

Возможно, проблема заключается в том, что состояние представления теперь хранится в ключе, отличном от __VIEWSTATE [код, который я видел, использует разные имена ключей - например, VSTATE).

Источники моей страницы выглядят так:

Источник страницы со сжатием (обратите внимание на пустую клавишу __VIEWSTATE):

<div>
<input type="hidden" name="__EVENTTARGET" id="__EVENTTARGET" value="" />
<input type="hidden" name="__EVENTARGUMENT" id="__EVENTARGUMENT" value="" />
<input type="hidden" name="__LASTFOCUS" id="__LASTFOCUS" value="" />
<input type="hidden" name="__VSTATE" id="__VSTATE" value="H4sIAAAAAEAO29B2AcSZYlJ
.
.
MKd2afqdaImFR5UiFXVyQPwLPA//8xt+pMsSQ8vlOklcoNgmZfJd8hHvk6/S/7UbxxAJTjzZfp6Qcm039
h3d3dvvPO7/Oa/7i57uemj1H2a/gw5lJQ+ySjFRtPZUL7A/3o2ImFR5UiFXVyLPA+38At70F1EkwAAA=" />
<input type="hidden" name="__VIEWSTATE" id="
__VIEWSTATE" value="" />
</div>

Источник страницы без сжатия:

<div>
<input type="hidden" name="__EVENTTARGET" id="__EVENTTARGET" value="" />
<input type="hidden" name="__EVENTARGUMENT" id="__EVENTARGUMENT" value="" />
<input type="hidden" name="__LASTFOCUS" id="__LASTFOCUS" value="" />
<input type="hidden" name="__VIEWSTATE" id="__VIEWSTATE" value="/wEPDwUKMTYxOTM1NDg4N
A9kFgJmD2QWAgIDD2QWAgIFD2QWAmYPZBYKAgEPZBYIAgcPZBYCAgMPDxYCHgRUZXh0BRdEYXduQyBbY2hhbm
dlIHBhc3N3b3JkXWRkAgkPFgIeB1Zpc2libGVoFgQCAQ8PFgIfAAUFQWRtaW5kZAIDDw8WAh8ABQUxNDoyNGR
.
.
.
.
.
.
kAgsPDxYEHwAFWVNlbGVjdGVkIFNlcnZpY2UgVXNlcjogPGEgY2xhc3M9J3N1U2VsZWN0b3InIGhyZWY9J2xp
c3RzZXJ2aWNldXNlcnMuYXNweCc+PGI+bm9uZTwvYj48L2E+HwFoZGQCDw8QZGQWAGQCBQ8UKwADZDwrABQEA
BYSHg9QYXJlbnRJdGVtQ2xhc3MFC2lnbW5fUGFyZW50HhdUb3BMZXZlbFBhcmVudEl0ZW1DbGFzcwUTaWdtbl
Ub3BFBhcmVudB4KSlNGaWxlTmFtZWUeFlRvcExldmVsSG92ZXJJdGVtQ2xhc3MFNGlnbW5fVG9wTGV"     
/>
</div>

Как .NET узнает, где хранится VIEWSTATE, и знает ли я, что я его переместил?

Нужно ли вносить какие-либо другие изменения в мой код, кроме реализации SavePageStateToPersistenceMedium и LoadPageStateFromPersistenceMedium?

Ответы [ 6 ]

3 голосов
/ 21 сентября 2010

если вы используете ajax на своей странице, пожалуйста, измените эту строку кода. Это решит вашу проблему. ClientScript.RegisterHiddenField ("__VSTATE", Convert.ToBase64String (bytes)); замените вышеприведенное заявление на ScriptManager. ScriptManager.RegisterHiddenField (this, "__VSTATE", Convert.ToBase64String (bytes));

3 голосов
/ 06 апреля 2009

эй сжатие viewstate работает для меня без каких-либо проблем. в основном у меня есть базовый класс для всех моих страниц aspx, которые используют viewstate. даже я использую другой ключ viewstate, чтобы сохранить мое viewstate. однако для этого вам необходимо переопределить 2 метода:

1) - для сохранения состояния просмотра 2) - загрузить viewstate

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

using System;
using System.IO;
using System.Web.UI;

namespace XC.UI.WebForms
{

    public class PageBase : System.Web.UI.Page
    {

        protected override object LoadPageStateFromPersistenceMedium()
        {
            string viewState = Request.Form["__VSTATE"];
            byte[] bytes = Convert.FromBase64String(viewState);
            bytes = XC.Common.ViewStateHelper.Decompress(bytes);
            LosFormatter formatter = new LosFormatter();
            return formatter.Deserialize(Convert.ToBase64String(bytes));
        }

        protected override void SavePageStateToPersistenceMedium(object viewState)
        {
            LosFormatter formatter = new LosFormatter();
            StringWriter writer = new StringWriter();
            formatter.Serialize(writer, viewState);
            string viewStateString = writer.ToString();
            byte[] bytes = Convert.FromBase64String(viewStateString);
            bytes = XC.Common.ViewStateHelper.Compress(bytes);
            ClientScript.RegisterHiddenField("__VSTATE", Convert.ToBase64String(bytes));
        }

    }

}
2 голосов
/ 06 апреля 2009

В .NET скрыта константа, которая содержит имя поля viewstate. Мы сделали сжатие, подключив описанные вами методы, но сохранив имя представления без изменений.

1 голос
/ 22 ноября 2011

Сжатие не сработало для меня, так как оно уменьшилось на 40%. У меня было 200-300 КБ ViewStates, и я резко снижал производительность приложений.

Я написал метод замены состояния представления, который заменил его на маркер GUID на странице и сохранил фактические данные на самом сервере в базе данных.

Вот код и техника.

http://ashishnangla.com/2011/07/21/reducing-size-of-viewstate-in-asp-net-webforms-by-writing-a-custom-viewstate-provider-pagestatepersister-part-12/

1 голос
/ 06 апреля 2009

Это может быть излишним, но есть очень крутое аппаратное решение этой проблемы на www.strangeloop.net. Нет связи, просто впечатлен технологией.

Вернуться на страницу tho - какие виды элементов управления генерируют все это представление? Сетки? Вы указали, что уже прошли через это, но обратите внимание на «ненужные runats» с таблицами, td, tr, div и т. Д., Для которых установлено runat = "server". Все содержимое этих элементов управления сохраняется в viewstate. Недавно мы сократили полезную нагрузку на 40% от нашего представления, узнав, что div был на стороне клиента и не нуждался в runat = "server".

0 голосов
/ 02 июля 2014

Следующий ответ не мой, а ОП (который был включен в вопрос). Я убираю это из вопроса и делаю это вики сообщества.


Я дошёл до сути - почти у меня всё работает! По некоторым причинам использование метода ClientScript.RegisterHiddenField, по-видимому, является источником проблемы. Изменение кода для использования метода сохранения базового класса, то есть base.SavePageStateToPersistenceMedium (compressBytes) и обработка объекта Pair, возвращенного base.LoadPageStateFromPersistenceMedium (). Теперь у меня есть рабочее решение. Тест показывает сокращение на 70% на тестовой странице, поэтому я очень доволен этим.

Теперь, когда у меня работает сжатие, я должен порекомендовать, чтобы следующий (первый правильный) Code Review был сосредоточен на удалении viewstate там, где он не нужен.

...