在线时间:8:00-16:00
迪恩网络APP
随时随地掌握行业动态
扫描二维码
关注迪恩网络微信公众号
每次将网页发送到服务器时,都会创建网页类的一个新实例。在传统的Web编程中,这通常意味着在每一次往返行程中,与该页及该页上的控件相关联的所有信息都会丢失。例如,如果用户将信息输入到文本框,该信息将在从浏览器或客户端设备到服务器的往返行程中丢失。 状态管理是您对同一页或不同页的多个请求维护状态和页信息的过程。与所有基于 HTTP 的技术一样,Web 窗体页是无状态的,这意味着它们不自动指示序列中的请求是否全部来自相同的客户端,或者单个浏览器实例是否一直在查看页或站点。此外,到服务器的每一往返过程都将销毁并重新创建页;因此,如果超出了单个页的生命周期,页信息将不存在。
可以使用Cookie来存储有关特定客户端、会话或应用程序的信息。Cookie保存在客户端设备上,当浏览器请求某页时,客户端会将Cookie中的信息连同请求信息一起发送。服务器可以读取Cookie并提取它的值。一项常见的用途是存储标记(可能已加密),以指示该用户已经在您的应用程序中进行了身份验证。
应用程序状态
暂存状态
会话
缓存
配置文件
+++++++++++++++++++++++++++++++++++++++
ASP.NET状态管理之十一(视图状态ViewState)
视图状态是 ASP.NET 页中的储存库,可以存储需要在回发过程中保留的值。例如,您可以将信息存储在视图状态中,下次将页面发送到服务器时,将会在页加载事件过程中访问这些信息。 视图状态数据以 Base64 编码字符串的格式存储在一个或多个隐藏字段中。您可以使用页的 ViewState 属性(此属性公开一个字典对象)来访问视图状态信息。由于视图状态数据以字符串的形式存储,因此只能存储可以序列化的对象。 由于视图状态是作为隐藏字段发送的,因此直到发生 PreRenderComplete 事件之前,都可以对视图状态进行更改。一旦将页呈现到浏览器,便无法保存对视图状态的更改。 如果查看页输出源,则可以看到隐藏视图状态字段中的信息,这可能产生安全性问题。若要缓解该问题,可以通过将 @ Page 指令中的 viewStateEncryptionMode 属性设置为“Always”来加密视图状态。 注意
可以存储在视图状态中的数据类型
使用视图状态的注意事项 视图状态信息将序列化为 XML,然后使用 Base64 编码进行编码,这将生成大量的数据。将页回发到服务器时,视图状态的内容将作为页回发信息的一部分发送。如果视图状态包含大量信息,则会影响页的性能。 另一个重要的考虑因素是,如果隐藏字段中的数据量过大,某些代理和防火墙将禁止访问包含这些数据的页。由于最大数量会随所采用的防火墙和代理的不同而不同,因此大量隐藏字段可能会导致偶发性问题。为了帮助避免这一问题,如果 ViewState 属性中存储的数据量超过了页的 MaxPageStateFieldLength 属性中指定的值,该页会将视图状态拆分为多个隐藏字段,以将每个单独字段的大小减少到防火墙拒绝的大小以下。 某些移动设备根本不允许使用隐藏字段。因此,视图状态对于这些设备无效。
从视图状态中读取值 this.GridView1.DataSource = arrayList; 视图状态中的值被类型化为 String。如本例所示。在 C# 中,当您读取视图状态值时,应该始终强制转换为适当的类型。
将值保存到视图状态 // Add property values to view state with set; set 加密视图状态
ASP.NET状态管理之十二(控件状态ControlState)
如果您在编写控件,可以将控件的状态信息存储在 ViewState 字典中,该字典是一个 StateBag 对象。开发人员将通过 ControlState 属性检索控件状态。您为 ViewState 属性指定键和值,Page 对象将对请求之间的状态信息进行序列化。要在您的控件中执行自定义状态处理,可重写 LoadViewState 和 SaveViewState 方法。在页开发人员禁用视图状态时,存储在此字典中的所有状态信息都会丢失。为弥补这一缺陷,在 ASP.NET 2.0 版中,您可以将关键状态信息存储在一个称为控件状态的单独对象中。在页开发人员禁用视图状态时,控件状态对象不会受到影响。要将状态信息存储在控件状态对象中,控件需要重写 LoadControlState 和 SaveControlState 方法,并且需要在每次初始化该控件时将其注册为在控件状态中存储状态信息。可以通过重写 OnInit 方法并调用 RegisterRequiresControlState 方法将控件注册为使用控件状态。 下面的代码示例演示一个从 PageStatePersister 类派生的类如何初始化 ControlState 属性。此示例将 ControlState 属性指派给 Pair 对象的 Second 字段,并使用 ObjectStateFormatter 类对该属性进行序列化。调用 Load 方法时,使用 ObjectStateFormatter 类对视图状态和控件状态信息进行反序列化,并使用所得 Pair 对象的 Second 字段初始化 ControlState 属性。 // Read the state string, using the StateFormatter. IStateFormatter formatter = this.StateFormatter; // Deserilize returns the Pair object that is serialized in ViewState = statePair.First;
ASP.NET状态管理之三(隐藏域HiddenField)
ASP.NET 允许您将信息存储在 HiddenField 控件中,此控件将呈现为一个标准的 HTML 隐藏域。 安全注意 HiddenField 控件在其Value属性中只存储一个变量,并且必须通过显式方式添加到页上。 HiddenField 控件用于存储一个值,在向服务器的各次发送过程中,需保持该值。它呈现为 <input type= "hidden"/> 元素。 若要指定 HiddenField 控件的值,请使用 Value 属性。 在向服务器的各次发送过程中,当 HiddenField 控件的值更改时,将引发ValueChanged事件 <html xmlns="http://www.w3.org/1999/xhtml"> <script type="text/javascript"> </script> </head>
总结 可以在页上的隐藏域中存储特定于页的信息,作为维护页的状态的一种方式。 注意: 使用隐藏域的优点 使用隐藏域的缺点 ASP.NET状态管理之五(Cookie)Cookie 提供了一种在 Web 应用程序中存储用户特定信息的方法。 什么是 Cookie? 例如,如果在用户请求站点中的页面时应用程序发送给该用户的不仅仅是一个页面,还有一个包含日期和时间的 Cookie,用户的浏览器在获得页面的同时还获得了该 Cookie,并将它存储在用户硬盘上的某个文件夹中。 以后,如果该用户再次请求您站点中的页面,当该用户输入 URL 时,浏览器便会在本地硬盘上查找与该 URL 关联的 Cookie。如果该 Cookie 存在,浏览器便将该 Cookie 与页请求一起发送到您的站点。然后,应用程序便可以确定该用户上次访问站点的日期和时间。您可以使用这些信息向用户显示一条消息,也可以检查到期日期。 Cookie 与网站关联,而不是与特定的页面关联。因此,无论用户请求站点中的哪一个页面,浏览器和服务器都将交换 Cookie 信息。用户访问不同站点时,各个站点都可能会向用户的浏览器发送一个 Cookie;浏览器会分别存储所有 Cookie。 Cookie 帮助网站存储有关访问者的信息。一般来说,Cookie 是一种保持 Web 应用程序连续性(即执行状态管理)的方法。除短暂的实际交换信息的时间外,浏览器和 Web 服务器间都是断开连接的。对于用户向 Web 服务器发出的每个请求,Web 服务器都会单独处理。但是在很多情况下,Web 服务器在用户请求页时识别出用户会十分有用。例如,购物站点上的 Web 服务器跟踪每位购物者,这样站点就可以管理购物车和其他的用户特定信息。因此,Cookie 可以作为一种名片,提供相关的标识信息帮助应用程序确定如何继续执行。 使用 Cookie 能够达到多种目的,所有这些目的都是为了帮助网站记住用户。例如,一个实施民意测验的站点可以简单地将 Cookie 作为一个 Boolean 值,用它来指示用户的浏览器是否已参与了投票,这样用户便无法进行第二次投票。要求用户登录的站点则可以通过 Cookie 来记录用户已经登录,这样用户就不必每次都输入凭据。 Cookie 的限制 浏览器还限制站点可以在用户计算机上存储的 Cookie 的数量。大多数浏览器只允许每个站点存储 20 个 Cookie;如果试图存储更多 Cookie,则最旧的 Cookie 便会被丢弃。有些浏览器还会对它们将接受的来自所有站点的 Cookie 总数作出绝对限制,通常为 300 个。 您可能遇到的 Cookie 限制是用户可以将其浏览器设置为拒绝接受 Cookie。如果定义一个 P3P 隐私策略,并将其放置在网站的根目录中,则更多的浏览器将接受您站点的 Cookie。但是,您可能会不得不完全放弃 Cookie,而通过其他机制来存储用户特定的信息。 编写 Cookie 还可以设置 Cookie 的到期日期和时间。用户访问编写 Cookie 的站点时,浏览器将删除过期的 Cookie。只要应用程序认为 Cookie 值有效,就应将 Cookie 的有效期设置为这一段时间。对于永不过期的 Cookie,可将到期日期设置为从现在起 50 年。 注意: 如果没有设置 Cookie 的有效期,仍会创建 Cookie,但不会将其存储在用户的硬盘上。而会将 Cookie 作为用户会话信息的一部分进行维护。当用户关闭浏览器时,Cookie 便会被丢弃。这种非永久性 Cookie 很适合用来保存只需短时间存储的信息,或者保存由于安全原因不应该写入客户端计算机上的磁盘的信息。例如,如果用户在使用一台公用计算机,而您不希望将 Cookie 写入该计算机的磁盘中,这时就可以使用非永久性 Cookie。 可以通过多种方法将 Cookie 添加到 Cookies 集合中。下面的示例演示两种编写 Cookie 的方法: HttpCookie aCookie = new HttpCookie("lastVisit"); 此示例向 Cookies 集合添加两个 Cookie,一个名为 userName,另一个名为 lastVisit。 对于第二个 Cookie,代码创建了一个 HttpCookie 类型的对象实例,设置其属性,然后通过 Add 方法将其添加到 Cookies 集合。在实例化 HttpCookie 对象时,必须将该 Cookie 的名称作为构造函数的一部分进行传递。 这两个示例都完成了同一任务,即向浏览器写入一个 Cookie。在这两种方法中,有效期值必须为 DateTime 类型。但是,lastVisited 值也是日期时间值。因为所有 Cookie 值都存储为字符串,因此,必须将日期时间值转换为 String。 多值 Cookie 您可能会出于多种原因来使用子键。首先,将相关或类似的信息放在一个 Cookie 中很方便。此外,由于所有信息都在一个 Cookie 中,所以诸如有效期之类的 Cookie 属性就适用于所有信息。(反之,如果要为不同类型的信息指定不同的到期日期,就应该把信息存储在单独的 Cookie 中。) 带有子键的 Cookie 还可帮助您限制 Cookie 文件的大小。正如前面“Cookie 的限制”一节中所提到的,Cookie 通常限制为 4096 字节,并且每个站点最多可存储 20 个 Cookie。使用带子键的单个 Cookie,使用的 Cookie 数就不会超过分配给站点的 20 个的限制。此外,一个 Cookie 会占用大约 50 个字符的系统开销(用于保存有效期信息等),再加上其中存储的值的长度,其总和接近 4096 字节的限制。如果存储五个子键而不是五个单独的 Cookie,便可节省单独 Cookie 的系统开销,节省大约 200 字节。 若要创建带子键的 Cookie,您可以使用编写单个 Cookie 的各种语法。 HttpCookie aCookie = new HttpCookie("userInfo"); 控制 Cookie 的范围 将 Cookie 限制到某个文件夹或应用程序 路径可以是站点根目录下的物理路径,也可以是虚拟根目录。所产生的效果是 Cookie 只能用于 Application1 文件夹或虚拟根目录中的页面。例如,如果您的站点名称为 http://www.contoso.com/,则在前面示例中创建的 Cookie 将只能用于路径为 http://www.contoso.com/Application1/ 的页面以及该文件夹下的所有页面。但是,Cookie 将不能用于其他应用程序中的页面,如 http://www.contoso.com/Application2/ 或 http://www.contoso.com/ 中的页面。 注意: 默认情况下,一个站点的全部 Cookie 都一起存储在客户端上,而且所有 Cookie 都会随着对该站点发送的任何请求一起发送到服务器。也就是说,一个站点中的每个页面都能获得该站点的所有 Cookie。但是,可以通过两种方式设置 Cookie 的范围: 将 Cookie 的范围限制到服务器上的某个文件夹,这允许您将 Cookie 限制到站点上的某个应用程序。 将范围设置为某个域,这允许您指定域中的哪些子域可以访问 Cookie。 将 Cookie 限制到某个文件夹或应用程序 路径可以是站点根目录下的物理路径,也可以是虚拟根目录。所产生的效果是 Cookie 只能用于 Application1 文件夹或虚拟根目录中的页面。例如,如果您的站点名称为 http://www.contoso.com/,则在前面示例中创建的 Cookie 将只能用于路径为 http://www.contoso.com/Application1/ 的页面以及该文件夹下的所有页面。但是,Cookie 将不能用于其他应用程序中的页面,如 http://www.contoso.com/Application2/ 或 http://www.contoso.com/ 中的页面。 注意 限制 Cookie 的域范围 当以此方式设置域时,Cookie 将仅可用于指定的子域中的页面。还可以使用 Domain 属性创建可在多个子域间共享的 Cookie,如下面的示例所示: 随后 Cookie 将可用于主域,也可用于 sales.contoso.com 和 support.contoso.com 域。 读取 Cookie if(Request.Cookies["userName"] != null) 在尝试获取 Cookie 的值之前,应确保该 Cookie 存在;如果该 Cookie 不存在,将会收到 NullReferenceException 异常。还请注意在页面中显示 Cookie 的内容前,先调用 HtmlEncode 方法对 Cookie 的内容进行编码。这样可以确保恶意用户没有向 Cookie 中添加可执行脚本。 注意 读取 Cookie 中子键值的方法与设置该值的方法类似。下面的代码示例演示获取子键值的一种方法: Label2.Text = 在上面的示例中,代码读取子键 lastVisit 的值,该值先前被设置为字符串表示形式的 DateTime 值。Cookie 将值存储为字符串,因此,如果要将 lastVisit 值作为日期使用,必须将其转换为适当的类型,如此示例所示: DateTime dt; 更改 Cookie 的到期日期 注意 读取 Cookie 集合 注意 上面的示例有一个限制:如果 Cookie 有子键,则会以一个名称/值字符串来显示子键。可以读取 Cookie 的 HasKeys 属性,以确定 Cookie 是否有子键。如果有,则可以读取子键集合以获取各个子键名称和值。可以通过索引值直接从 Values 集合中读取子键值。相应的子键名称可在 Values 集合的 AllKeys 成员中获得,该成员将返回一个字符串数组。还可以使用 Values 集合的 Keys 成员。但是,首次访问 AllKeys 属性时,该属性会被缓存。相比之下,每次访问 Keys 属性时,该属性都生成一个数组。因此在同一页请求的上下文内,在随后访问时,AllKeys 属性要快得多。 下面的示例演示对前一示例的修改。该示例使用 HasKeys 属性来测试是否存在子键,如果检测到子键,便从 Values 集合获取子键: 或者,可将子键作为 NameValueCollection 对象提取,如下面的示例所示: for (int i = 0; i < Request.Cookies.Count; i++) 修改和删除 Cookie Response.Cookies["counter"].Value = counter.ToString(); 删除 Cookie 修改或删除子键 若要删除单个子键,可以操作 Cookie 的 Values 集合,该集合用于保存子键。首先通过从 Cookies 对象中获取 Cookie 来重新创建 Cookie。然后您就可以调用 Values 集合的 Remove 方法,将要删除的子键的名称传递给 Remove 方法。接着,将 Cookie 添加到 Cookies 集合,这样 Cookie 便会以修改后的格式发送回浏览器。下面的代码示例演示如何删除子键。在此示例中,要移除的子键的名称在变量中指定。 Cookie 和安全性 千万不要在 Cookie 中存储敏感信息,如用户名、密码、信用卡号等等。不要在 Cookie 中放置任何不应由用户掌握的内容,也不要放可能被其他窃取 Cookie 的人控制的内容。 同样,不要轻信从 Cookie 中得到的信息。不要假定数据与您写出时相同;处理 Cookie 值时采用的安全措施应该与处理网页中用户键入的数据时采用的安全措施相同。本主题前面的示例演示在页面中显示值前,先对 Cookie 内容进行 HTML 编码的方法,这与在显示从用户处得到的任何信息之前的做法相同。 Cookie 以明文形式在浏览器和服务器间发送,任何可以截获 Web 通信的人都可以读取 Cookie。可以设置 Cookie 属性,使 Cookie 只能在使用安全套接字层 (SSL) 的连接上传输。SSL 并不能防止保存在用户计算机上的 Cookie 被读取或操作,但可防止 Cookie 在传输过程中被读取,因为 Cookie 已被加密。 确定浏览器是否接受 Cookie 注意 确定 Cookie 是否被接受的一种方法是尝试编写一个 Cookie,然后再尝试读取该 Cookie。如果无法读取您编写的 Cookie,则可以假定浏览器不接受 Cookie。 下面的代码示例演示如何测试浏览器是否接受 Cookie。此示例由两个页面组成。第一个页面写出 Cookie,然后将浏览器重定向到第二个页面。第二个页面尝试读取该 Cookie。然后再将浏览器重定向回第一个页面,并将带有测试结果的查询字符串变量添加到 URL。 该页面首先测试以确定是不是回发,如果不是,则查找包含测试结果的查询字符串变量名 AcceptsCookies。如果不存在查询字符串变量,表示测试还未完成,因此代码会写出一个名为 TestCookie 的 Cookie。写出 Cookie 后,该示例调用 Redirect 来切换到 TestForCookies.aspx 测试页。附加到测试页 URL 的信息是一个名为 redirect 的查询字符串变量,该变量包含当前页的 URL;这样就能在执行测试后重定向回此页面。 测试页可完全由代码组成;不需要包含控件。下面的代码示例阐释了该测试页。 读取重定向查询字符串变量后,代码尝试读取 Cookie。出于管理目的,如果该 Cookie 存在,则立即删除。测试完成后,代码通过 redirect 查询字符串变量传递给它的 URL 构造一个新的 URL。新 URL 也包括一个包含测试结果的查询字符串变量。最后一步是使用新 URL 将浏览器重定向到最初页面。 该示例的一个改进是可将 Cookie 测试结果保存到永久存储区(如数据库)中,这样就不必在用户每次查看最初页面时都重复进行测试。(默认情况下,在会话状态中存储测试结果需要 Cookie。) Cookie 和会话状态 ASP.NET 必须跟踪每个用户的会话 ID,以便可以将用户映射到服务器上的会话状态信息。默认情况下,ASP.NET 使用非永久性 Cookie 来存储会话状态。但是,如果用户已在浏览器上禁用 Cookie,会话状态信息便无法存储在 Cookie 中。 ASP.NET 提供了无 Cookie 会话作为替代。可以将应用程序配置为不将会话 ID 存储在 Cookie 中,而存储在站点中页面的 URL 中。如果应用程序依赖于会话状态,可以考虑将其配置为使用无 Cookie 会话。但是在较少的情况下,如果用户与他人共享 URL(可能是用户将 URL 发送给同事,而该用户的会话仍然处于活动状态),则最终这两个用户可能共享同一个会话,结果将难以预料。
总结 使用 Cookie 的缺点 注意 ASP.NET状态管理之二(查询字苻串QueryString)查询字苻串是追加在URL后的数据(也是我常用的) 查询字符串是在页 URL 的结尾附加的信息。 可以使用查询字符串来通过 URL 将数据提交回您的页或另一页上。 使用查询字符串的优点 使用查询字符串的缺点 2.有限的容量
ASP.NET状态管理之八(应用程序Application)
ASP.NET 允许您使用应用程序状态来保存每个活动的 Web 应用程序的值,应用程序状态是 HttpApplicationState 类的一个实例。 应用程序状态存储在一个键/值字典中,在每次请求一个特定的 URL 期间就会创建这样一个字典。可以将特定于应用程序的信息添加到此结构以在页请求期间存储它。 一旦将应用程序特定的信息添加到应用程序状态中,服务器就会管理该对象。 应用程序状态是可用于 ASP.NET 应用程序中的所有类的数据储存库。 应用程序状态存储于 HttpApplicationState 类中,用户首次访问应用程序中的 URL 资源时将创建该类的新实例。
如何:从应用程序状态中读取值 确定应用程序变量是否存在,然后在访问该变量时将其转换为相应的类型。
如何:保存应用程序状态中的值 |
请发表评论