ASP.NET 2.0 页面模型

Microsoft

在 ASP.NET 1.x 中,开发人员可以选择内联代码模型和代码隐藏代码模型。 可以使用 指令的 Src 属性或 CodeBehind 属性 @Page 实现代码隐藏。 在 ASP.NET 2.0 中,开发人员仍可以选择内联代码和代码隐藏,但代码隐藏模型已得到显著增强。

在 ASP.NET 1.x 中,开发人员可以选择内联代码模型和代码隐藏代码模型。 可以使用 指令的 Src 属性或 CodeBehind 属性 @Page 实现代码隐藏。 在 ASP.NET 2.0 中,开发人员仍可以选择内联代码和代码隐藏,但代码隐藏模型已得到显著增强。

Code-Behind模型中的改进

为了充分了解 ASP.NET 2.0 中代码隐藏模型中的更改,最好快速查看 ASP.NET 1.x 中存在的模型。

ASP.NET 1.x 中的Code-Behind模型

在 ASP.NET 1.x 中,代码隐藏模型由 (Webform) 的 ASPX 文件和包含编程代码的代码隐藏文件组成。 这两个文件是使用 @Page ASPX 文件中的 指令连接的。 ASPX 页上的每个控件在代码隐藏文件中都有相应的声明作为实例变量。 代码隐藏文件还包含用于事件绑定的代码,以及 Visual Studio 设计器所需的生成的代码。 此模型运行得很好,但由于 ASPX 页中的每个 ASP.NET 元素都需要代码隐藏文件中的相应代码,因此没有真正的代码和内容分离。 例如,如果设计器向 Visual Studio IDE 外部的 ASPX 文件添加了新的服务器控件,则应用程序会中断,因为代码隐藏文件中没有该控件的声明。

ASP.NET 2.0 中的Code-Behind模型

ASP.NET 2.0 大大改进了此模型。 在 ASP.NET 2.0 中,代码隐藏是使用 ASP.NET 2.0 中提供的新 分部类 实现的。 ASP.NET 2.0 中的代码隐藏类定义为分部类,这意味着它仅包含类定义的一部分。 类定义的其余部分由 ASP.NET 2.0 在运行时或预编译网站时使用 ASPX 页动态生成。 代码隐藏文件和 ASPX 页之间的链接仍使用 @ Page 指令建立。 但是,ASP.NET 2.0 现在使用 CodeFile 属性,而不是 CodeBehind 或 Src 属性。 Inherits 属性还用于指定页面的类名。

典型的 @ Page 指令可能如下所示:

<%@Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" %>

ASP.NET 2.0 代码隐藏文件中的典型类定义可能如下所示:

public partial class _Default : System.Web.UI.Page

注意

C# 和 Visual Basic 是目前唯一支持分部类的托管语言。 因此,使用 J# 的开发人员将无法使用 ASP.NET 2.0 中的代码隐藏模型。

新模型增强了代码隐藏模型,因为开发人员现在将拥有仅包含他们创建的代码的代码文件。 它还提供了代码和内容的真正分离,因为代码隐藏文件中没有实例变量声明。

注意

由于 ASPX 页的分部类是发生事件绑定的位置,因此 Visual Basic 开发人员可以使用代码隐藏中的 Handles 关键字 (keyword) 来绑定事件,从而略微提高性能。 C# 没有等效关键字 (keyword) 。

新建 @ Page 指令属性

ASP.NET 2.0 向 @ Page 指令添加了许多新属性。 以下属性是 ASP.NET 2.0 中的新增属性。

异步

Async 属性允许将页面配置为异步执行。 请在此模块后面部分介绍异步页面。

异步超时

指定异步页的超时。 默认值为 45 秒。

CodeFile

CodeFile 属性是 Visual Studio 2002/2003 中 CodeBehind 属性的替代项。

CodeFileBaseClass

