anthony moore microsoft corporation
2000年9月
摘要: 本文讨论如何习惯于使用 asp+ 和 web forms 设计器。该程序针对不熟悉 web 开发的 microsoft visual basic 或类似的 gui 编程工具的传统用户。
目录
如果您使用 microsoft visual basic 但又不熟悉 web 开发,则首先使用带 asp+ 的 forms 设计器最为方便。 总的来讲,在 asp+ 中使用控件、属性、事件和数据,与使用 visual basic 6.0 编写 windows 应用程序没有太大差别。通过比较,asp 和其它 web 开发环境确实有很大不同,从一种环境换到另一种环境进行编程,可能就象再次学步。
到现在,您可能已见过 web 窗体演示,或者动手试过一些,包括这一个。通常,下面是您要使用 visual studio 进行的操作:
- 创建一个新的 visual basic web 应用程序。
- 将一个 button 控件和一个 label 控件放到页面上。
- 双击按钮,以获得一个事件处理器。
- 将 label 文本改为“hello world!”
- 运行该项目。
下面是您的第一个 asp+ 页面在 web forms 设计器中的样子:

图 1. web forms 设计器中的一个 asp+ 页面
我并不了解你,但我第一次这样做时,我的感觉是“这下可把 asp 或 cgi 脚本干掉了。这真是太容易了!”
与创建 windows 应用程序一样,创建一个可靠且可缩放的 web 应用程序也极其复杂。我们希望 asp+ 能够将这种复杂性的大部分隐藏起来,就象 visual basic 1.0 为 windows 开发所做的那样。我们还想将使这两种经历尽量彼此相似,以便您可以“利用您已有的技能”。
web forms 能够奇妙地完成 web 开发任务,就象 gui 开发一样,以至于它能在安全方面给您一个错误的感觉。然而,在这两者之间还存在一些最基本的差异,如果您不注意这些差异,就可能在着手做的时候产生一些常见的错误。
在您第一次尝试做以下各项时,您可能会有些束手无策:
- 声明并使用一个成员变量。
- 在运行时添加控件。
- 在页面之间传递数据。
- 尝试使用数据绑定。
在页面上添加一个计数器以统计这个按钮被单击的次数:
private mycounter as integer
protected sub button1_click(byval sender as system.object,
byval e as system.eventargs)
mycounter += 1
label1.text = mycounter.tostring()
end sub
看起来它应能够工作,但当您运行这个页面时,您会发现计数器的值永远不会大于 1。
当借助控件事件和属性做简单事情时,看起来页面和控件在创建后, 在用户操作过程中将一直存在。即使我作为一个富有经验的 visual basic 用户,当第一次使用 asp+ 时,我都会有以下两个关于页面寿命的问题:
- 在将页面废弃之前,服务器将该页面保留多长时间?
- 这些对象是否大量占用服务器的内存?
这两个问题的答案分别是“0 秒”和“否”。每次访问页面时,页面及其控件在创建后被完全丢弃。只有在处理用户请求的特定瞬间才会发生占用服务器内存的 page 类实例。
asp+ 的伟大技术成就之一在于它能够在到服务器的往返过程中保持大部分的页面状态,并且从不在内存中保持页面。然而,它并不是绝对地自动保存任何事件,当您声明一个新的成员变量时,除非您明确地将其保存,否则它将被丢弃。这就是计数器例子为什么不能像预期设定的那样工作。
以下是一个能够正确运行的事件处理器的方案:
protected sub button1_click(
byval sender as system.object,
byval e as system.eventargs)
dim mycounter as integer
mycounter = cint(state("mycounter"))
mycounter += 1
state("mycounter") = mycounter
label1.text = mycounter.tostring()
end sub
state 对象是 page 类中各对象的集合,在这个对象中,您可以对其赋值并在往返过程中进行保存。这成为页面的查看状态的一部分,实际上是写在 html 中隐藏区域的信息的集合。运行时属性发生变化的控件,也可以在重新处理该页时利用查看状态来恢复这些值。
拥有持续值的一个更加简洁的方法是定义一个正式的属性:
private property mycounter() as integer
get
return cint(state("mycounter"))
end get
set
state("mycounter") = value
end set
end property
protected sub button1_click(
byval sender as system.object,
byval e as system.eventargs)
mycounter += 1
label1.text = mycounter.tostring()
end sub
您实际上可以在 state 中加入较为复杂的对象,而依旧使其得到保持。不同于其它简单的类型,可以存储许多由通用语言运行时定义的容器类型,例如:arraylist、 hashtable 和 dataset 对象。
并非全部得到保存
事情容易搞乱的原因在于,大部分数据在往返过程中被保存,但不是所有的数据都得到保存。以下是保存与不保存数据的一个小结。
保存:
- 页面属性
- 页面中声明的控件的属性