服务器控件

Microsoft

ASP.NET 2.0 以多种方式增强了服务器控制。 在本模块中,我们将介绍 ASP.NET 2.0 和 Visual Studio 2005 处理服务器控件的方式的一些体系结构更改。

ASP.NET 2.0 以多种方式增强了服务器控制。 在本模块中,我们将介绍 ASP.NET 2.0 和 Visual Studio 2005 处理服务器控件的方式的一些体系结构更改。

查看状态

ASP.NET 2.0 中视图状态的主要变化是大小急剧减小。 考虑一个页面上只有日历控件的页面。 下面是 ASP.NET 1.1 中的视图状态。

dDwtMTg1NDkwMjc0Nzt0PDtsPGk8MT47PjtsPHQ8O2w8aTwxPjs
+O2w8dDxAMDxwPHA8bDxTRDs+O2w8bDxTeXN0ZW0uRGF0ZVRpbWUsIG1
zY29ybGliLCBWZXJzaW9uPTEuMC41MDAwLjAsIEN1bHR1cmU9bmV1dHJ
hbCwgUHVibGljS2V5VG9rZW49Yjc3YTVjNTYxOTM0ZTA4OTwyMDA1LTE
xLTA4Pjs+Oz4+Oz47Ozs7Ozs7Ozs7Pjs7Pjs+Pjs+Pjs+lkX2YWqfACtP
/VWr8G03pob/+tU=

下面是 ASP.NET 2.0 中相同页面上的视图状态。

/wEPDwULLTEzNjg5MjAxMzgPZBYCAgMPZBYCAgEPPCsAC
gEADxYCHgJTRBYBBgDAEX8OsscIZGRkllfArINjlhvzQX7Xfign2q6HK5E=

这是一个相当重要的更改,考虑到视图状态是通过网络来回传输的,此更改可以让开发人员显著提高性能。 视图状态大小减小的主要原因是我们在内部处理它的方式。 请记住,视图状态是 Base64 编码的字符串。 为了更好地了解 ASP.NET 2.0 中视图状态的变化,我们来看看上面示例中的解码值。

下面是解码的 1.1 视图状态:

t<-1854902747;t<;l<i<1>;>;l<t<;l<
i<1>;>;l<t<@0<p<p<l<SD;>;l<l<
System.DateTime, mscorlib, Version=1.0.5000.0, Culture=neutral, 
PublicKeyToken=b77a5c561934e089<2005-11-08>;>;>>;
>;;;;;;;;;;>;;>;>>;>>;>Eaj

这看起来有点像胡言乱语,但这里有一个模式。 在 ASP.NET 1.x 中,我们使用单个字符来标识数据类型,并使用 <> 字符分隔值。 上述视图状态示例中的“t”表示一个 Triplet。 Triplet 包含一对 ArrayLists, (“l”表示 ArrayList。) 其中一个 ArrayLists 包含值为 1 的 Int32 (“i”) ,另一个包含另一个 Triplet。 Triplet 包含一对 ArrayLists 等。需要记住的重要一点是,我们使用包含对的三元组,通过字母标识数据类型,并使用 < 和 > 字符作为分隔符。

在 ASP.NET 2.0 中,解码的视图状态看起来略有不同。

