如何在没有声明的情况下随处访问 ViewState?

问题描述

我一直认为要在多个方法中访问变量,您必须将其声明为类成员或将其作为参数传递。 然而,我最近正在查看一些示例代码来学习 .NET,我遇到了一种叫做 ViewState 的东西。我知道它的目的是跟踪一些页面和控件属性,但我不明白这里是如何使用它的。

代码看起来有点像这样:

private void RowValidating(object sender,EventArg e) {
      ViewState[Backup] = ViewState["TestId"];
      // more code that does not include ViewStates
}


private void UpdateBox() {
     // some code that does not include ViewStates
     int box_id = ViewState[Backup];
     // ...
}

ViewState 如何随处访问?它没有在类或任何其他类文件中的任何地方声明,并且这个 [Backup] 键只是在没有初始化的情况下创建的。据我所知,在调用 RowValidating 之前,ViewState[Backup] 不存在。

是否可以将 ViewState 设置为全局变量?或者我可以总是制作可以在任何地方访问的自己的密钥吗?它似乎表现得像一本字典,但我认为在处理新项目时符号是 dict.Add(item,value),而不是 dict[item] = value。它必须在某处初始化,也许在某个导入的库中?

解决方法

Session() 和 ViewState 都可以用于在代码中持久化值。您不必声明它们,它们是内置于 asp.net 的功能

Session() 是针对每个用户的,因此通常用于保存值,甚至在页面之间传递值。但是在某些情况下,ViewState 更可取。

例如,如果您有产品 ID 或什至是您即将购买的房子?好吧,如果您打开了两个选项卡,甚至打开了两个不同的浏览器,那么 Session() 将适用于所有打开的浏览器实例。因此,如果用户打开了两个单独的浏览器,那么您在 session() 中保留的“ID”值将适用于两者(因此,请注意,当您将 3 个浏览器页面打开到 3 个不同的页面时,您打算购买哪个房屋 ID房子开了吗?所以 session() 对用户来说是全局的。

因此,对于“保留”一行数据以传递给下一个网页/表单,Session() 可能很棒 - 但请记住,它在该用户打开和运行的所有页面之间共享。因此 session() 仍然是针对每个用户的 - 但对该用户来说是全局的。

Session() 可以是服务器“在内存中”(默认)。但是,如果您使用的是服务器群,那么这些多个服务器中的每一个都不能共享它们的内存,因此您必须采用所谓的基于 SQL 服务器的会话。因此,代替将这些值保存在内存中,session() 状态是从存储在 SQL 服务器中的序列化“blob”中改组的。因此,如果您在 Azure 等基于云的系统上托管您的站点(而不是常规托管),则 session() 无法在这些所谓的基于“大型服务”的系统上持续存在(或者您正在使用带有负载的服务器场)出于可扩展性的原因,您有多个服务器托管站点的平衡)。由于托管网站的多个副本可以同时存在,因此需要一种拥有公共 session() 的方法(因此他们将 blob 内容推送到 SQL 服务器中)。所以你仍然可以使用 session(),但它实际上存储在 sql server 中。需要注意的是,在某些情况下,基于 SQL 服务器的 session() 会降低性能。高达 10% - 也许更多。我发现在大多数情况下,您不会注意到这种性能下降。但它可以无缝运行()并且实际上采用基于 SQL 服务器的会话意味着 session() 不会因为站点执行错误而频繁丢失。我遇到了网站丢失会话()的各种问题。如果 Web 托管和管理系统使服务器进入睡眠状态,甚至发生 .net 代码错误,它可能(并且将会!!)经常导致应用程序池重新启动 - 这会导致 session() (但不是 SQL基于服务器的 - 它们坚如磐石)。

ViewState 通常是首选,因为它是每个新网页的首选。这 100% 存储在浏览器中。因此,为了保留您将要购买的 houseID 或产品,这将按页面发生,而不是用户使用的所有网页(因此在这种情况下,VieweState 将是更好的选择)。 ViewState 因此由浏览器存储,并且与您在文本框中输入一堆值然后回发时使用的机制大致相同。网页传送到服务器 - 页面被处理并发送回。但是您会注意到页面上的 MOST 控件保留了它们的值。为了实现这一点,使用了 ViewState。这适用于隐藏文本框(或隐藏字段 - 与隐藏文本框非常相似)。所以这个加密的 blob 存在于浏览器客户端。因此,这种 blob 事件会用于回传和往返,以保持这些控件值不变。

因此您可以使用 session() 或 ViewState 但是,如前所述,您不想在该 ViewState 中填充太多内容,因为它成为往返生命周期的一部分。但是如上所述的 ViewState 通常是首选的,因为它是按页面操作的。但是,由于打开的每个新浏览器页面都会为每个页面创建一个新的本地 ViewState?那么作为一般规则,ViewState 不能像 Session() 那样用于在网页之间传递值。

但是,您可以将所有控件的所有值传递到下一页。您可以通过使用按钮的回发 URL 来完成此操作。执行此操作后,在首次加载页面时,您可以在 on-load 事件中使用 page.previous 属性。这将使您使用上一页中的所有值 - 您不需要 Session() 来执行此操作。如果您执行 server.TransferRequest 而不是 Response.Redirect(),您也可以使用 page.Previous。

最后但并非最不重要的?你会看到很多网站在 URL 中有一大堆参数。所以这个经常被使用并且有着悠久的使用历史。当然,用户可以使用这些值进行混乱和更改 - 但它们仍然经常使用并且经常使 URL 变得相当丑陋。出于这个原因,我确实喜欢 asp.net 站点,因为那时 URL 不会将 URL 中的一堆内容作为参数公开,并将此类信息排除在站点之外。您会看到许多购物网站仍在使用 URL 中的参数和值 - 他们这样做是出于可扩展性的原因 -(他们不必在服务器端存储持久值 - 这样可以节省资源)。

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...