2010-03-04 2 views
9

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

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

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

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

В sometning так:

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

ответ

1

Снова, после некоторых исследований в этом я обобщил свои выводы в блоге о Compressing View State.

Для сохранения сжатого View State, это то, что я сделал:

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); 
} 
+2

Интересно, что, создав свой экземпляр ObjectStateFormatter, он не получает ссылку на страницу, в которой он используется, и поэтому не будет пытаться зашифровать viewstate. Таким образом, ваш сериализованный viewstate намного проще сжимать, хотя он никогда не будет зашифрован независимо от вашей конфигурации. –

0

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

Вот ссылка на состояние зрения на 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

+1

Если кто-то собирается повторно заполнить элементы управления, то зачем вообще вообще использовать абстракцию веб-формы ASP.NET? Очевидно, что поскольку Seb отметил это как asp.net-webforms, «это не вариант. – IrishChieftain

+3

Вы можете использовать веб-формы без состояния представления. Люди делают это все время. Есть тонны мелочей, которые элементы управления обрабатывают для вас без даже касаясь окна просмотра. – kemiller2002

+0

Репопуляционные элементы управления не являются одним из них - вот почему мы в первую очередь используем веб-формы. Я думаю, что нужно отключить его выборочно для элементов управления, которые ему не нужны. – IrishChieftain

8

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

+3

+1 Я думаю, что мы все виноваты в том, что мы не проверяем наши страницы. – IrishChieftain

+0

+0,5, но слишком много случаев, когда элементам управления ASP.Net требуется ViewState, даже если они не имеют законных оснований требовать этого. Например, если я правильно помню, события, создаваемые с помощью элементов управления в DataGrid/DataView/DataList, будут неправильно вызваны, если у datagrid отключена функция просмотра (несмотря на то, что postback с правильными параметрами все еще выполняется на стороне клиента) – ckarras

2

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

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

+7

ViewState только base-64. Он не «сжат», если не считать сжатие базы-64. – Thomas

+1

Это правда, но его общая точка тоже не ошибается. Композицию Base64 очень сложно сжимать со стандартными алгоритмами. Попытка получить значительную экономию за счет сжатия ViewState бесполезна. –

+1

Строка ViewState не может быть легко сжата, но не потому, что она закодирована в base64. На самом деле, он зашифрован до того, как он закодирован, и все, что зашифровано, по определению трудно сжимать. Вы должны добавить сжатие перед шифрованием. –

7
  1. Избегайте использования ViewState
  2. Использовать сжатие на сервере IIS.
  3. Вы можете wireup то, что будет сжимать ViewState в и из страницы, делая что-то вроде:
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)); 
    } 
} 
+0

Предположительно, если вы используете это, вам также нужно будет удалить исходное скрытое поле ViewState? –

+0

В методе Save ...() я бы проверил, меньше ли viewStateBytes или Compress (viewStateBytes), а затем либо напишите __VIEWSTATE (с несжатым), либо __COMPRESSED_VIEWSTATE. Нет смысла отправлять сжатую версию, если она окажется больше. –

+0

@Graham - На самом деле нет. Вы перехватываете вызовы, которые будут сохраняться в нормальном скрытом поле __VIEWSTATE, чтобы оно было пустым. – Thomas

1

Это визуализация XML-lized вашей публикуемой ViewState:

<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-модулям, но это может быть не очень практичным и не нужно.

В случае, если viewstate намного больше в вашем реальном приложении, избегайте вообще получать объекты в viewstate.Это может быть достигнуто путем инициализации элементов управления в методах 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() может работать в более поздний момент, в результате чего эти свойства в конечном итоге попадают в viewstate. Если инициализация элемента управления не может произойти в OnInit(), установка EnableViewState="false" может использоваться в качестве обходного пути.

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

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

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

6

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

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

+0

Никогда не ошибаюсь, чтобы ответить на старый вопрос. Один голос от меня и, может быть, какой-то крутой значок от SO: P –

0

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