介绍

本文主要讲解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"]) + ;
}
else //第一次postback,我们写入信息
{
ViewState["number"] = ;
} 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) + ; //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();

这个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 = ; if (Request.QueryString["number"] != null) //Lets retrieve, increase and store again
{
postbacks = Convert.ToInt32(Request.QueryString["number"]) + ;
}
else //First postback, lets store the info
{
postbacks = ;
} 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"] = ;
} //In web pages
Application.Lock();
Application["number"] = Convert.ToInt32(Application["number"]) + ;
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"] = ;
} // Web forms
Session["number"] = Convert.ToInt32(Session["number"]) + ; 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

    State Management in ASP.NET and ASP.NET MVC

    ASP.NET客户端状态管理方式的优缺点

[译]面向初学者的Asp.Net状态管理技术的更多相关文章

  1. [Asp.Net]状态管理(Session、Application、Cache)

    上篇博文介绍了在客户端状态管理的两种方式:http://www.cnblogs.com/wolf-sun/p/3329773.html.除了在客户端上保存状态外,还可以在服务器上保存状态.使用客户端的 ...

  2. [Asp.Net]状态管理(ViewState、Cookie)

    简介 HTTP协议是无状态的.从客户端到服务器的连接可以在每个请求之后关闭.但是一般需要把一些客户端信息从一个页面传送给另一个页面. 无状态的根本原因是:浏览器和服务器使用Socket通信,服务器将请 ...

  3. 转载ASP.NET 状态管理Application,Session,Cookie和ViewState用法

    转载原地址 http://www.cnblogs.com/cuishao1985/archive/2009/09/24/1573403.html ASP.NET状态管理 APPlication,Ses ...

  4. ASP.NET状态管理的总结

    阅读目录 开始 hidden-input QueryString Cookie ApplicationState ViewState,ControlState Session Profile 各种状态 ...

  5. ASP.NET状态管理详解,让你明明白白

    开发WinFrom的程序员可能不会在意维护应用程序的状态,因为WinFrom本身就在客户端运行,可以直接在内存中维护其应用程序状态.但ASP.NET应用程序在服务器端运行,客户端使用无状态的http协 ...

  6. ASP.NET状态管理策略

    如果要想把信息存储在客户端那可以选择视图状态.控件状态.隐藏字段.cookie.和查询字符串. 1.web窗体页提供viewstate属性作为内置结构,在同一页的多个请求间自动保留值.他作为页面的隐藏 ...

  7. ASP.NET状态管理之四(暂存状态HttpContext.Items)

    ASP.NET提供一个类System.Web.HttpContext ,用来表示上下文,此对象有一个属性Items 暂存状态就是利用HttpContext.Items属性来存放数据 MSDN中Http ...

  8. 实验五 ASP.NET状态管理和应用程序配置 总结

    这次实验内容是对ASP.NET配置系统的了解和使用,还有就是对Application.Session.ViewState对象的应用.首先,我想说ASP.NET配置系统真的大大超乎我的想象,我以为会是上 ...

  9. [Asp.Net]状态管理(Session、Application、Cache、Cookie 、Viewstate、隐藏域 、查询字符串)

    Session:  1. 客户在服务器上第一次打开Asp.Net页面时,会话就开始了.当客户在20分钟之内没有访问服务器,会话结束,销毁session.(当然也可以在Web.config中设置缓存时间 ...

随机推荐

  1. awk用法

    目前虽然有很多工具可以代替awk,但是呢我还是认为awk还是非常重要,比如有时候load数据到hive,mysql发现数据有点问题,这样可以先对比文件和库中数据是否一致,这样awk就发挥用处了,还有从 ...

  2. Python PEP 492 中文翻译——协程与async/await语法

    原文标题:PEP 0492 -- Coroutines with async and await syntax 原文链接:https://www.python.org/dev/peps/pep-049 ...

  3. nginx环境下配置nagios-关于commands.cfg

    -w $ARG1$ -c $ARG2$ -M -b% -c % -f% -c % -f% -c % -f #  define command{         command_name    chec ...

  4. 关于 NPOI 报 Invalid column index (256). Allowable column range for BIFF8 is (0..255) or ('A'..'IV') 错误的解决办法

    当看到这个错误的时候,网上搜索可以会有些说列数有限制之类的说法,这个说法是相对于 Office 2003 的,在 Office 2007 之前,最多只可以创建  列:在 Office 2007 之后, ...

  5. Java设计模式——适配器模式

    JAVA 设计模式 适配器模式 用途 适配器模式 (Adapter) 将一个类的接口转换成客户希望的另外一个接口. Adapter模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作. 适配器 ...

  6. asp.net GDI+绘制矩形渐变

    using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.We ...

  7. 循序渐进Python3(六) -- 初识内置变量、反射、递归

    #python用下划线作为变量前缀和后缀指定特殊变量.稍后我们会发现,   #对于程序来说,其中的有些变量是非常有用的,而其他的则是未知或者无用的.   #我们总结一下Python中下划线的特殊用法  ...

  8. 自定义底部tab

    public class MainActivity extends TabActivity implements OnCheckedChangeListener { private RadioGrou ...

  9. udp-->socket通信原理

    UDP数据通讯原理     UDP数据通讯分服务端(软件)和客户端端:     服务端(软件)(服务器)先运行,服务端,不需要事先知道客户端IP和port     客户端(软件)(客户端机器)后运行, ...

  10. SPI数据传输(库函数方法)

    主机端: /********************************* 代码功能:SPI数据传输(主机端) 引脚说明: SS/CS:片选(高电平屏蔽,低电平启用) MOSI :主机送出信号 M ...