ASPNET状态管理的总结_第1页
ASPNET状态管理的总结_第2页
ASPNET状态管理的总结_第3页
ASPNET状态管理的总结_第4页
ASPNET状态管理的总结_第5页
已阅读5页,还剩7页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

ASP.NET状态管理的总结阅读目录开始hidden-inputQueryStringCookieApplicationStateViewState,ControlStateSessionProfile各种状态管理的对比与总结会话状态的选择改变开发方式,发现新方法由于HTTP协议的无状态特性,导致在ASP.NET编程中,每个请求都会在服务端从头到执行一次管线过程,对于ASP.NET页面来说,Page对象都会重新创建,所有控件以及内容都会重新生成,因此,如果希望上一次的页面状态能够在后续页面中保留,则必需引入状态管理功能。ASP.NET为了实现状态管理功能,提供了8种方法,可帮助我们在页面之间或者整个用户会话期间保留状态数据。这些方法分为二类:视图状态、控件状态、隐藏域、Cookie和查询字符串会以不同方式将数据发送到客户端上。而应用程序状态、会话状态和配置文件属性(Profile)则会将数据存储到服务端。虽然每种方法都有不同的优点和缺点,对于小的项目来说,可以选择自己认为最容易使用的方法,然而,对于有着较高要求的程序,尤其是对于性能与扩展性比较关注的程序来说,选择不同的方法最终导致的差别可能就非常大了。在这篇博客中,我将谈谈自己对ASP.NET状态管理方面的一些看法。

注意:本文的观点可能并不合适开发小型项目,因为我关注的不是易用性。回到顶部hidden-inputhidden-input这个名字我是取的,表示所有type="hidden"的input标签元素。在中文版的MSDN中,也称之为隐藏域。hidden-input通常存在于HTML表单之内,它不会显示到页面中,但可以随表单一起提交,因此,经常用于维护当前页面的相关状态,在服务端我们可以使用Request.Form[]来访问这些数据。一般说来,我通常使用hidden-input来保存一些中间结果,用于在多次提交中维持一系列状态,或者用它来保存一些固定参数用来提交给其它页面(或网站)。在这些场景中,我不希望用户看到这些数据,因此,使用hidden-input是比较方便的。关于表单的更多介绍可参考我的博客:细说Form(表单)在ASP.NETWebForm框架中,我们可以使用HiddenField控件来创建一个hidden-input控件,并可以在服务端操作它,还可以直接以手写的方式使用隐藏域,例如:<inputtype="hidden"name="hidden-1"value="aaaaaaa"/><inputtype="hidden"name="hidden-2"value="bbbbbbb"/><inputtype="hidden"name="hidden-3"value="ccccccc"/>另外,我们还可以调用ClientScript.RegisterHiddenField()方法来创建隐藏域:ClientScript.RegisterHiddenField("hidden-4","ddddddddd");输出结果:<inputtype="hidden"name="hidden-4"id="hidden-4"value="ddddddddd"/>这三种方法对于生成的HTML代码来说,主要差别在于它们出现位置不同:

1.HiddenField控件:由HiddenField的出现位置来决定(在form内部)。

2.RegisterHiddenField方法:在form标签的开头位置。

3.hidden-input:你写在哪里就是哪里。优点:

1.不需要任何服务器资源:隐藏域随页面一起发送到客户端。

2.广泛的支持:几乎所有浏览器和客户端设备都支持具有隐藏域的表单。

3.实现简单:隐藏域是标准的HTML控件,不需要复杂的编程逻辑。缺点:

1.不能在多页面跳转之间维持状态。

2.用户可见,保存敏感数据时需要加密。回到顶部QueryString查询字符串是存在于URL结尾的一段数据。下面是一个典型的查询字符串示例(红色部分文字):/demo.aspx?k1=aaa&k2=bbb&k3=ccc查询字符串经常用于页面的数据过滤,例如:

1.给列表页面增加分页参数,list.aspx?page=2

2.给列表页面增加过虑范围,Product.aspx?categoryId=5

