C# 让asp.net在会话中存储viewstate,而不是扩充html

C# 让asp.net在会话中存储viewstate,而不是扩充html,c#,asp.net,session,viewstate,C#,Asp.net,Session,Viewstate,我试图让asp.net在会话中存储viewstate,而不是扩充html 现在我已经读到asp.net附带了SessionPageStatePersister,可以使用它来代替默认的HiddenFieldPageStatePersister来执行此操作。我在想我该怎么把它放进去 到目前为止,我得到的是: 我想我需要创建一个PageAdapter,从它的GetStatePersister方法返回一个SessionPageStatePersister,并以某种方式让页面使用这个PageAdapter

我试图让asp.net在会话中存储viewstate,而不是扩充html

现在我已经读到asp.net附带了SessionPageStatePersister,可以使用它来代替默认的HiddenFieldPageStatePersister来执行此操作。我在想我该怎么把它放进去

到目前为止,我得到的是: 我想我需要创建一个PageAdapter,从它的GetStatePersister方法返回一个SessionPageStatePersister,并以某种方式让页面使用这个PageAdapter。但是Page.PageAdapter只有一个getter,所以我不确定如何设置它

请参见此处的“备注”标题:


谢谢

你确定要这样做吗?有问题

  • 你是如何把每一页分开的?当然,您可以在页面前面加上会话状态名称的前缀,例如session[“/default.aspx Viewstate”],但是当用户打开一个页面的多个实例时会发生什么
  • 为了解决这个问题,您在每个页面中放置了一个隐藏字段,比如说一个GUID,然后将其用作键。因此,会话大小会增加。并且生长。并且生长。您如何知道是否/何时可以安全地移除物品
  • 如果您坚持要向下阅读,那么您所需要做的就是从page派生一个类,并重写LoadPageStateFromPersistenceMedium()和SavePageStateToPersistenceMedium()。但你会恨自己,最终会把它撕下来


    只需确保服务器上已打开HTTP压缩,请担心其他问题。

    要使用自定义PageAdapter类,必须在.browser文件中注册它。你需要添加(如果你还没有)一个App\u浏览器目录。然后添加一个包含以下XML的.browser文件

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


    希望这能有所帮助。

    这是我用来解决眼前大问题的代码:将viewstate移出html。只需将此文件放入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());
    }
    
    protected override PageStatePersister PageStatePersister
    {
        get
        {
            return new SessionPageStatePersister(this);
        }
    }
    

    您是否考虑过将ViewState存储在DB中而不是会话中,这应该会更容易,而且扩展性也会更好Rpm:ViewState已经序列化,所以没有区别。我服务器上的RAM比在澳大利亚网络连接上双向发送100kb viewstate快得多。daveo:Db比RAM慢。缩放不是一个问题——不是那种网站。最后一句话让我笑了,但这是真的。gzip将弥补viewstate的不足。1:我认为这将由内置的SessionPageStatePersister类处理。2:公平调用。我相信我会想出办法的。也许是一个圆形阵列或者什么的。谢谢,这对我有用。但最终,使用此方法并使用SessionPageStatePersister类,它实际上根本没有减少viewstate大小(我对其进行了断点设置以确保调用它)。我认为它只是存储了pagestate,而不是viewstate,所以并不是很大的节省。哦,好吧。无论如何谢谢你!五年后,这个代码仍然值得复制。我可以把它放到VB.NET转换器中,只需几次小的编辑就可以将它粘贴到我的页面上。我从不建议将viewstate存储在服务器内存中,但这是一个临时解决方案,因为我们将已有15年历史的WebForms应用程序重写为使用Angular和WebAPI。只需确保在完成时清理缓存的viewstate,而不是等待它过期。@oscilatingcret因此,在LoadPageStateFromPersistenceMedium()中返回viewstate之前,是否执行Cache.Remove(viewStateKey)?我认为这样做是安全的,因为会为后续回调生成一个新的viewstate?在SavePageStateToPersistenceMedium()中清除旧的可能仍然是一个好主意忽略我的上一个建议。加载后不能删除;如果用户刷新页面并发回相同的表单数据,该怎么办?它将丢失该页的状态。@Radderz在完全后打包后,我没有丢失任何viewstate。代码在页面上注册了一个隐藏字段,该字段在回发过程中保持不变,因此GUID被保留。加载新页面(即,不是IsPostback)时,将创建一个新的GUID。至少,这是我的理解