【问题标题】:Using session like ViewState使用像 ViewState 这样的会话
【发布时间】:2009-08-13 13:27:36
【问题描述】:

我正在修复一个 ASP.NET 应用程序,该应用程序大量使用会话来跟踪每页数据。问题之一是页面之间的会话流血。

ViewState 会是更好的解决方案,除了:

  • 数据不可序列化
  • 每次回发来回发送的数据太多

所以我想:

  • 为会话数据创建一个页面键(即在隐藏字段中粘贴一个随机 GUID)
  • 即使整个会话处于活动状态,也会使废弃页面中的数据过期

有没有让部分会话数据过期的好方法?

【问题讨论】:

  • 更多信息会很有用。您是要为每一页存储相同的数据结构,还是每页存储一个唯一的数据结构?为什么会话数据在用户离开后仍然存在问题?
  • @Christian Hayter 他的问题暗示多个页面使用相同的会话密钥。因此,用于页面 A 的数据将留在会话中以供页面 B 查找。

标签: asp.net session viewstate


【解决方案1】:

以下临时存储位置可用:

  1. 会话。这会跟随用户并使用 cookie。它可以配置为使用 URL 参数来检索。会话也可以配置为存储在 web 服务器、SQL Server 或状态服务器上的 process(inproc) 中。 InProc 可以存储任何数据类型,但其他类型需要可序列化的类型。
  2. 缓存。存储在缓存中的数据可供会话中的任何用户使用。它的工作方式类似于会话,因为对象可以通过密钥检索。缓存的一个更好的功能是您可以控制事物的存储时间,并且您可以在它们过期时使用事件。您可以在此处存储任何内容,但在网络场中使用它时可能会遇到问题。
  3. HttpContext。这仅限于当前请求。请记住,请求可以是 Web 服务调用、获取网页以获取 HTML 的调用,或对返回图像的服务的调用。任何东西都可以在这里存储。
  4. 视图状态。视图状态的范围是一个页面。必须是可序列化的。

您可能想要检查缓存。如果您使用的是 webfarm,它将无法工作,但您可以使用某种 GUID 作为映射回会话的键。

【讨论】:

  • 如果我可以保证它会在会话持续 20 分钟左右时,缓存可能是可能的。
  • 这里是我使用的缓存代码:Cache.Insert(key, value, null, System.Web.Caching.Cache.NoAbsoluteExpiration, new TimeSpan(0, 20, 0), System.Web。 Caching.CacheItemPriority.NotRemovable, null);
  • CacheItemPriority.NotRemovable 防止缓存因内存压力而删除数据。
【解决方案2】:

我可能会这样做:

  1. 创建一个对象来存储您希望特定于页面的状态信息。如果不同的页面需要不同的信息,请创建多个类。
  2. 将此对象存储在单个会话键中:Session["PageSpecific"];例如。
  3. 创建一个继承自 System.Web.UI.Page 的类。
  4. 在基类的 OnLoad 事件中,如果页面没有执行回发,则清除会话密钥。
  5. 创建并调用一个可重载的方法来填充会话对象。
  6. 不要从每个页面中的 System.Web.UI.Page 继承,而是从新的基类继承。

类似这样的东西(警告:空气代码。可能包含语法错误):

public class PageBase
    : System.Web.UI.Page
{
    protected overrides OnInit(System.EventArgs e) {
        base.OnInit(e);

        if(!this.IsPostBack) {
            Guid requestToken = System.Guid.NewGuid();
            ViewState["RequestToken"] = requestToken;

            Session["PageSpecific" & requestToken.ToString()] = InitializePageSpecificState();
        }
    }

    protected virtual object InitializePageSpecificState() {
        return new GenericPageState();
    }

    //You can use generics to strongly type this, if you want to.
    protected object PageSpecificState {
        get {
            return Session["PageSpecific" & ViewState["RequestToken"].ToString()];
        }
    }
}

【讨论】:

  • 这和上一个答案有同样的问题。我的问题可能还不够清楚。一些用户可能在多个选项卡中查看 Default.aspx,请求数据不同(甚至相同)。我希望每个都有自己的服务器端存储空间。
  • @Korey 编辑您的原始问题将是一件好事。它也很容易解决:在初始加载时生成某种形式的令牌(例如 Guid)。将其附加到会话密钥 (Session["PageSpecific" & requestToken])。将密钥存储在 ViewState 中。
  • @Korey 允许打开多个选项卡的主要困难是,在整个 Session 过期之前,您无法从请求中清理 Session ......这可能是也可能不是问题取决于您的用户群规模。
【解决方案3】:

也许在每个页面上 !IsPostBack 或通过基本页面,您可以取消对与该页面无关的会话数据的所有引用。每次用户转到站点中的另一个页面时,这将使数据“过期”。

如果用户离开站点或处于非活动状态,在会话到期之前您无能为力,但在这种情况下,每个用户只有一页的会话数据。

【讨论】:

  • 我确实希望允许查看多个页面(同一页面,但具有不同的请求数据)。我不希望一个页面自动销毁另一个页面的会话数据,我只希望它能够过期。
猜你喜欢
  • 1970-01-01
  • 2010-12-26
  • 1970-01-01
  • 2018-10-04
  • 2019-04-21
  • 1970-01-01
  • 1970-01-01
  • 2015-08-03
  • 2021-05-13
相关资源
最近更新 更多