-1368920138 d 
 d 
 
 
 SD 
 dddWc A ('ڮ

应注意到解码视图状态的外观发生了巨大变化。 此更改具有多个体系结构基础。 ASP.NET 1.x 中的视图状态使用 LosFormatter 序列化数据。 在 2.0 版中,我们使用新的 ObjectStateFormatter 类。 此类专门用于帮助序列化和反序列化视图状态和控制状态。 下一部分将介绍 (控制状态。) 更改进行序列化和反序列化的方法可以获得许多好处。 其中一个最引人注目的事实是,与使用 TextWriter 的 LosFormatter 不同,ObjectStateFormatter 使用 BinaryWriter。 这允许 ASP.NET 2.0 存储一系列字节而不是字符串的视图状态。 例如,以整数为例。 在 ASP.NET 1.1 中,整数需要 4 个字节的视图状态。 在 ASP.NET 2.0 中,同一整数只需要 1 字节。 进行了其他增强,以减少存储的视图状态量。 例如,DateTime 值现在使用 TickCount 而不是字符串进行存储。

好像这一切还不够,需要特别注意一个事实,即 1.x 中视图状态的最大使用者之一是 DataGrid 和类似的控件。 视图状态所在的 DataGrid 等控件的主要缺点是它通常包含大量重复信息。 在 ASP.NET 1.x 中,重复的信息只是一遍又一遍地存储,从而导致视图状态膨胀。 在 ASP.NET 2.0 中,我们使用新的 IndexedString 类来存储此类数据。 如果字符串重复,我们只需将 IndexedString 的令牌和索引存储在 IndexedString 对象的运行表中。

控制状态

开发人员对视图状态的主要抱怨之一是它添加到 HTTP 有效负载的大小。 如前所述,视图状态的最大使用者之一是 DataGrid 控件。 为了避免 DataGrid 生成的大量视图状态,许多开发人员只是禁用了该控件的视图状态。 不幸的是,这种解决方案并不总是一个好的解决方案。 ASP.NET 1.x 中的视图状态不仅包含控件正确功能所需的数据。 它还包含有关控件 UI 状态的信息。 这意味着,如果想要允许对 DataGrid 进行分页,则必须启用视图状态,即使不需要视图状态包含的所有 UI 信息。 这是一个全有或全无的方案。

在 ASP.NET 2.0 中,控制状态通过引入控制状态很好地解决了该问题。 控件状态包含对控件的正常功能绝对必要的数据。 与视图状态不同,不能禁用控件状态。 因此,请务必仔细控制存储在控制状态中的数据。

注意

控件状态与视图状态一起保留在__VIEWSTATE隐藏窗体字段中。

此视频是视图状态和控件状态的演练。

介绍视图状态和控制状态字段的演练视频的屏幕截图,其中显示了 Windows 资源管理器浏览器窗口。

打开Full-Screen视频

为了使服务器控件能够读取和写入到控制状态,必须执行三个步骤。

步骤 1:调用 RegisterRequiresControlState 方法

RegisterRequiresControlState 方法通知 ASP.NET 控件需要保留控件状态。 它采用 Control 类型的一个参数,该参数是正在注册的控件。

请务必注意,注册不会从请求保存到请求。 因此,如果控件要保留控件状态,则必须在每个请求上调用此方法。 建议在 OnInit 中调用 方法。

protected override void OnInit(EventArgs e) { Page.RegisterRequiresControlState(this); base.OnInit(e); }

步骤 2:重写 SaveControlState

SaveControlState 方法保存自上次回发以来控件的控件状态更改。 它返回表示控件状态的 对象。

步骤 3:重写 LoadControlState

LoadControlState 方法将保存的状态加载到控件中。 方法采用 Object 类型的一个参数,该参数保存控件的保存状态。

完全 XHTML 合规性

任何 Web 开发人员都知道标准在 Web 应用程序中的重要性。 为了维护基于标准的开发环境,ASP.NET 2.0 完全符合 XHTML。 因此,所有标记都根据 XHTML 标准在支持 HTML 4.0 或更高版本的浏览器中呈现。

ASP.NET 1.1 中的 DOCTYPE 定义如下所示:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN

在 ASP.NET 2.0 中,默认 DOCTYPE 定义如下所示:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

如果选择,可以通过配置文件中的 xhtmlConformance 节点更改默认的 XHTML 符合性。 例如,web.config 文件中的以下节点会将 XHTML 合规性更改为 XHTML 1.0 Strict:

<xhtmlConformance mode="Strict" />

如果选择,还可以将 ASP.NET 配置为使用 ASP.NET 1.x 中使用的旧配置,如下所示:

<xhtmlConformance mode="Legacy" />

使用适配器进行自适应呈现

在 ASP.NET 1.x 中,配置文件包含填充 <HttpBrowserCapabilities 对象的 browserCaps> 节。 此对象允许开发人员确定发出特定请求的设备并相应地呈现代码。 在 ASP.NET 2.0 中,模型已得到改进,现在使用新的 ControlAdapter 类。 ControlAdapter 类替代控件生命周期中的事件,并根据用户代理的功能控制控件的呈现。 特定用户代理的功能由浏览器定义文件 (具有 .browser 文件扩展名的文件) 存储在 c:\windows\microsoft.net\framework\v2.0.****\CONFIG\Browser 文件夹中。

注意

ControlAdapter 类是一个抽象类。

与 1.x 中的 browserCaps> 部分非常相似<,浏览器定义文件使用正则表达式来分析用户代理字符串,以标识请求的浏览器。 它们定义了该用户代理的特定功能。 ControlAdapter 通过 Render 方法呈现控件。 因此,如果重写 Render 方法,则不应在基类上调用 Render。 这样做可能会导致呈现发生两次,一次用于适配器,一次用于控件本身。

开发自定义适配器

可以通过从 ControlAdapter 继承来开发自己的自定义适配器。 此外,在页面需要适配器的情况下,可以从抽象类 PageAdapter 继承。 控件到自定义适配器的映射是通过浏览器定义文件中的 <controlAdapters> 元素完成的。 例如,浏览器定义文件中的以下 XML 将 Menu 控件映射到 MenuAdapter 类:

<controlAdapters> <adapter controlType="System.Web.UI.WebControls.Menu" adapterType="System.Web.UI.WebControls.Adapters.MenuAdapter" /> </controlAdapters>

使用此模型,控件开发人员很容易以特定设备或浏览器为目标。 对于开发人员来说,完全控制页面在每个设备上的呈现方式也非常简单。

Per-Device渲染

可以使用特定于浏览器的前缀为每个设备指定 ASP.NET 2.0 中的服务器控件属性。 例如,下面的代码将更改标签的文本,具体取决于用于浏览页面的设备。

<asp:Label ID="lblBrowser" runat="server" Text="You are browsing from an unknown device." ie:Text="You are browsing from Internet Explorer." mozilla:Text="You are browsing from Firefox."> </asp:Label>

当从 Internet Explorer 浏览包含此标签的页面时,标签将显示文本“你正在从 Internet Explorer 浏览”。从 Firefox 浏览页面时,标签将显示文本“你正在从 Firefox 浏览”。从任何其他设备浏览页面时,将显示“你正在从未知设备浏览”。可以使用此特殊语法指定任何属性。

设置焦点

ASP.NET 1.x 开发人员经常询问如何在特定控件上设置初始焦点。 例如,在登录页上,让“用户 ID”文本框在页面首次加载时获得焦点非常有用。 在 ASP.NET 1.x 中,执行此操作需要编写一些客户端脚本。 尽管此类脚本是一项琐碎的任务,但由于 SetFocus 方法,ASP.NET 2.0 中不再需要它。 SetFocus 方法采用一个参数,指示应接收焦点的控件。 此参数可以是字符串形式的控件的客户端 ID,也可以是作为 Control 对象的 Server 控件的名称。 例如,若要在页面首次加载时将初始焦点设置为名为 txtUserID 的 TextBox 控件,请将以下代码添加到Page_Load:

if (!IsPostBack) {
    SetFocus(txtUserID);
}

--或

if (!IsPostBack) {
    SetFocus(txtUserID.ClientID);
}

ASP.NET 2.0 使用前面) 讨论 (Webresource.axd 处理程序来呈现设置焦点的客户端函数。 客户端函数的名称WebForm_AutoFocus,如下所示:

<script type="text/javascript"> <!-- WebForm_AutoFocus('txtUserID'); // --> </script>

或者,可以使用控件的 Focus 方法将初始焦点设置为该控件。 Focus 方法派生自 Control 类,可用于所有 ASP.NET 2.0 控件。 还可以在发生验证错误时将焦点设置为特定控件。 后面的模块将介绍这一点。

ASP.NET 2.0 中的新服务器控件

以下是 ASP.NET 2.0 中的新服务器控件。 我们将在后面的模块中更详细地介绍其中一些内容。

ImageMap 控件

ImageMap 控件允许向可启动回发或导航到 URL 的图像添加热点。 有三种类型的热点可用:CircleHotSpot、RectangleHotSpot 和 PolygonHotSpot。 热点是通过 Visual Studio 中的集合编辑器添加的,或在代码中以编程方式添加的。 没有可用于在图像上绘制热点的用户界面。 必须以声明方式指定热点的坐标和大小或半径。 设计器中也没有热点的可视表示形式。 如果热点配置为导航到 URL,则通过热点的 NavigateUrl 属性指定该 URL。 对于回发热点,PostBackValue 属性允许在回发中传递可在服务器端代码中检索的字符串。

“默认点 A S P X 文件”窗口中显示的“HotSpot 集合编辑器”屏幕的屏幕截图。

图 1:Visual Studio 中的 HotSpot 集合编辑器

BulletedList 控件

BulletedList 控件是可以轻松绑定数据的项目符号列表。 列表可以通过 BulletStyle 属性 (编号) 或无序排序。 列表中的每个项都由一个 ListItem 对象表示。

无序列表上“项目符号列表”任务下拉菜单的屏幕截图,其中“选择数据源”选项悬停在上方。

图 2:Visual Studio 中的 BulletedList 控件

HiddenField 控件

HiddenField 控件将隐藏的窗体域添加到页面,其值在服务器端代码中可用。 通常,隐藏窗体域的值在回发之间保持不变。 但是,恶意用户有可能在回发之前更改值。 如果发生这种情况,HiddenField 控件将引发 ValueChanged 事件。 如果 HiddenField 控件中有敏感信息,并且希望确保它保持不变,则应在代码中处理 ValueChanged 事件。

FileUpload 控件

ASP.NET 2.0 中的 FileUpload 控件允许通过 ASP.NET 页将文件上传到 Web 服务器。 此控件与 ASP.NET 1.x HtmlInputFile 类非常相似,但有一些例外。 在 ASP.NET 1.x 中,建议检查 PostedFile 属性是否为 null,以确定文件是否良好。 ASP.NET 2.0 中的 FileUpload 控件添加了一个新的 HasFile 属性,可用于同一目的,并且效率更高。

PostedFile 属性仍可用于访问 HttpPostedFile 对象,但 HttpPostedFile 的某些功能现在通过 FileUpload 控件以固有方式提供。 例如,若要将上传的文件保存在 ASP.NET 1.x 中,请对 HttpPostedFile 对象调用 SaveAs 方法。 使用 ASP.NET 2.0 中的 FileUpload 控件,可对 FileUpload 控件本身调用 SaveAs 方法。

2.0 行为的另一个重大更改 (可能是) 最重要的更改是,在保存文件之前,不再需要将整个上传的文件加载到内存中。 在 1.x 中,上传的任何文件在写入磁盘之前将完全保存到内存中。 此体系结构可防止上传大型文件。

在 ASP.NET 2.0 中,httpRuntime 元素的 requestLengthDiskThreshold 属性允许配置在写入磁盘之前在内存中的缓冲区中保留的千字节数。

重要提示:MSDN 文档 (,其他文档) 指定此值以字节为单位 (而不是千字节) ,默认值为 256。 该值实际上以千字节为单位指定,默认值为 80。 通过将默认值设置为 80K,可以确保缓冲区不会最终位于大型对象堆上。

向导控件

遇到 ASP.NET 开发人员在尝试使用面板或通过从页面转移到页面来收集一系列“页面”中的信息时,这是相当常见的。 通常,这种努力是令人沮丧的,而且很耗时。 新的 Wizard 控件通过在用户熟悉的向导界面中允许线性和非线性步骤来解决问题。 向导控件在一系列步骤中显示输入窗体。 每个步骤都是由控件的 StepType 属性指定的特定类型。 可用的步骤类型如下:

步骤类型 解释
Auto 向导根据步骤在步骤层次结构中的位置自动确定步骤的类型。
开始 第一步,通常用于演示介绍性陈述。
步骤 普通步骤。
完成 最后一步,通常用于显示完成向导的按钮。
完成 显示传达成功或失败的消息。

注意

向导控件使用 ASP.NET 控件状态跟踪其状态。 因此,EnableViewState 属性可以设置为 false,而不会有任何损害。

此视频是向导控件的演练。

向导控件的视频演练的屏幕截图。显示带有 Microsoft Visual Studio 窗口的“服务器控件”屏幕。

打开Full-Screen视频

本地化控件

Localize 控件类似于 Literal 控件。 但是,Localize 控件具有 Mode 属性,该属性控制如何呈现添加到它的标记。 Mode 属性支持以下值:

模式 解释
转换 标记根据发出请求的浏览器的协议进行转换。
PassThrough 标记按原样呈现。
编码 添加到 控件的标记使用 HtmlEncode 进行编码。

MultiView 和 View 控件

MultiView 控件充当视图控件的容器,视图控件充当容器, (就像面板控件) 其他控件一样。 MultiView 控件中的每个视图都由单个 View 控件表示。 MultiView 中的第一个视图控件是视图 0,第二个控件是视图 1,等等。可以通过指定 MultiView 控件的 ActiveViewIndex 来切换视图。

替换控件

替换控件与 ASP.NET 缓存结合使用。 如果想要利用缓存,但页面的某些部分必须针对每个请求进行更新, (换句话说,即页面的某些部分不受缓存) ,则替换组件提供了一个很好的解决方案。 控件实际上不会自行呈现任何输出。 而是绑定到服务器端代码中的 方法。 请求页面时,将调用 方法,并呈现返回的标记来代替替换控件。

替换控件绑定到的方法是通过 MethodName 属性指定的。 该方法必须满足以下条件:

  • 它必须是 VB) 方法中共享的静态 (。
  • 它接受 HttpContext 类型的一个参数。
  • 它返回一个字符串,表示应替换页面上控件的标记。

替换控件无法修改页面上的任何其他控件,但它可以通过其参数访问当前 HttpContext。

GridView 控件

GridView 控件取代了 DataGrid 控件。 稍后的模块将更详细地介绍此控件。

DetailsView 控件

利用 DetailsView 控件,可以显示数据源中的单个记录并编辑或删除该记录。 稍后的模块将更详细地介绍这一点。

FormView 控件

FormView 控件用于在可配置接口中显示数据源中的单个记录。 稍后的模块将更详细地介绍这一点。

AccessDataSource 控件

AccessDataSource 控件用于数据绑定 Access 数据库。 稍后的模块将更详细地介绍这一点。

ObjectDataSource 控件

ObjectDataSource 控件用于支持三层体系结构,以便控件可以将数据绑定到中间层业务对象,而不是将控件直接绑定到数据源的两层模型。 将在后面的模块中对此进行更详细的讨论。

XmlDataSource 控件

XmlDataSource 控件用于将数据绑定到 XML 数据源。 稍后的模块将更详细地介绍这一点。

SiteMapDataSource 控件

SiteMapDataSource 控件为基于站点地图的站点导航控件提供数据绑定。 将在后面的模块中对此进行更详细的讨论。

SiteMapPath 控件

SiteMapPath 控件显示一系列导航链接,通常称为痕迹导航。 稍后的模块将更详细地介绍这一点。

Menu 控件使用 DHTML 显示动态菜单。 稍后的模块将更详细地介绍这一点。

TreeView 控件

TreeView 控件用于显示数据的分层树视图。 稍后的模块将更详细地介绍这一点。

登录控件

Login 控件提供了一种用于登录网站的机制。 稍后的模块将更详细地介绍这一点。

LoginView 控件

LoginView 控件允许根据用户的登录状态显示不同的模板。 稍后的模块将更详细地介绍这一点。

PasswordRecovery Control

PasswordRecovery 控件用于检索 ASP.NET 应用程序的用户忘记的密码。 稍后的模块将更详细地介绍这一点。

LoginStatus

LoginStatus 控件显示用户的登录状态。 稍后的模块将更详细地介绍这一点。

LoginName

LoginName 控件在登录到 ASP.NET 应用程序后显示用户的用户名。 稍后的模块将更详细地介绍这一点。

CreateUserWizard

CreateUserWizard 是一个可配置的向导,使用户能够创建 ASP.NET 成员身份帐户以用于 ASP.NET 应用程序。 稍后的模块将更详细地介绍这一点。

ChangePassword

ChangePassword 控件允许用户更改 ASP.NET 应用程序的密码。 稍后的模块将更详细地介绍这一点。

各种 Web 部件

ASP.NET 2.0 附带各种 Web 部件。 后续模块中将详细介绍这些内容。