### ASP.NET 中的 HTMLControl 和 WebControl

与以前的 ASP 版本相比，ASP.NET 有了很大的改进。这些改进之中，主要的一点就是新引入的服务端控件。现在我们就来一起研究 ASP.NET 中的 HTMLControl 和 WebControl 这两类服务端控件。
回忆：一个不使用服务端控件的例子
为了说明服务端控件所能带来的好处，我们现在用传统的 ASP 来做一个页面。这个页面的功能是根据用户选择的电吉它和功放组合，显示一些对这个组合的评论信息。
从组合框里选择好吉它和功放的类型，然后按 Information 按钮。ASP 代码根据选择的吉它和功放的型号做一起判断，并给出有关此组合的一些评论。清单 1 显示了这个页面的传统 ASP 代码。
当我们在写 ASP 代码的时候，我们事实上在告诉 ASP DLL 去生成一些特定的 HTML 标记和文本信息。在我们的 ASP 代码里已经明确包含了这些标记和文本。ASP DLL 将<html>、<body>以及<form>这些标记扔给客户端，然后接着是标题行“Axe 'n' Stacks”，然后接着发给客户端<select>标记去告诉它显示一个组合框。
在这个例子中，为了正确在组合框里显示我们所选择的选项，我们不得不写一大段的 if…then 语句才能实现。这段代码虽然看上去有些冗长，但毕竟它能够实现一个只用 HTML 几乎无法实现的功能。
清单 2 是我们的 ASP 程序运行时发给客户端的 HTML 代码，其中的<select>标记显示出一个组合框，这个组合框显示出我们所有可以选择的项目，同时高亮条停留在我们实际选择的一项上。
这里存在的一个基本问题是，传送 HTML 的 HTTP 协议是一个“无连接”协议，因此，它也是一个“无状态”协议。服务端并不会保存客户端每次请求之间的状态。而我们桌面应用中使用组合框以及其他控件的时候，保持这种状态很容易，因为所有的代码都在同一个屋檐下——只会有一个用户在点击你的程序上的按钮。
Web 开发时可就不同了。由于 Web 是基于 HTTP 这个“无连接”的协议，有可能每次对你页面的访问都来自于一个不同的客户。因此，作为 Web 开发者的我们必须自己写代码去追踪每个用户在不同次访问之间的状态。在上面的例子中，我们通过获得并解析查询字符串来得到用户上一次的状态，然后才能选取适当的<option>项，给它加入“selected”属性。
如果我们编程的语言给我们提供了这些基础的服务，岂不妙哉？
非常幸运，ASP.NET 正是为此目的引入了服务端控件。
ASP.NET 中的服务端控件
传统的 ASP 代码是一堆 HTML 与可执行脚本代码的混合物。每当有一个客户提交请求，服务器便生成一堆的 HTML 回应码。不幸的是，随着程序逻辑的复杂，这种 ASP 代码最后变得和 20 世纪 80 年代初那些便宜的编程教科书上非结构化的 Basic 程序一样，杂乱不堪。
如前所示，经典的 ASP Web 处理包括手动解析表单数据和处理控件。ASP.NET 引入服务端控件使得对控件的访问变得更加直观。由于 HTTP 是一个“无连接”协议，客户状态的保持一直是个令人头痛的问题。服务端控件能够自动保持用户在不同的回传（Postback）中的状态，使我们不用再费神一次又一次去写类似的代码。
使用服务端控件进行开发时，与我们习惯的桌面开发更为相似了。在桌面开发时，你可以认为同一个控件的状态在整个桌面程序的运行期内都是一致的；服务端控件使你在进行 Web 开发的时候可以假设同样的事情，虽然 Web 应用的 UI 正在被成千上万的人访问。
前面我们曾经提到，ASP.NET 的服务端控件包括两种开式：HTMLControl 和 WebControl。这样控件将内部的一系列烦琐的管理操作封装起来，我们只需与最关心的部分打交道。不同于传统的 ASP，我们不用在代码中手工嵌入各种 HTML 的标记，我们只需使用 HTMLControl 和 WebControl 这些控件即可，它们会帮我们处理这一切。它们会自已维护不同 Session 之间的状态，使我们能够比传统的 ASP 程序员更早地完成工作回家！
现在让我们从 HTMLControl 开始。
HTMLControls
ASP.NET 中的 HTMLControl 和 WebControl 都是标准的基于 CLR 的控件。如同其他的所有 CLR 类一样，它们也从 System.Object 对象继承而来，而且它们也一样有属性、方法，以及代理和事件。它们的主要功能就是在 Web 页面上管理控件。
HTMLControl 的类与 HTML 中的各种标记一一对应。例如，当 ASP.NET 引擎发现你在 ASP 代码中定义了一个 Button，它便会将之包装为一个 HtmlButton 的类。当你需要在程序中访问这个 Button 时，你只需访问这个 HtmlButton 类的对象即可。
下表列出了目前 ASP.NET 中支持的 HtmlButton 类。
类名
功能
HtmlAnchor
HTML <a>
HtmlButton
HTML <button>
HtmlContainerControl
表示一个 HTML 服务端控件，该控件必须有一个结束标记
HtmlControl
表示一个 HTML 服务端控件
HtmlForm
HTML <form>
HtmlGenericControl
表示一个没有专门.NET Framework 类的 HTML 服务端控件
HtmlImage
HTML <img>
HtmlInputButton
HTML <input type= button>, <input type= submit>, 以及<input type= reset>
HtmlInputCheckBox
HTML <input type= checkbox>
HtmlInputControl
HTML 输入型控件的抽象类，这些输入控件包括 <input type=text>, <input type=submit>, 以及<input type= file>等
HtmlInputFile
HTML <input type= file>
HtmlInputHidden
HTML <input type=hidden>
HtmlInputImage
HTML <input type= image>
HtmlInputRadioButton
HTML <input type= radio> element on the server
HtmlInputText
HTML <input type= text> 和 <input type= password>
HtmlSelect
HTML <select>
HtmlTable
HTML <table>
HtmlTableCell
包含于 HtmlTableRow 中的单个的 HTML <td>和<th> 元素
HtmlTableCellCollection
包含于 HtmlTable 中的表格单元集合
HtmlTableRow
包含于 HtmlTable 中的单个 HTML <tr> 元素
HtmlTableRowCollection
TableRow 集合
HtmlTextArea
HTML <textarea>
清单 3 展示了用 ASP.NET HTMLControl 写的“Axe 'n' Stacks”页面。注意到各个选择框、按钮、图像元素的布局都与传统的 ASP 代码的效果非常相似。当 ASP.NET 引擎遇到这些标记时，它们会将之映射为相应的 HTMLControl。从代码可以看出，提交按钮（“Information”）被连接至消息处理例程 FetchInfo_Click。注意 FetchInfo_Click 通过访问表单域来管理控件的方法。它首先检查传送进来的吉它、功放组合，再在文本框控件里填充入相应的内容。然后它设置好图像控件，在其中显示出正确的吉它、功放的图片。