3.显示特定记录,ProductInfo.aspx?page=3关于查询字符串的用法,我补充二点:

1.可以调用HttpUtility.ParseQueryString()来解析查询字符串。

2.允许参数名重复:list.aspx?page=2&page=3,因此在修改URL参数时,使用替换方式而不是追加。

关于参数重名的读取问题,请参考我的博客:细说Request[]与Request.Params[]优点:

1.不需要任何服务器资源:查询字符串的数据包含在每个URL中。

2.广泛的支持:几乎所有的浏览器和客户端设备均支持使用查询字符串传递参数值。

3.实现简单:在服务端直接访问Request.QueryString[]可读取数据。

4.页面传值简单:<ahref="url">或者Response.Redirect(url)都可以实现。缺点:

1.有长度限制。

2.用户可见,不能保存敏感数据。回到顶部Cookie由于HTTP协议是无状态的,对于一个浏览器发出的多次请求,WEB服务器无法区分它们是不是来源于同一个浏览器。所以,需要额外的数据用于维护会话。Cookie正是这样的一段随HTTP请求一起被传递的额外数据。Cookie是一小段文本信息,它的工作方式就是伴随着用户请求和页面在Web服务器和浏览器之间传递。Cookie包含每次用户访问站点时Web应用程序都可以读取的信息。与hidden-input,QueryString相比,Cookie有更多的属性,许多浏览器可以直接查看这些信息:由于Cookie拥有这些属性,因此在客户端状态管理中可以实现更多的功能,尤其是在实现客户端会话方面具有不可替代的作用。关于Cookie的更多讲解,请参考我的另一篇博客:细说Cookie优点:

1.可配置到期规则:Cookie可以在客户端长期存在,也可以在浏览器关闭时清除。

2.不需要任何服务器资源:Cookie存储在客户端。

3.简单性:Cookie是一种基于文本的轻量结构,包含简单的键值对。

4.数据持久性:与其它的客户端状态数据相比,Cookie可以实现长久保存。

5.良好的扩展性:Cookie的读写要经过ASP.NET管线,拥有无限的扩展性。这里我要解释一下Cookie【良好的扩展性】是个什么概念,比如:

1.我可以实现把Cookie保存到数据库中而不需要修改现有的项目代码。

2.把SessionId这样由ASP.NET产生的临时Cookie让它变成持久保存。缺点:

1.大小受到限制。

2.增加请求头长度。

3.用户可见,保存敏感数据时需要加密。回到顶部ApplicationState应用程序状态是指采用HttpApplicationState实现的状态维持方式,使用代码如下:Application.Lock();Application["PageRequestCount"]=((int)Application["PageRequestCount"])+1;Application.UnLock();对于这种方法,我不建议使用,因为:

1.与使用静态变量差不多,直接使用静态变量可以不需要字典查找。

2.选择强类型的集合或者变量可以避免装箱拆箱。回到顶部ViewState,ControlState视图状态,控件状态,二者是类似,在页面中表现为一个hidden-input元素:<inputtype="hidden"name="__VIEWSTATE"id="__VIEWSTATE"value=""/>控件状态是ASP.NET2.0中引入,与视图状态相比,它不允许关闭。

由于它们使用方式一致,而且视图状态是基于控件状态的实现逻辑,所以我就不区分它们了。在ASP.NET的早期,微软为了能帮助广大开发人员提高开发效率,引用入一大批的服务端控件,并为了能将事件编程机制引入ASP.NET中,又发明了ViewState。这种方式虽然可以简化开发工作量,然而却有一些限制和缺点:

1.视图状态的数据只能用于回发(postback)。

2.视图状态的【滥用】容易导致生成的HTML较大,这会引起一个恶性循环:

a.过大的ViewState在序列化过程中会消耗较多的服务器CPU资源,

b.过大的ViewState最终生成的HTML输出也会很大,它会浪费服务端网络资源,

c.过大的ViewState输出导致表单在下次提交时,会占用客户端网络资源。

d.过大的ViewState数据上传到服务端后,反序列化又会消耗较多的服务器CPU资源。

