科创学院Web应用开发课件第五章使用ASPNET状态管理实现购物车.ppt_第1页
科创学院Web应用开发课件第五章使用ASPNET状态管理实现购物车.ppt_第2页
科创学院Web应用开发课件第五章使用ASPNET状态管理实现购物车.ppt_第3页
科创学院Web应用开发课件第五章使用ASPNET状态管理实现购物车.ppt_第4页
科创学院Web应用开发课件第五章使用ASPNET状态管理实现购物车.ppt_第5页
已阅读5页,还剩74页未读 继续免费阅读

下载本文档

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

文档简介

第五章 学习情境:使用ASP.NET状态管理实现购物车,5.1 学习情境引入 5.2 基础知识:ASP.NET的状态管理 5.3 基本知识2:跨页面数据传递 5.4 决策与计划 5.5 实施 5.6 检查与评价 5.7 训练,5.1 学习情境引入,5.1.1 网上书店的购物车功能需求和主要问题 5.1.2 网上书店购物车功能展示 5.1.3 网上书店购物车技术分解,5.1.1网上书店的购物车功能需求和主要问题,1功能需求 网上书店需要购物车功能,先购书,然后下订单,由于下订单需要数据库操作,本章只介绍购书部分,图 51 会员购书行为的详细描述,会员的购书行为如图 51,结合前面网上书店系统的展示,购书过程描述为: 会员在主页搜索到了某些图书; 通过主页书名超链接到该图书的详细信息页面,填入购买数量,将其加入购物车; 在购物车页面中浏览刚才的购物车数据(也可以删除购物车数据)。,5.1.1网上书店的购物车功能需求和主要问题,主要问题 (1)问题描述 记录多次购书数据:每个用户可以连续重复上述的购书过程,以购买不同的图书,而在个人购物车中,可以看到每次购买得到的图书数据。也就是图书详细信息页面能够记录每次的购书数据。 记录多用户购书数据:一个网站可能多个用户同时访问,每个用户都将在个人购物车中看到自己的购物数据。也就是图书详细信息页面在记录购书数据时能够区分用户。 跨页传递购书数据:购物车页面能够获得图书详细信息页面的购物数据,用来浏览和管理。即可以在两个页面请求之间记住购物车信息。 问题分析 以我们桌面程序设计的经验来看,这根本不应成为问题,只需要加一些变量,每次用户单击时记录一些值就可以实现。但在网站程序中却成为了问题,因为HTTP协议是没有“记忆”的,它本身不会记住是哪个用户曾经访问过哪个网页,对于“无记忆”的HTTP协议而言,某个用户第一次访问页面BookDetails.aspx和第二次访问页面BookDetails.aspx之间没有什么联系,它不知道这是两次不同的购书。同样,也不知道是否不同的用户来访问。让我们看例 51。,5.1.1网上书店的购物车功能需求和主要问题,例 51 设置页面字段变量,无法实现计数的反面例子。在一个新的Web窗体页中,添加一个Button,修改其Text为“提交”,并编写如下的后台代码:,); public partial class _Default : System.Web.UI.Page int requestTimes = 0; protected void Page_Load(object sender, EventArgs e) requestTimes = requestTimes + 1; Response.Write(requestTimes ,在浏览器中查看本页面,多次点击“提交”按钮,查看网页显示的数值。 结果与分析:由于HTTP协议没有“记忆”,默认情况下,ASP.NET 每次收到请求都会重新实例化对应的页面类,造成requestTimes变量的值每次都初始化为0,因此该页面总是显示1。 为什么ASP.NET要每次都重新实例化对应的页面类?这是因为我们设计的是动态网页,可能有许多用户同时访问我们的网站,即使单个用户也可能多次和网页交互,这些用户即使都访问页面BookDetails.aspx,也可能看到不同的页面BookDetails.aspx:比如用户甲在浏览图书1的详细信息,用户乙则在浏览图书2的详细信息等等。所以不能事先实例化好页面BookDetails类,等待用户来请求,那会导致给他们响应有同样数据的页面实例。而只能是收到一个请求,就根据用户请求实例化所请求的页面,如果不加处理,每次请求所得的页面实例成员都是初始状态,字段变量值总是初始值。 看来,要避免这种“狗熊掰棒子”的结果,必须让HTTP协议变得有“记忆”。要让HTTP协议变得有“记忆”,实际上是一个保持状态的问题,也就是服务器在收到请求时,要能够得到上次请求的状态(包括网页的数据和客户端的标识等)。ASP.NET中有丰富的状态保持方法,适用于各种场合。保持了状态,就可以解决前面提到的问题了。,5.1.2网上书店购物车功能展示,从教材网站下载BookStoreWebSite源码,在本机调试运行。从首页以“test”用户名登录,单击某书名链接,则会打开图书详细信息页面,如图 51所示,输入购买数量,单击“购买”按钮。重复此过程若干次,以建立多条购书数据。单击页面上部“购物车”链接查看购物车,如图 52。 重新打开一个IE程序窗口(不能是选项卡),以另一个用户名“ee”登录,按照前述过程,购买不同的若干图书。再查看其购物车,如图 53,比较两图可知,“ee”用户、“test”用户能够分别保存每次的购物数据。,5.1.3网上书店购物车技术分解,1技术分解 开发实现购物车的技术方案并不唯一,但总是要既保持购物车数据状态,并进行跨页传递,所以,ASP.NET中有以下两部分相关技术: (1).ASP.NET的状态管理 ASP.NET采用多种技术来保持页面级别的状态,以及其他级别的状态,使得动态网站的开发变得简单而灵活,这是ASP.NET的核心技术。 对于程序员,使用ASP.NET提供的状态,是很容易的,但要灵活运用它们,就需要了解aspx页面的生命周期,熟悉了页面生命周期后,ASP.NET网站开发中的许多问题就可以迎刃而解,这也是我们把状态管理作为ASP.NET的核心技术的理由之一。,图 52 图书详细信息页面,图 53 “test”用户的购物车,图 54 “ee”用户的购物车,(2).ASP.NET跨页面数据传递技术 在页面之间传递数据的技术也很多,有的完全是传统的HTTP协议所支持的,有的只在ASP.NET的支持下才能使用,这也是与页面生命周期有关的常用技术。 2.学习安排 学习ASP.NET状态管理、跨页数据传递的相关知识后,实现购物车功能,并进行检查和评价,是本章的主要内容。 页面生命周期知识部分,理解起来有一定的难度,对初学者列为选学内容。但要成为一个熟练的ASP.NET开发者,页面生命周期是必须掌握的内容,建议初学者在实施中遇到问题后,反复查阅此部分内容,以将其逐步掌握。,5.2 基本知识1:ASP.NET的状态管理,5.2.1 视图状态 5.2.2 应用程序状态 5.2.3 会话状态 5.2.4 Cookie状态(选学) 5.2.5 自测 5.2.6 演练,5.2.1 视图状态,视图状态(ViewState),是使HTTP协议变得“有记忆”的关键技术,深入了解了视图状态,就能理解ASP.NET基于事件编程的许多重要工作原理。 在每次请求发生(包括原始请求)后,视图状态数据由ASP.NET在服务器端生成,默认情况下,存放在页面中的“_VIEWSTATE”隐藏域中,该隐藏域数据和页面的其他数据一起,随HTTP响应数据发送给客户端浏览器,隐藏域数据对用户不可见,也就不会因用户的正常操作而改变,当用户再次请求本网页时,随HTTP请求的Post数据一起,再发回服务器端,由ASP.NET处理。 视图状态的这个处理过程,是由ASP.NET自动完成的。默认情况下,所保存的数据也是自动筛选的,这些数据涉及Web窗体内几乎所有服务器控件,HTML控件不被保存。 除了自动筛选的视图状态数据,ASP.NET也提供给程序员将自定义数据(ViewState变量)保存在视图状态中的功能。 视图状态只能在本网页与服务器的往返中保持,而不能在不同网页之间传递,这是和其它状态所不同的地方。 关于视图状态,要学会ViewState变量使用的基本技能,要在理解视图状态和页面生命周期事件的关系的基础上,掌握何时可以禁用自动的视图状态。,1. 视图状态隐藏域,隐藏域并不是ASP.NET的新技术,而属于传统的HTML技术,是客户端页面代码中的一个标记,浏览器并不将其呈现给用户,所以称为隐藏域。 ASP.NET中用于存放视图状态数据的隐藏域是自动生成、经过编码的HTML标记,程序员和用户都不参与该区域的数据读写,在网页回发时,隐藏域数据随着HTTP请求发回服务器,由ASP.NET处理。例 52展示了视图状态隐藏域,例 53展示了视图状态隐藏域数据随着HTTP请求回发的情况。 ASP.NET还提供了HiddenField服务器控件,也会生成客户端隐藏域标记,程序员可以用HiddenField控件保存自定义信息,在网页回发时,程序员还可以通过读取该控件的值,从而取得HTTP协议的“记忆”。例 54利用HiddenField控件“记忆”对本页的请求次数。 另外,由于HiddenField控件也可以在浏览器中被客户端程序访问,因此可以用来充当服务器端和客户端的中间变量,在服务器C#程序和客户端Javascript程序之间交换数据。,例 52 查看ASP.NET的视图状态隐藏域。 在网站项目解决方案管理器中,右击网站根结点,选择“添加新项”,添加一个“Web窗体”,按F5调试运行项目,在IE8浏览器中,选择“页面”按钮下的“查看源文件”,可以看到如下页面HTML原始源代码: 分析:本例在服务器端只包含一个“空”页面,但ASP.NET生成的客户端网页代码中,自动产生了视图状态数据的隐藏域,value属性中的值是经过编码的,保存了本页面中ASP.NET认为需要“记忆”的数据。,例 53 查看视图状态隐藏域数据随着HTTP请求回发。 在例 52中的Web窗体页上,放上一个Button控件,修改其ID为“ButtonSubmit”,Text为“提交”,编写其Click事件委托函数如下:protected void ButtonSubmit_Click(object sender, EventArgs e) Request.SaveAs(“c:request.txt“, true); 在浏览器中查看本页面,按照例 52中的方法在浏览器中查看源文件,可看到自动生成的视图状态隐藏域标记: 再点击页面的“提交”按钮,然后打开C盘的request.txt文件,可以看到视图状态数据也被回发,相关数据如下:_VIEWSTATE=%2FwEPDwUKMTQ2OTkzNDMyMWRkmN60Y81Lx0LZIGBNhhmeMMu7oco%3D 分析: 比较例 52和例 53中的input标记,可以看到它们value属性不同,这是因为例 53中的Web窗体页多了一个Button按钮,所以视图状态数据不同。 “提交”按钮的Click事件委托函数,用Request对象的SaveAs方法,实现了将HTTP请求数据保存在C盘的request.txt文件中的功能。 比较例 53中源文件中的和回发请求中的视图状态数据,可以发现在回发请求中,分别用“%2F”、“%3D”代替了源数据中的“/”和“=”字符,这是HTTP协议所规定的,除此之外,回发前后的视图状态数据并未发生变化。,例 54 利用ASP.NET的HiddenField控件,使HTTP协议“记忆”上次请求的数据:使用Response.Write方法,显示当前是对本页面的第几次请求。 在项目中添加一个Web窗体页,放上一个HiddenField控件,修改其ID属性为“HiddenFieldRequestCounter”,修改其value属性为“0”,放上一个Button控件,修改其Text为“提交”。编写Page_Load事件委托函数如下:protected void Page_Load(object sender, EventArgs e) int 请求次数=Convert.ToInt32(HiddenFieldRequestCounter.Value); 请求次数=请求次数+1; HiddenFieldRequestCounter.Value=请求次数.ToString(); Response.Write(请求次数); 在浏览器中查看本页面,多次点击“提交”按钮,查看网页显示的数值。 分析: “提交”按钮没有任何事件代码,其作用只是引发页面回发请求。 HiddenFieldRequestCounter控件保存了上次响应页面时的请求次数,这是在两次响应之间能够保持“记忆”,实现计数的关键,例 51是一个未使用控件或其他方法导致不能实现请求计数的反例,我们不能用字段来记忆本页面上次响应的数据,而应该用HiddenField或ViewState变量。 注意不能用刷新页面的办法代替“提交”按钮,因为刷新的作用只是把刚才相同的请求再发送一次,即HiddenFieldRequestCounter计数数据为上一次提交的数据。 如果每次在浏览器中查看源文件,可以看到HiddenFieldRequestCounter也生成了一个隐藏域标记,其value数据未经编码,并且每次请求数据不同。但每次视图状态的隐藏域并未改变。,2.ViewState变量,程序员可以用ViewState变量保存页面级的数据,在别的页面中无法访问它们。ViewState变量是一个StateBag类型。StateBag数据是一个键值对元素集合,其中键数据是string类型,相当于变量名,可以用作ViewState集合的索引项;值数据是object类型,可以看作变量的值。相比之下,HiddenField只能保持一个string值。 StateBag类具有集合类型的常用方法和属性,如Add()方法、Count属性等。 例 55 利用ASP.NET的ViewState变量,使HTTP协议“记忆”上次请求的数据:使用Response.Write方法,显示当前是对本页面的第几次请求。 在项目中添加一个Web窗体页,放上一个Button控件,修改其Text为“提交”。编写Page_Load事件委托函数如下:protected void Page_Load(object sender, EventArgs e) if (!IsPostBack) ViewState“requestCounter“ = 0; int 请求次数 = Convert.ToInt32(ViewState“requestCounter“); 请求次数 = 请求次数 + 1; ViewState“requestCounter“ = 请求次数; Response.Write(请求次数); 在浏览器中查看本页面,多次点击“提交”按钮,查看网页显示的数值。 分析: 与例 54相比,本例使用ViewState变量代替HiddenField控件完成了同样的功能,从而节省了一个控件,减少了客户端和服务器端往返的数据。 如果每次在浏览器中查看源文件,可以看到视图状态隐藏域的数据每次都发生改变,这是因为其中包含了请求次数的计数值。 ViewState变量和HiddenField本质上都是传统的隐藏域技术。ASP.NET还有更新颖实用的状态管理技术。,3.视图状态和页面的生命周期事件(选学),(1).页面生命周期 如前所述,要在用户连续访问页面时予以恰当的事件响应,必须“记忆”用户操作前、操作后的页面状态(主要是上次响应时的视图状态数据、本次提交的Post数据),视图状态在“记忆”过程中起到了关键的作用,但要完整了解“记忆”的过程,有必要学习页面的生命周期。 响应原始请求和回发请求的页面生命周期是不同的。响应原始请求,是产生页面,并“记忆”的过程;响应回发请求(PostBack),是产生页面,恢复“记忆”,并根据请求做出改变,然后重新“记忆”的过程。ASP.NET还允许发出回调请求(CallBack,客户端程序调用服务器端的方法,而不是回传整个页面,ASP.NET只需响应方法的返回值),回调是AJAX技术的基础。有时将回发和回调统称为回传。 图 54列出了ASP.NET 2.0的页面生命周期,ASP.NET 3.5的页面生命周期与之相同。从Web服务器(如IIS)接受HTTP请求开始,要首先创建应用程序域,由ASP.NET 建立HttpContext对象,该对象包含Request数据,并包含了新建的Response对象,ASP.NET 对客户端HTTP请求的响应过程,就是分析Request、填充Response的过程,也就是HttpContext对象被“加工”的过程。ASP.NET给每个HttpContext对象分配HttpApplication对象,以管理对HttpContext的“加工”过程。 HttpApplication对象负责应用程序级别的处理工作,好比加工厂的“总管”。首先由一些称为HttpModule的程序对HttpContext对象进行检查、验证、调用页面级别构造函数、获取应用程序级别的状态数据等“加工”,这称为预处理,HttpModules就是一些预加工“工人”。实际上,还有一些HttpModules负责后处理工作,主要完成释放资源等的收尾工作。高级ASP.NET开发人员,可以通过将自定义的HttpModule插入到“流水线”,来干预应用程序级别的处理过程。,页面级的处理,处在预处理和后处理之间,是“加工”的核心。客户端请求的可能是aspx页面,也可能是别的资源(通过扩展名区分),对不同类型的请求,有不同的HttpHandler来进行核心“加工”。高级ASP.NET开发人员,可以通过自定义HttpHandler来代替默认的“加工”,从而改变页面级的处理过程。图 54所示的页面生命周期,就是指ASP.NET内置的HttpHandler对aspx请求的处理过程。 在处理页面的过程中,包含了控件级的处理,熟练的ASP.NET开发人员,可以通过自定义服务器控件来设计控件的属性和行为,从而在控件级别改变默认的处理过程。但自定义控件并不能改变控件的生命周期行为。 控件也有生命周期,并且和页面的生命周期基本同步。除了设计期就放在页面中的静态控件,程序员还可以在页面生命周期内创建动态控件。程序员动态创建的控件,在Page的PreInit事件委托函数中创建的,会由ASP.NET打开控件视图状态跟踪,并和Page一起进入Init阶段,并一直保持同步;在Page的Load事件委托函数中创建的,在执行form1.Controls.Add()方法后,会由ASP.NET控制自动“追赶”页面的生命周期,经历打开视图状态跟踪、初始化阶段,到达Load阶段,对于回发重建的动态控件,还要加载视图数据,从而和页面一起恢复“记忆”,并在Page的Load事件后,加载Post数据,达到和Page一致的生命阶段。若在打开控件的视图状态跟踪之前改变动态控件的属性,则这些改变不会被记入视图状态;若在Page的Load的事件之后,动态创建控件,则这些控件永远不会获得Post数据。 除了程序员赋值、网站用户输入,控件的数据还有三个方面的来源:初始化数据、视图状态数据(或控件状态数据,见后)、Post数据,控件中的数据由最后的赋值决定。 通过图 54我们可以看到,HttpContext对象经过预处理后,如果启用了页面缓存,且缓存可用,将取缓存的页面进行处理,不再启动页面生命周期。 页面生命周期包含开始、初始化、加载及回传事件处理、状态保存及页面呈现、卸载等阶段。图中浅灰色背景的方框表示只有回传页面才会经历的处理,深灰色背景的表示页面中有数据绑定控件时才会经历的处理。请读者通过看图,找出在哪个事件时页面已经完全恢复“记忆”,在哪个事件后页面已经按照客户端的请求完成修改,并在母版页、数据库访问等章节后,再来看此图,深入理解页面的生命周期,尽快完成从“菜鸟级”到“大虾级”开发人员的升华。,(2).控制视图状态数据,视图状态数据是存放在页面隐藏域中,每次往返都要包含这些数据,默认情况下,ASP.NET自动为所有服务器控件在视图状态中保存数据(并非所有数据)。为了减少往返数据,加快响应,ASP.NET为页面和每个服务器控件提供了EnableViewState属性,允许程序员根据需要禁用服务器控件的视图状态。 若在页面aspx代码的Page指令中,添加EnableViewState=“false“属性,例 55将不能实现计数功能。 何时禁用控件或页面的视图状态?禁用视图状态会引起什么后果?禁用视图状态是否会使服务器控件数据无法保持?下面我们通过例 56、例 57、例 58来说明。 例 56 使用下拉框让用户选择地区(启用视图状态、静态绑定数据,往返数据少)。,在Web窗体页中放一个DropDownList控件,修改ID为DropDownListZone,EnableViewState属性默认为true,暂不为DropDownListZone绑定选择项,直接在浏览器中查看页面,查看源文件,并用记事本记录视图状态数据,关闭浏览器。 使用DropDownListZone的任务按钮中的“编辑项”,添加“北京”、“上海”、“天津”、“重庆”四个项,再次在浏览器中查看页面,查看源文件,在记事本中比较两次的视图状态数据。 为实现选择功能,在任务按钮中选中“启用AutoPostBack”复选框,并在页面中显示所选项以模拟对选择功能的处理:使用属性面板,为DropDownListZone控件创建SelectIndexChanged事件委托函数如下:protected void DropDownListZone_SelectedIndexChanged(object sender, EventArgs e) Response.Write(DropDownListZone.SelectedValue); 再次在浏览器中查看页面,反复选择不同的选项,观察页面显示。 结果与分析: DropDownListZone未绑定数据和绑定数据两种情况,视图状态数据长度相同。这说明,ASP.NET并没有把静态绑定的数据(在页面的aspx代码中可以看到的数据)筛选到视图状态中。实际上,在Page的Init事件发生前,才开始跟踪服务器控件的数据,若启用视图状态,在此之后被修改的控件数据就会被加入到视图状态(未修改过的不会被加入),而之前的修改(包括静态的或者动态的修改)总是不会被加入视图状态,静态数据的赋值早于Init事件,所以对希望保持状态的动态控件,最好在Page的PreInit事件委托函数中创建,以便此后的属性修改能被自动保存到视图状态。 选项改变时,页面能正常显示选中的项。,例 57 使用下拉框让用户选择地区(启用视图状态、动态绑定数据,往返数据多)。 将例 56第步改为:在Page_Load方法中通过编程给DropDownListZone添加项,代码如下:protected void Page_Load(object sender, EventArgs e) if (!IsPostBack) DropDownListZone.Items.Add(“北京“); DropDownListZone.Items.Add(“上海“); DropDownListZone.Items.Add(“天津“); DropDownListZone.Items.Add(“重庆“); 其他步骤和例 56相同。在浏览器中查看页面,查看源文件,比较数据绑定前后的视图状态,反复选择不同的选项,观察页面显示。 结果与分析: DropDownListZone绑定数据时比未绑定数据时,视图状态数据明显增多。实际上,因为Page的Load事件晚于Init事件,所以被修改的DropDownListZone控件数据将加入到视图状态。 选项改变时,页面能正常显示选中的项。 注意:如果去掉if(!IsPostBack)条件,会导致回发后DropDownListZone中重复绑定选项数据,这是因为视图状态中已经包含了下拉框的原有选项集合。,例 58 使用下拉框让用户选择地区(禁用视图状态,事件响应不正常)。 将DropDownListZone的EnableViewState属性设为false,其他与例 56相同,即采用静态绑定数据的方法。在浏览器中查看页面,反复选择不同的选项,观察页面显示。 将DropDownListZone的EnableViewState属性设为false,其他与例 57相同,即采用动态绑定数据的方法。在浏览器中查看页面,反复选择不同的选项,观察页面显示。 结果与分析: 下拉框静态绑定数据情况下,禁用视图状态,不能使视图状态数据减少。 下拉框静态绑定数据情况下,禁用视图状态,选项改变时,页面显示不正常:默认显示第一个选项“北京”,选择后面的任何选项,页面回发并正常显示,但当选择过其他选项(如“上海”)后,再选择“北京”,则页面回发但不显示所选项,就像没有改变选项一样。 发生这种现象的原因是: 在启用视图状态的情况下,视图状态数据保存了上次的响应状态,本次的控件值由Post数据保存,只要用户选择了下拉框不同的选项,当AutoPostBack为true时,浏览器将两个数据同时回发,ASP.NET初始化页面后,DropDownListZone选中项默认为“北京”,按照视图状态数据设置DropDownListZone下拉框的数据(“上海”),将页面恢复到上次响应时的原状态(“上海”),在处理Post数据时,比较原状态(“上海”)和Post数据中的现状态(“北京”),判断出应该激发SelectIndexChanged事件。下面是启用视图状态情况下,选项由“上海”改变为“北京”的相关回发请求数据:_VIEWSTATE=%2FwEPDwUJNjQ2NTQxNTc2D2QWAgIDD2QWAgIBDxBkZBYBAgFkZIPvNdV4Ixi8CS1YSv9EBrApGzKUDropDownListZone=%E5%8C%97%E4%BA%AC 其中,_VIEWSTATE值中包含了编码过的数据“上海”,DropDownListZone的值为“北京”的URL编码。 在禁用视图状态的情况下,上次的选择状态未能保存,虽然用户选择了不同的选项,当AutoPostBack为true时,浏览器也将数据回发,ASP.NET 初始化页面后,由于其中没有上次响应时的下拉框选项数据,DropDownListZone的选项只是默认值“北京”,在处理Post数据时,将“北京”与Post数据的现状态(“北京”)比较,判断出不应该激发SelectedIndexChanged事件。下面是禁用视图状态情况下,选项由“上海”改变为“北京”的相关回发请求数据:_VIEWSTATE=%2FwEPDwUJNjQ2NTQxNTc2ZGQ4b14QHUj9GB%2BPNRTvVk%2Bb3tLlXQ%3D%3DDropDownListZone=%E5%8C%97%E4%BA%AC 其中,_VIEWSTATE值中没有原状态数据“上海”(即使原状态为“天津”等,视图状态数据相同),DropDownListZone的值为“北京”的URL编码。,下拉框动态绑定数据情况下,禁用视图状态,能够使视图状态数据减少。 下拉框动态绑定数据情况下,禁用视图状态,选项改变时,下拉框中无选项数据。发生这种现象的原因是:由于有if(!IsPostBack)条件,并且禁用了视图状态,回发情况下下拉框不进行数据绑定。只要去掉if(!IsPostBack)条件即可解决此问题。 下拉框动态绑定数据情况下,禁用视图状态,去掉if(!IsPostBack)条件,页面显示不正常:选择任何选项,回发后,页面上都没有选中项的显示,并且下拉框一直显示第一个选项“北京”。发生这种现象的原因,与下拉框静态绑定数据、禁用视图状态的情况类似,但由于ASP.NET初始化页面时,下拉框DropDownListZone没有选项数据,不激发SelectIndexChanged事件。 通过上述例子,我们得出结论: 可以使用静态数据的场合,不要使用动态数据,以减小视图状态数据,加快响应。 使用静态数据或动态数据的场合,在不需要Changed事件时,禁用视图状态,以减小视图状态数据。 另外,服务器控件数据除了可以保存在视图状态中,还可以保存在控件状态(ControlState)中,控件状态无法由控件的使用者禁用,有些控件的Changed事件相关数据保存在控件状态中,这时禁用视图状态对控件的Changed事件没有影响。如GridView禁用视图状态,SelectIndexChanged事件仍能正常激发,但可能会造成不必要的数据库访问,这时应该通过调试,在数据库访问和客户端往返造成的性能影响之间权衡。关于控件状态,程序员可以在自定义Web控件时保存少量的、重要的数据,此处不做深入探讨。,5.2.2应用程序状态,应用程序状态(Application)对象,由整个网站的所有网页、所有用户共用,适合用于保持网站应用程序级的共享信息,可以实现跨页面数据传递,即可以认为整个网站应用程序只有一个Application对象实例。 Application对象是HttpApplicationState类的实例。由程序员用声明或定义的方式创建,存储在服务器内存中,当客户端第一次访问网站时被创建,退出网站应用程序或关闭服务器时被撤销,即网站运行时一直可用。 应用程序状态是纯粹的服务器端技术,与客户端无关,不像视图状态出现在客户端和服务器端的往返行程中,只会影响服务器性能,不会影响传输性能,对于瓶颈是网络传输的网站环境,对响应速度影响较小。 HttpApplicationState类具有集合类型的常用方法和属性,如Add()方法、Count属性。HttpApplicationState没有公开的事件,应用程序级别的事件由HttpApplication对象公开,程序员可以在网站根目录的Global.asax文件中使用其事件委托函数。Global.asax是应用程序级别的事件处理文件,可以在解决方案资源管理器中添加,每个网站应用程序只能有一个Global.asax文件。 与ViewState变量不同的是,Application对象的索引,可以是string类型的变量名,也可以是int类型的序号,另外Application对象的键数据不区分大小写,不要试图依靠大小写来区分多个变量。 需要注意的是,由于全局共用,可能多个用户、多个网页要同时写入同一个Application变量,而发生冲突,因此,在对Application变量进行赋值操作前,需要先加锁,禁止其他操作,写入后解锁。为此,Application对象提供了Lock和UnLock方法,如:Application.Lock(); Application“counter“ = Convert.ToInt32(Application“counter“) + 1; Application.UnLock(); 稍后我们实现一个网站在线用户数量计数器,来进一步学习Application对象的应用,5.2.3会话状态,(1)会话状态概述 会话状态(Session)对象,是为单个用户保存的状态,可以实现跨页面数据传递,但不同的用户即使对同名的Session变量,也不能互相访问,对于已经登录的用户和匿名用户都是如此,这是因为不同的用户有不同的会话ID(SessionID)。 Session对象指HttpSessionState类的实例。ASP.NET为每个新访问网站的用户创建独立的Session对象,默认存储在服务器内存中,也可以设置为保存在数据库中以避免内存存储的易失性,Session还有其他的保存方式,并且有丰富的管理功能,应该说,Session是ASP.NET中最强大的状态管理技术。 与Application对象不同的是,为了防止在客户关闭网站时(此时HTTP协议不会通知服务器)服务器继续无限期维护Session对象,设置了Session对象的过期时间,默认为20分钟,即不论用户是否关闭网站,如果在20分钟内用户没有发出过任何请求,对应该用户的Session对象将被撤销,以后的同一用户的请求也将创建新的Session对象。 会话状态数据不出现在客户端和服务器端的往返行程中,但SessionID除外。简单说,ASP.NET 在接受一个客户端浏览器程序的原始请求后生成新的SessionID,附加到响应数据送给该客户端,此后该客户端浏览器程序的每次请求都将包含此SessionID。实际上,ASP.NET还将在用户登录、注销,以及会话过期等情况下,对SessionID做其他的处理。 HttpSessionState类不但具有集合类型的常用方法和属性,还有会话管理的方法和属性。网站程序中管理会话状态的SessionStateModule对象还提供了Session的Start和End事件,但这些事件是应用程序级别的,是在ASP.NET创建Session对象和撤销Session对象时发生,并不特定于某个用户的Session对象,程序员可以在Global.asax文件中使用Session_Start和Session_End事件委托函数。 Session对象的访问方法,与Application对象相似,但写入操作不需要加、解锁。 与ViewState相似的是,Session默认启用,但可以被禁用。可以设置Page指令的属性,在页面级别禁用Session: 也可以在网站级别禁用Session,需要在网站根目录下的web.config文件中设置: 在网站级别用pages节禁用Session后,若要在单个网页启用Session,只需设置Page指令的EnableSessionState=“true“即可,即遵从最小范围有效性原则,类似变量发生重命名时的处理规则。,(2) Session对象基本成员,属性 Mode:当前会话状态的模式,只能读取,SessionStateMode枚举类型。如果希望设置该属性的值,需要在Web.config文件中添加sessionState节。 该属性主要用于管理Session的存储方式,取值有Off、InProc、StateServer、SQLServer、Custom五种。 InProc是默认的方式,存储在网站应用程序进程中,即内存中; StateServer方式,存储在网站应用程序进程之外的一个专用进程中,也是在内存中,对大型网站提供更高级的管理功能; SQL Server方式,存储在SQL Server数据库文件中,适用于永久保持Session的场合,但理论上存取速度慢; Off方式,关闭Session功能,即使设置页面的Page指令属性EnableSessionState=“true“也不能再启用Session。 SessionID:会话的唯一标识符,只能读取,string类型。不同用户的SessionID不相同。SessionID是会话状态机制在客户端和服务器端往返的数据。 IsCookieless:SessionID是否存储在Cookie中,只能读取,bool类型。在Web.config文件中的sessionState节,应写为cookieless,而不是IsCookieless。如果为false,会话ID将嵌入在HTTP请求的URL 中,此时要防止针对会话ID的攻击。 TimeOut:分钟为单位的会话状态过期时间,可以读写。Int32类型。但通常在Web.config文件中设置该值。 例 59 在Web.config文件中配置Session的属性。 本例配置Session在进程内存储,不使用Cookie传递SessionID,Session的超时时间为30分钟。,(2).方法 Abandon:取消当前会话,无返回值,无参数。在Mode属性为InProc情况下,调用此方法会引起SessionStateModule对象执行Session_End事件。 (3).相关事件 HttpSessionState类不处理事件,但SessionStateModule类有针对会话管理的事件,程序员可以在Global.asax文件中处理下面两个应用程序级的会话事件。 Start事件:在ASP.NET创建新会话时发生。此事件在被请求页面的构造函数之后、IsPostBack等属性被设置之前发生,早于所有的页面事件。通常用来处理网站访问日志。 客户端原始请求后的正常回发,并不引起ASP.NET创建新会话。如果发送的请求未包含会话标识符、会话标识符无效或与会话标识符关联的会话已过期,则会创建新的会话。调用Abandon方法后,如果有后续处理,比如后续调用Response.Redirect方法,也会创建新的会话。 End事件:会话Abandon或过期后发生。,5.2.4 Cookie状态(选学),1. Cookie概述 Cookie也属于传统的浏览器技术。Cookie状态一方面与Session状态类似,也可以为单个用户保存状态,但Cookie数据是保存在客户端,由浏览器管理。 浏览器将Cookie保存在本地计算机中,按照不同的URL分隔Cookie的共享范围,同一个网站的Cookie可以在多个网页中共享,即Cookie也可以实现跨页面数据传递。 即使打开两个独立的浏览器进程(不是按Ctrl+N组合键)访问同一个路径下的网页,也将共用相同的Cookie数据,此时将会由服务器端ASP.NET分配两个SessionID,即会话状态不能共用。所以,严格来说,Cookie是为不同的客户端设备保存状态,会话状态则是为单个用户进程保存状态。 与Session对象类似的是,Cookie在客户端有一定的过期时间,默认在浏览器关闭时Cookie过期,过期的Cookie数据将不可正常访问。Cookie的过期时间可以由程序员定义,为某Cookie项定义一个早于当前时间的过期时间,是程序员实现此Cookie项删除操作的唯一方法。 Cookie也可以被禁用,但与ViewState、Session不同的是,必须在客户端浏览器中设置是否禁用Cookie。也就是说,ASP.NET网站管不着客户端是否、何时进行启用和禁用Cookie的操作,要考虑客户端禁用Cookie的情况,不能完全依赖Cookie进行状态保存。比如,Cookie是用来保存和传递客户标识(指SessionID)的默认方式,当客户端禁用Cookie时,ASP.NET将用URL来传递SessionID。请读者自行练习客户端浏览器中的禁用Cookie等设置项。 在用户请求(包括原始请求)时,有效的Cookie作为HTTP请求头标,以字符串形式,由客户端浏览器发送到服务器端,ASP.NET在预处理阶段将其包装成HttpCookie类的实例对象,供程序员使用,ASP.NET在HTTP响应中,再将其发回客户端浏览器。这和ViewState有些类似,但它们是两种完全不同的技术,比如: ViewState是页面级别的,多个页面之间不能共享;Cookie可以在网站级别共享。 ViewState主要目的是供服务器端保持页面状态,主要在服务器端操作,不要在客户端改变ViewState数据;Cookie的服务器端操作只是给客户端浏览器发出操作指令,所有的操作最终都是由客户端浏览器完成;Cookie与隐藏域类似,是客户端程序和服务器程序交互数据的常用方式。 ViewState的HTML基础技术是隐藏域,本身没有最大长度限制;Cookie则由浏览器限制长度。 浏览器仅仅把ViewState和隐藏域看成页面的一部分,不做专门的管理;但浏览器对Cookie有更多的管理功能,如启用、禁用、保存到硬盘、处理过期等,Cookie的属性和操作是最终取决于客户端浏览器的行为,服务器端ASP.NET仅仅是为程序员提供了操作Cookie的一个接口,ASP.NET不对Cookie做任何实质的管理。 Cookie对象在ASP.NET服务器端程序中是HttpCookie类的实例,在客户端程序中是一个带有附加属性的键值对组成的字符串。需要注意的是,服务器端收到的Cookie信息仅包括未过期的Cookie的键和值,不包括附加属性,访问HttpCookie对象的附加属性(如过期时间Expires),总是为初始值,2. Cookie的特性 由于服务器端和客户端编程语言(分别以C#和Javascript为例)不同,各属性的命名、类型都有一定差异,但含义相同。以下介绍以C#语言为主。 基本属性 Name:表示Cookie对象的名称,是不能包含分号等特殊字符的字符串。在Javascript中使用camel命名规则,即为name,下同。该属性出现在HTTP请求中。 Value:表示Cookie对象的值,是不能包含分号等特殊字符的字符串。默认值为空字符串。该属性出现在HTTP请求中。 Javascript中,为防止特殊字符影响Cookie的处理,程序员需要将值字符串进行URL编码,然后再赋给Value属性。服务器端将自动处理编码。 附加属性 附加属性规定了Cookie对象的有效期、访问范围、安全性等。这些属性只能设置,浏览器使之生效,无法读取这些属性的当前值,它们不出现在HTTP请求中。Cookie并不是真正的键值对,不同访问范围的Cookie被浏览器视为不同的Cookie,即name属性不是区分Cookie的唯一标识。 Expires:到期时刻,DateTime类型。在Javascript中需将其转换为字符串再写入Cookie。默认将Cookie保存在内存中,在断开连接后失效,当关闭浏览器后相关的Cookie消失;若设置了该属性值,浏览器就将对应的Cookie保存在外存中,到达到期时刻后失效,浏览器不再将其作为HTTP请求的一部分发送给服务器。 Path:Cookie的访问范围属性之一,对应访问者(某个页面)的URL中的路径部分,字符串类型。默认情况的访问范围是设置Cookie的网页所在路径,如在/registedUser/default.aspx页面中设置一个Cookie,Path默认为“/registedUser”,即只有/registedUser路径下的网页可以访问此Cookie,父路径下的网页不能访问此Cookie,但父路径的Cookie可以被子路径访问。 Domain:Cookie的访问范围属性之一,对应访问者(某个页面)的URL中的域名部分,字符串类型。默认值为设置Cookie的网页所在站点的基本域名。 一般来说,该属性值中至少有两个点分隔符(“.”),客户端Javascript中要求domain属性值以点分隔符开头,如“.”,服务器端C#中无此要求。 需要注意的是,为防止不同站点互相影响,正常情况下,Cookie不允许跨域访问,即设置和读取某Cookie的所有网页应该在同一域名下。如在/default.aspx页面中设置一个Cookie,可以将其Domain属性设为“”,但设置为“”是无效的。 Secure:Cookie的安全性属性,是否仅对使用安全套接字(SSL)(即使用HTTPS协议)的连接传输对应的Cookie,bool类型。默认值为false。在Javascript中该属性为true表示为“secure”字符

温馨提示

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

评论

0/150

提交评论