指定母版页中的标题、元标记和其他 HTML 标头 (VB)

作者 :Scott Mitchell

下载 PDF

从内容页查看用于在母版页中定义各种 <头> 元素的不同技术。

简介

默认情况下,在 Visual Studio 2008 中创建的新母版页具有两个 ContentPlaceHolder 控件:一个名为 head,位于 元素中 <head> ;一个名为 ContentPlaceHolder1,位于 Web 窗体中。 的用途 ContentPlaceHolder1 是在 Web 窗体中定义可逐页自定义的区域。 ContentPlaceHolder head 使页面能够向节添加自定义内容 <head> 。 (当然,可以修改或删除这两个 ContentPlaceHolder,并且可以将其他 ContentPlaceHolder 添加到母版页。母版页 Site.master目前有四个 ContentPlaceHolder controls.)

HTML <head> 元素用作有关不属于文档本身的网页文档信息的存储库。 这包括网页标题、搜索引擎或内部爬网程序使用的元信息以及指向外部资源(如 RSS 源、JavaScript 和 CSS 文件)的链接等信息。 其中一些信息可能与网站中的所有页面相关。 例如,你可能希望为每个 ASP.NET 页全局导入相同的 CSS 规则和 JavaScript 文件。 但是,元素的某些部分 <head> 特定于页面。 页面标题就是一个主要示例。

本教程介绍如何在母版页及其内容页中定义全局和特定于 <head> 页面的节标记。

检查母版页的<head>

Visual Studio 2008 创建的默认母版页文件在其 <head> 部分中包含以下标记:

<head runat="server">
 <title>Untitled Page</title>
 <asp:ContentPlaceHolder id="head" runat="server">
 </asp:ContentPlaceHolder>
</head>

请注意, <head> 元素包含属性 runat="server" ,该属性指示它是服务器控件 (而不是静态 HTML) 。 所有 ASP.NET 页都派生自 Page位于 命名空间中的 System.Web.UI 类。 此类包含一个 Header 属性 ,该属性提供对页面 <head> 区域的访问权限。 使用 属性, Header 我们可以设置 ASP.NET 页面的标题或向呈现 <head> 的节添加其他标记。 然后,可以通过在页面的 <head> 事件处理程序中编写一些代码来自定义内容页的 Page_Load 元素。 我们将在步骤 1 中了解如何以编程方式设置页面标题。

上述元素中显示的 <head> 标记还包括名为 的 headContentPlaceHolder 控件。 此 ContentPlaceHolder 控件不是必需的,因为内容页可以通过编程方式向 <head> 元素添加自定义内容。 但是,当内容页需要向元素添加静态标记 <head> 时,它很有用,因为静态标记可以声明方式添加到相应的 Content 控件,而不是以编程方式添加。

除了 <title> 元素和 head ContentPlaceHolder 之外,母版页的 <head> 元素还应包含所有页面通用的任何 <head>级别标记。 在我们的网站上,所有页面都使用 文件中定义的 Styles.css CSS 规则。 因此,我们更新 <head>使用母版页创建 Site-Wide 布局 教程中的 元素,以包含相应的 <link> 元素。 母 Site.master 版页的当前 <head> 标记如下所示。

<head runat="server">
 <title>Untitled Page</title>
 <asp:ContentPlaceHolder id="head" runat="server">
 </asp:ContentPlaceHolder>
 <link href="Styles.css" rel="stylesheet" type="text/css" />
</head>

步骤 1:设置内容页的标题

网页的标题通过 <title> 元素指定。 请务必将每个页面的标题设置为适当的值。 访问页面时,其标题将显示在浏览器的标题栏中。 此外,为页面添加书签时,浏览器会将页面的标题用作书签的建议名称。 此外,许多搜索引擎在显示搜索结果时都会显示页面的标题。

注意

默认情况下,Visual Studio 将 <title> 母版页中的 元素设置为“无标题页面”。 同样,新 ASP.NET 页面也 <title> 将其设置为“无标题页面”。 由于很容易忘记将页面标题设置为适当的值,因此 Internet 上有许多标题为“无标题页面”的页面。 在 Google 中搜索具有此标题的网页将返回大约 2,460,000 个结果。 甚至 Microsoft 也容易发布标题为“无标题页面”的网页。 撰写本文时,Google 搜索报告了 Microsoft.com 域中的 236 个此类网页。