如果希望多个页面派生自单个基类,则使用 CodeFileBaseClass 属性。 由于 ASP.NET 中分部类的实现,如果没有此属性,使用共享公共字段引用 ASPX 页中声明的控件的基类将无法正常工作,因为 ASP。NET 编译引擎将根据页面中的控件自动创建新成员。 因此,如果要在 ASP.NET 中为两个或更多页创建一个公共基类,则需要在 CodeFileBaseClass 属性中定义指定基类,然后从该基类派生每个页面类。 使用此属性时,还需要 CodeFile 属性。

CompilationMode

此属性允许设置 ASPX 页的 CompilationMode 属性。 CompilationMode 属性是包含 AlwaysAutoNever 值的枚举。 默认值为 Always。 如果可能, “自动 ”设置将阻止 ASP.NET 动态编译页面。 从动态编译中排除页面可提高性能。 但是,如果排除的页面包含必须编译的代码,则在浏览页面时将引发错误。

启用事件验证

此属性指定是否验证回发和回调事件。 启用此功能后,将检查回发或回调事件的参数,以确保它们源自最初呈现它们的服务器控件。

启用主题

此属性指定是否在页面上使用 ASP.NET 主题。 默认值为 false模块 10 中介绍了 ASP.NET 主题。

LinePragmas

此属性指定是否应在编译期间添加行杂注。 行杂注是调试器用于标记代码的特定部分的选项。

MaintainScrollPositionOnPostback

此属性指定是否将 JavaScript 注入页面,以保持回发之间的滚动位置。 默认情况下,此属性为 false

当此属性为 true 时,ASP.NET 将在回发时添加如下所示 <的脚本> 块:

<script src="/website/WebResource.axd?d=jBAvpwrdOM_V_Xzeox989A2 &t=632653133849531250" type="text/javascript"> </script>

请注意,此脚本块的 src 为 WebResource.axd。 此资源不是物理路径。 请求此脚本时,ASP.NET 动态生成该脚本。

MasterPageFile

此属性指定当前页的母版页文件。 路径可以是相对路径或绝对路径。 模块 4 中介绍了母版页。

样式表主题

此属性允许重写由 ASP.NET 2.0 主题定义的用户界面外观属性。 模块 10 中介绍了主题。

主题值

指定页面的主题。 如果未为 StyleSheetTheme 属性指定值,则 Theme 属性将替代应用于页面上的控件的所有样式。

游戏值

设置页面的标题。 此处指定的值将显示在所呈现页面的 title> 元素中<。

ViewStateEncryptionMode

设置 ViewStateEncryptionMode 枚举的值。 可用值为 AlwaysAutoNever。 默认值为 Auto。当此属性设置为 Auto 值时,viewstate 是一个通过调用 RegisterRequiresViewStateEncryption 方法请求它的控件加密。

通过 @ Page 指令设置公共属性值

ASP.NET 2.0 中 @ Page 指令的另一项新功能是能够设置基类的公共属性的初始值。 例如,假设基类中有一个名为 SomeText 的公共属性,并且希望在加载页面时将其初始化为 Hello 。 只需在 @ Page 指令中设置值即可完成此操作,如下所示:

<%@Page Language="C#" SomeText="Hello!" Inherits="PageBase" %>

@ Page 指令的 SomeText 属性将基类中的 SomeText 属性的初始值设置为 Hello!。 下面的视频演示了如何使用 @ Page 指令在基类中设置公共属性的初始值。

Microsoft Visual Studio 窗口的屏幕截图,其中一行上有一个红色箭头,指示“某些文本”属性。

打开Full-Screen视频

Page 类的新公共属性

以下公共属性是 ASP.NET 2.0 中的新增属性。

AppRelativeTemplateSourceDirectory

返回页或控件的应用程序相对路径。 例如,对于位于 http://app/folder/page.aspx的页, 属性返回 ~/folder/。

AppRelativeVirtualPath

返回页或控件的相对虚拟目录路径。 例如,对于位于 http://app/folder/page.aspx的页, 属性返回 ~/folder/page.aspx。

AsyncTimeout

获取或设置用于异步页面处理的超时。 本模块稍后将介绍 (异步页面。)

