预编译网站 (C#)

作者 :Scott Mitchell

Visual Studio ASP.NET 为开发人员提供了两种类型的项目:Web 应用程序项目 (WAP) 和网站项目 (WSP) 。 这两个项目类型之间的主要区别之一是,WAP 必须在部署之前显式编译代码,而 WSP 中的代码可以在 Web 服务器上自动编译。 但是,在部署之前,可以预编译 WSP。 本教程探讨预编译的优点,并演示如何从 Visual Studio 和命令行预编译网站。

简介

Visual Studio ASP.NET 为开发人员提供了两种不同的项目类型:Web 应用程序项目 (WAP) 和网站项目 (WSP) 。 这些项目类型之间的主要区别之一是,WAP 需要 显式编译 ,而 WSP 默认使用 自动编译。 使用 WAP,可以将 Web 应用程序的代码编译为在网站 Bin 文件夹中创建的单个程序集。 部署需要复制项目 (.aspx.ascx标记内容以及 .master 项目中) 的文件以及文件夹中的 Bin 程序集;无需部署代码隐藏类文件本身。 另一方面,通过将标记页及其相应的代码隐藏类复制到生产环境来部署 WSP。 代码隐藏类在 Web 服务器上按需编译。

注意

请参阅“确定需要部署哪些文件”教程中的“显式编译与自动编译”部分,了解项目模型之间的差异、显式编译和自动编译以及编译模型如何影响部署。

自动编译选项易于使用。 没有显式编译步骤,只需要部署修改的文件,而显式编译需要部署更改的标记页和刚刚编译的程序集。 但是,自动部署有两个潜在缺点:

  • 由于首次访问页面时必须自动编译这些页面,因此在部署后首次请求 ASP.NET 页面时,可能会有短暂但明显的延迟。
  • 自动编译要求 Web 服务器上同时存在声明性标记和源代码。 如果计划向将 Web 应用程序安装在 Web 服务器上的客户销售 Web 应用程序,则此选项可能是一个无吸引力选项。

如果上述两个缺点之一是交易中断程序,则可以在部署之前切换到 WAP 模型或 预编译 WSP。 本教程介绍最适合托管网站的预编译选项,并演练预编译过程和预编译网站的部署。

ASP.NET 代码生成和编译概述

在查看可用的预编译选项之前,让我们先讨论自创建或上次更新时间以来首次请求 ASP.NET 页面时发生的代码生成和编译。 如你所知,ASP.NET 页面由两个部分组成:文件中的声明性标记 .aspx ;源代码部分(通常位于单独的代码隐藏类文件中), (.aspx.cs) 。 请求 ASP.NET 页时运行时执行的步骤取决于应用程序的编译模型。

使用 WAP 时,必须先将页面的源代码显式编译为单个程序集,然后才能进行部署。 在部署期间,此程序集和各种标记页将复制到生产环境。 当请求到达 web 服务器进行 ASP.NET 页面时,运行时将创建页面代码隐藏类的实例并调用其 ProcessRequest 方法,该方法启动页面生命周期,并最终生成页面的内容,该内容将返回到请求者。 运行时可以使用 ASP.NET 页的代码隐藏类,因为代码隐藏类已在部署前编译为程序集。

使用 WSP 和自动编译,部署前没有显式编译步骤。 相反,部署涉及将声明性和源代码内容复制到生产环境。 当请求自创建或上次更新页面以来第一次到达 Web 服务器 ASP.NET 时,运行时必须首先将代码隐藏类编译为程序集。 此编译的程序集保存在文件夹中%WINDIR%\Microsoft.NET\Framework\v2.0.50727\Temporary ASP.NET Files,尽管此文件夹的位置可以通过通常位于Web.config的元素<system.web>自定义<compilation tempDirectory="" />。 由于程序集保存到磁盘,因此无需在后续请求中重新编译到同一页。

注意

正如预期的那样,首次 (请求页面或首次请求页面时会稍有延迟,因为该页面在站点中) 更改,因为服务器编译页面的代码需要一些时间,并将生成的程序集保存到磁盘。

简言之,使用显式编译,需要在部署之前编译网站的源代码,从而节省运行时执行此步骤。 通过自动编译,运行时会处理页面源代码的编译,但自创建页面或上次更新后首次访问页面时,会略有初始化成本。

但是,ASP.NET 页面 .aspx 的声明性部分 (文件) 呢? 很明显,文件与代码隐藏类中的代码之间存在 .aspx 关系,因为代码中定义的 Web 控件在代码中是可访问的。 此外,文件中的内容 .aspx 也显著影响页面生成的呈现标记。 那么运行时如何处理文件中定义的 .aspx 文本、HTML 和 Web 控件语法,以生成请求的页面呈现的内容?

我不想在低级别实现详细信息上过于旁观,这在 WAP 和 WSP 之间有所不同,但简言之,运行时会自动生成一个类文件,其中包含作为受保护成员和方法的各种 Web 控件。 此生成的文件作为 分部类 实现到相应的代码隐藏类。 (分部类 允许将单个类的内容分散到多个 files.) 因此,代码隐藏类在两个位置定义: .aspx.cs 在创建的文件中,以及运行时创建的此自动生成的类中。 此自动生成的类存储在 %WINDIR%\Microsoft.NET\Framework\v2.0.50727\Temporary ASP.NET Files 文件夹中。

此处的重要要点是,运行时要呈现 ASP.NET 页面,其声明性部分和源代码部分都必须编译为程序集。 使用 WAP 时,源代码在部署前显式编译为程序集,但声明性标记仍必须转换为代码,并由 Web 服务器上的运行时编译。 使用自动编译的 WSP 时,Web 服务器需要编译源代码和声明性标记。

可以将显式编译与 WSP 模型配合使用。 可以显式编译源代码部分,例如 WAP 模型。 此外,还可以编译声明性标记。

预编译选项

.NET Framework附带了一个 ASP.NET 编译工具 (aspnet_compiler.exe) ,使你可以编译源代码 (,甚至是使用 WSP 模型生成的 ASP.NET 应用程序的内容) 。 此工具随 .NET Framework 版本 2.0 一起发布,位于%WINDIR%\Microsoft.NET\Framework\v2.0.50727文件夹中;可通过“生成”菜单的“发布网站”选项从命令行使用或从 Visual Studio 中启动该工具。

编译工具提供两种常规形式的编译:就地预编译和预编译进行部署。 使用就地预编译,可以从命令行运行 aspnet_compiler.exe 该工具,并指定驻留在计算机上的网站虚拟目录或物理路径的路径。 然后,编译工具在项目中编译每个 ASP.NET 页,将编译的版本 %WINDIR%\Microsoft.NET\Framework\v2.0.50727\Temporary ASP.NET Files 存储在文件夹中,就像从浏览器首次访问页面一样。 就地预编译可以加快对站点上新部署的 ASP.NET 页面发出的第一个请求,因为它可以缓解运行时需要执行此步骤。 但是,就地预编译对大多数托管网站并不有用,因为它要求你能够从 Web 服务器的命令行运行程序。 在共享托管环境中,不允许此级别的访问。

注意

有关就地预编译的详细信息,请查看如何:ASP.NET 2.0 中的预编译 ASP.NET 网站和预编译。

部署预编译页面而不是将网站中的页面编译到 Temporary ASP.NET Files 文件夹中,而是将页面编译到所选目录,并且采用可部署到生产环境的格式。

本教程介绍的部署有两种预编译风格:使用可更新的用户界面进行预编译,以及使用不可更新的用户界面预编译。 使用可更新的用户界面进行预编译会留下声明性标记和.aspx.ascx.master文件,从而使开发人员能够在生产服务器上查看声明性标记,并根据需要修改声明性标记。 使用不可更新的用户界面预编译会 .aspx 生成任何内容和删除 .ascx.master 文件的空白页面,从而隐藏声明性标记,并禁止开发人员从生产环境更改它。

使用可更新用户界面预编译部署

了解预编译部署的最佳方法是查看一个操作示例。 让我们预编译 Book Reviews WSP,以便使用可更新的用户界面进行部署。 可以从 Visual Studio 的“生成”菜单或命令行调用 ASP.NET 编译工具。 本部分介绍在 Visual Studio 中使用该工具;“从命令行预编译”部分查看从命令行运行编译器工具。

在 Visual Studio 中打开 Book Review WSP,转到“生成”菜单,然后选择“发布网站”菜单选项。 这会启动“发布网站”对话框, (请参阅 图 1) ,可在其中指定目标位置、预编译站点的用户界面是否可更新以及其他编译器工具选项。 目标位置可以是远程 Web 服务器或 FTP 服务器,但现在请选择计算机上的硬盘驱动器上的文件夹。 由于我们希望使用可更新的用户界面预编译站点,因此请选中“允许此预编译站点可更新”复选框,然后单击“确定”。

“发布网站”对话框的屏幕截图,用于指定目标位置。

图 1:ASP.NET 编译工具将网站预编译到指定的目标位置
(单击以查看全尺寸图像)

注意

“生成”菜单中的“发布网站”选项在 Visual Web Developer 中不可用。 如果使用 Visual Web 开发人员,则需要使用 ASP.NET 编译工具的命令行版本,该工具在“命令行预编译”部分中进行了介绍。

预编译网站后,导航到在“发布网站”对话框中输入的目标位置。 请花点时间将此文件夹的内容与网站的内容进行比较。 图 2 显示了“书籍评论”网站文件夹。 请注意,它包含文件和.aspx.aspx.cs文件。 另请注意,该Bin目录仅包含一个文件,Elmah.dll我们在前面的教程中添加了该文件

在“发布网站”对话框中输入的目标位置的屏幕截图,用于将此文件夹的内容与网站的内容进行比较。

图 2:项目目录包含 .aspx.aspx.cs 文件; Bin 文件夹仅包含 Elmah.dll
(单击以查看全尺寸图像)

图 3 显示了由 ASP.NET 编译工具创建其内容的目标位置文件夹。 此文件夹不包含任何代码隐藏文件。 此外,此文件夹的 Bin 目录还包括多个程序集和两 .compiled 个文件,以及 Elmah.dll 程序集。

其内容由 A S P 创建的目标位置文件夹的屏幕截图。N E T 编译工具。

图 3:目标位置文件夹包括用于部署的文件
(单击以查看全尺寸图像)

与 WAP 中的显式编译不同,部署过程的预编译不会为整个站点创建一个程序集。 相反,它会将多个页面一起批处理到每个程序集中。 它还会将文件编译为 ((如果存在) )并将其编译 Global.asax 为自己的程序集,以及文件夹中的任何类 App_Code 。 保存 ASP.NET 网页、用户控件和母版页的声明性标记的文件 (.aspx.ascx.master文件分别) 按原样复制到目标位置目录。 同样,文件 Web.config 将直接复制,以及图像、CSS 类和 PDF 文件等任何静态文件。 有关编译工具如何处理各种文件类型的更正式说明,请参阅 ASP.NET 预编译期间的文件处理

注意

可以通过选中“发布网站”对话框中的“已用固定命名和单页程序集”复选框,指示编译工具为每个 ASP.NET 页、用户控件或母版页创建一个程序集。 将每个 ASP.NET 页编译到其自己的程序集后,可以更精细地控制部署。 例如,如果更新了单个 ASP.NET 网页,并且需要部署该更改,则只需将页面 .aspx 的文件和关联的程序集部署到生产环境。 有关详细信息 ,请参阅如何:使用 ASP.NET 编译工具生成固定名称

目标位置目录还包含不是预编译 Web 项目的一部分的文件,即 PrecompiledApp.config。 此文件通知 ASP.NET 运行时应用程序已预编译,以及应用程序是使用可更新的 UI 还是可更新的 UI 进行预编译。

最后,请花点时间使用 Visual Studio 或所选文本编辑器在目标位置打开其中 .aspx 一个文件。 使用可更新的用户界面预编译部署时,目标位置目录中 ASP.NET 页包含与网站中相应文件的完全相同标记。

使用不可更新的用户界面预编译部署

ASP.NET 编译器工具还可用于预编译站点,以便使用不可更新的 UI 进行部署。 使用不可更新的 UI 预编译网站的工作方式与使用可更新 UI 进行预编译类似,主要区别在于目标目录中的 ASP.NET 页、用户控件和母版页被去除其标记。 若要预编译网站以使用不可更新的 UI 进行部署,请从“生成”菜单中选择“发布网站”选项,但取消选中“允许此预编译网站可更新”选项, (请参阅 图 4) 。

“发布网站”选项的屏幕截图,从“生成”菜单预编译网站以使用不可更新的用户界面进行部署。

图 4:取消选中“允许此预编译站点可更新”选项,以使用不可更新的 UI 进行预编译
(单击以查看全尺寸图像)

图 5 显示了使用不可更新的用户界面预编译后的目标位置文件夹。

使用不可更新的用户界面进行预编译后的目标位置文件夹的屏幕截图。

图 5:使用不可更新 UI 进行部署的目标位置文件夹
(单击以查看全尺寸图像)

比较 图 3图 5。 虽然这两个文件夹可能看起来完全相同,但请注意,不可更新的 UI 文件夹缺少母版页。 Site.master 虽然 图 5 包含各种 ASP.NET 页面,但如果查看这些文件的内容,则会看到它们已被去除其声明性标记并替换为占位符文本:“这是预编译工具生成的标记文件,不应删除!

A S P 的屏幕截图。取消声明性标记并替换为占位符文本的 N E T 文件。

图 5:声明性标记已从 ASP.NET 页中删除

Bin图 35 中的文件夹具有更大的差异。 除了程序集,Bin图 5 中的文件夹还包括每个 .compiled ASP.NET 页、用户控件和母版页的文件。

如果不希望在生产环境中安装或管理网站的人员或公司修改 ASP.NET 页面的内容,则使用不可更新的 UI 预编译网站非常有用。 如果你构建了一个 ASP.NET 向客户销售的 Web 应用程序以在其自己的 Web 服务器上安装,你可能希望确保他们不会通过直接编辑 .aspx 寄送的页面来修改网站的外观。 通过将网站预编译为不可更新的 UI,可以将占位符 .aspx 页作为安装的一部分交付,从而阻止客户检查或修改其内容。

从命令行预编译

在后台,Visual Studio 的“发布网站”对话框调用 ASP.NET 编译工具, (aspnet_compiler.exe) 预编译网站。 或者,可以从命令行调用此工具。 事实上,如果使用 Visual Web Developer,则需要从命令行运行编译器工具,因为 Visual Web 开发人员的“生成”菜单不包括“发布网站”选项。

若要从命令行使用编译器工具,请首先删除到命令行并导航到框架目录 %WINDIR%\Microsoft.NET\Framework\v2.0.50727。 接下来,在命令行中输入以下语句:

aspnet_compiler -p "physical_path_to_app" -v / -f -u "target_location_folder"

上述命令启动 ASP.NET 编译器工具 (aspnet_compiler.exe) ,并通过 -p 开关指示它预编译根于 physical_path_to_app的网站;此值将类似 C:\MySites\BookReviews,应用引号分隔。

-v 开关指定站点的虚拟目录。 如果站点注册为 IIS 元数据库中的默认网站,则可以省略 -p 交换机,只需指定应用程序的虚拟目录即可。 如果使用 -p 开关,则继续切换的值 -v 指示网站的根目录,并用于解析应用程序根引用。 例如,如果指定一个值 -v /MySite ,则应用程序中要 ~/path/file 解析为 ~/MySite/path/file引用的值。 因为书籍评论网站位于我的 Web 托管公司的根目录,我使用了开关 -v /

如果存在,则 -f 开关指示编译工具覆盖 target_location_folder 目录(如果已存在)。 如果省略 -f 开关并且目标位置文件夹已存在,编译工具将退出并显示错误:“错误 ASPRUNTIME:目标目录不为空。 请手动删除它或选择其他目标。

开关 -u (如果存在)会通知工具创建可更新的用户界面。 省略此开关以使用不可更新的用户界面预编译站点。

最后, target_location_folder 是目标位置目录的物理路径;此值将类似 C:\MySites\Output\BookReviews,应用引号分隔。

部署预编译网站

此时,我们已了解如何使用 ASP.NET 编译工具使用可更新和不可更新的用户界面选项预编译网站。 但是,到目前为止,我们的示例已将网站预编译到本地文件夹,而不是编译到生产环境。 好消息是,部署预编译的网站是一种轻而易举的,可以通过 Visual Studio 或其他文件复制机制(例如来自独立 FTP 客户端)来完成。

“发布网站”对话框 (图 1 中首先显示) 具有目标位置选项,该选项指示预编译的网站文件复制到的位置。 此位置可以是远程 Web 服务器或 FTP 服务器。 在此文本框中输入远程服务器预编译,并在一个步骤中将网站部署到指定的服务器。 或者,你可以将网站预编译到本地文件夹,然后通过 FTP 或其他方法手动将该文件夹的内容复制到生产环境。

通过 Visual Studio 的“发布网站”对话框自动部署预编译网站对于在开发和生产环境之间没有配置差异的简单网站非常有用。 但是,如开发和生产教程中的常见配置差异中所述,存在此类差异并不罕见。 例如,Book Reviews Web 应用程序在生产环境中使用不同于开发环境中的数据库。 当 Visual Studio 将网站发布到远程服务器时,它会盲目复制开发环境中的配置文件信息。

对于开发环境与生产环境之间存在配置差异的站点,最好将站点预编译到本地目录,复制生产特定的配置文件,然后将预编译输出的内容复制到生产环境中。

有关将文件从开发环境复制到生产环境的刷新程序,请参阅 使用 FTP 客户端部署网站 并使用 Visual Studio 部署网站 教程。

摘要

ASP.NET 支持两种编译模式:自动和显式。 如前面的教程中所述,默认情况下,Web 应用程序项目 (WAP) 使用显式编译,而网站项目 (WSP) 使用自动编译。 但是,可以使用 ASP.NET 编译工具在部署之前显式编译 WSP。

本教程重点介绍编译工具的预编译部署支持。 预编译部署时,编译工具将创建目标位置文件夹,编译指定的 Web 应用程序的源代码,并将这些编译的程序集和内容文件复制到目标位置文件夹中。 编译工具可配置为创建可更新或不可更新的用户界面。 使用不可更新的用户界面选项预编译时,将删除内容文件中的声明性标记。 简言之,预编译允许部署基于网站 Project 的应用程序,而无需包括任何源代码文件和删除声明性标记(如果需要)。

快乐编程!

深入阅读

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