ASP.NET 页可以通过以下方式之一指定其标题:

  • 通过将值直接放置在 元素中<title>
  • Title在 指令中使用 <%@ Page %> 特性
  • 使用 或 Page.Header.Title="title"Page.Title="title"代码以编程方式设置页面Title的属性。

内容页没有 <title> 元素,因为它是在母版页中定义的。 因此,若要设置内容页的标题,可以使用 <%@ Page %> 指令的 Title 属性或以编程方式设置它。

以声明方式设置页面的标题

可以通过 指令的 属性以声明方式Title设置内容页的<%@ Page %>标题。 可以通过直接修改 <%@ Page %> 指令或通过属性窗口来设置此属性。 让我们看看这两种方法。

在“源”视图中,找到 <%@ Page %> 位于页面声明性标记顶部的 指令。 的 <%@ Page %>Default.aspx 指令如下所示:

<%@ Page Language="VB" MasterPageFile="~/Site.master" AutoEventWireup="false" CodeFile="Default.aspx.vb" Inherits="_Default" Title="Untitled Page" %>

指令 <%@ Page %> 指定 ASP.NET 引擎在分析和编译页面时使用的特定于页面的属性。 这包括其母版页文件、代码文件的位置、标题等信息。

默认情况下,创建新内容页时,Visual Studio 会将 Title 属性设置为“无标题页面”。 将 Default.aspxTitle 属性从“无标题页面”更改为“母版页教程”,然后通过浏览器查看页面。 图 1 显示了浏览器的标题栏,它反映了新的页面标题。

浏览器的标题栏现在显示“母版页教程”,而不是“无标题页面”

图 01:浏览器的标题栏现在显示“母版页教程”,而不是“无标题页”

也可以从属性窗口设置页面的标题。 从属性窗口,从下拉列表中选择“DOCUMENT”以加载页面级属性,其中包括 Title 属性。 图 2 显示后属性窗口Title已设置为“母版页教程”。

也可以从“属性”窗口配置标题

图 02:也可以从“属性”窗口配置游戏

以编程方式设置页面的标题

当 ASP.NET 引擎呈现母版 <head runat="server"> 页时,母版页的标记将转换为 HtmlHead 实例。 类HtmlHead具有属性Title,其值反映在呈现<title>的元素中。 可以通过 从 ASP.NET 页的代码隐藏类 Page.Header.Title访问此属性;也可以通过 Page.Title访问同一属性。

若要练习以编程方式设置页面标题,请导航到 About.aspx 页面的代码隐藏类,并为页面 Load 的事件创建事件处理程序。 接下来,将页面的标题设置为“母版页教程::关于 :: date”,其中 date 是当前日期。 添加此代码后, Page_Load 事件处理程序应如下所示:

Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
 Page.Title = String.Format("Master Page Tutorials :: About :: {0:d}", DateTime.Now)
End Sub

图 3 显示了访问页面时浏览器的 About.aspx 标题栏。

页面标题以编程方式设置并包含当前日期

图 03:页面标题以编程方式设置并包含当前日期

步骤 2:自动分配页面标题

正如我们在步骤 1 中看到的,页面标题可以通过声明方式或编程方式进行设置。 但是,如果忘记将标题显式更改为更具描述性的内容,则页面将具有默认标题“无标题页面”。 理想情况下,如果未显式指定页面的值,将自动为我们设置页面标题。 例如,如果在运行时页面的标题为“无标题页面”,则我们可能希望将标题自动更新为与 ASP.NET 页的文件名相同。 好消息是,通过一点前期工作,可以自动分配标题。

所有 ASP.NET 网页都派生自 Page System.Web.UI 命名空间中的 类。 类Page定义 ASP.NET 页所需的最小功能,并公开 、、 RequestResponse等基本属性IsPostBackIsValid。 通常,Web 应用程序中的每个页面都需要其他特性或功能。 提供此功能的一种常见方法是创建自定义基页类。 自定义基页类是你创建的类,它派生自 类, Page 并包含其他功能。 创建此基类后,可以将 ASP.NET 页派生自 (Page 而不是类) 派生,从而为 ASP.NET 页提供扩展功能。

在此步骤中,我们将创建一个基页,该基页会自动将页面的标题设置为 ASP.NET 页的文件名(如果标题尚未显式设置)。 步骤 3 查看基于站点地图设置页面标题。

注意

有关创建和使用自定义基页类的彻底检查超出了本教程系列的范围。

创建基页类