ClientQueryString

一个只读属性,返回所请求 URL 的查询字符串部分。 此值是 URL 编码的。 可以使用 HttpServerUtility 类的 UrlDecode 方法对其进行解码。

ClientScript

此属性返回可用于管理 ASP 的 ClientScriptManager 对象。客户端脚本的 NET 发射。 (本模块稍后将介绍 ClientScriptManager 类。)

EnableEventValidation

此属性控制是否为回发和回调事件启用事件验证。 启用后,将验证回发或回调事件的参数,以确保它们源自最初呈现它们的服务器控件。

EnableTheming

此属性获取或设置一个布尔值,该值指定 ASP.NET 2.0 主题是否应用于页面。

窗体

此属性将 ASPX 页上的 HTML 窗体作为 HtmlForm 对象返回。

此属性返回对包含页眉的 HtmlHead 对象的引用。 可以使用返回的 HtmlHead 对象来获取/设置样式表、Meta 标记等。

IdSeparator

当 ASP.NET 为页面上的控件生成唯一 ID 时,此只读属性获取用于分隔控件标识符的字符。 它不可直接通过代码使用。

IsAsync

此属性允许异步页面。 本模块稍后将讨论异步页面。

IsCallback

如果页面是回调的结果,则此只读属性返回 true 。 本模块稍后将讨论回叫。

IsCrossPagePostBack

如果页面是跨页回发的一部分,则此只读属性返回 true 。 本模块稍后将介绍跨页回发。

Items

返回对 IDictionary 实例的引用,该实例包含存储在页面上下文中的所有对象。 可以将项添加到此 IDictionary 对象,它们将在上下文的整个生存期内可用。

MaintainScrollPositionOnPostBack

此属性控制 ASP.NET 是否发出 JavaScript,该 JavaScript 在回发发生后在浏览器中保持页面滚动位置。 (本模块前面部分讨论了此属性的详细信息。)

Master

此只读属性返回对已应用母版页的页面的 MasterPage 实例的引用。

MasterPageFile

获取或设置页面的母版页文件名。 此属性只能在 PreInit 方法中设置。

MaxPageStateFieldLength

此属性获取或设置页状态的最大长度(以字节为单位)。 如果 属性设置为正数,则页面视图状态将分解为多个隐藏字段,使其不会超过指定的字节数。 如果 属性是负数,则视图状态不会分解为区块。

PageAdapter

返回对 PageAdapter 对象的引用,该对象修改请求浏览器的页面。

PreviousPage

在 Server.Transfer 或跨页面回发的情况下,返回对上一页的引用。

SkinID

指定要应用于页面的 ASP.NET 2.0 外观。

StyleSheetTheme

此属性获取或设置应用于页面的样式表。

TemplateControl

返回对页面的包含控件的引用。

主题

获取或设置应用于页面的 ASP.NET 2.0 主题的名称。 此值必须在 PreInit 方法之前设置。

标题

此属性获取或设置从页眉获取的页面标题。

ViewStateEncryptionMode

获取或设置页面的 ViewStateEncryptionMode。 请参阅本模块前面的有关此属性的详细讨论。

Page 类的新受保护属性

以下是 ASP.NET 2.0 中 Page 类的新受保护属性。

适配器

返回对 ControlAdapter 的引用,该引用在请求它的设备上呈现页面。

AsyncMode

此属性指示是否以异步方式处理页面。 它旨在供运行时使用,而不是直接在代码中使用。

ClientIDSeparator

此属性返回在为控件创建唯一客户端 ID 时用作分隔符的字符。 它旨在供运行时使用,而不是直接在代码中使用。

PageStatePersister

此属性返回页面的 PageStatePersister 对象。 此属性主要由 ASP.NET 控件开发人员使用。

UniqueFilePathSuffix

此属性返回一个唯一的后缀,该后缀追加到用于缓存浏览器的文件路径。 默认值为 __ufps= 和 6 位数字。

Page 类的新公共方法

