Precompiling Your Website (C#)
Visual Studio offers ASP.NET developers two types of projects: Web Application Projects (WAPs) and Web Site Projects (WSPs). One of the key differences between the two project types is that WAPs must have the code explicitly compiled prior to deployment whereas the code in a WSP can be automatically compiled on the web server. However, it is possible to precompile a WSP prior to deployment. This tutorial explores the benefits of precompilation and shows how to precompile a website from within Visual Studio and from the command line.
Visual Studio offers ASP.NET developers two different project types:
Web Application Projects (WAP) and Web Site Projects (WSP). One of the key differences
between these project types is that WAPs require explicit compilation
whereas WSPs use automatic compilation, by default. With WAPs, you
compile the web application's code into a single assembly, which is created in the
Bin folder. Deployment entails copying the
markup content (the
.master files) in the project, along with the assembly in the
Bin folder; the code-behind class files themselves do not
need to be deployed. On the other hand, you deploy WSPs by copying both the markup
pages and their corresponding code-behind classes to the production environment. The
code-behind classes are compiled on demand on the web server.
Note: Refer back to the "Explicit Compilation Versus Automatic Compilation" section in the Determining What Files Need to Be Deployed tutorial for more background on the differences between the project models, explicit and automatic compilation, and how the compilation model affects deployment.
The automatic compilation option is simple to use. There's no explicit compilation step and only the files that have been modified need to be deployed, whereas explicit compilation necessitates deploying the changed markup pages and the just-compiled assembly. However, automatic deployment has two potential drawbacks:
- Because the pages must be automatically compiled when they are first visited, there can be a short but noticeable delay when an ASP.NET page is requested for the first time after being deployed.
- Automatic compilation requires that both the declarative markup and source code be present on the web server. This can be an unattractive option if you plan on selling the web application to customers who will install it on their web servers.
If either of the two above shortcomings are deal breakers, you can either switch to the WAP model or precompile the WSP prior to deployment. This tutorial examines the precompilation options best suited for a hosted website and walks through the precompilation process and deployment of a precompiled website.
An Overview of ASP.NET Code Generation and Compilation
Before we look at the available precompilation options, let's first
talk about the code generation and compilation that occurs when an ASP.NET page is
requested for the first time since it's been created or last updated. As you know,
ASP.NET pages are composed of two portions: declarative markup in the
.aspx file; and a source code portion, typically in a separate
code-behind class file (
.aspx.cs). The steps performed by
the runtime when an ASP.NET page is requested depends on the application's compilation
With WAPs, the pages' source code must be explicitly compiled into a
single assembly before being deployed. During deployment, this assembly and the various
markup pages are copied to the production environment. When a request arrives to the
web server for an ASP.NET page, the runtime creates an instance of the page's
code-behind class and invokes its
which starts the page lifecycle and, ultimately, generates the page's content, which is
returned to the requestor. The runtime can work with the ASP.NET page's code-behind
class because the code-behind class was already compiled into an assembly prior to
With WSPs and automatic compilation, there is no explicit compilation
step prior to deployment. Instead, deployment involves copying both the declarative and
the source code content to the production environment. When a request arrives to the
web server for an ASP.NET page for the first time since the page has been created or
last updated, the runtime must first compile the code-behind class into an assembly.
This compiled assembly is saved in the folder
%WINDIR%\Microsoft.NET\Framework\v2.0.50727\Temporary ASP.NET Files,
although the location of this folder can be customized via the
<pages> element in
Because the assembly is saved to disk, it does not need to be recompiled on subsequent
requests to the same page.
Note: As you would expect, there is a slight delay when requesting a page for the first time (or for the first time since it's been changed) in a site that uses automatic compilation as it takes a moment for the server to compile the page's code and save the resulting assembly to disk.
In short, with explicit compilation you are required to compile the website's source code before deployment, saving the runtime from having to perform that step. With automatic compilation the runtime handles the compilation of the pages' source code, but with a slight initialization cost for the first visit to the page since it was created or last updated.
But what about the declarative part of ASP.NET pages (the
.aspx file)? It's obvious that there's a relationship between the
.aspx files and the code in their code-behind classes, as
the Web controls defined in the declarative markup are accessible in the code. It's
also obvious that the content in the
.aspx files greatly
influences the rendered markup generated by the page. So how does the runtime work with
the text, HTML, and Web control syntax defined in the
.aspx file to generate the requested page's rendered content?
I don't want to get too sidetracked on the low-level implementation
details, which vary between WAPs and WSPs, but in a nutshell the runtime automatically
generates a class file that contains the various Web controls as protected members and
methods. This generated file is implemented as a partial class to the
corresponding code-behind class. (Partial classes allow for the
contents of a single class to be spread across multiple files.) Therefore, the
code-behind class is defined in two places: in the
.aspx.cs file that you create, and in this auto-generated class
created by the runtime. This auto-generated class is stored in the
%WINDIR%\Microsoft.NET\Framework\v2.0.50727\Temporary ASP.NET Files
The important take away here is that for an ASP.NET page to be rendered by the runtime both its declarative and source code portions must be compiled into an assembly. With WAPs, the source code is explicitly compiled into an assembly prior to deployment, but the declarative markup must still be converted into code and compiled by the runtime on the web server. With WSPs using automatic compilation, both the source code and the declarative markup need to be compiled by the web server.
It is possible to use explicit compilation with the WSP model. You can explicitly compile the source code portion, like with the WAP model. What's more, you can also compile the declarative markup.
The .NET Framework ships with an ASP.NET compilation tool
that enables you to compile the source code (and even the content) of an ASP.NET
application built using the WSP model. This tool was released with the .NET Framework
version 2.0 and is located in the
%WINDIR%\Microsoft.NET\Framework\v2.0.50727 folder; it can be used
from the command line or launched from within Visual Studio via the Build menu's
Publish Web Site option.
The compilation tool provides two general forms of compilation:
in-place precompilation and precompilation for deployment. With in-place precompilation
you run the
aspnet_compiler.exe tool from the
command-line and specify the path to the virtual directory or physical path of a
website that resides on your computer. The compilation tool then compiles each ASP.NET
page in the project, storing the compiled version in the
%WINDIR%\Microsoft.NET\Framework\v2.0.50727\Temporary ASP.NET Files
folder just like if the pages had each been visited for the first time from a browser.
In-place precompilation can speed up the first request made to newly deployed ASP.NET
pages on your site because it alleviates the runtime from needing to perform this step.
However, in-place precompilation is not useful for the majority of hosted websites
because it requires that you are able to run programs from the web server's
command-line. In shared hosting environments this level of access is not permitted.
Instead of compiling the pages in the website to the
Temporary ASP.NET Files folder, precompilation for deployment
compiles the pages to a directory of your choosing and in a format that can be deployed
to the production environment.
There are two flavors of precompilation for deployment that we explore
in this tutorial: precompilation with an updatable user interface, and precompilation
with a non-updatable user interface. Precompilation with an updatable user interface
leaves the declarative markup in the
.master files, thereby
allowing a developer to view and, if desired, modify the declarative markup on the
production server. Precompilation with a non-updatable user interface generates
.aspx pages that are void of any content and removes
thereby hiding the declarative markup and prohibiting a developer from changing it from
the production environment.
Precompiling for Deployment With an Updatable User Interface
The best way to understand precompilation for deployment is to see an example in action. Let's precompile the Book Reviews WSP for deployment using an updatable user interface. The ASP.NET compilation tool can be invoked from Visual Studio's Build menu or from the command-line. This section examines using the tool from within Visual Studio; the "Precompiling from the Command Line" section looks at running the compiler tool from the command line.
Open the Book Review WSP in Visual Studio, go to the Build menu, and select the Publish Web Site menu option. This launches the Publish Web Site dialog box (see Figure 1), where you can specify the target location, whether or not the precompiled site's user interface is updatable, and other compiler tool options. The target location can be a remote web server or FTP server, but for now choose a folder on your computer's hard drive. Because we want to precompile the site with an updatable user interface, leave the "Allow this precompiled site to be updatable" checkbox checked and click OK.
Note: The Publish Web Site option in the Build menu is not available in Visual Web Developer. If you are using Visual Web Developer you will need to use the command-line version of the ASP.NET compilation tool, which is covered in the "Precompiling from the Command Line" section.
After precompiling the website, navigate to the target location you
entered in the Publish Web Site dialog box. Take a moment to compare the contents of
this folder with the contents of your website. Figure 2 shows the Book Reviews website
folder. Note that it contains both
.aspx.cs files. Also, note that the
directory includes only one file,
Elmah.dll, which we
added in the preceding tutorial
Figure 3 shows the target location folder whose contents were created
by the ASP.NET compilation tool. This folder does not contain any code-behind files.
Moreover, this folder's
Bin directory includes several
assemblies and two
.compiled files in addition to the
Unlike explicit compilation in WAPs, the precompilation for deployment
process does not create one assembly for the entire site. Instead, it batches together
several pages into each assembly. It also compiles the
Global.asax file (if present) into its own assembly, as well as any
classes in the
App_Code folder. The files that hold the
declarative markup for ASP.NET web pages, User Controls, and master pages (
.master files, respectively) are copied as-is to the target location
directory. Likewise, the
Web.config file is copied
straight over, along with any static files, such as images, CSS classes, and PDF files.
For a more formal description of how the compilation tool handles various file types,
refer to File Handling
During ASP.NET Precompilation.
Note: You can instruct the compilation tool to
create one assembly per ASP.NET page, User Control, or master page by checking the
"Used fixed naming and single page assemblies" checkbox from the Publish Web Site
dialog box. Having each ASP.NET page compiled into its own assembly allows for more
fine-grained control over deployment. For example, if you updated a single ASP.NET web
page and needed to deploy that change, you need only deploy that page's
.aspx file and associated assembly to the production environment.
Consult How To:
Generate Fixed Names with the ASP.NET Compilation Tool for more information.
The target location directory also contains a file that was not part of
the precompiled web project, namely
PrecompiledApp.config. This file informs the ASP.NET runtime that the
application was precompiled and whether it was precompiled with an updatable or
Finally, take a moment to open one of the
.aspx files in the target location using Visual Studio or your text
editor of choice. When precompiling for deployment with an updatable user interface,
the ASP.NET pages in the target location directory contain the exact same markup as the
corresponding files in the website.
Precompiling for Deployment With a Non-Updatable User Interface
The ASP.NET compiler tool can also be used to precompile a site for deployment with a non-updatable UI. Precompiling the site with a non-updatable UI works much like precompiling with an updatable UI, the key difference being that the ASP.NET pages, User Controls, and master pages in the target directory are stripped of their markup. To precompile a website for deployment with a non-updatable UI, choose the Publish Web Site option from the Build menu, but uncheck the "Allow this precompiled site to be updatable" option (see Figure 4).
Figure 5 shows the target location folder after precompiling with a non-updatable user interface.
Compare Figure 3 to Figure 5. While the two folders may look identical,
note that the non-updatable UI folder lacks the master page,
Site.master. And while Figure 5 includes the various ASP.NET pages,
if you view the contents of these files you'll see that they've been stripped of their
declarative markup and replaced with the placeholder text: "This is a marker file
generated by the precompilation tool, and should not be deleted!"
Bin folders in Figures 3 and 5 differ
more substantially. In addition to the assemblies, the
Bin folder in Figure 5 includes a
.compiled file for each ASP.NET page, User Control, and master
Precompiling a site with a non-updatable UI is useful in situations
where you do not want the ASP.NET pages' contents to be modified by the person or
company who installs or manages the website in the production environment. If you build
an ASP.NET web application that you sell to customers to install on their own web
servers, you may want to ensure that they do not modify the look and feel of your site
by directly editing the
.aspx pages you ship them. By
precompiling your website with a non-updatable UI, you ship the placeholder
.aspx pages as part of the installation, thereby
preventing your customers from examining or modifying their content.
Precompiling from the Command Line
Behind the scenes, Visual Studio's Publish Web Site dialog box invokes
the ASP.NET compilation tool (
precompile the website. Alternatively, you can invoke this tool from the command line.
In fact, if you use Visual Web Developer then you will need to run the compiler tool
from the command line, as Visual Web Developer's Build menu does not include the
Publish Web Site option.
To use the compiler tool from the command line, start by dropping to
the command line and navigating to the framework directory,
%WINDIR%\Microsoft.NET\Framework\v2.0.50727. Next, enter the
following statement into the command line:
"physical_path_to_app" -v / -f -u "target_location_folder"
The above command launches the ASP.NET compiler tool (
aspnet_compiler.exe) and, via the
switch, instructs it to precompile the website rooted at physical_path_to_app; this value will be something like
C:\MySites\BookReviews, and should be delimited by quotation
-v switch specifies the virtual
directory of the site. If your site is registered as the default website in the IIS
metabase then you can omit the
-p switch and just specify
the virtual directory of the application. If you use the
-p switch, the value proceeding the
switch indicates the root of the website, and is used to resolve application-root
references. For instance, if you specify a value of
/MySite then references in the application to
~/path/file will be resolved as
~/MySite/path/file. Because the Book
Reviews site is located at the root directory at my web hosting company I have used the
-f switch, if present, instructs the
compilation tool to overwrite the target_location_folder directory if
it already exists. If you omit the
-f switch and the
target location folder already exists, the compilation tool will quit with the error:
"error ASPRUNTIME: The target directory is not empty. Please delete it manually or
choose a different target."
-u switch, if present, informs the
tool to create an updatable user interface. Omit this switch to precompile the site
with a non-updatable user interface.
Lastly, the target_location_folder is the physical path
to the target location directory; this value will be something like
C:\MySites\Output\BookReviews, and should be delimited by quotation
Deploying the Precompiled Website
At this point we have seen how to use the ASP.NET compilation tool to precompile a website using both the updatable and non-updatable user interface options. However, our examples thus far have precompiled the website to a local folder, and not to the production environment. The good news is that deploying the precompiled website is a breeze and can be done through Visual Studio or through some other file copy mechanism, such as from a stand-alone FTP client.
The Publish Web Site dialog box (first shown in Figure 1) has a target location option, which indicates where the precompiled website files are copied to. This location can be a remote web server or FTP server. Entering a remote server into this textbox precompiles and deploys the website to the specified server in one step. Alternatively, you can precompile the website to a local folder and then manually copy the contents of that folder to the production environment via FTP or some other approach.
Having the precompiled website automatically deployed via Visual Studio's Publish Web Site dialog box is helpful for simple sites where there are no configuration differences between the development and production environments. However, as noted in the Common Configuration Differences Between Development and Production tutorial it is not uncommon for such differences to exist. For example, the Book Reviews web application uses a different database in the production environment than in the development environment. When Visual Studio publishes the website to a remote server it blindly copies up the configuration file information in the development environment.
For sites with configuration differences between the development and production environments it may be best to precompile the site to a local directory, copy over the production-specific configuration files, and then copy the contents of the precompiled output to production.
For a refresher on copying files from the development environment to the production environment refer to the Deploying Your Website Using an FTP Client and Deploying Your Website Using Visual Studio tutorials.
ASP.NET supports two modes of compilation: automatic and explicit. As discussed in previous tutorials, Web Application Projects (WAPs) use explicit compilation whereas Web Site Projects (WSPs) use automatic compilation, by default. However, it is possible to explicitly compile a WSP prior to deployment by using the ASP.NET compilation tool.
This tutorial focused on the compilation tool's Precompilation for Deployment support. When precompiling for deployment, the compilation tool creates a target location folder, compiles the specified web application's source code, and copies these compiled assemblies and the content files into the target location folder. The compilation tool can be configured to create an updatable or non-updatable user interface. When precompiling with a non-updatable user interface option, the declarative markup in the content files is removed. In a nutshell, precompilation permits you to deploy your Web Site Project-based application without including any source code files and with the declarative markup removed, if desired.
For more information on the topics discussed in this tutorial, refer to the following resources: