Как удалить или сжать ваше viewstate asp.net

Просто потратил много времени, изгнав asp.net большое (но понятно полезное) viewstate из приложения, и я думаю, что стоит поделиться тем, как это делается.

В принципе, я хочу, чтобы этот вопрос был открыт для всех решений для сжатия/сжатия/удаления viewstate.

Ответ 1

Еще один лучший вариант: сверните свой собственный PageStatePersister. Здесь мой, сильно вдохновленный http://aspalliance.com/72:

using System.Web.UI;

... in your page class:

PageStatePersister pageStatePersister;
protected override PageStatePersister PageStatePersister
{
  get
  {
    // Unlike as exemplified in the MSDN docs, we cannot simply return a new PageStatePersister
    // every call to this property, as it causes problems
    return pageStatePersister ?? (pageStatePersister = new BetterSessionPageStatePersister(this));
  }
}

... in your BetterSessionPageStatePersister.cs:

/// <summary>
/// This class allows the viewstate to be kept server-side, so that postbacks are as small as possible.
/// It is similar to the built-in 'SessionPageStatePersister', but it yields smaller postbacks,
/// because the SessionPageStatePersister still leaves some viewstate (possibly it leaves the controlstate)
/// in the postback.
/// </summary>
class BetterSessionPageStatePersister : PageStatePersister
{
  public BetterSessionPageStatePersister(Page page)
    : base(page)
  { }

  const string ViewStateFieldName = "__VIEWSTATEKEY";
  const string ViewStateKeyPrefix = "ViewState_";
  const string RecentViewStateQueue = "ViewStateQueue";
  const int RecentViewStateQueueMaxLength = 5;

  public override void Load()
  {
    // The cache key for this viewstate is stored in a hidden field, so grab it
    string viewStateKey = Page.Request.Form[ViewStateFieldName] as string;

    // Grab the viewstate data using the key to look it up
    if (viewStateKey != null)
    {
      Pair p = (Pair)Page.Session[viewStateKey];
      ViewState = p.First;
      ControlState = p.Second;
    }
  }

  public override void Save()
  {
    // Give this viewstate a random key
    string viewStateKey = ViewStateKeyPrefix + Guid.NewGuid().ToString();

    // Store the view and control state
    Page.Session[viewStateKey] = new Pair(ViewState, ControlState);

    // Store the viewstate key in a hidden field, so on postback we can grab it from the cache
    Page.ClientScript.RegisterHiddenField(ViewStateFieldName, viewStateKey);

    // Some tidying up: keep track of the X most recent viewstates for this user, and remove old ones
    var recent = Page.Session[RecentViewStateQueue] as Queue<string>;
    if (recent == null) Page.Session[RecentViewStateQueue] = recent = new Queue<string>();
    recent.Enqueue(viewStateKey); // Add this new one so it'll get removed later
    while (recent.Count > RecentViewStateQueueMaxLength) // If we've got lots in the queue, remove the old ones
      Page.Session.Remove(recent.Dequeue());
  }
}

Ответ 2

Первый простой вариант, используйте встроенный класс SessionPageStatePersister. Это делает сохранение состояния просмотра в сеансе на сервере, а не отправку его клиенту. Тем не менее, он по-прежнему отправляет меньше viewstate вниз, поэтому не все розы:

using System.Web.UI;
... the following goes in your Page class (eg your .aspx.cs) ...
PageStatePersister pageStatePersister;
protected override PageStatePersister PageStatePersister
{
  get
  {
    // Unlike as exemplified in the MSDN docs, we cannot simply return a new PageStatePersister
    // every call to this property, as it causes problems
    return pageStatePersister ?? (pageStatePersister = new SessionPageStatePersister(this));
  }
}

Этот метод уменьшил особенно большую отдачу от 100 к до 80 тыс. Не здорово, но хорошее начало.

Ответ 4

Важно сначала понять, что это за образцовое представление, и почему вы хотите его в первую очередь. После этого просто нужно помнить о том, что приложение делает для вас, и помнить о том, чтобы прикрепить UseViewState = "false" ко всем элементам, которые обычно будут использовать viewstate.

Теперь, чтобы запомнить, почему это полезно, у вас будет определенная потребность чаще извлекать вещи вручную.

Время и место для всех инструментов, да?

Ответ 5

Полностью избавиться от него:

    protected override object LoadPageStateFromPersistenceMedium()
    {
        return null;
    }

    protected override void SavePageStateToPersistenceMedium(object viewState)
    {
    }

Ответ 6

Вы можете попробовать it или it!

Ответ 7

Вы можете с небольшим обманом захватить только сериализацию состояния страницы, получив из System.Web.Page и переопределив свойство PageStatePersister:

    private PageStatePersister _pageStatePersister = null;
    protected override PageStatePersister PageStatePersister
    {
        get { return _pageStatePersister ?? (_pageStatePersister = new PersistState(this)); }
    }

Как только вы это сделаете, вы можете получить новый экземпляр из HiddenFieldPageStatePersister и оттуда использовать отражение для изменения реализации сохранения:

    class PersistState : HiddenFieldPageStatePersister, IStateFormatter
    {
        public PersistState(Page p) : base(p)
        {
            FieldInfo f = typeof(PageStatePersister).GetField("_stateFormatter", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.SetField);
            f.SetValue(this, this);
        }

        object IStateFormatter.Deserialize(string serializedState)
        {
            BinaryFormatter f = new BinaryFormatter();
            using (GZipStream gz = new GZipStream(new MemoryStream(Convert.FromBase64String(serializedState)), CompressionMode.Decompress, false))
                return f.Deserialize(gz);                    
        }

        string IStateFormatter.Serialize(object state)
        {
            BinaryFormatter f = new BinaryFormatter();
            using (MemoryStream ms = new MemoryStream())
            {
                using (GZipStream gz = new GZipStream(ms, CompressionMode.Compress, true))
                    f.Serialize(gz, state);
                return Convert.ToBase64String(ms.ToArray());
            }
        }
    }

BEWARE

Это пример только для исследовательских целей. Вышеприведенный код является ОБЕСПЕЧЕНИЕМ БЕЗОПАСНОСТИ, поскольку он не подписывает и не шифрует полезную нагрузку, и поэтому его можно легко взломать любым, кто пытается причинить вред вашему сайту.

Снова НЕ ИСПОЛЬЗУЙТЕ ЭТОТ КОД без полного и полного понимания безопасности, криптографии и сериализации .Net.

</warning>

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

Ответ 8

Один из методов, который мы использовали в моей компании, - удалить большую часть из них, удалив вызовы runat="server". Затем мы используем javascript или хорошую библиотеку javascript, такую ​​как jQuery или Prototype, для заполнения элементов HTML с помощью аякс-вызовов на сервере.

Мой босс проделал большую работу с веб-сайтом, на котором было несколько мегабайт данных viewstate. Он использовал вышеупомянутый метод, и он "отлично работает без просмотра".