基本上，如果你在代码中用传统的 ASP 方式定义一个控件，并给它加上“runat=server”属性，ASP.NET 就会将之包装成一个 HTMLControl。
WebControls
大致来说，WebControl 和 HTMLControl 的功能差不多。很多的 WebControl 也可以直接映射到标准的 HTML 控件。但是，WebControl 提供了一个比 HTMLControl 更加一致的接口。例如，有时候 HTMLControl 的背景颜色可以通过 Style 属性来修改，有时候却也可通过其他专门属性进行修改。而对 WebControl 却总是通过 BackColor 属性来进行修改。
WebControl 与 HTMLControl 的定义方法有些不一样。清单 4 是“Axe 'n' Stacks”网页的 WebControl 版本。注意到选择用的组合框在 WebControl 中被定义成“asp:DropDownList”，其内容也用 asp:ListItem 定义。类似地，WebControl 用 asp:Button 来定义 Button，图像和文本框控件也被分别定义成 asp:Image 和 asp:TextBox。如果你读读程序顶部的消息处理代码，还会发现很多控件用于存储数据的属性的名字也已经发生了改变。例如，HTMLSelect 的 Value 属性改成了 DropDownList's SelectedItem.Text 属性。除此之外，程序的结构与用 HTMLControl 书写的基本相同。
复杂些的 WebControls
前面已经提到，WebControl 有着比 HTMLControl 更为一致的接口。此外 WebControl 比 HTMLControl 的一个优势在于 WebControl 提供了一些更为复杂但很有用的控件，包括 AdRotator，Calendar, 以及 DataGrid 等。AdRotator 控件接收一些图像（如 JPG 和 GIF 文件），并且将它们分别映射到一系列的 URL。每次页面刷新时，AdRotator 就会随机抽取一个图像来显示。当它被点击时，页面会被重定向到相应的 URL。Calendar 控件可以在浏览器里显示一个功能较强的日历表；而 DataGrid 控件则相当于一个 mini 型的电子表格。
结论
今天，基于 Web 的开发都可归结为 HTTP 的请求与回复，而在很多时候，这些回复需要将控件的标记回送给浏览器。当直接使用 ASP 来编程的时候，你经常会需要花很多的时间和精力来保证控件在不同的请求中保持一致性。毕竟，这个世界已经不再是桌面应用的天下！ASP.NET 的控件能帮你解决掉很多烦杂的琐事，让你感觉就象在用 MFC 或 Visual Basic 做开发，让你的应用分布于全球的计算机上，时刻被成千上万的用户所访问。