Сжатие ASP.Net ViewState: я должен беспокоиться? - PullRequest
2 голосов
/ 13 мая 2009

Итак, я работаю над сайтом, который пытается оптимизировать работу с телефонами (в том числе практически с любым браузером). Из-за особенностей сайта я хочу, чтобы он загружался как можно быстрее. На данный момент я думаю, что размер страницы составляет около 30 КБ.

Теперь я использую viewstate, в основном для таких вещей, как datagrids, а не сам "сохраняю" какие-либо поля.

Я видел много примеров, подобных этому (я клянусь, что не мой блог) с учетом 2.0, но ничего не связано с 3.5, что заставляет меня задаться вопросом, ничего не изменилось с тех пор, или сжатие состояния просмотра потерял самообладание.

Вопрос в том, стоит ли мне пытаться сжать состояние представления или есть лучшее решение?

Ответы [ 5 ]

4 голосов
/ 13 мая 2009

Я использую viewstate, в основном для таких вещей, как datagrids, а не для "сохранения" каких-либо полей в нем.

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

Помните, что пользователь должен загружать содержимое viewstate из браузера на сервер, а затем загружать его обратно при каждой обратной передаче. Если у вас есть 100 Мбит соединение с веб-сервером & mdash; как с корпоративной сетью, где веб-формы становятся более популярными & mdash; тогда viewstate великолепен. Но в браузерах сотовых телефонов многие пользователи могут использовать телефонный набор или даже хуже: платит байтом . В этом сценарии я постараюсь максимально отключить его и включить только при необходимости.

2 голосов
/ 21 марта 2011

Сжатие и распаковка данных в памяти

Прежде всего, нам нужен способ сжатия и распаковки массива байтов в памяти. Я собрал этот простой статический класс, который предоставляет два метода: Compress и Decompress. Два доступных класса, GZipStream и DeflateStream, согласно MSDN, используют один и тот же алгоритм, поэтому не имеет значения, какой из них вы выберете.

Код, приведенный ниже, действительно прост и не нуждается в дополнительных пояснениях:



    using System.IO;
    using System.IO.Compression;

    public static class Compressor {

      public static byte[] Compress(byte[] data) {
        MemoryStream output = new MemoryStream();
        GZipStream gzip = new GZipStream(output, 
                          CompressionMode.Compress, true);
        gzip.Write(data, 0, data.Length);
        gzip.Close();
        return output.ToArray();
      }

      public static byte[] Decompress(byte[] data) {
        MemoryStream input = new MemoryStream();
        input.Write(data, 0, data.Length);
        input.Position = 0;
        GZipStream gzip = new GZipStream(input, 
                          CompressionMode.Decompress, true);
        MemoryStream output = new MemoryStream();
        byte[] buff = new byte[64];
        int read = -1;
        read = gzip.Read(buff, 0, buff.Length);
        while(read > 0) {
          output.Write(buff, 0, read);
          read = gzip.Read(buff, 0, buff.Length);
        }
        gzip.Close();
        return output.ToArray();
      }
    }

Вам нужно сохранить этот класс в файле .cs и поместить его в каталог App_Code вашего приложения ASP.NET, убедившись, что он содержится в надлежащем настраиваемом пространстве имен (если вы не укажете пространство имен, класс будет быть доступным во встроенном пространстве имен ASP).

Сжатие ViewState

Теперь мы можем сжать ViewState страницы. Чтобы сделать это, мы должны переопределить два метода LoadPageStateFromPersistenceMedium и SavePageStateToPersistenceMedium. Код просто использует дополнительное скрытое поле __VSTATE для хранения сжатого ViewState. Как вы можете видеть, просматривая HTML-код страницы, поле __VIEWSTATE пустое, а наше поле __VSTATE содержит сжатый ViewState, закодированный в Base64. Давайте посмотрим код.



    public partial class MyPage : System.Web.UI.Page {

      protected override object LoadPageStateFromPersistenceMedium() {
        string viewState = Request.Form["__VSTATE"];
        byte[] bytes = Convert.FromBase64String(viewState);
        bytes = Compressor.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 = Compressor.Compress(bytes);
        ClientScript.RegisterHiddenField("__VSTATE", Convert.ToBase64String(bytes));
      }

      // The rest of your code here...

    }

В первом методе мы просто декодируем из Base64, распаковываем и десериализуем содержимое __VSTATE и возвращаем его во время выполнения. Во втором методе мы выполняем противоположную операцию: сериализуем, сжимаем и кодируем в Base64. Строка Base64 затем сохраняется в скрытом поле __VSTATE. Объект LosFormatter выполняет задачи сериализации и десериализации.

Вы также можете создать новый класс, например, CompressedPage, унаследованный от System.Web.UI.Page, в котором вы переопределяете два метода, а затем наследуете свою страницу от этого класса, например MyPage: CompressedPage. Просто помните, что .NET имеет только одно наследование, и, следуя этим путем, вы «тратите» свой единственный шанс наследования на использование сжатия ViewState. С другой стороны, переопределение двух методов в каждом классе - пустая трата времени, поэтому вы должны выбрать способ, который наилучшим образом соответствует вашим потребностям.

Вышесказанное было впервые опубликовано Дарио Солерой на codeproject. http://www.codeproject.com/Articles/14733/ViewState-Compression

1 голос
/ 13 мая 2009

Я не думаю, что это пошло не так, просто сохранение состояния просмотра в 2.0 должно работать так же, как сохранение в 3.5. Лучший способ уменьшить viewstate - не использовать его, но это не всегда возможно.

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

Редактировать

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

Вот код проекта статьи
Похоже на хорошую статью

0 голосов
/ 22 ноября 2011

Сжатие состояния просмотра может уменьшить его только на 50% или около того. Я пошел на несколько шагов вперед и использовал метод подстановки ViewState, где ViewState заменяется GUID на странице. Фактические данные ViewState сохраняются в базе данных на самом сервере, а клиент (браузер) получает и отправляет всего лишь 62-байтовый токен. Уменьшено на 200-300 КБ больших ViewStates до 62 байт.

Здесь я написал, как это сделать с кодом .. http://ashishnangla.com/2011/07/21/reducing-size-of-viewstate-in-asp-net-webforms-by-writing-a-custom-viewstate-provider-pagestatepersister-part-12/

0 голосов
/ 13 мая 2009

Наличие ViewState противоречит быстрой загрузке веб-страницы. Зачем вам нужен ViewState? Пересмотрите свой дизайн и используйте как можно меньше. Я бы поместил пакет данных Session на сервер и / или базу данных, пока не появится причина сохранить некоторые данные во ViewState.

...