以下公共方法是 ASP.NET 2.0 中的 Page 类的新增方法。

AddOnPreRenderCompleteAsync

此方法注册用于异步页面执行的事件处理程序委托。 本模块稍后将讨论异步页面。

ApplyStyleSheetSkin

将页面样式表中的属性应用于页面。

ExecuteRegisteredAsyncTasks

此方法是异步任务。

GetValidators

返回指定验证组的验证程序集合,如果未指定任何验证组,则返回默认验证组。

RegisterAsyncTask

此方法注册新的异步任务。 本模块稍后将介绍异步页面。

RegisterRequiresControlState

此方法告知 ASP.NET 必须保留页面控件状态。

RegisterRequiresViewStateEncryption

此方法告知 ASP.NET 页面视图状态需要加密。

ResolveClientUrl

返回一个相对 URL,该 URL 可用于客户端对图像等的请求。

SetFocus

此方法会将焦点设置为最初加载页面时指定的控件。

UnregisterRequiresControlState

此方法将取消注册传递给它的控件,因为不再需要控件状态持久性。

对页面生命周期的更改

ASP.NET 2.0 中的页面生命周期没有发生重大变化,但应注意一些新方法。 下面概述了 ASP.NET 2.0 页生命周期。

PreInit (ASP.NET 2.0) 中的新增功能

PreInit 事件是开发人员可以访问的生命周期中最早的阶段。 通过添加此事件,可以编程方式更改 ASP.NET 2.0 主题、母版页、ASP.NET 2.0 配置文件的访问属性等。如果处于回发状态,请务必认识到 Viewstate 尚未应用于生命周期中此时的控件。 因此,如果开发人员在此阶段更改控件的属性,则它很可能在页面生命周期的后面被覆盖。

Init

Init 事件未从 ASP.NET 1.x 更改。 这是需要读取或初始化页面上控件属性的位置。 在此阶段,母版页、主题等。已应用于页面。

InitComplete (2.0) 中的新增功能

InitComplete 事件在页面初始化阶段结束时调用。 在生命周期的此时,可以访问页面上的控件,但尚未填充其状态。

预加载 (2.0) 中的新增功能

此事件在应用所有回发数据之后调用,并且就在Page_Load之前。

加载

Load 事件未从 ASP.NET 1.x 更改。

LoadComplete (2.0) 中的新增功能

LoadComplete 事件是页面加载阶段的最后一个事件。 在此阶段,所有回发和 viewstate 数据都已应用于页面。

PreRender

如果要为动态添加到页面的控件正确维护 viewstate,PreRender 事件是添加这些控件的最后一次机会。

PreRenderComplete (2.0) 中的新增功能

在 PreRenderComplete 阶段,所有控件都已添加到页面,并且页面已准备好呈现。 PreRenderComplete 事件是在保存页面视图状态之前引发的最后一个事件。

SaveStateComplete (2.0) 中的新增功能

保存所有页面视图状态和控制状态后,将立即调用 SaveStateComplete 事件。 这是页面实际呈现到浏览器之前的最后一个事件。

呈现

Render 方法自 ASP.NET 1.x 后未更改。 这是初始化 HtmlTextWriter 并将页面呈现到浏览器的位置。

ASP.NET 2.0 中的跨页回发

在 ASP.NET 1.x 中,需要回发到同一页面。 不允许跨页回发。 ASP.NET 2.0 添加了通过 IButtonControl 接口发回其他页面的功能。 实现新 IButtonControl 接口 (Button、LinkButton 和 ImageButton 以及第三方自定义控件) 的任何控件都可以通过使用 PostBackUrl 属性来利用此新功能。 以下代码显示一个按钮控件,该控件发回第二页。

<asp:Button ID="SubmitReport" PostBackUrl="~/Default.aspx" runat="server" Text="Submit Report" />

当页面发回时,可通过第二页上的 PreviousPage 属性访问启动回发的页面。 此功能通过新的 WebForm_DoPostBackWithOptions 客户端函数实现,ASP.NET 2.0 在控件发回其他页面时呈现到页面。 此 JavaScript 函数由向客户端发出脚本的新 WebResource.axd 处理程序提供。

