Как удалить или сжать ваше представление asp.net - PullRequest
10 голосов
/ 18 января 2011

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

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

Ответы [ 8 ]

7 голосов
/ 18 января 2011

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

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

Этот метод сократил особенно большой постбэк с 100k до 80k.Не отлично, но хорошее начало.

6 голосов
/ 18 января 2011

Переключиться на ASP.NET MVC ! Нет ViewState !

5 голосов
/ 18 января 2011

Еще один лучший вариант, накатить свой собственный 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's 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 голосов
/ 18 января 2011

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

    protected override object LoadPageStateFromPersistenceMedium()
    {
        return null;
    }

    protected override void SavePageStateToPersistenceMedium(object viewState)
    {
    }
2 голосов
/ 18 января 2011

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

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

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

1 голос
/ 18 января 2011

Вы можете с небольшой хитростью перехватить только сериализацию состояния страницы, выведя из 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.

1 голос
/ 18 января 2011

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

0 голосов
/ 18 января 2011

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

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

...