ASP.NET: сжатие ViewState - PullRequest
       10

ASP.NET: сжатие ViewState

9 голосов
/ 04 марта 2010

Каковы последние и лучшие способы сжатия содержимого ASP.NET ViewState?

Как насчет производительности этого? Стоит ли держать страницы быстрыми и минимизировать трафик данных?

Как я могу сделать:

<input type="hidden" name="__VIEWSTATE" id="__VIEWSTATE" 
value="/wEPDwUKMTM4Mjc3NDEyOWQYAQUeX19Db250cm9sc1JlcXVpcmVQb3N0QmFja0tleV9fFgkFLGN0b
DAwJENvbnRlbnRQbGFjZUhvbGRlcl9NYWluQ29udGVudCRSYWRCdXQxBSxjdGwwMCRDb250ZW50UGxhY2VIb
2xkZXJfTWFpbkNvbnRlbnQkUmFkQnV0MQUsY3RsMDAkQ29udGVudFBsYWNlSG9sZGVyX01haW5Db250ZW50J
FJhZEJ1dDIFLGN0bDAwJENvbnRlbnRQbGFjZUhvbGRlcl9NYWluQ29udGVudCRSYWRCdXQyBSxjdGwwMCRDb
250ZW50UGxhY2VIb2xkZXJfTWFpbkNvbnRlbnQkUmFkQnV0MwUsY3RsMDAkQ29udGVudFBsYWNlSG9sZGVyX
01haW5Db250ZW50JFJhZEJ1dDQFLGN0bDAwJENvbnRlbnRQbGFjZUhvbGRlcl9NYWluQ29udGVudCRSYWRCd
XQ0BSxjdGwwMCRDb250ZW50UGxhY2VIb2xkZXJfTWFpbkNvbnRlbnQkUmFkQnV0NQUsY3RsMDAkQ29udGVud
FBsYWNlSG9sZGVyX01haW5Db250ZW50JFJhZEJ1dDXz21BS0eJ7991pzjjj4VXbs2fGBw==" />

В чем-то вроде этого:

<input type="hidden" name="__VIEWSTATE"  id="__VIEWSTATE" 
value="/wEPDwUKMTM4Mjc3N==" />

Ответы [ 8 ]

8 голосов
/ 04 марта 2010
  1. Избегайте использования ViewState
  2. Использовать сжатие на сервере IIS.
  3. Вы можете подключить что-то, что сожмет состояние просмотра на страницу и из нее, выполнив что-то вроде:
public abstract class PageBase : System.Web.UI.Page
{
    private ObjectStateFormatter _formatter = new ObjectStateFormatter();

    private static byte[] Compress( byte[] data )
    {
            var compressedData = new MemoryStream();
            var compressStream = new GZipStream(output, CompressionMode.Compress, true);
            compressStream.Write(data, 0, data.Length);
            compressStream.Close();
            return compressedData.ToArray();
    }
    private static byte[] Uncompress( byte[] data )
    {
            var compressedData = new MemoryStream();
            input.Write(compressedData, 0, compressedData.Length);
            input.Position = 0;
            var compressStream = new GZipStream(compressedData, CompressionMode.Decompress, true);
            var uncompressedData = new MemoryStream();
            var buffer = new byte[64];
            var read = compressStream.Read(buffer, 0, buffer.Length);

            while (read > 0)
            {
                uncompressedData.Write(buffer, 0, read);
                read = compressStream.Read(buffer, 0, buffer.Length);
            }
            compressStream.Close();
            return uncompressedData.ToArray();
    }
    protected override void SavePageStateToPersistenceMedium(object viewState)
    {
        var ms = new MemoryStream();
        _formatter.Serialize(ms, viewState);
        var viewStateBytes = ms.ToArray();
        ClientScript.RegisterHiddenField("__COMPRESSED_VIEWSTATE"
            , Convert.ToBase64String( Compress(viewStateArray)) );
    }
    protected override object LoadPageStateFromPersistenceMedium()
    {
        var compressedViewState = Request.Form["__COMPRESSED_VIEWSTATE"];
        var bytes = Uncompress( Convert.FromBase64String( compressedViewState ) );
        return _formatter.Deserialize( Convert.ToBase64String( bytes ) );
    }
}
8 голосов
/ 04 марта 2010

Простой ответ может быть не тем, что вы хотите услышать. Слишком часто элементы управления на странице имеют состояние просмотра по умолчанию, когда им это действительно не нужно. Хорошей идеей будет отключение состояния просмотра, пока вы не узнаете, что оно вам понадобится, и включайте его только для (надеюсь) нескольких случаев, когда вы действительно хотите сохранить состояние просмотра.

6 голосов
/ 13 мая 2011

Я понимаю, что это старый поток, но мы уже давно используем HttpModule RadCompression от Telerik, и он невероятно хорошо работает при сжатии ответов ViewState, AJAX и Web-сервисов. Вы также можете обманывать и сохранять ViewState в сеансе - хорошо для сайтов с низким трафиком.

http://www.telerik.com/help/aspnet-ajax/radcompression.html

1 голос
/ 23 сентября 2011

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

1 голос
/ 09 апреля 2010

Опять же, после некоторого исследования этого я обобщил свои выводы в блоге о Сжатии состояния просмотра .

Чтобы сохранить сжатое состояние просмотра, я сделал следующее:

protected override void SavePageStateToPersistenceMedium(object state) {
    SaveCompressedPageState(state);
}

