Asp.net里实用静态变量问题与ViewState

Asp.net里实用静态变量问题与ViewState(转)

在.Net平台下进行CS软件开发时,咱们常常遇到之后还要用到某些变量上次修改后的值,为了简单起见,不少人都习惯用static来定义这些变量,我也是。这样很是方便,下一次调用某个函数时该变量仍然保存的是处理过的值,直接拿来用就能够了。
        数据库

如今转入了BS软件开发,咱们很天然地会沿用这种习惯。如在页面中统计某个按钮被按下的次数,先在类中OnClick事件的处理过程前定义一static变量times,则每次调用该按钮的OnClick事件时,令times增1便可,很是方便:
[C#]:
...
static int times=0;
...
private void Button1_Click(object sender,EventArgs e)
{
   times++;
   Label1.Text=times.ToString();
}
        浏览器

在咱们庆幸如此方便之余,咱们应该意识到,这样会给咱们带来严重的问题。安全

        

这还要从Asp.net的运行机制谈起。在CS模式软件开发过程当中,咱们一般不会关心应用程序是在哪里运行的,变量存放在哪里,客户端程序就运行在客户端,服务器端程序就运行在服务器端,通常状况下,两者除了数据库中的数据外基本没有其余共享的东西。因此这时客户端的用户大可放心的使用static变量,由于它们就存放在客户端程序中。
        服务器

因而咱们就习惯的在作BS模式的页面时也用static变量,却不知Asp.net中的static已不一样于CS中的static。缘由很简单,就是由于在Asp.net中全部的用户将使用同一个static变量。这就意味着每个使用该页面的用户对该变量的操做将会影响到其余用户。就 拿上面计数器的例子来讲,假设times初试值为0,由于此时只有咱们本身在使用这个页面,固然不会有什么问题,但若是有两我的同时链接到这个页面,若是 A单击了Button1一次,则B刷新页面后Label1将显示1,若是B再单击Button1一次,则times变成2,两我的刷新页面后就出现问题 了:A和B都会说,我明明只单击了Button1一次,怎么Label1就显示我单击了两次哪?——这就是由于两我的共用的是服务器上同一个times, 任何一我的对times的操做都会在使用该页面的他人的浏览器中表现出来。问题就出在这里。
        网络

 

怎么办哪?还好,除了传统的Asp中的Session对象外,Asp.net提供了一个更好的ViewState对象。ViewState 对象用来保存页面中的各类变量,甚至是对象。使用方法和HashTable相似,只要用变量名称作索引,如ViewState["Var"],就能够用存 取变量Var的值,而无论Var是普通变量,仍是对象,甚至是内存中的一张DataTable,太方便了。为何能够用ViewState而不能用static变量哪?缘由就是服务器端会为每一个链接到该页面的用户分别创建一个ViewState,因此ViewState至关于页面级的Session。这下咱们能够放心地使用ViewState来存取须要暂寸的变量和对象了。
        ide

ViewState的用法很简单,以下所示函数


一、保存变量到ViewState中:
ViewState["times"]=times;//存放普通变量timespa

ViewState["Orders"]=dtOrders;//存放DataTable型对象dtOrders
        .net

二、读出ViewState中的值:对象

times=(int)ViewState["times"];
dtOrders=(DataTable)ViewState["Orders"];
        

但值得注意的是

 

linq to Sql 所获得的数据集不能保存在ViewState中,linq实体类只支持 DataContractAttribute 属性的序列化操做,也就是说他不支持XML与bin形式的序列化操做,这样就给咱们在使用上带来了储多不便。那么咱们可使用Session,Cookie来替代

 

 

看见了吧?就如此简单!有的朋友会问读出变量的值时为何要进行强制类型转换?这是由于当变量(不论是int型的普通变量times,仍是 DataTable型的对象dtOrders)被存放到ViewState中后,ViewState可无论你是普通变量仍是对象,通通按Object来对 待。因此当咱们取出存放在ViewState中的东西时,必定要转换成相应的类型,不然就会报错。而这一操做不用在用ViewState保存变量时进行, 系统会自动转换。(注意ViewState括号中的字符串只是为了标识不一样变量的索引,用不着非要和变量同名)因此上面计数器的代码应该这样写才好:
       ...
       ViewState["times"]=0;
       ...
       private void Button1_Click(object sender,EventArgs e)
       {
           int times=(int)ViewState["times"];
           times++;
           ViewState["times"]=times;
           Label1.Text=times.ToString();
         }
        

这是否是说static型变量就没用了哪?固然不是!在C#中用static声明的类不用实例化直接使用。正是因为全部用户共享服务器端的同一个 static变量,因此能够用static型对象来存取一些公用的处理模块,好比类型转换、变量验证等工做。因此要根据具体状况而定。
        

还有一点须要注意:若是在页面中多个过程要共享一个对象或变量,咱们在页面类的开始部分定义一个页面级的全局变量是不行的,static原本能够,但上面说了这种类型的变量不安全,因此这时就能够用ViewState。
        

好了,这下咱们能够放心的暂存某些变量或对象了。
        

但在随后的实践中我发现,在页面中仍是尽可能少用ViewState变量,由于ViewState变量在客户端其实是用<input type="hidden" value="ADFAIB3P234P-AFAFAF......"/>保存的一个对象,这样若是要保存的是个对象,甚至是个很复杂的对象(如DataTable),这样以来就会增长网络传输的负担。

相关文章
相关标签/搜索