[译]面向初学者的Asp.Net状态管理技术
介绍
本文主要讲解Asp.Net应用程序中的状态管理技术(Asp.Net中有多种状态管理技术),并批判性地分析所有状态管理技术的优缺点。
背景
HTTP是无状态的协议。客户端发起一个请求,服务器响应完请求后,立即断开。服务器断开后,所有因请求而分配的资源会全部被清除。这些资源包括在请求期间创建的对象,分配的内存等等。Windows应用程序开发者可能会感到很惊讶,因为他没有办法依靠对象和成员变量来跟踪Web应用程序的当前状态。
如果我们要跟踪用户在多个页面访问间,或同一页的多个访问间的信息,我们就需要使用由ASP.NET提供的状态管理技术。状态管理是由ASP.NET用以让开发者在相同或不同页面的多个请求中保存交互状态和页面信息的处理过程。
状态管理分类
ASP.NET主要提供了两种类型的状态管理技术:
● 客户端状态管理
● 服务器端状态管理
当我们使用客户端状态管理技术,与状态有关的信息将被存储在客户端。此信息将每次请求和响应中的来回传输。这可以看成是:
注:图片来自微软出版社的书。
这种状态管理主要的好处是,我们减少了服务器保存状态信息的压力,它节约了大量服务器内存。客户端状态管理的负面影响是,它需要更多的带宽,因为相当数量的数据需要来回传输。但是还有一个比带宽占用更大的问题。客户端状态管理让信息的来回传输,因此用户信息可能在传输过程中被人中途劫持。所以我们不能将敏感信息,像密码、信用卡号和应付金额存在客户端,这些东西需要用服务器端状态管理技术来保存。
跟客户端状态管理技术相比,服务器端状态管理技术将所有的状态信息保存在内存中。它的缺点是占用更多内存。优点是用户的机密和敏感信息更安全。
注:图片来自微软出版社的书。
我们不能绝对地说用哪一种状态管理技术好。根据信息的类型和大小,我们必须将客户端和服务端状态管理技术结合。现在让我们看看,在客户端和服务端上我们可以用多少不同的方式来管理状态。
客户端状态管理技术
● View State
● Control State
● Hidden fields
● Cookies
● Query String
服务端状态管理技术
● Application State
● Session State
View State
在同一个页面的请求中,ASP.NET使用这个机制来跟踪控件的值。我们也可以向View State中添加自定义的值。ASP.NET 自动将控件的信息保存在View State中,然后在回发过程中的页面渲染前将它从View State中取回。
如果我们需要使用viewsstate
存储自定义的信息,我们只需要记住 viewstate
是 一个dictionary
类型。我们可以把自己的数据作为键值对保存在viewstate中
(如以下代码所示). 在request过程中,这个控件的值也会被哈希化到这个字典对象中,然后在response过程中被填充回去。
由于这些信息保存在页面本身中,ASP.NET会信息进行加密。
我们可以在 web.config 调整相关的加密参数。
<Configuration> <system.web> <pages viewStateEncryptionMode="Always"/> </system.web> </configuration>
或者在页面声明中:
<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" ViewStateEncryptionMode="Always"%>
让我们看一下一段应用viewstate的代码。 我们写一个带textbox 和button的小页面。我们主要是想在text box中写入一些信息,然后看看ASP.NET是怎样将信息保存在view state中的。我们也会将自定义的信息存储在view state中。当我们运行页面,然后将我的名字写入textbox,并按下button后,触发一个回发,但是我的名字还留在 textbox中
。 Viewstate
让页面回发之后状态的保持成为可能。这个页面如下所示:
让我们看一下页面源代码,view state看起来就像:
<input type="hidden" name="__VIEWSTATE" id="__VIEWSTATE" value="/wEPDwUKMTkwNjc4NTIwMWRkfIZa4Yq8wUbdaypyAjKouH5Vn1Y=" />
现在让我们尝试着将自己信息添加进viewstate 。我们将跟踪用户收到的回发。当用户点击button的时候,我们就将保存在回发内容中的值加1.实现的代码如下所示:
protected void Page_Load(object sender, EventArgs e) { if(IsPostBack == true) { if (ViewState["number"] != null) //我们取出,增加,然后再次存储 { ViewState["number"] = Convert.ToInt32(ViewState["number"]) + 1; } else //第一次postback,我们写入信息 { ViewState["number"] = 1; } Label1.Text = ViewState["number"].ToString(); } }
当我们运行这个界面然后点击按钮去完成一次回发后,这个页面将会展示之前我们回发完成后存储在viewstate中的信息。
View State默认被开启,我们可以将每个控件的EnableViewState属性设为false来禁止view State。这会减少服务器处理时间和减小页面大小。
Control State
现在我们都知道什么是viewstate 并且我们也知道我们可以在页面上禁止某个控件的viewstate。但有假如我们要开发一个自定义控件,控件内部使用viewstate 来保存信息,但是用户可能禁止我们控件的viewstate。为了避免这个问题,我们可以使用一个跟viewstate原理相似,但是控件使用者无法禁用它,这种状态管理技术就叫做ControlState 。Control states内置于自定义控件,它的工作原理跟viewstate 相同。
为了在自定义控件里面使用control state,在初始化的时候,我们必须重写OnInit方法并且在初始化的时候调用RegisterRequiresControlState方法。然后,我们必须重写SaveControlState 和
LoadControlState
方法。
Hidden Fields
Hidden field是ASP.NET提供的一个控件,我们可以用它来保存一些信息。Hidden Fields唯一的限制就是:Hidden Field中的值只会在Http的post请求时被一起发往服务端。 比如说,一个button点击。它在Http的get请求不会生效。让我们使用HiddenFields做相同的实验来跟踪回发的内容。
(注意: hidden field内部也使用ViewState
.)
// 在Hidden Field保存一些信息 ----------------------------------------------------------- int newVal = Convert.ToInt32(HiddenField1.Value) + 1; //Hidden field 默认值为0 HiddenField1.Value = newVal.ToString(); Label2.Text = HiddenField1.Value;
当我们运行页面,单击按钮触发一次回发后,这个页面展示了回发后Hiddenfields 中值。(详见上面代码)
Cookies
在某些时候下,我们需要在多个页面的请求间保存一些信息。到目前为止,我们所讨论的状态管理技术都是用在单个页面的多次请求中的。现在让我们看看多个页面请求中的用来保存消息的技术。
Cookies是指少量的可被保存在用户电脑文本文件中的数据。这些信息可以被服务器读取,也可以在不同页面的访问,或在用户对同一个页面的多次访问中被请求。让我们使用cookie做同样的实验来跟踪回发的内容。
我们不可能用Cookie跟踪到回发的内容,因为cookie保存在用户的电脑中。所以实际上,我们通过观察用户触发回发的次数来判断。
当我们运行这个页面,然后触发一次回发后,这个页面会显示出回发结束时保存在Cookies中的值(详见代码)。Cookies可以有多个参数来比如像Cookie的有效期,存活周期等。这些参数可以像这样操作:
Response.Cookies["number"].Expires = DateTime.Now.AddDays(1);
这个Cookies从它创建后存活1天。
Query Strings
Query strings常被用来保存标识特定页面的变量,比如搜索结果或页码。Query strings就是附加在页面下方page URL中的信息。他们可以被用于保存/传递信息从一个页面到另一个页面或者同一个页面。让我们现在使用Query strings来保存回发的内容。
//GetDataItem from querystring if (Request.QueryString["number"] != null) //Lets retrieve, increase and store again { Label4.Text = Request.QueryString["number"]; } //set in query string int postbacks = 0; if (Request.QueryString["number"] != null) //Lets retrieve, increase and store again { postbacks = Convert.ToInt32(Request.QueryString["number"]) + 1; } else //First postback, lets store the info { postbacks = 1; } Response.Redirect("default.aspx?number=" + postbacks);
这里有一点要注意的是:在同一个页面中,我们不能将要回发的信息保存在query string中。原因是:每次我们使用query string的时候,它都会创建一个新的Url,它产生一个新的请求。所以,现在实际上,我们通过跟踪点击的次数来判断页面中状态值的变化。query string的设计思想是,我们可以将一个页面(假设为页面A)上的信息传递给另一个页面(假设为页面B),页面A上的这些信息可以被页面B所用。
注意:我们上面对Cookies和QueryString的使用只是为了演示它们的用法。在真实应用时,他们不应该被用于同一个页面的请求中用来传递信息。Querystrings应该用于多个页面访问中信息的保存。Cookies应该用于对特定站点的多次访问(在同一台电脑上)中数据的保存。
Application State
在ASP.NET中,我们可以用Application State来保存数据。在Web 应用程序(Web Application)中,它是一个可以被所有页面都访问到的全局信息共享机制。Application state保存在应用程序的key/value dictionary对象中。它的信息也可以被网站的所有用户共享。假如我们需要用户的特定信息,我们最好使用sessionstate.
ASP.NET提供了三个事件,让我们用来初始化系统变量( Application variables)(在应用程序关闭的时候,清理资源)和响应应用程序错误(Application errors):
l Application_Start: 在应用程序启动时触发. 我们可以在这个地方初始化系统变量(Application variables)。
l Application_End: 在应用程序关闭时触发.我们用它来清理系统资源和写一些应用程序日志。
l Application_Error: 在不能解决的异常发生时触发.我们可以用它来记录错误日志
让我们将页面回发的信息保存在application state中。
//global.asax void Application_Start(object sender, EventArgs e) { Application["number"] = 0; } //In web pages Application.Lock(); Application["number"] = Convert.ToInt32(Application["number"]) + 1; Application.UnLock(); Label5.Text = Application["number"].ToString();
当我们运行页面点击按钮触发一次回发时,页面上会显示回发完成后保存在ApplicationState中的信息。我们可以利用这个对象来跟踪网站上的所有用户的点击数。(详见代码)
Session State
如Application state,在Web应用程序中全局存储对象(a global storage)中的信息可以被所有的页面共享,但是当我们需要限制当前用户的信息只能被自己访问而他人不能访问的时候,我们就要用到Session State。Session State保存在每个会话中的key/value dictionary对象。Session State的信息只能被当前的用户访问,也就是只能被当前的会话访问。
//global.asax void Session_Start(object sender, EventArgs e) { // Code that runs when a new session is started Session["number"] = 0; } // Web forms Session["number"] = Convert.ToInt32(Session["number"]) + 1; Label6.Text = Session["number"].ToString();
当我们运行页面点击按钮触发一次回发时,页面上会显示回发完成后保存在SessionState中的信息。我们可以利用这个对象来跟踪当前用户的点击数,也就是拥有整个网站当前会话的用户的点击数。
客户端管理技术的优点
· 更好的可拓展性(Better scalability)
· 支持多浏览器(Support for multiple browser)
服务端管理技术的优点
· 更好的安全性
· 减少网络流量
兴趣点(Points of Interest)
我写了这篇小短文主要是因为我的学生有的需要一些关于状态管理技术的复习材料。我想如果我把它放在CodeProject 上,可能对一些初学者会有帮助。现在,我将总结一下状态管理技术:
-
当可扩展性要求比较高的时候,我们应该使用客户端管理技术。
-
当安全性要求比较高的时候,我们应该使用服务端管理技术。
-
ASP.NET默认的页面级的状态管理技术是ViewState。
-
我们可以将自定义的信息保存在ViewState中。
-
自定义控件使用ControlState 来保存信息。
-
Hidden field可以为同一个页面保存信息。
-
Cookies可以为同一台电脑上的多次访问提供相关的信息。
-
Query string可以将信息从一个页面传递到另一个页面。
-
ApplicationState 可以用于保存应该被所有页面和所有用户共享的信息。
-
SessionState 可以用于保存应该被所有页面共享,但只能被当前用户/会话访问到的信息。
参考连接
翻译自:A Beginner's Tutorial on ASP.NET State Management
作者:kissazi2
出处:http://www.cnblogs.com/kissazi2/
本文版权归作者所有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。