因此,整个交互过程中,用户一直在等待,用户体验极差。在ASP.NET兴起的年代,ViewState绝对是个了不起的发明。

然而,现在很多关于ASP.NET性能优化的方法中,都会将【关闭ViewState】放在头条位置。

为什么会这样呢,大家可以自己思考一下了。有些人认为:我现在做的程序只是在局域网内使用,使用ViewState完全没有问题!

然而,那些人或许没有想过:

1.未来用户可能会把它部署在互联网上运行(对于产品来说就是遇到大客户了)。

2.项目早期的设计与规划,对后期的开发与维护来说,影响是巨大的,因为许多基础部分通常是在早期开发的。

当这二种情况的任何一种发生时,想再禁用ViewState,可能已经晚了。对于视图状态,我认为它解决的问题比它引入的问题要多要复杂,

因此,我不想花时间整理它的优缺点,我只想说一句:把它关了,在web.config中关了。另外,我不排斥使用服务器控件,我认为:你可以使用服务端控件显示数据,但不要用它处理回发。如果你仍然认为视图状态是不可缺少的,那我还是建议你看看ASP.NETMVC框架,看看没有视图状态是不是照样可以写ASP.NET程序。回到顶部SessionSession是ASP.NET实现的一种服务端会话技术,它允许我们方便地在服务端保存与用户有关的会话数据。我认为Session只有一个优点:最简单的服务端会话实现方式。缺点:

1.当mode="InProc"时,容易丢失数据,为什么?因为网站会因为各种原因重启。

2.当mode="InProc"时,Session保存的东西越多,就越占用服务器内存,对于用户在线人数较多的网站,服务器的内存压力会比较大。

3.当mode="InProc"时,程序的扩展性会受到影响,原因很简单:服务器的内存不能在多台服务器间共享。

4.当采用进程外模式时,在每次请求中,不管你用不用会话数据,所有的会话数据都为你准备好了(反序列化),这其实很是浪费资源的。

5.如果你没有关闭Session,SessionStateModule就一直在工作中,尤其是全采用默认设置时,会对每个请求执行一系列的调用,浪费资源。

6.阻塞同一客户端发起的多次请求(默认方式)。

7.无Cookie会话可能会丢失数据(重新生成已过期的会话标识符)。Session的这些缺点也提醒我们:

1.当网站的在线人数较多时,一定不要用Session保存较大的对象。

2.在密集型的AJAX型网站或者大量使用iframe的网站中,要关注Session可能引起的服务端阻塞问题。

3.当采用进程外模式时,不需要访问Session的页面,一定要关闭,否则会浪费服务器资源。如果想了解更多的Session特点,以及我对Session的看法,可以浏览我的博客:Session,有没有必要使用它?Session的本质有二点:

1.SessionId+服务端字典:服务端字典保存了某个用户的所有会话数据。

2.用SessionId识别不同的客户端:SessionId通常以Cookie形式发送到客户端。我认为了解Sesssion本质非常有用,因为可以借鉴并实现自己的服务端会话方法。关于Session我还想说一点:

有些新手喜欢用Session来实现身份认证功能,这是一种【不正确】的方法。

如果你的ASP.NET应用程序需要身份认证功能,请使用Forms身份认证或者Windows身份认证回到顶部ProfileProfile在中文版的MSDN中被称为配置文件属性,这个功能是在ASP.NET2.0中引入的。ASP.NET提供这个功能主要是为了简化与用户相关的个性化信息的读写方式。

简化主要体现在3个方面:

1.自动与某个用户关联,已登录用户或者未登录都支持。

2.不需要我们设计用户的个性化信息的保存表结构,只要修改配置文件就够了。

3.不需要我们实现数据的加载与保存逻辑,ASP.NET框架替我们实现好了。为了使用Profile,我们首先在web.config中定义所需要的用户个性化信息:<profile><properties><addname="Address"/><addname="Tel"/></properties></profile>然后,就可以在页面中使用了:为什么会这样呢?