private void SaveCompressedPageState(object state) {
    byte[] viewStateBytes;
    using(MemoryStream stream = new MemoryStream()) {
        ObjectStateFormatter formatter = new ObjectStateFormatter();
        formatter.Serialize(stream, state);
        viewStateBytes = stream.ToArray();
    }

    byte[] compressed = CompressionHelper.Compress(viewStateBytes);
    string compressedBase64 = Convert.ToBase64String(compressed);

    ClientScript.RegisterHiddenField(ViewStateFieldName, compressedBase64);
}

А для загрузочной части этот код заставил меня работать:

protected override object LoadPageStateFromPersistenceMedium() {
    return LoadCompressedPageState();
}

private object LoadCompressedPageState() {
    string viewState = Request.Form[ViewStateFieldName];
    if(string.IsNullOrEmpty(viewState)) {
        return string.Empty;
    }

    byte[] decompressed = CompressionHelper.Decompress(viewState);
    string decompressedBase64 = Convert.ToBase64String(decompressed);

    ObjectStateFormatter formatter = new ObjectStateFormatter();
    return formatter.Deserialize(decompressedBase64);
}
1 голос
/ 08 марта 2010

Это XML-визуализация вашего опубликованного состояния:

<viewstate>
  <Pair>
    <Pair>
      <String>1382774129</String>
    </Pair>
  </Pair>
</viewstate>
<controlstate>
  <HybridDictionary>
    <DictionaryEntry>
      <String>__ControlsRequirePostBackKey__</String>
      <ArrayList>
        <String>ctl00$ContentPlaceHolder_MainContent$RadBut1</String>
        <String>ctl00$ContentPlaceHolder_MainContent$RadBut1</String>
        <String>ctl00$ContentPlaceHolder_MainContent$RadBut2</String>
        <String>ctl00$ContentPlaceHolder_MainContent$RadBut2</String>
        <String>ctl00$ContentPlaceHolder_MainContent$RadBut3</String>
        <String>ctl00$ContentPlaceHolder_MainContent$RadBut4</String>
        <String>ctl00$ContentPlaceHolder_MainContent$RadBut4</String>
        <String>ctl00$ContentPlaceHolder_MainContent$RadBut5</String>
        <String>ctl00$ContentPlaceHolder_MainContent$RadBut5</String>
      </ArrayList>
    </DictionaryEntry>
  </HybridDictionary>
</controlstate>

В основном лишь несколько радиокнопок, которые хотели бы знать об их существовании (браузеры не отправляют поле <input type="radio"> с постданными, если оно не отмечено). Это уже довольно минимально.

Скорее всего, его можно сжать, подключив методы загрузки / сохранения или модули HTTP, но это может быть не очень практичным и не нужно.


В случае, если в вашем реальном приложении намного больше представление, избегайте попадания каких-либо объектов в него. Это может быть достигнуто путем инициализации элементов управления в методах OnInit() или Page_Init() вместо значения по умолчанию Page_Load().

Обоснование этого можно найти на http://weblogs.asp.net/infinitiesloop/archive/2006/08/03/Truly-Understanding-Viewstate.aspx и http://msdn.microsoft.com/en-us/library/ms972976.aspx

Краткое резюме:

  • ViewState - это просто хранилище для почти всех свойств элемента управления, включая значения по умолчанию.
  • После установки значений по умолчанию OnInit() вызывается метод TrackViewState().
  • Любые последующие изменения (например, Page_Load()) или обработчик событий будут отслеживаться и отправляться клиенту. Таким образом, эти элементы управления могут восстановить свое состояние при следующем запросе.
  • Вместо того чтобы полагаться на каркас для восстановления объектов, восстанавливайте объекты в OnInit() при необходимости. (например, повторное заполнение параметров DropDownList из базы данных).

Одно исключение:

Если элемент управления динамически добавляется в дерево элементов управления, он воспроизводит данные. Их метод OnInit() может быть запущен позднее, в результате чего эти свойства в конечном итоге окажутся в состоянии просмотра. Если инициализация элемента управления не может произойти в OnInit(), в качестве обходного пути можно использовать настройку EnableViewState="false".

Каждый раз, когда мое состояние просмотра неожиданно увеличивается, я использую приложение ViewState Decoder 2.2, чтобы выяснить, что же произошло в состоянии просмотра. Часто это не требуется для данных.

И последнее слово:

Состояние просмотра не используется для повторного заполнения форм !! Эти значения уже отправлены с постданными.

1 голос
/ 04 марта 2010

Seb, ViewState уже сжат ... это то, что вы видите ... сжатая версия вашего управления. Если вы хотите уменьшить накладные расходы, не используйте viewstate:)

Использование Viewstate должно быть минимальным!

0 голосов
/ 04 марта 2010

Лучший способ минимизировать состояние просмотра - просто не использовать его. Это заставит вас заняться дополнительным рабочим программированием (повторное заполнение контрольных значений и т. Д. При отправке назад, но это сэкономит вам объем информации, отправляемой в браузер). Вы не можете вмешиваться в это.

Вот ссылка на состояние просмотра в MSDN:

http://msdn.microsoft.com/en-us/library/ms972976.aspx

Вот ссылка, описывающая некоторые лучшие практики:

http://mnairooz.blogspot.com/2007/01/aspnet-20-viewstate-and-good-practices.html

И еще один при отключении ViewState:

http://www.codeproject.com/KB/aspnet/ASPNET_Best_Practices.aspx

...