在线时间:8:00-16:00
迪恩网络APP
随时随地掌握行业动态
扫描二维码
关注迪恩网络微信公众号
由于HTTP协议的无状态特性,导致在ASP.NET编程中,每个请求都会在服务端从头到执行一次管线过程, 对于ASP.NET页面来说,Page对象都会重新创建,所有控件以及内容都会重新生成, 因此,如果希望上一次的页面状态能够在后续页面中保留,则必需引入状态管理功能。 ASP.NET为了实现状态管理功能,提供了8种方法,可帮助我们在页面之间或者整个用户会话期间保留状态数据。 这些方法分为二类:视图状态、控件状态、隐藏域、Cookie 和查询字符串会以不同方式将数据发送到客户端上。 而应用程序状态、会话状态和配置文件属性(Profile)则会将数据存储到服务端。 虽然每种方法都有不同的优点和缺点,对于小的项目来说,可以选择自己认为最容易使用的方法, 然而,对于有着较高要求的程序,尤其是对于性能与扩展性比较关注的程序来说, 选择不同的方法最终导致的差别可能就非常大了。 在这篇博客中,我将谈谈自己对ASP.NET状态管理方面的一些看法。 hidden-input 这个名字我是取的,表示所有type="hidden"的input标签元素。 在中文版的MSDN中,也称之为 隐藏域 。 hidden-input通常存在于HTML表单之内,它不会显示到页面中, 但可以随表单一起提交,因此,经常用于维护当前页面的相关状态,在服务端我们可以使用Request.Form[]来访问这些数据。 一般说来,我通常使用hidden-input来保存一些中间结果,用于在多次提交中维持一系列状态, 或者用它来保存一些固定参数用来提交给其它页面(或网站)。 在这些场景中,我不希望用户看到这些数据,因此,使用hidden-input是比较方便的。 关于表单的更多介绍可参考我的博客:细说 Form (表单) 在ASP.NET WebForm框架中,我们可以使用HiddenField控件来创建一个hidden-input控件,并可以在服务端操作它, 还可以直接以手写的方式使用隐藏域,例如: <input type="hidden" name="hidden-1" value="aaaaaaa" /> <input type="hidden" name="hidden-2" value="bbbbbbb" /> <input type="hidden" name="hidden-3" value="ccccccc" /> 另外,我们还可以调用ClientScript.RegisterHiddenField()方法来创建隐藏域: ClientScript.RegisterHiddenField("hidden-4", "ddddddddd"); 输出结果: <input type="hidden" name="hidden-4" id="hidden-4" value="ddddddddd" /> 这三种方法对于生成的HTML代码来说,主要差别在于它们出现位置不同: 优点: 缺点: QueryString查询字符串是存在于 URL 结尾的一段数据。下面是一个典型的查询字符串示例(红色部分文字): http://www.abc.com/demo.aspx?k1=aaa&k2=bbb&k3=ccc 查询字符串经常用于页面的数据过滤,例如: 关于查询字符串的用法,我补充二点: 优点: 缺点: Cookie由于HTTP协议是无状态的,对于一个浏览器发出的多次请求,WEB服务器无法区分它们是不是来源于同一个浏览器。所以,需要额外的数据用于维护会话。 Cookie 正是这样的一段随HTTP请求一起被传递的额外数据。 Cookie 是一小段文本信息,它的工作方式就是伴随着用户请求和页面在 Web 服务器和浏览器之间传递。Cookie 包含每次用户访问站点时 Web 应用程序都可以读取的信息。 与hidden-input, QueryString相比,Cookie有更多的属性,许多浏览器可以直接查看这些信息: 由于Cookie拥有这些属性,因此在客户端状态管理中可以实现更多的功能,尤其是在实现客户端会话方面具有不可替代的作用。 关于Cookie的更多讲解,请参考我的另一篇博客:细说Cookie 优点: 这里我要解释一下Cookie 【良好的扩展性】是个什么概念,比如: 缺点: ApplicationState应用程序状态是指采用HttpApplicationState实现的状态维持方式,使用代码如下: Application.Lock(); Application["PageRequestCount"] = ((int)Application["PageRequestCount"]) + 1; Application.UnLock(); 对于这种方法,我不建议使用,因为: ViewState,ControlState视图状态,控件状态,二者是类似,在页面中表现为一个hidden-input元素: <input type="hidden" name="__VIEWSTATE" id="__VIEWSTATE" value="......................" /> 控件状态是ASP.NET 2.0中引入,与视图状态相比,它不允许关闭。 在ASP.NET的早期,微软为了能帮助广大开发人员提高开发效率,引用入一大批的服务端控件,并为了能将事件编程机制引入ASP.NET中,又发明了ViewState。 这种方式虽然可以简化开发工作量,然而却有一些限制和缺点:
在ASP.NET兴起的年代,ViewState绝对是个了不起的发明。 有些人认为:我现在做的程序只是在局域网内使用,使用ViewState完全没有问题! 对于视图状态,我认为它引入的问题比它解决的问题要多要复杂, 另外,我不排斥使用服务器控件,我认为:你可以使用服务端控件显示数据,但不要用它处理回发。 如果你仍然认为视图状态是不可缺少的,那我还是建议你看看ASP.NET MVC框架,看看没有视图状态是不是照样可以写ASP.NET程序。 SessionSession是ASP.NET实现的一种服务端会话技术,它允许我们方便地在服务端保存与用户有关的会话数据。 我认为Session只有一个优点:最简单的服务端会话实现方式。 缺点: Session的这些缺点也提醒我们: 如果想了解更多的Session特点,以及我对Session的看法,可以浏览我的博客:Session,有没有必要使用它? Session的本质有二点: 我认为了解Sesssion本质非常有用,因为可以借鉴并实现自己的服务端会话方法。 关于Session我还想说一点: ProfileProfile 在中文版的MSDN中被称为 配置文件属性,这个功能是在 ASP.NET 2.0 中引入的。 ASP.NET提供这个功能主要是为了简化与用户相关的个性化信息的读写方式。 为了使用Profile,我们首先在web.config中定义所需要的用户个性化信息: <profile> <properties> <add name="Address"/> <add name="Tel"/> </properties> </profile> 然后,就可以在页面中使用了: 为什么会这样呢? using System; using System.Web.Profile; public class ProfileCommon : ProfileBase { public ProfileCommon(); public virtual string Address { get; set; } public virtual string Tel { get; set; } public virtual ProfileCommon GetProfile(string username); } 有了这个类型后,当我们访问HttpContext.Profile属性时,ASP.NET会创建一个ProfileCommon的实例。 也正是由于Profile的强类型机制,在使用Profile时才会有智能提示功能。 如果我们希望为未登录的匿名用户也提供这种支持,需要将配置修改成: <profile> <properties> <add name="Address" allowAnonymous="true" /> <add name="Tel" allowAnonymous="true"/> </properties> </profile> <anonymousIdentification enabled="true" /> Profile中的每个属性还允许指定类型和默认值,以及序列化方式,因此,扩展性还是比较好的。 尽管Profile看上去很美,然而,使用Profile的人却很少。 还是给Profile做个总结吧: 各种状态管理的对比与总结前面分别介绍了ASP.NET的8种状态管理技术,这里打算给它们做个总结。
表格中主要考察了数据保存与服务端水平扩展的相关重要指标。 下面我来解释表格的结果。 从这个表格我们还可以得到以下结论: 会话状态的选择接下来,我们再来看看会话状态,它与状态管理有着一些关系,属于比较类似的概念。 谈到会话状态,首先我要申明一点:会话状态与状态不是一回事。 本文前面所说的状态分为二种: 而会话状态是针对某个用户来说,他(她)在多次操作之间的状态。 在ASP.NET中,使用会话状态有二个选择:Session 或者 Cookie 。 那么到底选择哪个呢? 下面是我选择Cookie实现会话状态的理由: 如果选择使用Cookie实现会话状态,有3点需要特别注意: 或许有些人认为:每种技术都有它们的优缺点,有各自的适用领域。 改变开发方式,发现新方法回想一下:为什么在ASP.NET中需要状态管理? 为什么Windows计算器(这类)程序不用考虑会话问题呢? 再来看这样一个场景: 图片左边是一个列表页面,允许调整每条记录的优先级,但是有2个要求: 显然,完成这个任务必须要有状态才能实现。 面对这个问题,你可以思考一下:选择哪种ASP.NET支持的状态管理方法都很麻烦。 怎么办? 我的解决方法:创建一个JavaScript数组,用每个数组元素保存每条记录的状态, 这个案例也提醒我们:当发现ASP.NET提供的状态管理功能全部不合适时, 我们需要改变开发方式了。 为什么WEB编程都有【无状态】问题,而桌面程序没有? |
请发表评论