Getting asp.net to store viewstate in the session

2020-02-11 04:08发布

I'm trying to get asp.net to store viewstate in the session rather than bulking up the html.

Now i've read that asp.net comes with the SessionPageStatePersister which can be used instead of the default HiddenFieldPageStatePersister to do this. I was wondering how i go about dropping it in?

This is what i've got so far: I think i need to create a PageAdapter that returns a SessionPageStatePersister from its GetStatePersister method, and somehow get the page to use this pageadapter. But Page.PageAdapter only has a getter, so i'm not sure how you set it.

See the 'remarks' heading here: http://msdn.microsoft.com/en-us/library/system.web.ui.hiddenfieldpagestatepersister.aspx

Thanks!

3条回答
\"骚年 ilove
2楼-- · 2020-02-11 04:16

In order to use your custom PageAdapter class you have to register it with .browser file. You need to add (if you don't already have) a App_Browsers directory. Then add a .browser file with following XML

<browsers>
    <browser refID="Default">
        <controlAdapters>
           <adapter controlType="System.Web.UI.Page" adapterType="{Your adapter type}" />
        </controlAdapters>
    </browser>
</browsers> 

replace {Your adapter type} with your adapter type.

More information here

Hope this helps.

查看更多
不美不萌又怎样
3楼-- · 2020-02-11 04:17

For what it's worth, here's the code i ended up using to solve the big-picture problem at hand: moving viewstate out of the html. Just pop this into your mypage.aspx.cs:

// Inspired by: http://aspalliance.com/72
const string ViewStateFieldName = "__VIEWSTATEKEY";
const string RecentViewStateQueue = "RecentViewStateQueue";
const int RecentViewStateQueueMaxLength = 5;

protected override object LoadPageStateFromPersistenceMedium()
{
    // The cache key for this viewstate is stored where the viewstate normally is, so grab it
    string viewStateKey = Request.Form[ViewStateFieldName] as string;
    if (viewStateKey == null) return null;

    // Grab the viewstate data from the cache using the key to look it up
    string viewStateData = Cache[viewStateKey] as string;
    if (viewStateData == null) return null;

    // Deserialise it
    return new LosFormatter().Deserialize(viewStateData);
}

protected override void SavePageStateToPersistenceMedium(object viewState)
{
    // Serialise the viewstate information
    StringBuilder _viewState = new StringBuilder();
    StringWriter _writer = new StringWriter(_viewState);
    new LosFormatter().Serialize(_writer, viewState);

    // Give this viewstate a random key
    string viewStateKey = Guid.NewGuid().ToString();

    // Store the viewstate in the cache
    Cache.Add(viewStateKey, _viewState.ToString(), null, Cache.NoAbsoluteExpiration, TimeSpan.FromMinutes(Session.Timeout), CacheItemPriority.Normal, null);

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

    // Some tidying up: keep track of the X most recent viewstates for this user, and remove old ones
    var recent = Session[RecentViewStateQueue] as Queue<string>;
    if (recent == null) 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
    Cache.Remove(recent.Dequeue());
}

And for a super-simple way of using the SessionPageStatePersister, again put this in your mypage.aspx.cs:

protected override PageStatePersister PageStatePersister
{
    get
    {
        return new SessionPageStatePersister(this);
    }
}
查看更多
淡お忘
4楼-- · 2020-02-11 04:20

You sure you want to do this? There are problems

  1. How do you keep individual pages apart? Sure, you can prefix the session state name with the page, eg. Session["/default.aspx-Viewstate"] but what happens when the user has multiple instances of a page open?
  2. So to solve that you put a hidden field with, say, a GUID in each page, which you then use as a key. So your session size grows. And grows. And grows. How will you know if/when you can remove things safely?

If you insist on heading down this read then all you need to do is derive a class from page and override LoadPageStateFromPersistenceMedium() and SavePageStateToPersistenceMedium(). But you'll hate yourself and rip it out eventually.

Just make sure you have HTTP compression turned on at your server, and please, worry about something else instead.

查看更多
登录 后发表回答