下面的视频是跨页回发的演练。

跨页回发的视频演练的屏幕截图,其中显示了显示“提交报表”选项的 Internet Explorer 浏览器页面。

打开Full-Screen视频

有关跨页回发的更多详细信息

Viewstate

你可能已经问过自己,在跨页回发方案中,第一页的 viewstate 会发生什么情况。 毕竟,任何未实现 IPostBackDataHandler 的控件都将通过 viewstate 保留其状态,因此,若要在跨页回发的第二页上访问该控件的属性,必须有权访问该页面的 viewstate。 ASP.NET 2.0 使用第二页中名为 __PREVIOUSPAGE 的新隐藏字段处理此方案。 __PREVIOUSPAGE窗体字段包含第一页的 viewstate,以便你可以访问第二页中所有控件的属性。

规避 FindControl

在跨页回发的视频演练中,我使用 FindControl 方法获取对第一页上 TextBox 控件的引用。 此方法适用于该目的,但 FindControl 成本高昂,需要编写其他代码。 幸运的是,ASP.NET 2.0 为此提供了 FindControl 的替代方法,可在许多方案中使用。 PreviousPageType 指令允许使用 TypeName 或 VirtualPath 属性对上一页进行强类型引用。 TypeName 属性允许指定上一页的类型,而 VirtualPath 属性允许你使用虚拟路径引用上一页。 设置 PreviousPageType 指令后,必须公开控件等。希望允许使用公共属性进行访问。

实验室 1 跨页回发

在本实验室中,你将创建一个使用 ASP.NET 2.0 的新跨页回发功能的应用程序。

  1. 打开 Visual Studio 2005 并创建新的 ASP.NET 网站。

  2. 添加名为 page2.aspx 的新 Web 窗体。

  3. 在“设计”视图中打开 Default.aspx,并添加 Button 控件和 TextBox 控件。

    1. 为 Button 控件提供 SubmitButton 的 ID,为 TextBox 控件提供 UserName 的 ID。
    2. 将 Button 的 PostBackUrl 属性设置为 page2.aspx。
  4. 在“源”视图中打开 page2.aspx。

  5. 添加 @ PreviousPageType 指令,如下所示:

  6. 将以下代码添加到 page2.aspx 的代码隐藏Page_Load:

    Response.Write(PreviousPage.UserName.Text);
    
  7. 通过单击“生成”菜单上的“生成”来生成项目。

  8. 将以下代码添加到 Default.aspx 的代码隐藏:

    public TextBox txtUserName {
        get { return this.UserName; }
    }
    
  9. 将 page2.aspx 中的Page_Load更改为以下内容:

    Response.Write(PreviousPage.txtUserName.Text);
    
  10. 生成项目。

  11. 运行该项目。

  12. 在 TextBox 中输入你的姓名,然后单击按钮。

  13. 结果是什么?

ASP.NET 2.0 中的异步页面

ASP.NET 中的许多争用问题是由外部调用 (延迟引起的,例如 Web 服务或数据库调用) 、文件 IO 延迟等。当对 ASP.NET 应用程序发出请求时,ASP.NET 使用其工作线程之一来为该请求提供服务。 该请求拥有该线程,直到请求完成且已发送响应。 ASP.NET 2.0 旨在通过添加异步执行页面的功能来解决此类问题的延迟问题。 这意味着工作线程可以启动请求,然后将其他执行移交给另一个线程,从而快速返回到可用的线程池。 当文件 IO、数据库调用等时。已完成,将从线程池获取新线程以完成请求。

使页面以异步方式执行的第一步是设置 page 指令的 Async 属性,如下所示:

<%@ Page Async="true" %>

此属性告知 ASP.NET 为页面实现 IHttpAsyncHandler。

