13

语境:

我经常遇到这样的情况,我们的 ASP.NET 页面必须在 GridView 上向用户显示数据,让他随意更改(单元格上的文本框),并且只有在他实际点击“保存按钮”。该数据通常是页面上信息的虚拟状态,这意味着用户可以更改所有内容而无需真正保存,直到他点击“保存按钮”。在这些情况下,始终存在需要跨 ASP.NET 回发持久化的数据列表。该数据可能是 a 的一个实例,也可能DataTable只是一些List<Someclass>.

我经常看到人们实现这一点并将数据保存在Session. 在这种情况下,当涉及到一些用户在打开多个选项卡的情况下(有时在同一页面上)导航时,我通常也会看到问题。两个不同选项卡的数据会合并并导致信息被打乱的问题。

Session 的常用用法示例:

private List<SomeClass> DataList
{
    get
    {
        return Session["SomeKey"] as List<SomeClass>;
    }
    set 
    {
        Session["SomeKey"] = value;
    }
}

人们经常尝试通过执行以下操作来解决它:

protected void Page_Load(object sender, EventArgs e)
{
    if (!IsPostBack)
    {
        DataList = null
    }
    else
    {
        FillGridView(DataList);
    }
}

但是当两个选项卡已经加载并且用户正在更改 GridView 值并且出于某种奇怪的原因他试图通过点击另一页上的“保存”按钮来保存数据时呢?我个人不喜欢这个选项。

执行此操作的其他方法是将数据放在ViewState. 然而,当涉及到持久化非常大的列表时,当它存储在页面上时,它可能会严重影响页面 ( HiddenField)。

但是,使这项工作的最佳方法是什么?曾经,我想与whereSession一起使用将保存一个唯一标识符,该标识符将索引保存的数据。这将阻止在浏览器上的选项卡之间共享数据:ViewStateViewStateSession

private List<SomeClass> DataList
{
    get
    {
        if (ViewState["SomeKey"] == null)
        {
            ViewState["SomeKey"] = Guid.NewGuid().ToString();
        }

        return Session[ViewState["SomeKey"].ToString()] as List<SomeClass>;
    }
    set {

        if (ViewState["SomeKey"] == null)
        {
            ViewState["SomeKey"] = Guid.NewGuid().ToString();
        }

        Session[ViewState["SomeKey"].ToString()] = value;
    }
}

另一方面,每次用户进入页面时,它都会向 Session 存储一个新的数据列表。这会影响服务器内存。也许他们可以以某种方式被抹去。

问题:

考虑到浏览器上多个选项卡的上下文,以及降低服务器和维护编码团队的成本,在 Postbacks 中持久保存此类数据的最佳方式是什么?

更新:

正如@nunespascal 很好地发布的那样,一种选择是将 存储ViewStateSession使用SessionPageStatePersister. 但不幸的是,这不是我的选择。然而,它与我的上一个示例并没有太大区别,将数据保存在由存储在 ViewState 中的 UniqueId 索引的 Session 上。

还有其他选择吗?

4

2 回答 2

2

这个问题有一个简单的解决方案。将 ViewState 存储在 Session 中。

为此,您需要使用SessionPageStatePersister

参考:页面状态持久化

您需要做的就是覆盖PageStatePersister并使用它SessionPageStatePersister而不是默认值HiddenFieldPageStatePersister

protected override PageStatePersister PageStatePersister
{
    get
    {
        return new SessionPageStatePersister(this);
    }
}

这甚至可以为您省去维护唯一密钥的麻烦。隐藏字段将自动用于为页面的每个实例保留唯一键。

于 2013-02-14T11:43:31.567 回答
0

我遇到过类似的情况。这个想法是,如果您允许每个用户的长时间会话来更改网格视图,这意味着您还会遇到并发问题,因为最终您将只接受对数据的最后一组修改。

所以,我的解决方案是,允许对数据库进行更改,但确保所有用户通过SignalR看到相同的状态。

现在,并发问题已经消失,但您仍然需要即时进行更改。毕竟,您可能不想保存更改。我通过应用命令设计模式解决了这个问题。现在,任何一组更改都可以被批准或放弃。每当您检查索引时,您都会看到最后批准的网格视图。转到更新页面,您会看到实时更新的网格视图。此外,请转到修订版以查看旧的批准 gridview -命令设计模式的另一个优点-。

于 2017-11-08T11:33:50.950 回答