我们的第一个任务是创建基页类,该类是扩展类的 Page 类。 首先,App_Code在解决方案资源管理器中右键单击项目名称,选择“添加 ASP.NET 文件夹”,然后选择 App_Code将文件夹添加到项目。 接下来,右键单击 App_Code 文件夹并添加名为 BasePage.vb的新类。 图 4 显示了添加文件夹和BasePage.vb类后App_Code解决方案资源管理器。

添加App_Code文件夹和名为 BasePage 的类

图 04:添加 App_Code 文件夹和名为 的类 BasePage

注意

Visual Studio 支持两种项目管理模式:网站项目和 Web 应用程序项目。 文件夹 App_Code 设计为与网站项目模型一起使用。 如果使用 Web 应用程序项目模型,请将 BasePage.vb 类放在名为 的 App_Code文件夹中,而不是 ,例如 Classes。 有关本主题的详细信息,请参阅 将网站项目迁移到 Web 应用程序项目

由于自定义基页充当 ASP.NET 页代码隐藏类的基类,因此需要扩展类 Page

Public Class BasePage
 Inherits System.Web.UI.Page

End Class

每当请求 ASP.NET 页时,它都将继续执行一系列阶段,最终请求的页面呈现为 HTML。 我们可以通过重写 Page 类的 OnEvent 方法进入阶段。 对于我们的基页,如果阶段 (未显式指定 LoadComplete 标题,我们会自动设置标题,正如你可能猜到的那样,在阶段) 之后 Load 发生。

若要完成此操作,请重写 OnLoadComplete 方法并输入以下代码:

Protected Overrides Sub OnLoadComplete(ByVal e As EventArgs)
 ' Set the page's title, if necessary
 If String.IsNullOrEmpty(Page.Title) OrElse Page.Title = "Untitled Page" Then
 ' Determine the filename for this page
 Dim fileName As String = System.IO.Path.GetFileNameWithoutExtension(Request.PhysicalPath)

 Page.Title = fileName
 End If

 MyBase.OnLoadComplete(e)
End Sub

方法 OnLoadComplete 首先确定属性是否 Title 尚未显式设置。 Title如果 属性为 Nothing、空字符串或具有值“无标题页”,则将其分配给所请求 ASP.NET 页的文件名。 请求 ASP.NET 页的物理路径( C:\MySites\Tutorial03\Login.aspx例如 )可通过 Request.PhysicalPath 属性访问。 方法 Path.GetFileNameWithoutExtension 用于仅提取文件名部分,然后将此文件名分配给 Page.Title 属性。

注意

我邀请你增强此逻辑,以改进标题的格式。 例如,如果页面的文件名为 Company-Products.aspx,则上述代码将生成标题“Company-Products”,但理想情况下,短划线将替换为空格,如“公司产品”中所示。 此外,请考虑在大小写发生更改时添加空格。 也就是说,请考虑添加将文件名 OurBusinessHours.aspx 转换为标题“我们的工作时间”的代码。

让内容页继承基页类

我们现在需要更新站点中的 ASP.NET 页,以派生自自定义基页 (BasePage) 而不是 Page 类。 若要完成此操作,请转到每个代码隐藏类,并从以下项更改类声明:

Partial Class About
 Inherits System.Web.UI.Page
   ...
End Class

到:

Partial Class About
 Inherits BasePage
   ...
End Class

执行此操作后,请通过浏览器访问站点。 如果访问其标题已显式设置的页面,例如 Default.aspxAbout.aspx,则使用显式指定的标题。 但是,如果访问其标题未从默认 (“无标题页面”) 更改的页面,则基页类会将标题设置为页面的文件名。

图 5 显示了 MultipleContentPlaceHolders.aspx 通过浏览器查看时的页面。 请注意,标题正是页面的文件名, (少扩展名) “MultipleContentPlaceHolders”。

如果未显式指定标题,则会自动使用页面的文件名

图 05:如果未显式指定标题,则会自动使用页面的文件名 (单击以查看全尺寸图像)

步骤 3:基于网站地图上的页面标题

ASP.NET 提供了一个可靠的站点地图框架,使页面开发人员能够在外部资源 ((如 XML 文件或数据库表) )中定义分层站点地图,以及用于显示站点地图 ((如 SiteMapPath、Menu 和 TreeView 控件)) 的信息的 Web 控件。