下一步是在 PreRender 之前的页生命周期中某个时间点调用 AddOnPreRenderCompleteAsync 方法。 (此方法通常在 Page_Load.) AddOnPreRenderCompleteAsync 方法采用两个参数;a BeginEventHandler 和 EndEventHandler。 BeginEventHandler 返回一个 IAsyncResult,该 IAsyncResult 随后作为参数传递给 EndEventHandler。

下面的视频是异步页面请求的演练。

异步页面请求的视频演练的屏幕截图,其中显示了 Microsoft Visual Code 屏幕。

打开Full-Screen视频

注意

在 EndEventHandler 完成之前,异步页面不会呈现给浏览器。 毫无疑问,但一些开发人员会认为异步请求类似于异步回调。 请务必意识到它们不是。 异步请求的好处是,可以将第一个工作线程返回到线程池,以便为新请求提供服务,从而减少由于 IO 绑定而导致的争用,等等。

ASP.NET 2.0 中的脚本回调

Web 开发人员一直在寻找防止与回调关联的闪烁的方法。 在 ASP.NET 1.x 中,SmartNavigation 是避免闪烁的最常见方法,但 SmartNavigation 为某些开发人员带来了问题,因为其实现在客户端上很复杂。 ASP.NET 2.0 解决了脚本回调的此问题。 脚本回调利用 XMLHttp 通过 JavaScript 对 Web 服务器发出请求。 XMLHttp 请求返回 XML 数据,然后可以通过浏览器的 DOM 进行操作。 新的 WebResource.axd 处理程序对用户隐藏 XMLHttp 代码。

若要在 ASP.NET 2.0 中配置脚本回调,需要执行几个步骤。

步骤 1:实现 ICallbackEventHandler 接口

为了使 ASP.NET 将页面识别为参与脚本回调,必须实现 ICallbackEventHandler 接口。 可以在代码隐藏文件中执行此操作,如下所示:

public partial class _Default : System.Web.UI.Page, ICallbackEventHandler

也可以使用 @ Implements 指令执行此操作,如下所示:

<%@ Implements Interface="System.Web.UI.ICallbackEventHandler" %>

使用内联 ASP.NET 代码时,通常会使用 @ Implements 指令。

步骤 2:调用 GetCallbackEventReference

如前所述,XMLHttp 调用封装在 WebResource.axd 处理程序中。 呈现页面时,ASP.NET 将添加对 WebForm_DoCallback(WebResource.axd 提供的客户端脚本)的调用。 WebForm_DoCallback 函数替换回调的 __doPostBack 函数。 请记住,__doPostBack以编程方式在页面上提交表单。 在回调方案中,你想要阻止回发,因此__doPostBack是不够的。

注意

__doPostBack仍呈现到客户端脚本回调方案中的页面。 但是,它不用于回调。

WebForm_DoCallback客户端函数的参数通过服务器端函数 GetCallbackEventReference 提供,该函数通常在 Page_Load 中调用。 对 GetCallbackEventReference 的典型调用可能如下所示:

// Set up the JavaScript callback string cbRef = cm.GetCallbackEventReference(this, "document.getElementById('ddlCompany').value", "ShowCompanyName", "null", true);

注意

在本例中,cm 是 ClientScriptManager 的实例。 本模块稍后将介绍 ClientScriptManager 类。

GetCallbackEventReference 有多个重载版本。 在本例中,参数如下所示:

this

对调用 GetCallbackEventReference 的控件的引用。 在本例中,它是页面本身。

document.getElementById('ddlCompany').value

将从客户端代码传递到服务器端事件的字符串参数。 在本例中,我传递了名为 ddlCompany 的下拉列表的值。

ShowCompanyName