原因是ASP.NET已经根据web.config为我们创建了一个新类型:usingSystem;usingSystem.Web.Profile;publicclassProfileCommon:ProfileBase{publicProfileCommon();publicvirtualstringAddress{get;set;}publicvirtualstringTel{get;set;}publicvirtualProfileCommonGetProfile(stringusername);}有了这个类型后,当我们访问HttpContext.Profile属性时,ASP.NET会创建一个ProfileCommon的实例。也正是由于Profile的强类型机制,在使用Profile时才会有智能提示功能。如果我们希望为未登录的匿名用户也提供这种支持,需要将配置修改成:<profile><properties><addname="Address"allowAnonymous="true"/><addname="Tel"allowAnonymous="true"/></properties></profile><anonymousIdentificationenabled="true"/>Profile中的每个属性还允许指定类型和默认值,以及序列化方式,因此,扩展性还是比较好的。尽管Profile看上去很美,然而,使用Profile的人却很少。

比如我就不用它,我也没见有人有过它。

为什么会这样?

我个人认为:它与MemberShip一样,是个鸡肋。

通常说来,我们会为用户信息创建一张User表,增加用户信息时,会通过增加字段的方式解决。

我认为这样集中的数据才会更好,而不是说,有一部分数据由我维护,另一部分数据由ASP.NET维护。

另一个特例是:我们根本不创建User表,直接使用MemberShip,那么Profile用来保存MemberShip没有信息是有必要的。还是给Profile做个总结吧:

优点:使用简单。

缺点:不实用。回到顶部各种状态管理的对比与总结前面分别介绍了ASP.NET的8种状态管理技术,这里打算给它们做个总结。客户端服务端数据安全性差好数据长度限制有受硬件限制占用服务器资源否是集群扩展性好差表格中主要考察了数据保存与服务端水平扩展的相关重要指标。下面我来解释表格的结果。

1.客户端方式的状态数据(hidden-input,QueryString,Cookie):

a.数据对用户来说,可见可修改,因此数据不安全。

b.QueryString,Cookie都有长度限制。

c.数据在客户端,因此不占用服务端资源。这个特性对于在线人数很多的网站非常重要。

d.数据在客户端,因此和服务端没有耦合关系,WEB服务器可以更容易实现水平扩展。

2.服务端方式的状态数据(ApplicationState,ViewState,ControlState,Session,Profile):

a.数据对用户不可见,因此安全性好。(ApplicationState,Session,Profile)

b.数所长度只受硬件限制,因此,对于在线人数较多的网站,需谨慎选择。

c.对于存放在内存中的状态数据,由于不能共享内存,因此会限制水平扩展能力。

d.如果状态数据保存到一台机器,会有单点失败的可能,也会限制了水平扩展能力。从这个表格我们还可以得到以下结论:

1.如果很关注数据的安全性,应该首选服务端的状态管理方法。

2.如果你关注服务端的水平扩展性,应该首选客户端的状态管理方法。回到顶部会话状态的选择接下来,我们再来看看会话状态,它与状态管理有着一些关系,属于比较类似的概念。谈到会话状态,首先我要申明一点:会话状态与状态不是一回事。本文前面所说的状态分为二种:

1.页面之间的状态。

2.应用程序范围内的状态。而会话状态是针对某个用户来说,他(她)在多次操作之间的状态。

在用户的操作期间,有可能状态需要在页面之间持续使用,

也有可能服务端程序做过重启,但数据仍然有效。

因此,这种状态数据更持久。在ASP.NET中,使用会话状态有二个选择:Session或者Cookie。

前者由ASP.NET实现,并有可能依赖后者。

后者则由浏览器实现,ASP.NET提供读写方法。那么到底选择哪个呢?

如果你要问我这个问题,我肯定会说:我选Cookie!下面是我选择Cookie实现会话状态的理由:

1.不会有服务端阻塞问题。

2.不占用服务端资源。

3.水平扩展没有限制。

4.也支持过期设置,而且更灵活。

5.可以在客户端直接使用会话数据。

6.可以实现更灵活的会话数据加载策略。

7.扩展性较好(源于ASP.NET

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论