首页 > 编程 > .NET > 正文

用 ASP.NET 2.0 改进的 ViewState 加快网站速度

2024-07-10 12:55:08
字体:
来源:转载
供稿:网友
    如果您是个经验丰富的 asp.net 开发人员,一提起 viewstate ,您可能会不寒而栗,因为您想到的是大量通过“鸡尾酒吸管”吸入的 base64 编码数据。除非采取步骤进行预防,否则大部分 asp.net 页面将有大量辅助数据被存储在一个名为 __viewstate 的隐藏字段中,多数情况下,甚至不需要这个字段。浏览用 asp.net 生成的您喜爱的站点,查看页面源代码,计算隐藏在 __viewstate 字段中的字符数。我尝试了一下,数量为 800 到 7,800 个字符。

  当然, viewstate 在 asp.net 中有个重要的角色。如果使用恰当,它能够简化页面开发,改进用户与站点的交互。如果置之不理,它能够显著增加站点响应大小,在连接速度慢的情况下,使您的响应时间更加缓慢。asp.net 2.0 的发布带来了 viewstate 机制的一些改进,这使得 viewstate 使用更简单,又不会防碍站点性能。这些改进包括:减少编码数量,采用控件状态从内容中分离出行为状态,以及智能集成数据绑定控件。

  viewstate 基本原理

  在介绍 asp.net 2.0 viewstate 的改进之前,简要总结目前版本中 viewstate 的用途和实现是适宜的。 viewstate 为 asp.net 开发人员解决了一个特定问题 — 保留服务器端不形成元素的控件的状态。这很重要,因为 asp.net 中的大部分服务器端控件模型是根据这样一个假设生成的,那就是 — 如果用户回发到相同页面,所有控件保持其状态不变。也就是说,如果在处理请求期间修改任何控件的内容,任何后续 post 请求回到相同页面时,您可以依赖于那些仍然存在的修改。作为一个活动的 viewstate 示例,尝试运行下面显示的代码。

<%@ page language="c#" %>
<script runat="server">
protected override void onload(eventargs e)
{
  int val = int.parse(_sum.innertext);
  _sum.innertext = (val+1).tostring();
  base.onload(e);
}
</script>
<html>
  <body>
    <form runat="server">
      <h2>viewstate test page</h2>
      <span id="_sum" runat="server">0</span>
      <br />
      <input type="submit" />
    </form>
  </body>
</html>

  每次按下 submit 按钮时,_sum 范围值递增。因为 viewstate 在请求期间保持以前的值,因此它将从上一次显示的值开始,显示 1、2、3、4 等等。如果想知道 viewstate 不可用时发生的事情,尝试添加 enableviewstate='false' 作为范围元素的一个属性。因为以前的范围值在请求处理时没有传播,所以不论页面发布多少次,都将显示值为 1。

  在 asp.net 中, viewstate 完成基于控件的编程模型。如果没有 viewstate ,一些控件(如文本框和下拉列表)在 post 请求期间保持状态,而其他控件不保持,使用这些状态各异的控件记录一些特殊的情况是令人沮丧的体验。使用 viewstate ,开发人员能够专注于编程模型和用户界面,而不用担心状态保持。还能对 viewstate 进行哈希或加密,以防止用户篡改或解码。

  使用 viewstate 的另一个重要之处是在控件中发布服务器端更改事件。如果用户改变了文本框中的值或切换了下拉列表中的选定元素,您就能够注册一个事件处理程序,引发事件时,执行代码。这些控件比较其当前值与以前值,如果有任何过程预订更改事件,以前值隐式存储在 viewstate 中。如果禁用一个控件的 viewstate ,而您正在处理该控件的更改通知事件,因为总是假定以前值与窗体默认值相同,所以更改通知事件不会正确激发。

  viewstate 问题

  正如我早前指出的,在 asp.net 1.x 中, viewstate 有很多问题。默认情况下,它是启用的,除非您知道在不需要使用时找到并禁用它,否则它能显著增加页面呈现的数据量。当使用数据绑定控件时,所有控件都使用 viewstate 保存回发后的状态,这将变得异常痛苦。作为一个简单而生动的示例,asp.net 页面代码:

