[Asp.Net]状态管理(ViewState、Cookie)
简介
HTTP协议是无状态的。从客户端到服务器的连接可以在每个请求之后关闭。但是一般需要把一些客户端信息从一个页面传送给另一个页面。
- 无状态的根本原因是:浏览器和服务器使用Socket通信,服务器将请求结果返回给浏览器后,会关闭当前Socket连接。而且服务器会在处理页面完毕后销毁页面对象。
- 应用层面的原因是:浏览器和服务器之间通信都遵守HTTP协议。
- Http协议是无状态的,不会记得上次和网页“发生了什么。服务器不记得上次给了浏览器什么。
- 对网站造成的影响:如果用户录入了一些信息,当跳转到下一个页面时,数据丢失,再也不能获得那些数据。
如果要知道上一次的状态信息,我们就得把这个状态信息记录在某个地方:
a.服务器端
b.浏览器端(客户端)
c. 表单元素中—如:隐藏域<input type=“hidden”/>(Http报文)
在保存状态的各种方式中,主要区别是:状态是存储在客户端还是服务器上,下表列出了各种状态管理技术以及状态保持有效的时间。
状态类型 | 客户端或服务器资源 | 有效时间 |
ViewState | 客户端 | 只在一个页面中 |
Cookie | 客户端 | 关闭浏览器时会删除临时cookie(此时的cookie没有设置有效时间,存储在浏览器内存中,关闭浏览器cookie自动删除),永久存储在用户系统磁盘上。 |
Session | 服务器 | 回话状态与浏览器回话相关。回话在超时后无效(默认为20分钟) |
Application | 服务器 | 应用程序状态在所有的客户端上共享,这个状态在服务器重启之前都是有效的 |
Cache | 服务器 | 类似于应用程序状态,高速缓存是共享的。但是,使高速缓存无效有更好的控制方式 |
先将状态管理的五种方式基本概念放在一起,方便比较记忆。
网络上有一种划分更细的方案,如下图所示:
客户端的状态保持方案:ViewState、隐藏域、Cookies、控件状态、URL查询参数
服务端的状态保持方案:Session(会话)、Application、Caching(缓存)、DataBase(数据库)
客户端的状态管理
- ViewState
关于ViewState讲的太多了,我这里也是将需注意的地方写下来,方便日后查询,当然也希望能帮到别人。Web服务器控件自动使用ViewState来使事件工作。ViewState包含的状态与控件发送给客户端时所包含的状态相同。当浏览器把窗体发送给服务器时,ViewState包含了初始值,但所发送的控件包含新值。如果初始值和新值有区别,就调用相应的时间处理程序。
使用ViewState的缺点是。数据总是要从服务器传送给客户端,再从客户端传送给服务器,增加了网络流量。为了减少网络流量,可以关闭ViewState。在Page指令中把EnableViewState属性设置为false,就可以关闭页面中所有控件的ViewState。
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="Wolfy.WebChat.Server.Default" EnableViewState=" false" %>
设置一个控件的EnableViewState属性,也可以配置该控件的ViewState。无论页面进行了什么配置,只要定义了控件的EnableViewState属性,就使用控件配置的值(优先级较高),只有没有配置ViewState的控件才使用页面配置的值。
还可以把定制的数据存储在ViewState中。为此可以使用索引符和page类的ViewState属性。可以设置Index参数定义一个名称,用于访问ViewState值。
ViewState["mydata"] = "中秋节快乐";
可以读取前面存储的ViewState,如下所示:
string mydata = (string)ViewState["mydata"];
在发送给客户端的HTML代码中,整个页面的ViewState存储在一个隐藏域中:
<input type="hidden" name="__VIEWSTATE" id="__VIEWSTATE" value="pRdkV9UzTFimveKGNXH7EJyJbDjTrumX55ovGtz5zcgHVPI4HrWrE+I81Ox6/Pb8mOi2UVpNLkMyuEpl5Zj6UQQwwJpxpHbUpZbe2TkcyAJnmLda+oPgf/vO+rmInjm1" />
使用隐藏域的优点是,每个浏览器都可以使用这个特性,用户不能关闭它。
ViewState只保存在页面中。如果状态应保存在多个不同的页面中,就应使用cookie在客户端保存状态。
总结:
默认情况下,ViewState是被启用的,比如提交表单后,表单中输入的值会自动保留。但是如果不需要保留,也可以将其禁用,这样可以节省资源。
-
- 服务器在接收到用户请求一个页面后,会自动在请求报文中找看是否包含__VIEWSTATE的隐藏域,如果有,则将中间的值解码后添加到页面的ViewState属性中。
- 服务器在输出的时候,也会自动的将ViewState中的值添加到表单里名叫__VIEWSTATE的隐藏域中
-
- VIEWSTATE适用于同一个页面在不关闭的情况下多次与服务器交互
下面3种方式就可以分别禁用某一个控件、某一个页面和整个应用程序的ViewState。
1) 控件禁用:将控件的EnableViewState属性设置为false;
2) 页面禁用:在页面的Page指令中添加EnableViewState="false";
3) 应用程序禁用:在Web.Config文件中添加
<configuration> <system.web> <pages enableViewState="false"></pages> </system.web> </configuration>
2. Cookie
cookie在HTTP头中定义。使用HttpResponse类可以把cookie发送给客户端。Response是Page类的一个属性,它返回一个HttpResponse类型的对象。HttpResponse类定义了返回HttpCookieColletion的Cookies属性。使用HttpCookieColletion可以向客户端返回多个cookie。
下面的实例代码说明了如何把cookie发送给客户端。首先,实例化一个HttpCookie对象。在这个类的构造函数中,设置cookie的名称,这里是mycookie。HttpCookie类的Values属性可以添加多个cookie值。如果只返回一个cookie的值,就可以使用Value属性。但如果要发送多个cookie值,最好把值添加到一个cookie中,而不是使用多个cookie。
1 string myval = "myval"; 2 HttpCookie cookie = new HttpCookie("mycookie"); 3 cookie.Values.Add("mystate", myval); 4 Response.Cookies.Add(cookie);
cookie可以是临时的,仅在一个浏览器回话中有效,也可以存储在客户端的磁盘上。为了使cookie变成永久的,必须使用HttpCookie对象设置Expires属性。使用Expires属性可以定义cookie不再有效的日期,这里把它设置为三个月后。
尽管可以设置特定的日期,但不能保证cookie会存储到该日期位置。用户可以删除cookie,如果在本地存储了太多的cookie,浏览器应用程序也可能删除它,浏览器只能为每个服务器存储20个cookie,为所有的服务器存储300个cookie(根据各浏览器而定)。达到极限后,就删除有一段时间已不再使用的cookie。
1 string myval = "myval"; 2 HttpCookie cookie = new HttpCookie("mycookie"); 3 cookie.Values.Add("mystate", myval); 4 cookie.Expires = DateTime.Now.AddMonths(3); 5 Response.Cookies.Add(cookie);
客户端从服务器上请求一个页面时,这个服务器的cookie就可以在客户端上使用,并作为http请求的一部分发送给服务器。要在Asp.Net页面中读取cookie,可以访问HttpRequest对象中的cookie集合。
与Http响应一样,Page类也有一个Request属性返回HttpRequest类型的对象。Cookies属性返回HttpCookieCollection,它可以用于读取客户端发送的cookie。可以用索引符通过其名来访问cookies,然后使用HttpCookie的Values属性从cookie中获取值。
1 HttpCookie cookie = Request.Cookies["mycookie"]; 2 string myval = cookie.Values["mystate"];
Asp.Net很容易使用cookie。但必须了解cookie的限制。如前所述,浏览器只能接收来自一个服务器的20个cookie,以及来自所有服务器的300个cookie。另外,cookie的大小也有限制。cookie不能存储多余4K的数据。这些限制的存在使客户端磁盘不会被cookie占满。
Cookie原理:cookie是如何往返的?
* 服务器向浏览器写出Cookie实际上就是在 响应报文中 生成响应行:
* Set-Cookie: uinfo2=123; expires=Mon, 06-Jun-2011 06:48:47 GMT; path=/
* 浏览器读取此 响应行后 会自动在客户端硬盘中产生一个Cookie文件,名为:
* Cookie:administrator@localhost/,注意@后的 localhoust/ ,实际上是颁发此Cookie网站的域名;
* 当浏览器下次再访问此域名时,就会自动将 后缀为 localhoust/ 的cookie文件内容发送到服务器。
补充:
不同浏览器间cookie总大小也不同:
Firefox和Safari允许cookie多达4097个字节,包括名(name)、值(value)和等号。
Opera允许cookie多达4096个字节,包括:名(name)、值(value)和等号。
InternetExplorer允许cookie多达4095个字节,包括:名(name)、值(value)和等号。
浏览器允许每个域名所包含的cookie数:
Microsoft指出InternetExplorer8增加cookie限制为每个域名50个,但IE7似乎也允许每个域名50个cookie。
Firefox每个域名cookie限制为50个。
Opera每个域名cookie限制为30个。
Safari/WebKit貌似没有cookie限制。但是如果cookie很多,则会使header大小超过服务器的处理的限制,会导致错误发生。
注:“每个域名cookie限制为20个”将不再正确!
当很多的cookie被设置,浏览器如何去响应。
除Safari(可以设置全部cookie,不管数量多少),有两个方法:
最少最近使用(leastrecentlyused(LRU))的方法:当Cookie已达到限额,自动踢除最老的Cookie,以使给最新的Cookie一些空间。InternetExplorer和Opera使用此方法。
Firefox很独特:虽然最后的设置的Cookie始终保留,但似乎随机决定哪些cookie被保留。似乎没有任何计划(建议:在Firefox中不要超过Cookie限制)。
-
博客地址:http://www.cnblogs.com/wolf-sun/
博客版权:如果文中有不妥或者错误的地方还望高手的你指出,以免误人子弟。如果觉得本文对你有所帮助不如【推荐】一下!如果你有更好的建议,不如留言一起讨论,共同进步! 再次感谢您耐心的读完本篇文章。