也可以通过 ASP.NET 页的代码隐藏类以编程方式访问站点地图结构。 通过这种方式,我们可以将页面的标题自动设置为站点地图中相应节点的标题。 让我们增强在步骤 2 中创建的 BasePage 类,使其提供此功能。 但首先,我们需要为站点创建站点地图。

注意

本教程假定读者已熟悉 ASP。NET 的站点地图功能。 有关使用站点地图的详细信息,请参阅我的多部分文章系列 检查 ASP。NET 的站点导航

创建站点地图

站点地图系统构建在 提供程序模型之上,该模型将站点地图 API 与在内存和永久性存储之间序列化站点地图信息的逻辑分离。 .NET Framework随 类一起XmlSiteMapProvider提供,类是默认的站点地图提供程序。 顾名思义, XmlSiteMapProvider 使用 XML 文件作为其站点地图存储。 让我们使用此提供程序来定义站点地图。

首先在网站的根文件夹中创建名为 Web.sitemap的站点地图文件。 若要完成此操作,请在 解决方案资源管理器 中右键单击网站名称,选择“添加新项”,然后选择“网站地图”模板。 确保文件已命名 Web.sitemap ,然后单击“添加”。

将名为 Web.sitemap 的文件添加到网站的根文件夹

图 06:将名为 Web.sitemap 的文件添加到网站的根文件夹 (单击以查看全尺寸图像)

将以下 XML 添加到 Web.sitemap 文件:

<?xml version="1.0" encoding="utf-8" ?>
<siteMap xmlns="http://schemas.microsoft.com/AspNet/SiteMap-File-1.0" >
 <siteMapNode url="~/Default.aspx" title="Home">
 <siteMapNode url="~/About.aspx" title="About the Author" />
 <siteMapNode url="~/MultipleContentPlaceHolders.aspx" title="Using Multiple ContentPlaceHolder Controls" />
 </siteMapNode>
</siteMap>

此 XML 定义分层站点地图结构,如图 7 所示。

站点地图当前由三个站点地图节点组成

图 07:站点地图当前由三个站点地图节点组成

我们将在将来的教程中更新站点地图结构,因为我们添加新的示例。

更新母版页以包括导航 Web 控件

定义站点地图后,让我们更新母版页以包含导航 Web 控件。 具体而言,让我们将 ListView 控件添加到 Lessons 部分中的左列,该控件呈现一个无序列表,其中包含站点地图中定义的每个节点的列表项。

注意

ListView 控件是新 ASP.NET 版本 3.5。 如果使用早期版本的 ASP.NET,请改用 Repeater 控件。

首先从“课程”部分删除现有的无序列表标记。 接下来,从“工具箱”中拖动 ListView 控件,并将其拖放到“课程”标题下。 ListView 位于工具箱的“数据”部分,以及其他视图控件:GridView、DetailsView 和 FormView。 将 ListView 的 ID 属性设置为 LessonsList

在数据源配置向导中,选择将 ListView 绑定到名为 LessonsDataSource的新 SiteMapDataSource 控件。 SiteMapDataSource 控件从站点地图系统返回分层结构。

将 SiteMapDataSource 控件绑定到 LessonsList ListView 控件

图 08:将 SiteMapDataSource 控件绑定到 LessonsList ListView 控件 (单击以查看全尺寸图像)

创建 SiteMapDataSource 控件后,我们需要定义 ListView 的模板,以便它呈现一个无序列表,其中包含 SiteMapDataSource 控件返回的每个节点的列表项。 这可以通过以下模板标记来实现:

<asp:ListView ID="LessonsList" runat="server" DataSourceID="LessonsDataSource">
 <LayoutTemplate>
 <ul>
 <asp:PlaceHolder runat="server" ID="itemPlaceholder" />
 </ul>
 </LayoutTemplate>
 
 <ItemTemplate>
 <li><asp:HyperLink runat="server" ID="lnkLesson" NavigateUrl='<%# Eval("Url") %>'
 Text='<%# Eval("Title") %>' /></li>
 </ItemTemplate>
</asp:ListView>

生成 LayoutTemplate 无序列表 (<ul>...</ul>) 标记,而 ItemTemplate 将 SiteMapDataSource 返回的每个项呈现为列表项, (<li> 包含指向特定课程的链接) 。

