VIEWSTATE无疑是ASP.NET机制中最备受争议的概念之一,很多ASP.NET优化的文章都提到“禁用‘不必要’的VIEWSTATE”,博客园里老赵说过,“我如果新建一个Web项目,做的第一件事情就是去Web.config中将enableViewState从全局关闭”。而持相反的观念的人则质疑,如果没有VIEWSTATE,Web Form还有什么意义?记得csdn上sp1234,曾写过一篇强烈支持VIEWSTATE的文章,反响异常激烈,我通过“csdn sp1234 viewstate”关键字,居然搜出了“
駁sp1234之[如果你必须开发交互式页面,ViewState越大可能意味着越有本事]一貼”?遥想当年烽火四起,硝烟弥漫,不觉感慨万千。
据说ASP.NET4.0将会默认设置VIEWSTATE=“false”,不知此后争议是否会小一些?
高手坐而论道,我们小辈,本是不应该插嘴的,所以我只想把VIEWSTATE彻底弄明白,先。
首先,学老赵,“去Web.config中将enableViewState从全局关闭”。再打开一个空页面看看,是不是清爽了很多。啊?页面源代码中,仍然出现了:
居然还有,怎么禁不掉呢?微软动了什么手脚,这不忽悠人吗?(你还可以再试试,页面声明,控件声明,当年我都试过,呵呵)好吧,故事就从这里开始吧!
把TextBox的值改掉,假设改成"changed"吧,选中DropDownList的第3项,点Button提交,Postback。结果是什么?
TextBox的值还是changed,DropDownList还是选中的第3项,状态被保存了呀?不是说“http无状态”么?是不是我的VIEWSTATE没被禁掉?难怪页面源代码里还看得见“__VIEWSTATE”!
我还试过按F5刷新,将页面转到另一个页面再“Back”回来,结果我很失望的发现,无论我如何试图禁用viewstate,控件的状态都保持得很好!
然后,运行。点击Button按钮,你会发现Label已经变成“changed”;然后,再点击LinkButton。你发现了什么?这就是VIEWSTATE=“false”时的效果,也应该是正常的效果。我认为这还是好理解的,除了“HTTP无状态协议”以外,你还可以这样想:“当我点Button的时候,会触发ButtonClick事件,所以Label会改变;而我点击ImageButton的时候,页面会重新加载,却不会触发ButtonClick事件,所以Label也就自然按页面声明的那样显示了”。(这本是事物的本原,被微软默认使用了viewstate之后,事情反而变得更难以理解了,微软啊微软!)
到此为止,我们对于viewstate的理解可以说是入门了。viewstate是用于:
1. 保存“某些”控件的状态的;
2. 所谓的“状态”是在页面后台(cs文件)中被修改的。
但这里仍然有很多问题值得我们探讨:
1. 为什么禁用viewstate之后,页面源代码中仍然有“<input type="hidden" name="__VIEWSTATE"……”?
2. 为什么是“某些”控件,不是所有的控件都有viewstate么?对了,viewstate是属于页面的还是控件的?
3. 能更深入的探寻viewstate的内部机制么?
今天先解释几个比较简单的问题吧。
据说ASP.NET4.0将会默认设置VIEWSTATE=“false”,不知此后争议是否会小一些?
高手坐而论道,我们小辈,本是不应该插嘴的,所以我只想把VIEWSTATE彻底弄明白,先。
首先,学老赵,“去Web.config中将enableViewState从全局关闭”。再打开一个空页面看看,是不是清爽了很多。啊?页面源代码中,仍然出现了:
<
input
type
="hidden"
name
="__VIEWSTATE"
id
="__VIEWSTATE"
value
="/wEPDwULLTE2MTY2ODcyMjlkZI7OBu+sMrYke3ELlQKIiNbArzXe"
/>
居然还有,怎么禁不掉呢?微软动了什么手脚,这不忽悠人吗?(你还可以再试试,页面声明,控件声明,当年我都试过,呵呵)好吧,故事就从这里开始吧!
无论如何,据说VIEWSTATE是“保持页面/控件状态”的,我们先试试看,拖几个控件到页面,先。
代码
<
body
>
< form id ="form1" runat ="server" >
< div >
< asp:Label ID ="Label1" runat ="server" Text ="I am Label" ></ asp:Label >< br />
< asp:TextBox ID ="TextBox1" runat ="server" Text ="I am TextBox" ></ asp:TextBox >< br />
< asp:DropDownList ID ="DropDownList1" runat ="server" >
< asp:ListItem Text ="I am ListItem (1)" ></ asp:ListItem >
< asp:ListItem Text ="I am ListItem (3)" ></ asp:ListItem >
< asp:ListItem Text ="I am ListItem (2)" ></ asp:ListItem >
</ asp:DropDownList >< br />
< asp:LinkButton ID ="LinkButton1" runat ="server" Text ="I am LinkButton" > LinkButton </ asp:LinkButton >< br />
< asp:Button ID ="Button1" runat ="server" Text ="I am Button"
onclick ="Button1_Click" />< br />
< asp:HyperLink ID ="HyperLink1" runat ="server" NavigateUrl ="~/Default2.aspx" > HyperLink </ asp:HyperLink >
</ div >
</ form >
</ body >
< form id ="form1" runat ="server" >
< div >
< asp:Label ID ="Label1" runat ="server" Text ="I am Label" ></ asp:Label >< br />
< asp:TextBox ID ="TextBox1" runat ="server" Text ="I am TextBox" ></ asp:TextBox >< br />
< asp:DropDownList ID ="DropDownList1" runat ="server" >
< asp:ListItem Text ="I am ListItem (1)" ></ asp:ListItem >
< asp:ListItem Text ="I am ListItem (3)" ></ asp:ListItem >
< asp:ListItem Text ="I am ListItem (2)" ></ asp:ListItem >
</ asp:DropDownList >< br />
< asp:LinkButton ID ="LinkButton1" runat ="server" Text ="I am LinkButton" > LinkButton </ asp:LinkButton >< br />
< asp:Button ID ="Button1" runat ="server" Text ="I am Button"
onclick ="Button1_Click" />< br />
< asp:HyperLink ID ="HyperLink1" runat ="server" NavigateUrl ="~/Default2.aspx" > HyperLink </ asp:HyperLink >
</ div >
</ form >
</ body >
把TextBox的值改掉,假设改成"changed"吧,选中DropDownList的第3项,点Button提交,Postback。结果是什么?
TextBox的值还是changed,DropDownList还是选中的第3项,状态被保存了呀?不是说“http无状态”么?是不是我的VIEWSTATE没被禁掉?难怪页面源代码里还看得见“__VIEWSTATE”!
我还试过按F5刷新,将页面转到另一个页面再“Back”回来,结果我很失望的发现,无论我如何试图禁用viewstate,控件的状态都保持得很好!
后来我被告知,这是浏览器自身的特性,和VIEWSTATE无关,为了验证这一点,我们可以通过纯的html页面进行试验(此处略)。
以上是错误的理解! 真正的原因是因为这些控件实现了IPostBackDataHandler接口,我会在后面的文章中详细解释。
所以,正确的验证VIEWSTATE失效的方式其实是这样的,在后台代码(cs文件)中添加以下代码:
代码
public
partial
class
_Default : System.Web.UI.Page
{
protected void Page_Load( object sender, EventArgs e)
{
}
protected void Button1_Click( object sender, EventArgs e)
{
this .Label1.Text = " changed " ;
}
}
{
protected void Page_Load( object sender, EventArgs e)
{
}
protected void Button1_Click( object sender, EventArgs e)
{
this .Label1.Text = " changed " ;
}
}
然后,运行。点击Button按钮,你会发现Label已经变成“changed”;然后,再点击LinkButton。你发现了什么?这就是VIEWSTATE=“false”时的效果,也应该是正常的效果。我认为这还是好理解的,除了“HTTP无状态协议”以外,你还可以这样想:“当我点Button的时候,会触发ButtonClick事件,所以Label会改变;而我点击ImageButton的时候,页面会重新加载,却不会触发ButtonClick事件,所以Label也就自然按页面声明的那样显示了”。(这本是事物的本原,被微软默认使用了viewstate之后,事情反而变得更难以理解了,微软啊微软!)
好吧,我们再看看使用了viewstate之后的效果。在当前页面声明如下,
<%
@ Page Language
=
"
C#
"
AutoEventWireup
=
"
true
"
CodeFile
=
"
Default.aspx.cs
"
Inherits
=
"
_Default
"
EnableViewState
=
"
false
"
%>
哈哈,你又上当了!注意,viewstate的设置规则是:但你在上一级(如web.config)禁用了viewstate,你在下级(page/control)里是无法再启用的。(所以viewstate目前使用起来还是不不方便的。无论如何,asp.net4.0就好了)
xiaosuo 在后面的评论中给出了一个有效的解决方案。
到此为止,我们对于viewstate的理解可以说是入门了。viewstate是用于:
1. 保存“某些”控件的状态的;
2. 所谓的“状态”是在页面后台(cs文件)中被修改的。
但这里仍然有很多问题值得我们探讨:
1. 为什么禁用viewstate之后,页面源代码中仍然有“<input type="hidden" name="__VIEWSTATE"……”?
2. 为什么是“某些”控件,不是所有的控件都有viewstate么?对了,viewstate是属于页面的还是控件的?
3. 能更深入的探寻viewstate的内部机制么?
今天先解释几个比较简单的问题吧。
1. <input type="hidden" name="__VIEWSTATE"……>里,存放的其实有两种数据:一是传统的viewstate,二是所谓的ControlState。而ControlState是不能被禁用的。所以,你总是能看到以上的声明。(我的理解,还不能证明,如有缪误,望指点!)
后面评论指出,这里的VIEWSTATE是<form runat="server"/>的结果。
2. viewstate是属于控件的,而页面本身其实就是一个控件。我曾在 用简单的代码测一测你是否真的了解:Asp.Net中的事件和委托的实现 一文中指出,这里贴出代码:
代码
//
Summary:
// Represents an .aspx file, also known as a Web Forms page, requested from
// a server that hosts an ASP.NET Web application.
[DefaultEvent( " Load " )]
[Designer( " Microsoft.VisualStudio.Web.WebForms.WebFormDesigner, Microsoft.VisualStudio.Web, Version=8.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a " , typeof (IRootDesigner))]
[DesignerCategory( " ASPXCodeBehind " )]
[DesignerSerializer( " Microsoft.VisualStudio.Web.WebForms.WebFormCodeDomSerializer, Microsoft.VisualStudio.Web, Version=8.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a " , " System.ComponentModel.Design.Serialization.TypeCodeDomSerializer, System.Design, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a " )]
[ToolboxItem( false )]
public class Page : TemplateControl, IHttpHandler
// Represents an .aspx file, also known as a Web Forms page, requested from
// a server that hosts an ASP.NET Web application.
[DefaultEvent( " Load " )]
[Designer( " Microsoft.VisualStudio.Web.WebForms.WebFormDesigner, Microsoft.VisualStudio.Web, Version=8.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a " , typeof (IRootDesigner))]
[DesignerCategory( " ASPXCodeBehind " )]
[DesignerSerializer( " Microsoft.VisualStudio.Web.WebForms.WebFormCodeDomSerializer, Microsoft.VisualStudio.Web, Version=8.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a " , " System.ComponentModel.Design.Serialization.TypeCodeDomSerializer, System.Design, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a " )]
[ToolboxItem( false )]
public class Page : TemplateControl, IHttpHandler
后面的内容待我先整理一下,然后再发布,呵呵。