`
sogotobj
  • 浏览: 662781 次
  • 性别: Icon_minigender_2
  • 来自: 北京
文章分类
社区版块
存档分类
最新评论

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

阅读更多

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

发布日期: 2006-1-13 |
本文讨论:

ViewState 如何工作

ASP.NET 2.0 ViewState 的改进

使用控件状态维护功能

性能考虑

本文使用以下技术:
ASP.NET、C#

代码下载:
ViewState.exe(122KB)

*
本页内容
 ViewState 基本原理 ViewState 基本原理
 ViewState 问题 ViewState 问题
ASP.NET 2.0 中的 ViewState 改进 ASP.NET 2.0 中的 ViewState 改进
控件状态 控件状态
声明性数据源和 ViewState 声明性数据源和 ViewState
小结 小结

如果您是个经验丰富的 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 示例,尝试运行图 1 显示的页面。

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

在 ASP.NET 中, ViewState 完成基于控件的编程模型。如果没有 ViewState ,一些控件(如文本框和下拉列表)在 POST 请求期间保持状态,而其他控件不保持,使用这些状态各异的控件记录一些特殊的情况是令人沮丧的体验。使用 ViewState ,开发人员能够专注于编程模型和用户界面,而不用担心状态保持。还能对 ViewState 进行哈希或加密,以防止用户篡改或解码。关于这个主题的更多信息,请参见在线书籍 Securing Your ASP.NET Application and Web Services 的第 19 章。

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

ViewState 问题


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

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

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

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

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

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

ASP.NET 2.0 中的 ViewState 改进


既然我概述了这些问题,是时候讨论 ASP.NET 2.0 中的所有改进了。第一个是 ViewState 序列化时的总大小。在 ASP.NET 1.x 中,两个字符串进入 ViewState 缓冲区中的序列化如下所示:

<p<l<string1;>;l<string2;>>;>;

ASP.NET 1.x 中使用的 ViewState 序列化格式是元组格式,由三个一组的层次集合和使用大于号和小于号的序列对组成。大于号之前的字母代表存储对象的类型(t=triplet,p=pair,i=integer,l=ArrayList,等)。大于号和小于号内的每个子元素由分号分隔。这是有趣的序列化格式,有点像一个压缩的 XML。但是,如果您关心空间,那么它不是最有效的序列化格式(只是比 XML 稍好一点)。

ASP.NET 2.0 改变了这种序列化格式。在 ASP.NET 2.0 中,相同的两个字符串进入 ViewState 缓冲区的序列化如以下代码行所示:

[][]string1[]string2

至少,这很像浏览器呈现的格式。方括号实际上是非打印字符,如果我们使用 Unicode 字符引用来重写,则变成了以下显示的编码:

&#15;&#5;string1&#5;string2

ASP.NET 2.0 使用一些非打印字符标识对象的起始并表述对象的类型,而非使用可打印字符集(“<”、“>”、“;”、“l”、“i”、“p”等)来分割 ViewState 流中的对象。

使用非打印字符分割 ViewState 中存储的对象有两个目的。第一个目的是改进解析 ViewState 字符串时进行词法分析的效率,因为此时不再需要匹配字符或解析标记。第二个,也是更重要的目的是它减少了为 ViewState 中的对象编码所使用的字符数量。在为两个字符串编码的简单示例中,第一种编码方法使用了 16 个分割字符,而 2.0 格式使用了 3 个。这种作用很快地复合而产生了重大的影响。

例如,如果我们在窗体上放置一个 DataGrid,将其绑定到 pubs 数据库的 authors 表格,如图 3所示,则 1.x 中的 ViewState 字符串大小是 12,648 个字符。如果在 2.0 中也这样做, ViewState 大小减少到 6,728 个字符,几乎减少了一半。图 4 显示 ASP.NET 1.x、ASP.NET 2.0 中 ViewState 所需的空间对比,以及不同输入大小在页面实际呈现的字符数。在这种情况下,authors 表格在 500 行处增加了额外的行,达到了 2,000 行。


图 4 ViewState 大小对比


随着 ASP.NET 2.0 版本的发布,您能够期望立即减小 ViewState 大小,而无需做任何特别的工作。这不意味着您应该停止考虑控件正常工作是否需要 ViewState ,这是因为它仍然对响应大小有很大影响,在图 4 中表现的很明显。然而, ViewState 的下一个改进能潜在地节省更多。

控件状态


我先前提过,ASP.NET 1.x 中使用服务器端控件最另人沮丧的一面是关于 ViewState 的非全有即全无的状态。控件的行为方面,如 DataGrid 中的分页或文本框中的选定更改通知,需要启用 ViewState 来正常运行。我确定在任何 DataGrid 中启用 ViewState 的前景令所有人十分沮丧。在 ASP.NET 2.0 中,Microsoft 通过将 ViewState 分割成两个独立不同的类别解决了这一特殊问题: ViewState 和控件状态。

控件状态是另一类隐藏的状态,专门为维护控件的核心行为功能而保留,而 ViewState 只包含维护控件内容 (UI) 的状态。从技术上来说,控件状态存储在与 ViewState 相同的隐藏字段中(只是在 ViewState 层次结构末端的另一个叶子节点),但是如果禁用一个特定控件或整个页面的 ViewState ,控件状态仍然传播。实现这一技术好的一面是,现在我们能够改进 ASP.NET 2.0 优化 ViewState 的原始原则,使之更强健:如果在每次请求页面时传播控件内容,您应该禁用该控件的 ViewState 。

只要控件生成器将其状态正确划分成行为状态(为了维护核心功能)和 UI 状态(为了保留内容),就应该坚定地遵守这个原则。我建议您现在使用 ASP.NET 2.0 时开始遵循这个原则,但是 DataGrid 还未重构以保留控件状态中的行为状态。幸运的是,新的 GridView 是 DataGrid 的逻辑继承者,它像 TextBox 和 DropDownList 控件的新版本一样正确使用控件状态。图 5 显示的是目前使用控件状态的控件列表及其存储的属性,供您参考。随着 ASP.NET 2.0 的最终发布,这个列表可能会作出变动。

如果您愿意进一步研究 ASP.NET 2.0 的新控件如何使用控件状态和 ViewState ,可以使用我编写的一个叫做 View State Decoder 的实用工具,它用来显示给定页面上所有的 ViewState 和控件状态。图 6 显示的是活动的实用工具的一个屏幕快照。您能够从本文顶端的链接下载该程序。注意,这个应用程序依赖于目前 ViewState 使用的编码字符,在最终版本发布前可能会改变。

对于您的那些生成控件,控件状态的使用模型不像 ViewState 一样方便。您必须重写 LoadControlState 和 SaveControlState 虚方法,手动管理您那部分映射到控件状态中的对象集合,而非提供一个带有索引的状态包用来插入和移除选项。另一件您必须做的事情是在初始化期间调用 Page.RegisterRequiresControlState 方法,使页面能够在正确的时间询问控件状态。在控件状态中存储选项比在 ViewState 中更难可能是一件好事,因为用户无法禁用它(控件状态有一个选择模型也有性能方面的好处)。开发人员在存储任何状态前应该认真考虑,因为它总是添加到呈现的页面中。图 7 显示在控件状态中存储一个字符串的自定义控件(本例中是它的颜色)。

当您决定控件状态和 ViewState 各存储什么内容时,请记住行为状态与内容或者 UI 状态应该有分别。诸如属性和数据集一样的内容一般应存储在 ViewState 中,而不是迁移到控件状态。触发服务器端事件的状态是存储在控件状态中最典型的一类状态。

声明性数据源和 ViewState


应用我们的 ViewState 优化原则有一个小问题 — 您经常不知道每次请求时是否正在填充控件内容。在 ASP.NET 2.0 中采用声明性数据源意味着将数据绑定到一个控件不再需要将数据源属性显式连接至 DataReader 或 DataSet,并调用 DataBind。而是在页面上声明性地放置一个数据源,并将控件指向该数据源。例如,使用绑定到 pubs 数据库中 authors 表格的新 GridView 类和与之相关的 SqlDataSource(参见 图 8)。如果运行这个页面,您将发现它正好有效。GridView 及其相应的数据源能够了解何时进行交互。在页面呈现之前,GridView 充满数据源的数据,并且很可能在客户端呈现整个 authors 表格。

在这个简单的情况中,我们还未禁用 GridView 的 ViewState ,因此您可能会认为,我们再一次仅仅使用 ViewState 存储了从未使用的数据。幸运的是,ASP.NET 2.0 引擎作了正确的事情,当控件上的 ViewState 可用时,它将不厌其烦地返回到数据库。

同样地,如果禁用 GridView 上的 ViewState ,数据绑定到数据源将发生在每次请求发生的时候,包括 POST back 请求。DataBoundControl 基类中置入了这一功能,其中的 AdRotator、BulletedList、CheckBoxList、DropDownList、ListBox、RadioButtonList、GridView、DetailsView 和 FormView 控件继承了该功能。这些控件展示了 ViewState 在绑定到声明性数据源时表现的智能使用。

小结


ASP.NET 的下一个版本对 Web 开发人员承诺了许多改进,不只是更有可能晚上好好休息,不会做 Base64 编码数据淹没了 Web 窗体的噩梦。使用更紧凑的序列化格式、行为状态和 UI 状态的分离以及数据绑定控件和声明性数据源的智能交互,那些 ViewState 的噩梦仅可能变成美梦。

分享到:
评论

相关推荐

    asp.net 2.0动态网站开发教程

    ASP.NET 2.0提供了多种状态管理机制,如视图状态(ViewState)、控制状态(ControlState)、会话状态(Session State)、应用程序状态(Application State)和cookie,它们可以帮助开发者在HTTP无状态的环境中保持...

    ASP.NET 2.0程序设计案例教程(课件)

    5. **会员和角色管理**:ASP.NET 2.0引入了安全性和身份验证的改进,如身份验证服务、成员资格提供程序和角色提供程序。这些使得创建安全的登录系统和权限控制变得简单。 6. **配置和部署**:课程可能涉及如何配置...

    ASP.NET 2.0动态网站开发教程(最新)

    3. **ViewState管理**:ASP.NET 2.0的ViewState机制用于在页面间保持状态,使控件的属性在回发时能保持一致。虽然有助于保持状态,但也会增加页面大小,因此需要合理使用。 4. **母版页(Master Pages)**:母版页...

    ASP.NET2.0+sql server 网络应用开发详解

    在ASP.NET 2.0版本中,引入了许多新特性,如改进的页面生命周期管理、母版页(Master Pages)用于统一网站布局、自定义控件增强用户体验、配置管理工具简化部署过程、以及ASP.NET AJAX框架实现页面无刷新交互等。...

    精通ASP.NET2.0+SQL Server 2005项目开发 源码.rar

    4. 状态管理:介绍Session、ViewState和Cookie等状态管理机制,以及在ASP.NET 2.0中如何有效地使用它们。 5. 文件上传与下载:实现文件上传和下载功能,涉及文件操作和流处理,以及与数据库的交互。 6. 错误处理与...

    ASP.NET 2.0网络编程自学手册

    总之,《ASP.NET 2.0网络编程自学手册》将带领读者逐步走进ASP.NET 2.0的世界,通过实例和详细的解释,使读者能够熟练掌握网络应用程序的开发技能,无论是搭建简单的信息展示网站,还是构建复杂的业务系统,都能...

    ASP.NET 2.0功能源码

    ASP.NET 2.0是微软开发的一个Web应用程序框架,它基于.NET Framework,为开发者提供了构建动态网站、Web应用和Web服务的强大工具。这个"ASP.NET 2.0功能源码"压缩包文件很可能是为了帮助学习者理解并探索ASP.NET 2.0...

    ASP.NET 2.0动态网站开发教程(很实用)

    ASP.NET 2.0改进了其前身ASP.NET 1.x的许多方面,引入了诸如母版页(Master Pages)、主题(Themes)、皮肤(Skin)、站点地图(Site Map)等新特性,极大地提高了开发效率和代码复用性。母版页允许开发者创建统一的...

    ASP.NET 2.0动态网站设计教程 作者:李春葆讲义PPT

    ASP.NET 2.0是微软开发的一个用于构建Web应用程序的框架,它是在.NET Framework 2.0版本上构建的,提供了丰富的功能和工具,使得开发者能够更高效地创建功能强大的动态网站。李春葆的这本《ASP.NET 2.0动态网站设计...

    Asp.Net2.0网站开发实战.iso

    《Asp.Net2.0网站开发实战》是一个深入学习Asp.Net 2.0技术的教程资源,以ISO格式提供,原始大小超过50MB,但压缩后仅3MB。这个教程涵盖了Asp.Net 2.0的核心概念、开发工具和实际应用,是初学者和进阶开发者的重要...

    ASP.NET 2.0 完全自学手册

    ASP.NET 2.0 是微软开发的一个用于构建Web应用程序的框架,它是在.NET Framework 2.0版本上构建的。本完全自学手册旨在为初学者和开发者提供全面、深入的指导,帮助他们掌握ASP.NET 2.0的核心概念和技术。 在ASP...

    ASP.NET 2.0动态网站设计教程

    9. **性能优化**:通过理解和应用缓存技术、减少ViewState大小、优化数据库查询等方式,可以显著提升ASP.NET 2.0网站的性能。 10. **代码分离和设计模式**:良好的代码组织和设计模式的应用,如MVC(Model-View-...

    ASP.NET 2.0动态网站开发基础教程(C# 2005)源文件

    ASP.NET 2.0是微软.NET Framework的一部分,它提供了一个用于构建动态网站、Web应用程序和服务的强大平台。本教程源文件基于C# 2005编程语言,旨在帮助初学者和开发者掌握ASP.NET 2.0的核心概念和技术。 在ASP.NET ...

    《Asp.Net2.0 完全开发指南——基于VB》随书光盘

    《Asp.Net2.0 完全开发指南——基于VB》随书光盘是一个压缩文件,其中包含了关于Asp.Net2.0技术的详细学习资料,特别针对使用Visual Basic(VB)编程语言的开发者。Asp.Net是微软推出的一个强大的Web应用程序框架,...

    ASP.NET 2.0入门经典:C#编程篇

    ASP.NET 2.0相较于1.1版本有诸多改进,包括增强的开发效率、更强大的控件和模板系统,以及改进的配置管理。它引入了如母版页(Master Pages)、皮肤(Skin)、站点导航(Site Navigation)等新特性,使得网页设计...

    ASP.NET 2.0快速入门(12):ASP.NET 2.0网站快速导航

    这意味着ASP.NET 2.0的网站导航特性也可以在非Windows环境中部署和使用。 五、快速入门 对于初学者,以下步骤可以帮助快速掌握ASP.NET 2.0网站导航: 1. **创建站点地图文件**:编写XML文件定义网站结构。 2. **...

    《Asp.net 2.0高级编程》(pdf版).rar

    Asp.net是微软.NET框架下的一个强大Web应用程序开发平台,2.0版本在1.1的基础上进行了大量改进和优化,提升了开发效率和性能。 首先,Asp.net 2.0引入了全新的Page生命周期模型,使得开发者能更精确地控制页面各...

    精通ASP.NET2.0网络应用系统开发 随书光盘ch07

    ASP.NET 2.0还包括了母版页(Master Pages)和站点导航(Site Navigation)功能,前者让网站保持一致的布局变得简单,后者则帮助构建易于使用的导航结构。同时,主题(Themes)和皮肤(Skin)机制可以实现全局的UI...

    ASP.Net 2.0 开发技术大全 -- 005

    ASP.NET 2.0是微软推出的用于构建动态网站、Web应用程序和Web服务的框架,它在.NET Framework 2.0之上构建,提供了丰富的功能和工具,使得开发者能够更高效地创建交互式、数据驱动的Web应用程序。在这个"ASP.Net 2.0...

Global site tag (gtag.js) - Google Analytics