配置 ListView 的模板后,请访问网站。 如图 9 所示,“课程”部分包含单个项目符号项目“主页”。 关于和使用多个 ContentPlaceHolder 控件课程在哪里? SiteMapDataSource 旨在返回一组分层数据,但 ListView 控件只能显示层次结构的单个级别。 因此,仅显示 SiteMapDataSource 返回的第一级站点地图节点。

课程部分包含单个列表项

图 09:“课程”部分包含单个列表项 (单击以查看全尺寸图像)

若要显示多个级别,可以在 中 ItemTemplate嵌套多个 ListView。 我的“使用数据”教程系列中的母版页和网站导航教程中介绍了此方法。 但是,对于本教程系列,我们的站点地图仅包含两个级别:主页 (顶级) ;和每个课程作为家庭的孩子。 我们可以指示 SiteMapDataSource 不返回起始节点,而不是创建嵌套的 ListView,方法是将其 ShowStartingNode 属性 设置为 False。 净效果是 SiteMapDataSource 从返回第二层站点地图节点开始。

通过此更改,ListView 会显示“关于”和“使用多个 ContentPlaceHolder 控件”课程的项目符号项,但省略“主页”的项目符号项。 若要解决此问题,我们可以在 中 LayoutTemplate为 Home 显式添加项目符号项:

<LayoutTemplate>
 <ul>
 <li><asp:HyperLink runat="server" ID="lnkLesson"
 NavigateUrl="~/Default.aspx" Text="Home" /></li>
 <asp:PlaceHolder runat="server" ID="itemPlaceholder" />
 </ul>
</LayoutTemplate>

通过将 SiteMapDataSource 配置为省略起始节点并显式添加主页项目符号项,“课程”部分现在会显示预期输出。

课程部分包含主页和每个子节点的项目符号项

图 10:“课程”部分包含“主页”和“每个子节点”的项目符号项 (单击以查看全尺寸图像)

基于站点地图设置标题

在站点地图就位后,我们可以更新类 BasePage 以使用站点地图中指定的标题。 正如我们在步骤 2 中所做的那样,如果页面的标题尚未由页面开发人员显式设置,我们只想使用站点地图节点的标题。 如果请求的页面没有显式设置的页面标题,并且未在网站地图中找到,则我们将回退到使用所请求页面的文件名 (减少扩展名) ,如步骤 2 中所做的那样。 图 11 演示了此决策过程。

在没有显式设置页面标题的情况下,将使用相应的站点地图节点的标题

图 11:在没有显式设置页面标题的情况下,使用了相应的站点地图节点的标题

更新 BasePage 类的 OnLoadComplete 方法以包含以下代码:

Protected Overrides Sub OnLoadComplete(ByVal e As EventArgs)
 ' Set the page's title, if necessary
 If String.IsNullOrEmpty(Page.Title) OrElse Page.Title = "Untitled Page" Then
 ' Is this page defined in the site map?
 Dim newTitle As String = Nothing

 Dim current As SiteMapNode = SiteMap.CurrentNode
 If current IsNot Nothing Then
 newTitle = current.Title
 Else
 ' Determine the filename for this page
 newTitle = System.IO.Path.GetFileNameWithoutExtension(Request.PhysicalPath)
 End If

 Page.Title = newTitle
 End If

 MyBase.OnLoadComplete(e)
End Sub

与之前一样, OnLoadComplete 方法首先确定是否已显式设置页面的标题。 如果 Page.TitleNothing、空字符串或 分配了值“无标题页面”,则代码会自动将值分配给 Page.Title

为了确定要使用的标题,代码首先引用 SiteMapCurrentNode 属性CurrentNode 返回 SiteMapNode 与当前请求的页面相对应的站点地图中的 实例。 假设当前请求的页面位于站点地图中,则会 SiteMapNode将 的 Title 属性分配给页面的标题。 如果当前请求的页面不在站点地图中,则 Nothing 返回 ,CurrentNode并且所请求页面的文件名用作标题 (,如步骤 2) 中所做的那样。

图 12 显示了 MultipleContentPlaceHolders.aspx 通过浏览器查看时的页面。 由于未显式设置此页面的标题,因此将改用其相应的站点地图节点的标题。

从站点地图拉取MultipleContentPlaceHolders.aspx页面标题

图 12:从网站地图拉取MultipleContentPlaceHolders.aspx页面标题

步骤 4:将其他 Page-Specific 标记添加到<head>分区

