客户端状态管理对象
它们是什么,如何选择和处理它们
引言
Web开发核心中一个重要且重要的主题是如何处理数据,如何存储数据以及如何在Web应用程序中传输数据。这是一个至关重要的问题,以至于许多项目的成功与否取决于它们如何处理数据。因此,状态管理在Web开发科学中占据了重要地位,并在许多书籍、文章和论坛中得到了广泛关注。
背景
状态管理方法论从HTML发明之初就存在了。当时,除了隐藏字段来存储数据之外,几乎没有其他方法。非常简单且页面作用域的变量。随着时间的推移,发现了其他存储数据的功能,如查询字符串和Cookie等。JavaScript的兴起也增加了更多存储数据的方式。
状态管理科学起源于经典ASP时代,当时出现了“应用程序/会话”的概念。这些对象被添加到视图状态、缓存和其他应用程序用于存储HTTP应用程序作用域数据以便在整个项目中的多个页面中使用的对象中。
然后,ASP.NET的革命出现了。Web开发中的一大步是.NET框架的全面增强和功能,包括状态管理。在那里,提出了全面的数据存储和处理方法论,并将其与经典ASP和HTML时代以来的一些旧有经典状态管理功能相结合。状态管理对象和方法论在客户端和服务器端之间有所不同。
状态管理对象的类型
状态管理对象存储要在同一页面中使用的、传输到其他页面以及在项目中的许多其他页面中使用的状态。通过使用对象和属性的许多功能和方法论,可以避免在回发时丢失数据,即使是本地控件变量。
状态管理对象分为两类:客户端对象和服务器端对象。客户端对象是页面作用域对象,用于保护数据免受回发影响,或在页面之间传输。服务器端对象是域作用域对象,用于存储应用程序供整个应用程序使用的数据,包括业务逻辑和脚本语言。
共有九个主要的状态管理对象,四个是服务器端对象,五个是客户端对象。它们的使用由我将在本文稍后讨论的许多因素决定。
Client-Side State Management Objects |
Server-Side State Management Objects |
Cookie | Application |
查询字符串 | 缓存对象 |
隐藏字段 | Session |
视图状态 | 数据库 |
控制状态 |
客户端状态管理对象如何工作
客户端状态管理对象分为三类:
1- URL(例如查询字符串)
2- 表单(例如隐藏字段、视图状态和控件状态)
3- HTTP处理程序(例如 Cookie)
URL用于通过HTTP请求和响应在两个页面之间传输数据。而表单状态管理对象是页面作用域对象,用于在同一页面中保存数据,以避免在回发和其他页面操作中丢失数据。而HTTP处理程序状态管理对象是域作用域对象,可以在应用程序中的任何位置使用。
客户端对象非常简单、可用且可靠。页面作用域和域作用域对象都可以通过代码隐藏和脚本语言进行双向操作。使用客户端状态管理对象的两个缺点是数据来回传递到服务器的成本。这意味着您将为它们传递的成本支付两次费用:一次是在您将请求发送到服务器时,因为它们将在HTTP请求中处理;一次是在数据返回到客户端的HTTP响应中。这意味着如果您拥有大量数据、巨大的视图状态或重量级的 Cookie,您可能需要等待 30 多秒才能从回发中获取页面。
使用客户端状态管理对象的第二个缺点是您无法确保您的数据安全。客户端对象中的安全性几乎不存在,因为即使在 URL、查询字符串或基于表单的对象和属性中也使用了显式数据。任何粗心的用户都可以读取和修改通过查询字符串传递的任何数据。如果用户更聪明,他可以找到 Cookie 文件并获取其数据。如果用户知道右键单击菜单中有“查看源代码”,那么您就可以说您的所有底牌都暴露了,因为用户将获得隐藏字段中存储的所有数据。
请求生命周期
当用户输入任何 URL(例如 www.codeproject.com)时,浏览器会向存储该页面的服务器发出 HTTP GET 请求。然后服务器将以 HTML 页面响应。如果浏览器之前从未访问过此 URL,服务器将在用户 PC 上创建一个新 Cookie,其中包含一个唯一的 ID,以便在下次访问时识别和跟踪 PC。服务器可能还在 Cookie 中添加其他数据,例如会话 ID 和任何可能的数据。在下次访问时,Cookie 将通过 HTTP GET 请求发送到服务器。服务器将获取 Cookie 中的唯一 ID,然后向用户显示添加到 Cookie 中的数据。
客户端对象
1- 查询字符串
查询字符串用于在页面之间传输数据,它非常简单易用。此外,它没有开销或成本,在请求和响应中几乎是无重量的,因为它无法处理大量数据对象,只是纯文本……这就是查询字符串的全部内容。查询字符串与所有浏览器和平台兼容,生活多么轻松!
Response.Redirect( "SecondPage.aspx?Type=01&Query=Query1" );
使用查询字符串的缺点有很多。它只能处理文本,这意味着我们不能使用查询字符串传输对象或控件。此外,它无法处理大量数据。
此外,查询字符串不是传输敏感数据(如 ID、姓名或任何有价值的数据)的合适方式,因为查询字符串会出现在浏览器顶部的 URL 中,并且用户可以清楚地看到它们。这是最重要的缺点,即用户可以轻松劫持和修改查询字符串。
一些网站会加密查询字符串以确保数据安全并避免劫持,例如下面的查询字符串:
http://site.site.com/login.srf?ID=#W2dtb$RGUgg35fO&wa=wsignin1.0&rpsnv=10&ct=1204020363&r
它们在发送查询字符串之前进行加密,然后在另一页收到页面后进行解密。
2- 隐藏字段
隐藏字段是 HTML 控件,用于保存页面作用域的使用数据,以避免回发和回调期间的数据丢失。隐藏字段非常有用且可靠,您可以将任何想要的数据保存在其中,并且可以随时从中检索数据,因为它们具有控件状态。您可以从代码隐藏中获取其数据。
隐藏字段有两个主要的缺点:隐藏字段无法处理对象或控件,并且有最大数据量限制。第二个缺点是隐藏字段不安全,任何可以访问“查看源代码”的用户都可以获取所有隐藏字段的所有数据,因为它们未加密,所以可以在 HTML 代码中可见。
3- 视图状态
视图状态是处理 HTML 控件数据、ASP 控件数据,甚至变量和原始数据的一种加密数据。在我个人看来,视图状态是最好的客户端状态管理对象,因为它最安全,而且是唯一可以处理任何大小数据的对象。
视图状态是序列化对象,在渲染给用户时会被加密。因此,即使用户查看“查看源代码”,他也只会看到一堆符号,数据完全加密,免受黑客的侵害。
视图状态通过 64 位编码进行加密,因此很难解密。视图状态的唯一缺点是它会增加页面大小的约 30% 的开销,因为它经过加密并且是序列化对象。这意味着它会为页面带来巨大的开销。对于不包含大量控件或大量视图状态的页面来说,这可能不是一个大问题,但在复杂页面和包含大量控件的页面中使用时,它会产生很大的影响。
视图状态可以处理来自控件和对象的数据。只需为任何控件添加“EnableViewState = true”属性即可保存其状态。但您应该注意重量级控件(如 DataGrid),因为如果您添加此属性,并且该控件包含大量数据,您将导致性能灾难。当您尝试从浏览器访问页面时,您可以清楚地感觉到这种差异。
这里是一个没有视图状态的页面
<html xmlns="%22%22%22%22%22%22%22%22%22http://www.w3.org/1999/xhtml%22%22%22%22%22%22%22%22%22">http://www.w3.org/1999/xhtml"> <head> <body id="MasterBody" style="margin-left:0; margin-right:0; margin-bottom:0; margin-top:0; width:98%;"> <form name="aspnetForm" method="post" id="aspnetForm"> form> Here is the data</form> </body> </html>
在这里,这是添加具有视图状态 = true 的 DataGrid 后相同页面的视图状态
<input type="hidden"name="__VIEWSTATE" id="__VIEWSTATE"_value="/wEPDwUJMjAwNTcxODExD2QWAm YPZBYCAgMPZBYEAgUPDxYCHgRTa2luBQ tXaW5uWHBPbGl2ZWRkAgcPZBYCZg9kFgRmD2QWAmYPZBYCAgEPZBYUAgMPD2QWBB4Hb25jbGl...bla bla bla"/>
仅此一项就可能需要两到十页!
我们要进行视图状态化的对象应设置为序列化,以便存储在页面中,如下所示:
[serializable]public class Person{string fName, lName;float weight;} public partial class _default : Web.UI.Pages { Person p = new Person(); p.fName = "aaa"; p.lName = "bbb"; p.weight = 73.21; ViewState["MyPerson"] = p; }
4- 控件状态
控件状态存储在控件中的数据。它们与视图状态相同,但专门用于控件。
5- Cookie
Cookie 是存储在客户端 PC 上的文件。此 Cookie 包含一个唯一 ID,以便服务器识别客户端 PC,此外,还可以保存任何想要保存的数据。Cookie 的工作原理已在上面讨论过。
如何确定哪个状态管理对象合适?
您想要使用的客户端状态管理对象的类型由许多因素决定:
1- 数据的重要性
如果您的数据具有一定的重要性,您就不能使用查询字符串或 Cookie,因为它们很容易被捕获。因此,如果它们非常重要且敏感,您也不能使用隐藏字段,您应该不计成本(如开销)地使用视图状态。
2- 数据大小
如果数据量很大,我们应该放弃那些需要序列化的对象,如视图状态和控件状态,我们还应该放弃查询字符串,因为它们不是为处理大量数据而设计的。如果您的数据量没有达到那个程度,您可以使用隐藏字段,或者您可以使用 Cookie,您可以在其中写入任意数量的数据。
3- 使用数据的目的
如果数据用于在页面之间传输数据,我们应该使用查询字符串或 Cookie,具体取决于数据的数量。但如果数据用于同一页面,我们应该使用隐藏字段、视图状态或控件状态。但如果我们想在整个应用程序中使用数据,我们应该使用 Cookie。