<%@ page language="c#" %>
<%@ import namespace="system.data" %>
<%@ import namespace="system.configuration" %>
<%@ import namespace="system.data.sqlclient" %>
<script language="c#" runat="server">
protected override void onload(eventargs e)
{
  string dsn = configurationsettings.appsettings["dsnpubs"];
  string sql = "select * from authors";
 
  using (sqlconnection conn = new sqlconnection(dsn))
  using (sqlcommand cmd = new sqlcommand(sql, conn))
  {
    conn.open();
    _dg1.datasource = cmd.executereader();
    _dg1.databind();
  }
  base.onload(e);
}
</script>
<html>
  <body>
    <form id="form1" runat="server">
      <asp:datagrid id="_dg1" runat="server" />
    </form>
  </body>
</html>

  这个页面有一个 datagrid 控件,该控件绑定对 pubs 数据库中 authors 表格进行简单查询的结果。如果运行这个页面(对连接字符串做出必要改正),查看 viewstate 字段,您可能吃惊地发现里面有超过 12,000 个字符。当查看页面内容,意识到显示浏览器中整个表格内容所需的实际字符数量大约是 1,600,您会更加吃惊。造成这个结果的原因之一是 viewstate 不仅编码数据,而且编码数据类型(元数据);同样,base64 编码一般要增加大约 33 % 的空间系统开销。而且,大量的系统开销只是为了保留 post 请求后的控件状态,这似乎与时间不成比例,必须竭尽全力避免发生。

  很明显,如果您关心响应大小,那么决定何时禁用控件的 viewstate 是重要的。刚才的示例就是一个典型的情况,传播了 viewstate ,但是从未使用,这是优化站点的 viewstate 使用时建议采用的主要规则:如果每次请求页面时填充控件内容,禁用该控件的 viewstate 一般是安全(而明智)的。

  另一方面,您可能决定利用 viewstate 保留控件状态这一实事,并且只在页面的首次 get 请求时,填充控件内容(只是贯穿后续 post 请求)。这省去了使用的任何后端数据源的往返行程。通过修改我的页面来利用这一结论,我更改了 onload 方法,使它在填充 datagrid 前检查 ispostback 标志,如以下代码所示。

protected override void onload(eventargs e)
{
  if (!ispostback)
  {
    string dsn = configurationsettings.appsettings["dsnpubs"];
    string sql = "select * from authors";
    using (sqlconnection conn = new sqlconnection(dsn))
    using (sqlcommand cmd = new sqlcommand(sql, conn))
    {
      conn.open();
      _dg1.datasource = cmd.executereader();
      _dg1.databind();
    }
  }
  base.onload(e);
}

  当然,有一些其他可能更好的选择,例如缓存服务器的查询结果,每次发出请求时重新绑定控件。由您权衡状态存储的位置和特定体系结构与应用程序的重要性。

  您可能注意到我曾小心提过,如果每次请求页面时填充控件内容,那么禁用 viewstate “一般”是安全的。例外情况是,一些控件既使用 viewstate 保留行为,也保留一般状态。如前所述,下拉列表和文本框控件使用 viewstate 存储以前的值来正确发布服务器上的更改通知事件。同样地,datagrid 类使用 viewstate 发布分页、编辑和排序事件。遗憾的是,如果您想要使用 datagrid 中诸如排序、分页或编辑的功能,则不能禁用其 viewstate 。对于尝试生成快速有效站点的开发人员来说,服务器端控件 viewstate 的非全有即全无的状况,是 asp.net 1.x 的服务器端控件模型另人沮丧的一面。

发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表