步骤 1、2 和 3 介绍了如何逐页自定义 <title> 元素。 除了 <title>之外, <head> 节还可能包含 <meta> 元素和 <link> 元素。 如本教程前面所述, Site.master部分<head>包含 <link> 元素。Styles.css 由于此 <link> 元素是在母版页中定义的,因此它包含在所有内容页的 节中 <head> 。 但是,如何逐页添加 <meta><link> 元素呢?

向节添加特定于页面的内容 <head> 的最简单方法是在母版页中创建 ContentPlaceHolder 控件。 我们已拥有名为) 的 ContentPlaceHolder (head 。 因此,若要添加自定义 <head> 标记,请在页面中创建相应的 Content 控件,并将标记放在其中。

为了说明如何向页面添加自定义 <head> 标记,让我们将说明元素添加到 <meta> 当前内容页集。 description <meta> 元素提供有关网页的简要说明;大多数搜索引擎在显示搜索结果时以某种形式合并此信息。

<meta> description 元素具有以下形式:

<meta name="description" content="description of the web page" />

若要将此标记添加到内容页,请将上述文本添加到映射到母版页的 ContentPlaceHolder 的 head Content 控件。 例如,若要为 Default.aspx定义 <meta> description 元素,请添加以下标记:

<asp:Content ID="Content1" ContentPlaceHolderID="head" Runat="Server">
 <meta name="description" content="Welcome to Scott Mitchell's Master Page Tutorials series." />
</asp:Content>

head由于 ContentPlaceHolder 不在 HTML 页面的正文中,因此添加到 Content 控件的标记不会显示在“设计”视图中。 若要查看 description 元素, <meta> 请访问 Default.aspx 通过浏览器。 加载页面后,查看源并注意节 <head> 包含 Content 控件中指定的标记。

花点时间将说明元素添加到 <meta>About.aspxMultipleContentPlaceHolders.aspxLogin.aspx

以编程方式将<head>标记添加到区域

ContentPlaceHolder head 允许我们以声明方式将自定义标记添加到母版页的区域 <head> 。 还可以以编程方式添加自定义标记。 回想一下, Page 类的 Header 属性返回 HtmlHead 母版页中定义的实例 (<head runat="server">) 。

当要添加的内容是动态的时, <head> 能够以编程方式将内容添加到区域非常有用。 也许它基于访问页面的用户;可能是从数据库拉取的。 无论原因如何,都可以通过将控件添加到 其Controls集合来添加内容HtmlHead,如下所示:

' Programmatically add a <meta> element to the Header
Dim keywords As New HtmlMeta()
keywords.Name = "keywords"
keywords.Content = "master page,asp.net,tutorial"

Page.Header.Controls.Add(keywords)

上面的代码将 <meta> keywords 元素添加到 <head> 区域,该区域提供一个以逗号分隔的关键字列表来描述页面。 请注意,若要添加标记, <meta> 请创建一个 HtmlMeta 实例,设置其 NameContent 属性,然后将其添加到 HeaderControls 集合。 同样,若要以编程方式添加 <link> 元素,请创建 对象 HtmlLink ,设置其属性,然后将其添加到 HeaderControls 集合。

注意

若要添加任意标记,请创建 实例 LiteralControl ,设置其 Text 属性,然后将其添加到 HeaderControls 集合。

总结

在本教程中,我们了解了按页添加 <head> 区域标记的各种方法。 母版页应包含具有 HtmlHead ContentPlaceHolder 的实例 (<head runat="server">) 。 实例 HtmlHead 允许内容页以编程方式访问 <head> 区域,以及以声明方式和编程方式设置页面的标题;ContentPlaceHolder 控件允许通过 Content 控件以声明方式将自定义标记添加到 <head> 节中。

编程愉快!

深入阅读

有关本教程中讨论的主题的详细信息,请参阅以下资源:

关于作者

Scott Mitchell 是多本 ASP/ASP.NET 书籍的作者,4GuysFromRolla.com 的创始人,自 1998 年以来一直从事 Microsoft Web 技术工作。 Scott 担任独立顾问、培训师和作家。 他的最新书是 山姆自学 ASP.NET 在24小时内3.5。 可在 上或通过他的博客http://ScottOnWriting.NET联系 mitchell@4GuysFromRolla.com Scott。

特别感谢

本教程系列由许多有用的审阅者查看。 本教程的主要审阅者是 Zack Jones 和 Suchi Banerjee。 有兴趣查看我即将发布的 MSDN 文章? 如果是,请在 处放置一行 mitchell@4GuysFromRolla.com