将接受服务器端回调事件) 字符串 (返回值的客户端函数的名称。 仅当服务器端回调成功时,才会调用此函数。 因此,为了保持可靠性,通常建议使用 GetCallbackEventReference 的重载版本,该版本采用附加的字符串参数,指定要在发生错误时执行的客户端函数的名称。

null

一个字符串,表示它在回调服务器之前启动的客户端函数。 在本例中,没有此类脚本,因此参数为 null。

true

一个布尔值,指定是否异步执行回调。

在客户端上调用 WebForm_DoCallback 将传递这些参数。 因此,在客户端上呈现此页面时,该代码将如下所示:

WebForm_DoCallback('__Page',document.getElementById('ddlCompany').value, ShowCompanyName,null,null,true)

请注意,客户端上函数的签名略有不同。 客户端函数传递 5 个字符串和一个布尔值。 上述示例中为 null 的附加字符串 () 包含将处理服务器端回调中任何错误的客户端函数。

步骤 3:挂钩Client-Side控件事件

请注意,上述 GetCallbackEventReference 的返回值已分配给字符串变量。 该字符串用于为启动回调的控件挂钩客户端事件。 在此示例中,回调由页面上的下拉列表启动,因此我想挂钩 OnChange 事件。

若要挂钩客户端事件,只需将处理程序添加到客户端标记,如下所示:

// Hook the JavaScript function to the onchange event of the dropdown ddlCompany.Attributes["onchange"] = String.Format("javascript:{0}", cbRef);

回想一下 ,cbRef 是调用 GetCallbackEventReference 的返回值。 它包含对上面所示WebForm_DoCallback的调用。

步骤 4:注册Client-Side脚本

回想一下,对 GetCallbackEventReference 的调用指定了在服务器端回调成功时将执行名为 ShowCompanyName 的 客户端脚本。 需要使用 ClientScriptManager 实例将该脚本添加到页面。 (本模块稍后将讨论 ClientScriptManager 类。) 如下所示:

System.Text.StringBuilder clientScript = new System.Text.StringBuilder(""); ClientScriptManager cm = Page.ClientScript; // Create the client script clientScript.Append("function ShowCompanyName(companyName)"); clientScript.Append("{"); clientScript.Append("document.getElementById('CoClicked').innerHTML = \"You chose \" + companyName + \".\";"); clientScript.Append("}"); cm.RegisterClientScriptBlock(this.GetType(), "showCo", clientScript.ToString(), true);

步骤 5:调用 ICallbackEventHandler 接口的方法

ICallbackEventHandler 包含需要在代码中实现的两种方法。 它们是 RaiseCallbackEventGetCallbackEvent

RaiseCallbackEvent 采用字符串作为参数,不返回任何内容。 字符串参数从客户端调用传递到 WebForm_DoCallback。 在这种情况下,该值是名为 ddlCompany 的下拉列表 的值 属性。 服务器端代码应放置在 RaiseCallbackEvent 方法中。 例如,如果回调针对外部资源进行 WebRequest,则应将代码放置在 RaiseCallbackEvent 中。

GetCallbackEvent 负责处理回调到客户端的返回。 它不采用任何参数,并返回字符串。 它返回的字符串将作为参数传递给客户端函数,在本例中 为 ShowCompanyName

完成上述步骤后,即可在 ASP.NET 2.0 中执行脚本回调。

在 A S P 点 NET 2 点 0 中执行脚本回调的视频演练的屏幕截图。“Microsoft”下拉列表突出显示。

打开Full-Screen视频

任何支持进行 XMLHttp 调用的浏览器都支持 ASP.NET 中的脚本回调。 这包括目前使用的所有新式浏览器。 Internet Explorer 使用 XMLHttp ActiveX 对象,而其他新式浏览器 (包括即将推出的 IE 7) 使用内部 XMLHttp 对象。 若要以编程方式确定浏览器是否支持回调,可以使用 Request.Browser.SupportCallback 属性。 如果请求的客户端支持脚本回调,则此属性将返回 true

在 ASP.NET 2.0 中使用客户端脚本

ASP.NET 2.0 中的客户端脚本通过使用 ClientScriptManager 类进行管理。 ClientScriptManager 类使用类型和名称跟踪客户端脚本。 这可以防止以编程方式多次在页面上插入同一脚本。

注意

在页面上成功注册脚本后,任何后续注册同一脚本的尝试都只会导致该脚本不再注册第二次。 不会添加重复的脚本,并且不会发生异常。 为了避免不必要的计算,可以使用一些方法来确定脚本是否已注册,这样就不会多次尝试注册该脚本。

所有当前 ASP.NET 开发人员都应该熟悉 ClientScriptManager 的方法:

RegisterClientScriptBlock

此方法将脚本添加到呈现页面的顶部。 这对于添加将在客户端上显式调用的函数很有用。

此方法有两个重载版本。 四个参数中的三个是常见的。 它们是:

type (string)

类型参数标识脚本的类型。 通常,最好 (使用页面的类型。类型的 GetType () ) 。

key (string)

key 参数是脚本的用户定义键。 对于每个脚本,这应该是唯一的。 如果尝试添加具有相同键和已添加脚本类型的脚本,则不会添加该脚本。

script (string)

script 参数是包含要添加的实际脚本的字符串。 建议使用 StringBuilder 创建脚本,然后使用 StringBuilder 上的 ToString () 方法分配 脚本 参数。

如果使用仅采用三个参数的重载 RegisterClientScriptBlock,则必须在脚本中包含脚本元素 (<脚本> 和 </script>) 。

可以选择使用 RegisterClientScriptBlock 的重载,该重载采用第四个参数。 第四个参数是一个布尔值,指定 ASP.NET 是否应添加脚本元素。 如果此参数 为 true,则脚本不应显式包含脚本元素。

使用 IsClientScriptBlockRegistered 方法确定脚本是否已注册。 这样就可以避免尝试重新注册已注册的脚本。

RegisterClientScriptInclude (2.0) 中的新增功能

RegisterClientScriptInclude 标记创建链接到外部脚本文件的脚本块。 它有两个重载。 一个获取密钥和 URL。 第二个参数添加指定类型的第三个参数。

例如,以下代码生成一个脚本块,该脚本块链接到应用程序的 scripts 文件夹的根目录中的jsfunctions.js:

ClientScriptManager cm = Page.ClientScript; if(!cm.IsClientScriptIncludeRegistered("jsfunc")) { cm.RegisterClientScriptInclude(this.GetType(), "jsfunc", "/scripts/jsfunctions.js"); }

此代码在呈现的页面中生成以下代码:

<script src="/scripts/jsfunctions.js" type="text/javascript"></script>

注意

脚本块呈现在页面底部。

使用 IsClientScriptIncludeRegistered 方法确定脚本是否已注册。 这样就可以避免尝试重新注册脚本。

RegisterStartupScript

RegisterStartupScript 方法采用与 RegisterClientScriptBlock 方法相同的参数。 向 RegisterStartupScript 注册的脚本在页面加载之后、OnLoad 客户端事件之前执行。 在 1.X 中,注册到 RegisterStartupScript 的脚本放置在结束 </form> 标记之前,而注册到 RegisterClientScriptBlock 的脚本紧接在打开 <的表单> 标记之后。 在 ASP.NET 2.0 中,两者都紧邻 /form> 结束<标记。

注意

如果使用 RegisterStartupScript 注册函数,则在客户端代码中显式调用该函数之前,该函数不会执行。

使用 IsStartupScriptRegistered 方法可确定脚本是否已注册,并避免尝试重新注册脚本。

其他 ClientScriptManager 方法

下面是 ClientScriptManager 类的一些其他有用方法。

GetCallbackEventReference 请参阅本模块前面的脚本回调。
GetPostBackClientHyperlink 获取 javaScript 引用 (javascript:<call>) ,可用于从客户端事件回发。
GetPostBackEventReference 获取可用于从客户端启动回发的字符串。
GetWebResourceUrl 返回嵌入程序集中的资源的 URL。 必须与 RegisterClientScriptResource 一起使用。
RegisterClientScriptResource 向页面注册 Web 资源。 这些资源嵌入到程序集中,并由新的 WebResource.axd 处理程序处理。
RegisterHiddenField 向页面注册隐藏的窗体字段。
RegisterOnSubmitStatement 注册提交 HTML 表单时执行的客户端代码。