ASP.NET 预编译概述
更新:2007 年 11 月
ASP.NET 可以预编译网站,然后再将其提供给用户。这样做有很多优点,包括缩短响应时间、执行错误检查、保护源代码以及提高部署效率。
此外,还可以使用 Web 应用程序项目模型编译项目。项目中的所有代码文件(独立文件、代码隐藏文件以及类文件)将被编译成单个程序集并存储在 Bin 目录中。由于编译会创建单个程序集,因此可以指定程序集名称和版本等属性。如果不想将输出程序集保存在 Bin 目录中,则也可以为其指定另一个位置。有关更多信息,请参见编译 Web 应用程序项目。
本主题包括:
方案
预编译功能
背景
代码示例
功能
预编译 ASP.NET 网站具有下列优点:
由于页和代码文件在第一次被请求时无需编译,因此可以缩短对用户的响应时间。这对于更新频繁的大型网站尤为有用。
可以在用户看到网站之前识别编译时的 Bug。
可以创建站点的已编译版本,并将该版本部署到成品服务器,而无需使用源代码。
返回页首
背景
默认情况下,在用户首次请求资源(如网站的一个页)时,将动态编译 ASP.NET 网页和代码文件。在首次编译页和代码文件后,将缓存已编译的资源。这样,对相同页的后续请求将十分有效。
ASP.NET 还可以预编译整个网站,然后再将其提供给用户。ASP.NET 提供了下列网站预编译选项:
预编译现有站点。如果您希望提高现有站点的性能并对站点执行错误检查,那么此选项十分有用。
针对部署预编译站点。此选项将创建一个特殊的输出,您可以将该输出部署到成品服务器。
另外,可以预编译一个站点,使它成为只读的或可以更新的站点。以下部分提供了有关每个选项的更多详细信息。
就地预编译
通过预编译网站,可在一定程度上提高网站的性能。这对于经常更改和补充 ASP.NET 网页及代码文件的网站则更是如此。在内容不固定的网站中,动态编译新增页和更改页所需的额外时间会影响用户对网站质量的感受。
就地预编译网站可以有效执行用户在请求网页时所发生的编译过程。因此,主要的性能改进在于在第一次请求页时无需对该页进行编译。
在执行就地预编译时,将编译所有 ASP.NET 文件类型。(HTML 文件、图形和其他非 ASP.NET 静态文件将保持原状。)预编译过程的逻辑与 ASP.NET 进行动态编译时所用的逻辑相同,说明了文件之间的依赖关系。在预编译过程中,编译器将为所有可执行输出创建程序集,并将它们放置在 %SystemRoot%\Microsoft.NET\Framework\版本\Temporary ASP.NET Files 文件夹下的特殊文件夹中。随后,ASP.NET 将通过此文件夹中的程序集来完成页请求。
如果再次预编译站点,那么将只编译新文件或更改过的文件(或那些与新文件或更改过的文件具有依赖关系的文件)。由于编译器的这一优化,因此,即使是在细微的更新之后也可以编译站点。
针对部署的预编译
预编译站点的另一个用处是生成可部署到成品服务器的站点的可执行版本。针对部署的预编译会以布局的形式创建输出。布局包含程序集、配置信息、网站文件夹信息以及静态文件(例如 HTML 文件和图形)。
编译网站之后,可以使用 Windows XCopy 命令、FTP、Windows 安装等工具将布局部署到成品服务器。布局在部署之后将作为网站运行,而 ASP.NET 将通过布局中的程序集来完成页请求。
针对部署预编译网站提供了一种保护源代码和其他知识产权的方式。有关编译器在针对部署的编译过程中如何处理文件的更多信息,请参见本主题后面的针对部署的网站编译过程中的文件处理。
您可以按照以下两种方式来针对部署进行预编译:仅针对部署进行预编译,或者针对部署和更新进行预编译。
仅针对部署进行预编译
当仅针对部署进行预编译时,编译器将基于正常情况下在运行时编译的几乎所有 ASP.NET 源文件来生成程序集。其中包括页中的程序代码、.cs 和 .vb 类文件以及其他代码文件和资源文件。编译器将从输出中移除所有源代码和标记。在生成的布局中,将为每个 .aspx 文件生成编译后的文件(扩展名为 .compiled),该文件包含指向与该页相应的程序集的指针。
若要更改网站(包括页的布局),必须更改原始文件、重新编译网站并重新部署布局。唯一的例外是网站配置。您可以直接对成品服务器上的 Web.config 文件进行更改,而无需重新编译网站。
此选项不仅为 ASP.NET 网页提供了最大程度的保护,还提供了最佳启动性能。
针对部署和更新进行预编译
当针对部署和更新进行预编译时,编译器将基于所有源代码(单文件页中的页代码除外)以及正常情况下用来生成程序集的其他文件(例如资源文件)来生成程序集。编译器将 .aspx 文件转换成使用编译后的代码隐藏模型的单个文件,并将它们复制到布局中。
使用此选项,可以在编译网站中的 ASP.NET 网页之后,对它们进行有限的更改。例如,可以更改控件的排列、页的颜色、字体和其他外观元素。您还可以添加不需要事件处理程序或其他代码的控件。
当网站第一次运行时,ASP.NET 将执行进一步的编译,以便基于标记创建输出。
说明: |
---|
预编译的可更新网站不允许多个页引用同一个 CodeFile 类。 |
预编译决策矩阵
使用下表来帮助您决定要使用哪种编译模型。本主题稍后将对此表中列出的部分选项进行介绍。
目标 |
编译模型 |
---|---|
快速开发应用程序而不考虑代码的编译。 |
使用默认编译(无预编译)。 |
缩短对网站的首次页请求的响应时间。 |
使用就地预编译或部署编译选项之一。 |
分离源代码和用户界面 (UI) 代码。 |
使用可更新用户界面的预编译。 |
在不更改源代码的情况下修改 UI 代码。 |
使用可更新用户界面的预编译。 |
从成品服务器移除所有源代码和用户界面代码。 |
使用不可更新用户界面的预编译。 |
通过替换特定程序集来更新应用程序。 |
使用名称固定的预编译。 |
使用具有强名称的程序集提高应用程序的安全性。 |
使用带签名程序集的预编译。 |
执行预编译
可以在命令行上使用 Aspnet_compiler.exe 工具预编译网站。有关更多信息,请参见如何:预编译 ASP.NET 网站以进行部署和 ASP.NET 编译工具 (Aspnet_compiler.exe)。Visual Studio 还包含从 IDE 中预编译网站的命令。
说明: |
---|
预编译网站只是对该站点进行编译,而不会编译所有子站点。如果网站包含在 IIS 中标记为应用程序的子文件夹,则当预编译父文件夹时,将不会编译子应用程序。 |
预编译网站时,如果要编译的网站启用了源代码保护,则存在一条编码限制。基页类(代码隐藏类)可以使用完全限定的类名来引用关联的页类(.aspx 文件)和页类成员。但是,在预编译启用了源代码保护的网站时,这种引用将不再起作用。这是因为代码隐藏文件中的基页类与 .aspx 页派生的页类不在相同的程序集中。有关在启用源代码保护下进行预编译的更多信息,请参见如何:为预编译网站的程序集签名。
默认编译
您无需手动编译 ASP.NET 应用程序。默认情况下,ASP.NET 会在 Web 浏览器首次请求 Web 应用程序中的页时编译该应用程序。如果对应用程序中的文件进行了更改,则在下次请求页时,ASP.NET 运行库将确定已更改文件的依赖项。它只编译受更改影响的文件。
优点
使用默认编译的优点包括:
简单易用。ASP.NET 编译器会为您完成所有工作。
当预编译网站所需的额外步骤减慢了开发过程时,默认编译是开发过程中可供选择的最佳编译模型。
缺点
使用默认编译的缺点包括:
在首次请求网站时可能会导致大量延迟。
要求将源代码文件存储在成品服务器上。
对服务器上的网站目录拥有文件系统访问权限的任何人都可以获取源代码和 UI 代码。
何时使用默认编译
在下列情况下使用默认编译:
在开发和测试网站时。
用于主要包含静态信息的网站。
用于不经常更改的网站。
在将源代码文件存储在成品服务器上不存在顾虑时。
就地编译
您可以预编译已部署在成品服务器上的网站。此过程称为就地编译。如果对应用程序中的文件进行了更改,则可以使用 ASP.NET 编译工具预编译受影响的文件。当下次从应用程序中请求页时,也会预编译受影响的文件。
有关此编译模型的更多信息,请参见 如何:预编译 ASP.NET 网站。
优点
使用就地编译的优点包括:
缩短了网站对首次请求的响应时间。
无需特殊的部署步骤;编译应用程序的过程完全就像从网站中请求页一样。
缺点
使用就地编译的缺点包括:
应用程序的所有源代码必须存储在成品服务器上。
对网站目录拥有访问权限的任何人都可以获取源代码和 UI 代码。
何时使用就地编译
在下列情况下使用就地编译:
经常对网站上的页进行更改。
将源代码文件存储在成品服务器上不存在顾虑。
想要缩短首次页请求的响应时间。
可更新 UI 的预编译
通过使用 ASP.NET 编译工具的 -u 开关,可以将源代码(.cs、.vb 文件和 .resource 文件)编译为 DLL。您可以将用户界面标记保留在 .aspx 文件中,以供更新使用。在将网站部署到成品服务器后,无需重新编译整个网站即可对 .aspx 代码进行更改。
有关此编译方法的更多信息,请参见 如何:预编译 ASP.NET 网站以进行部署。
优点
预编译具有可更新用户界面的网站具有下列优点:
缩短了网站对首次请求的响应时间。
用户界面设计人员可以修改网站的外观和行为,而无需重新编译整个网站。
它可以保护应用程序源代码中的知识产权。对网站目录拥有文件系统访问权限的任何人都不会在意外中看到这些知识产权。
缺点
预编译具有可更新用户界面的网站具有下列缺点:
在部署到成品服务器之前,需要执行单独的编译步骤。
对网站目录拥有访问权限的任何人都可以获取应用程序用户界面(.aspx 文件)中的知识产权。
多个页不能引用同一个 CodeFile 类,此类是与使用代码隐藏模型的页关联的代码文件。
何时使用可更新 UI 的预编译
在下列情况下将应用程序预编译为具有可更新的用户界面:
UI 设计人员与源代码开发人员独立工作。
程序源代码包含要加以保护以防被意外看到的知识产权。
您不想将程序源代码存储在成品服务器上。
不可更新 UI 的预编译
ASP.NET 编译工具可将应用程序的所有源代码编译为 DLL,并部署在该应用程序的 Bin 目录中。其中包括用户界面文件,例如 .aspx 和 .ascx 文件。
有关此编译方法的更多信息,请参见 如何:预编译 ASP.NET 网站以进行部署。
优点
不可更新 UI 的预编译的优点包括:
缩短了网站对首次请求的响应时间。
它可以保护应用程序源代码和用户界面代码中的知识产权。对网站目录拥有访问权限的任何人都不会在意外中看到这些知识产权。
缺点
不可更新 UI 的预编译的缺点包括:
在部署到成品服务器之前,需要执行单独的编译步骤。
即使对应用程序的用户界面进行少许更改,也需要重新编译整个网站。
何时使用不可更新 UI 的预编译
在下列情况下将网站预编译为具有不可更新的用户界面:
用户界面代码中包含要加以保护以防被意外看到的知识产权。
不需要经常更改用户界面。
只希望将已编译的 DLL 放在成品服务器上。
预编译为固定名称的程序集
ASP.NET 编译工具对编译期间生成的程序集使用随机名称。每次重新编译应用程序时,程序集的名称都会更改。
由于程序集名称会更改,因此必须为维护一个程序集而重新部署整个应用程序。但是,通过使用 ASP.NET 编译工具的 -fixednames 开关,可以为应用程序中的每个页分别创建一个程序集。在后续编译中,程序集的名称将不再更改。因此,可以创建应用程序的 Service Release,以便仅替换发生更改的程序集。
由于 -fixednames 开关将为每个页创建一个单独的程序集,因此应限制应用程序中的页数。
有关此预编译方法的更多信息,请参见 如何:使用 ASP.NET 编译工具生成固定名称。
优点
预编译为固定名称的程序集的优点包括:
各个程序集的名称不会随编译而更改。这样,无需重新部署整个应用程序即可替换特定的程序集。
对应用程序的次要更新将更具有针对性。
缺点
预编译为固定名称的程序集的缺点包括:
- 需要分别为应用程序中的每个页创建一个程序集。这样,如果网站包含的页数较多,则会创建大量的程序集。
何时预编译为固定名称的程序集
在下列情况下将网站预编译为名称固定的程序集:
- 必须在不替换整个应用程序的情况下维护 Web 应用程序。
预编译为签名的程序集
使用 ASP.NET 编译工具可以创建具有强名称的程序集,这些程序集可部署到服务器的全局程序集缓存 (GAC) 或应用程序的 Bin 目录中。利用签名的程序集,将使恶意用户更难用恶意代码替换应用程序的程序集。
有关此编译方法的更多信息,请参见 如何:为预编译网站的程序集签名。
优点
预编译为签名的程序集的优点包括:
- 通过使程序集更难被恶意代码替换,签名的程序集提高了应用程序的安全性。
缺点
预编译为签名的程序集的缺点包括:
共享开发环境中的密钥管理可能很复杂。
程序集必须让 ASP.NET 运行库调用 AllowPartiallyTrustedCallersAttribute 属性。
何时预编译为签名的程序集
在下列情况下将网站预编译为签名的程序集:
用户有权访问应用程序目录或 GAC,并且能够替换应用程序的程序集。
您希望限制第三方替换由应用程序代码所生成的程序集的能力。
写入预编译输出
预编译过程完成时,得到的输出被写入您指定的文件夹中。通过使用文件传输协议 (FTP) 或 HTTP,可以将输出写入文件系统中可供访问的任何文件夹内。必须具有相应权限才能向目标网站写入。
说明: |
---|
发布过程只部署网站文件夹和子文件夹中的文件。而不部署 Machine.config 文件。因此,目标 Web 服务器的配置可能与您计算机上的配置不同,这可能会将影响应用程序的行为。 |
您可以在临时服务器或成品服务器上指定目标文件夹,也可以将输出写入本地计算机上的文件夹中。如果在成品服务器上指定了文件夹,则可在一个步骤中预编译并部署。如果将输出写入不属于网站的文件夹中,则可以在单独的步骤中将输出复制到服务器上。
说明: |
---|
如果使用 Visual Studio 打开预编译的网站,则将无法生成该网站。将关闭生成选项。若要更改网站,建议先编辑原始网站中的文件,并在预编译网站后再重新发布。 |
预编译过程的输出包括所有代码或页的已编译程序集。如果选择允许更新预编译网站的选项,则 .aspx、.asmx 和 .ashx 文件的所有代码隐藏类都将编译到程序集中。但是,.aspx、.asmx 和 .ashx 文件本身将按原样复制到目标文件夹中,以便在部署网站后对这些文件的布局进行更改。对于可更新的预编译网站,单文件页中的代码不编译到程序集中,而是作为源代码部署。
不编译静态文件。相反,它们按原样复制到输出文件夹中。静态文件包括图形、.htm 或 .html 文件、文本文件等。有关更多信息,请参见本主题后面的针对部署的网站编译过程中的文件处理。
如果预编译期间发生错误,则将在**“输出”窗口及“错误列表”**窗口中向您报告。预编译期间发生的错误将阻止网站的编译和发布。
ASP.NET 预编译期间的文件处理
在预编译要部署的网站时,ASP.NET 将创建布局,这是一种包含编译器输出的结构。本节介绍预编译期间的文件处理方式,并对布局结构和内容进行说明。
您可以同时预编译源代码(生成程序集的所有文件,包括程序代码和资源)和标记(.aspx 文件),也可以只编译源代码。
已编译的文件
预编译过程对 ASP.NET Web 应用程序中各种类型的文件执行操作。文件的处理方式各不相同,这取决于应用程序预编译只是用于部署还是用于部署和更新。
说明: |
---|
在仅针对部署或同时针对部署和更新预编译网站时,将不保留目标文件和子目录上的文件访问控制列表 (ACL)。例如,如果您以前预编译了某个站点并将其部署到目标位置,更改了文件的 ACL,然后再次预编译并部署该站点,则 ACL 更改将丢失。 |
下表描述了不同的文件类型,以及在只针对部署预编译应用程序时对这些文件类型所执行的操作。
文件类型 |
预编译操作 |
输出位置 |
---|---|---|
.aspx、ascx、.master |
生成程序集和一个指向该程序集的 .compiled 文件。原始文件保留在原位置,作为完成请求的占位符。 |
程序集和 .compiled 文件写入 Bin 文件夹中。页(去除内容的 .aspx 文件)保留在其原始位置。 |
.asmx、.ashx |
生成程序集。原始文件保留在原位置,作为完成请求的占位符。 |
Bin 文件夹 |
App_Code 文件夹中的文件 |
生成一个或多个程序集(取决于 Web.config 设置)。
说明:
App_Code 文件夹中的静态内容不复制到目标文件夹中。
|
Bin 文件夹 |
未包含在 App_Code 文件夹中的 .cs 或 .vb 文件 |
与依赖于这些文件的页或资源一起编译。 |
Bin 文件夹 |
Bin 文件夹中的现有 .dll 文件 |
按原样复制文件。 |
Bin 文件夹 |
资源 (.resx) 文件 |
对于 App_LocalResources 或 App_GlobalResources 文件夹中找到的 .resx 文件,生成一个或多个程序集以及一个区域性结构。 |
Bin 文件夹 |
App_Themes 文件夹及子文件夹中的文件 |
在目标位置生成程序集并生成指向这些程序集的 .compiled 文件。 |
Bin |
静态文件(.htm、.html、.js、图形文件等) |
按原样复制文件。 |
与源中结构相同。 |
浏览器定义文件 |
按原样复制文件。
说明:
浏览器信息从计算机级的配置文件中继承,因此其行为在目标服务器上可能会有所不同。
|
App_Browsers |
依赖项目 |
将依赖项目的输出生成到程序集中。 |
Bin 文件夹 |
Web.config 文件 |
按原样复制文件。 |
与源中结构相同。 |
Global.asax 文件 |
生成程序集。 |
Bin 文件夹 |
下表描述了不同的文件类型,以及当对应用程序进行预编译以备部署和更新时对这些文件类型所执行的操作。
文件类型 |
预编译操作 |
输出位置 |
---|---|---|
.aspx、ascx、.master |
为具有代码隐藏类文件的文件生成程序集。同时生成指向程序集的 .compiled 文件。将这些文件的单文件版本原封不动地复制到目标位置。 |
程序集和 .compiled 文件写入 Bin 文件夹中。 |
.asmx、.ashx |
按原样复制文件,但不编译。 |
与源中结构相同。 |
App_Code 文件夹中的文件 |
生成一个或多个程序集(取决于 Web.config 设置)。
说明:
App_Code 文件夹中的静态内容不复制到目标文件夹中。
|
Bin 文件夹 |
未包含在 App_Code 文件夹中的 .cs 或 .vb 文件 |
与依赖于这些文件的页或资源一起编译。 |
Bin 文件夹 |
Bin 文件夹中的现有 .dll 文件 |
按原样复制文件。 |
Bin 文件夹 |
资源 (.resx) 文件 |
对于 App_GlobalResources 文件夹中的 .resx 文件,生成一个或多个程序集以及一个区域性结构。 对于 App_LocalResources 文件夹中的 .resx 文件,将它们按原样复制到输出位置的 App_LocalResources 文件夹中。 |
程序集放置在 Bin 文件夹中 |
App_Themes 文件夹及子文件夹中的文件 |
按原样复制文件。 |
与源中结构相同。 |
静态文件(.htm、.html、.js、图形文件等) |
按原样复制文件。 |
与源中结构相同。 |
浏览器定义文件 |
按原样复制文件。
说明:
浏览器信息从计算机级的配置文件中继承,因此其行为在目标服务器上可能会有所不同。
|
App_Browsers |
依赖项目 |
将依赖项目的输出生成到程序集中。 |
Bin 文件夹 |
Web.config 文件 |
按原样复制文件。 |
与源中结构相同。 |
Global.asax 文件 |
生成程序集。 |
Bin 文件夹 |
.compiled 文件
对于 ASP.NET Web 应用程序中的可执行文件,编译器会在程序集和文件的名称中添加 .compiled 文件扩展名。程序集名称由编译器生成。.compiled 文件不包含可执行代码。它只包含 ASP.NET 查找相应的程序集所必需的信息。
在部署预编译的应用程序之后,ASP.NET 使用 Bin 文件夹中的程序集来处理请求。预编译输出包含 .aspx 或 .asmx 文件作为页占位符。占位符文件不包含任何代码。它们只用于针对特定的页请求调用 ASP.NET。占位符文件还提供了一种将文件权限设置为对页面具有限制访问权限的方式。
更新预编译的网站
在部署预编译的网站之后,只能对网站中的文件进行有限的更改。下表描述了不同类型的更改所造成的影响。
文件类型 |
允许的更改(仅部署) |
允许的更改(部署和更新) |
---|---|---|
静态文件(.htm、.html、.js、图形文件等) |
可以更改、移除或添加静态文件。如果 ASP.NET 网页引用的页或页元素已被更改或移除,可能会发生错误。 |
可以更改、移除或添加静态文件。如果 ASP.NET 网页引用的页或页元素已被更改或移除,可能会发生错误。 |
.aspx 文件 |
不允许更改现有页。不允许添加新的 .aspx 文件。 |
您可以更改 .aspx 文件的布局并添加不需要代码的元素,例如 HTML 元素和不带事件处理程序的 ASP.NET 服务器控件。此外,还可以添加新的 .aspx 文件,这类文件将在首次请求时进行编译。 |
.skin 文件 |
忽略更改和新增的 .skin 文件。 |
允许更改和新增 .skin 文件。 |
Web.config 文件 |
允许进行影响 .aspx 文件编译的更改。忽略调试或批处理编译选项。 不允许更改配置文件属性或提供程序元素。 |
允许在不影响网站或页编译的情况下进行更改。这包括编译器设置、信任级别和全球化。将忽略影响编译或使已编译页中的行为发生变化的更改,否则可能会生成错误。允许进行其他更改。 |
浏览器定义 |
允许更改和新增文件。 |
允许更改和新增文件。 |
从资源 (.resx) 文件编译的程序集 |
可以为全局和局部资源添加新的资源程序集文件。 |
可以为全局和局部资源添加新的资源程序集文件。 |
代码示例
返回页首
请参见
参考
ASP.NET 编译工具 (Aspnet_compiler.exe)
返回页首