2

我仍然是一个相对的菜鸟,但是我对我所做的一个小测试的结果感到惊讶。

我想在视图状态中存储一个字符串列表。迄今为止,当我想修改列表时,我从 viewstate 中检索了它,执行了 List.Add 并将其保存回 viewstate。

但是,我随后决定做一个简单的测试,如下所示:

    protected void Page_Load(object sender, EventArgs e)
    {
        if (!IsPostBack)
        {
            List<string> s = new List<string>();
            s.Add("abc");
            s.Add("def");
            ViewState.Add("test", s);

            s.Add("one");
            s.Add("two");
        }
        var t = (List<string>)ViewState["test"];

        foreach (var str in t)
        {
            Response.Write(str + "<br>");
        }
    }

如您所见,我创建了一个列表,将其添加到 viewstate,然后修改该列表。令我惊讶的是,即使在回发之后,列表也会在 viewstate 中进行修改。

问题是,这样做是否安全,如果是,是否被认为是不好的做法。

提前致谢。

4

3 回答 3

1

ViewState 仅在回发时序列化到客户端页面。在此之前,它保存在内存中并且可以安全地进行编辑。

我经常使用 ViewState 作为属性的支持者:

public Class1 MyClass1
{
    get { return (Class1)ViewState["MyClass1"]; }
    set { ViewState["MyClass1"] = value; }
}

一般来说,我不会认为这样做是不好的做法,但以下情况除外:

  1. 存储敏感数据——由于数据被序列化到客户端,它很容易被改变。
  2. 大量数据 - 由于数据被持久化到客户端,因此大量数据会显着增加页面加载时间。
于 2013-08-01T16:16:40.880 回答
1

您看到这种情况的原因是 Asp.Net WebForms页面生命周期。在您修改视图状态时,Asp.Net 尚未将页面输出呈现为 HTML。由于您正在添加对字典的引用,因此您在渲染之前所做的更改将显示出来。生命周期中的其他点可能不会出现此类更改,尽管我没有调查过是否是这种情况。

但是,我不会考虑这种好的做法。ViewState 在您的网页中被序列化为隐藏的表单字段,因此其中的任何数据都是您页面的一部分。这充其量只能增加发送给客户端的响应的大小(如果您在那里存储大量数据,有时会显着增加)。由于它是一个隐藏的表单域,所以返回服务器的请求也更大。

它还可以打开安全漏洞。你不能信任必要的信任视图状态,尽管有一些方法可以保护它,但我会说最好不要发送任何你不需要渲染页面的数据。

作为替代方案,您可以考虑将特定于用户的状态存储在Session中,尽管如果您的应用程序将位于 Web 场中的负载均衡器后面,您确实需要付出一些额外的努力。将数据存储在会话中将使其与其他用户隔离,并且根本不需要将数据暴露给客户端。

于 2013-08-01T16:22:17.500 回答
0

有点主观,但通过实践我认为这没有任何问题。这是页面上不同表单控件中一直发生的事情。控件将编辑与它们自己相关的视图状态信息,并将其保留在回发中。将列表添加到视图状态后对其进行修改时,列表在视图状态中发生变化的原因是它不会立即序列化。该列表通过引用传递给它所在的视图状态集合,直到页面在完成请求前不久序列化视图状态。

于 2013-08-01T16:14:32.993 回答