关于Asp.net中static与ViewState使用的探讨

关于Asp.net中static与ViewState使用的探讨
  摘 要: 利用asp.net 开发基于B/S模式的应用系统,经常会遇到同一页面类的各函数 成员之间、同一会话各页面之间、不同机器各用户页面之间的传值问题,即要解决数据共享 的问题。这可以选择使用Application、Session、cookie、Static、ViewState等方法实现 。其中Static变量的使用容易出现问题,使用不好会导致数据紊乱,给系统造成故障隐患。 用ViewState作为页内数据传值也是一种较好的选择 。根据开发设计实践特对此问题进行了 总结探讨。

  关键词:asp.net;编程;应用研究;对象。 

  中图分类号:TP311.1 文献标识码:A 文章编号:1008-7508( 2010)09-0077-02

  利用asp.net 开发基于B/S模式的应用系统,经常会遇到同一页面类的各函数成员之间、 同一会话各页面之间、不同机器各用户页面之间的传值问题,即要解决数据共享的问题。这 可以选择使用Application、Session、cookie、Static、ViewState等方法实现。其中Stati c变量的使用容易出现问题,使用不好会导致数据紊乱,给系统造成故障隐患。用ViewState 作为页内数据传值也是一种较好的选择 。根据开发设计实践特对此问题进行了总结探讨。 

  在C#中,“当用static修饰符定义成员时,得到静态成员,静态成员属于类,为这个类 的所有实例所共享”①。也就是该类的所有实例共享一个static变量。asp.net页面就是 一 个类,每访问一个页面就会在服务器上实例化一个该类的实例,来响应用户的请求。所有实 例共享一个static变量, 这就意味着,所有的客户端访问到的asp.net页面中static变量都 是同一个变量。

  “所谓ViewState,实际上是一些键值对,ASP.NET通过它维护网页和服务器的状态,并 将ViewState封装成一个或几个隐藏的表单域传递到客户端。而客户端提交时,ViewState也 将被提交到服务器端。这样后续的请求可以获得上一次请求的状态。”②

  由于我们每次刷新asp.net页面都是一个全新的对象,而不是上一次访问的对象。所以 上次页面访问时对页面中变量的改动都没有保留。遇到这个问题的时候直觉就将这个变量设 置成static,这样是可以保留住页面中变量的状态。但这个状态是针对一个客户端的(如同 session的效果)。而得到的结果是只要一个客户端改变了该值则所有的其他客户端都受到 了影响(如同Applicatin的效果)。

  究其原因这还要从Asp.net的运行机制谈起。在C/S模式软件开发过程中,我们通常不会 关心应用程序是在哪里运行的,变量存放在哪里,客户端程序就运行在客户端,服务器端程 序就运行在服务器端,一般情况下,二者除了数据库中的数据外基本没有其他共享的问题。 所以这时客户端的用户大可放心的使用static变量,因为它们就存放在客户端程序中。

  于是我们就习惯的在做B/S模式的页面时也用static变量,殊不知Asp.net中的static已 不同于C/S中的static。是因为在Asp.net中所有的用户将使用同一个static变量。这就意味 着每一个使用该页面的用户对该变量的操作将会影响到其他用户。

  解决的办法之一是可以选择Asp.net提供的ViewState对象。ViewState对象可以用来保 存页面中的各种变量,甚至是对象。“有些数据可以直接保存到ViewState中,诸如字符串 、整数、布尔、数组里表、哈希表等。”③只要用变量名称做索引,如ViewState[“Var ”], 就可以存取变量Var的值,而不管Var是普通变量,还是对象,甚至是内存中的一张DataTabl e。服务器端会为每个连接到该页面的用户分别建立一个ViewState,所以ViewState相当于 页面级的Session。相当于页面全局变量,但是一旦退出当前页面,它就会丢失。

ViewState的用法很简单,如下所示:

  1、保存变量到ViewState中:

  ViewState[“times”]=times; //存放普通变量times

  ViewState[“Orders”]=dtOrders; //存放DataTable型对象dtOrders

  2、读出ViewState中的值:

  times=(int)ViewState[“times”];

  dtOrders=(DataTable)ViewState[“Orders”];

  读出变量的值时要进行强制类型转换,这是因为当变量(不管是int型的普通变量times ,还是DataTable型的对象dtOrders)被存放到ViewState中后统统按Object类型存放。所以 当我们从ViewState取出时,一定要转换成相应的类型,否则就会报错。在变量保存到ViewS tate中时,系统会自动转换。 

  这不是说static型变量就没用了,在C#中用static声明的类不用实例化直接使用。正是 由于所有用户共享服务器端的同一个static变量,所以可以用static型对象来存取一些公用 的处理模块,比如类型转换、变量验证等工作。所以要根据具体情况而定。

  还有一点需要注意:如果在页面中多个过程要共享一个对象或变量,我们在页面类的开 始部分定义一个页面级的全局变量是不行的,static本来可以,但上面说了这种类型的变量 不安全,所以这时就可以用ViewState。

  ViewState是将数据存入到页面隐藏控件里,不再占用服务器资源,因此, 我们可以将一 些需要服务器"记住"的变量和对象保存到viewstate里面。viewstate并不能存储所有的.net 类型数据,它仅仅支持String、Integer、Boolean、Array、ArrayList、Hashtable 以及自 定义的一些类型。

  ViewState 常用于保存单个用户的状态信息,生存期等于页面的生存期。viewstate是 在本页面之内各函数间进行传值的 , 至于为什么要使用这种方法是因为在一个事件发生之 后 , 页面可能会刷新 , 如果定义全局变量会被清零 , 所以要使用 viewstate保持数据,任何事物都有两面性, 因为ViewState变量在客户端实际上是用<input type=“hidden ” value=“ADFAIB3P234P-AFAFAF……”/>保存的一个对象,这样如果要保存的是个对象, 甚 至是个很复杂的对象(如DataTable),这样以来就会增加网络传输的负担。 使用viewstat e会增加页面html的输出量,占用更多的带宽,这一点是需要慎重考虑的。另外, 由于所有的v iewstate都是存储在一个隐藏域里面,用户可以很容易的通过查看源码来看到这个经过base6 4编码的值,然后再经过转换就可以获取你存储其中的对象和变量值。

  ViewState只能在一个页面上传值(session可跨多个页面传值),ViewState只是在当 前page内有效,关了当前页,再重新打开,ViewState所保存的值也就消失了。需要在用户 访问一个页面时保持一个变量的值,并随时改变它的值,用ViewState好些。ViewState是用 来同步客户端与服务端的变量状态的?当有两个用户对同一页面进行操作时,若使用Static? 出现了数据张冠李戴的严重错误时,改为ViewState后就会一切正常了。

  开发C/S模式的系统和开发B/S模式的系统有很大的不同。因此我们一定要根据不同情况 正确理解各种变量的作用域和生存期,以便能够正确使用各种保存数据的方法而不至于出现 错误。

注释:

①②陈志泊,ASP.Net数据库应用程序开发[M].人民邮电出版社.2005.

③徐新华,精通ASP.Net2.0[M].机械工业出版社.2006.

参考文献:

[1]刘培义,ASP.Net程序设计教程[M].清华大学出版社.2009.

[2]董义革,ASP.Net程序设计基础与应用[M].科海出版社新址.2006.

收稿日期:2010-09-06

作者简介: 杨敏(1963~),女,吉林市人,长春汽车工业高等专科学校副教授,主要从事自 动化控制技术的教学和研究。刘丹洁(1964~),女,吉林长春人,女,长春汽车工业高等专 科学校副教授。主要从事自动化控制技术的教学和研究。