The default deployment model in ASP.NET 2.0 is to compile pages in place. In other words if you specify a CodeFile and the CodeFile exists ASP.NET will compile this file on the fly the first time the page is loaded.

 

This is the default when Visual Studio creates a new projects and adds pages to the project. So you will have an ASPX page and a .cs or .vb source file that is the partial codebehind file that contains your event and page handling code. The other half of the partial class then contains all the control declarations and event hookups. I talked about this in more detail in my post yesterday. While this sounds a lot like V1.x of ASP.NET there is at least one major advantage here:

 

The control declarations are generated at compile time not at design time which means they are always in sync – no more issues where a control exists in the ASPX page, but not in the source code.

 

This also has an impact on compile time behavior. An ASPX page with this new model consists of a base class containing two (actually three) partial classes, and then the actual ASPX class itself which inherits from the combined partial classes. Note however, that the Control and Event Hookup partial class is generated by ASP.NET at compile time so both  classes require compile time generated code!

 

This means it’s not possible to separate out just the compiled code from the ASPX page code as was possible in the ASPX 1.1. Note though that the ASP.NET 1.1 model still works – you can still use the old codebehind syntax just as before, but Visual Studio doesn’t support it by default. If you are using the new model with the compiled partial classes and ASPX inheritance based on them you get basically two compilation options:

 

  • In place compilation
  • Site Pre-Compilation

In place compilation

In place compilation is ASP.NET 2.0’s default which compiles each page in place when it’s accessed for the first time. This applies both to Inline code (ie. Code and HTML markup in a single document) or for ASPX + .cs/.vb source files specified with the CodeFile= attribute. ASP.NET compiles both the ASPX and CodeFile when the page is first accessed.

 

This model works well for development because in order to run a page you don’t have to recompile anything. If a change is made to the ASPX file or the CS file ASP.NET automatically recompiles both and the page runs.

 

But there are problems with this approach as well:

 

  • Deployment
    You probably don’t want to deploy your .cs/.vb source code files on your Web Site. Yet with in place compilation you don’t get a choice.

  • Checking for Errors
    Because pages are compiled at run time, it’s very easy to have errors slip by. To really catch errors beforehand you need to compile the entire project. VS.NET 2005 provides this functionality using the Precompiler along with all the issues that go along with that (see below)

 

 

Pros:
Easy to use
Change and run – no compilation whatsoever

Great for development

 

Cons:

Requires that source code is present and deployed

Security risk
Unwieldy to deploy - you have to make sure ASPX and source file are in sync

 

 

 

A variation of the In Place compilation is Batch Compilation which works by using directives in web.config to automatically compile the site when the first page is hit. This makes the first hit very slow, but all subsequent requests should be a lot faster, as opposed to each page having a first time startup hit. This behavior is essentially the same as ASP.NET 1.1.

 

Site Pre-Compilation

You can also precompile sites completely by using a new utility ASPNET_COMPILER. You can compile a site in place which basically compiles all pages in to the ASP.NET directory, or you can compile a site for deployment. The former is of dubious use unless you can somehow conincide that with the startup of your application or Web Server. The deployment pre-compilation is what’s interesting.

Basically what this tool does is run through the entire site and build a deployment directory for the entire site. A precompiled site removes all ASPX code and all codebehind code and leaves only a couple assemblies and marker files for each of the ASPX/ASCX/Master files etc. in the /Bin directory.  The ASPX pages are stripped of all markup leaving only an empty shell.

 

The process copies ALL files of the Web into the deployment directory. This includes images and subdirectories. The command line looks something like this:

 

aspnet_compiler –f –v /whatsnewinaspnet c:\temp\deploy

 

where –v is the name of the virtual directory on the local Web Server. –f is force overwrite an existing directory. You can also specify a directory or an IIS ADSI virtual directory path (/LM/W3SVC/1/ROOT/WhatsNewInAspNet). The output generated looks something like this for a real simple site:


The root directory and subs contain all the ASPX pages but the pages are all empty except for this notice:

 

This is a marker file generated by the precompilation tool, and should not be deleted!

 

Basically ASP.NET requires a file to be present as the ASPX ISAPI scriptmap is marked to verify file existence so the file must exist but all the content is contained in the compiled assemblies in the BIN directory. As you can see there’s one assembly for each page and control/master page etc. plus at least one assembly for the main application.

 

The compiled files go into the BIN directory. In the image above the compiled assemblies are App_Web.xxxx.dll. ASP.NET splits files up although I’m not sure I see exactly how the splitting occurs. In my simple examples all ASPX pages ended up in one assembly with the master pages in the other. For each page that was compiled there’s also a .compiled file that gets created. This file is another marker file that contains some XML identifying the file as compiled.

 

<preserve resultType="3" virtualPath="/whatsnewinaspnet/Default.aspx" hash="fffffff2f8ab3fa2" filehash="ee44bf24aef64a77" flags="10000" assembly="App_Web_9p7gh6zm" type="ASP.Default_aspx">

      <filedeps>

            <filedep name="/whatsnewinaspnet/Default.aspx" />

            <filedep name="/whatsnewinaspnet/default.aspx.cs" />

      </filedeps>

</preserve>

 

This file serves as a map between the actual ASPX file which contains no information about the class inheritance and the actual class that services the request.

 

I personally think that this secondary file approach is ugly as hell. This means you have to deploy the ASPX file, the large compiled assembly files plus these Compiled files. Because there are going to be a lot of these there’s a good chance this will cause problems with updating large sites where the assembly might get updated on the site but the Compiled file not until a bit later which is likely to cause failures on the site, if users are accessing files that haven’t been updated yet. Ugggh…

On the upside once the ASPX files are deployed you never have to touch them again. So files to update are localized in one directory unless you add new files.

 

What’s in the pre-compiled assemblies

The assemblies created are split. I didn’t test with complex scenarios at this point, but in the simple project all the ASPX pages ended up in one assembly and user controls and master pages in another. If you look at the assembly with Reflector you can see the inheritance structure of the I described in my last post. Default_aspx inherits from the _default class which is made up of the two partial classes. Default_aspx contains the page related code which is basically the page parser and any script code embedded on the page. The _default class contains all the control properties and event code. Each page also generates a factory method in the FastObjectFactory class which ASP uses to instantiate the class.

 

 

Once compiled the page logic doesn’t look all that different from ASP.NET 1.x which is reassuring. The main difference seems to lie in how the assemblies are compiled until we get to this point.

 

PreComilation is for full deployment

It seems pretty clear that precompilation is essentially geared at deploying a site in full – it’s not really geared towards a partial redeployment. It’s different than what my scenario in 1.1 typically looked like. In 1.1  I was usually re-uploading just the compiled CodeBehind assembly (and support assemblies). With precompilation, because the filenames are dynamically re-generated for each build you will have to redeploy all files!

 

Pros:

Secure  (you can configure the app to be non-updateable)

Command Line accessible – you can add it to a daily build
No Source code at all on the site
No ASPX code on the site

You can hide your intellectual property

 

Cons:
All or nothing approach

Creates deployment of Everything
Creates potentially a lot of files to be deployed

Must deploy all at once

Can cause continous service problems as large assemblies are swapped

Can’t compile application that have sub virtuals

 

 

CodeBehind Assemblies still work

Actually, there’s a third model which is the ASP.NET 1.x model of ASPX file with a compiled CodeBehind assembly. This of course still works, but VS.NET doesn’t directly support building applications that way. You can still use the same mechanism of pure inheritance just by creating an ASPX page and specifying a Inherits clause to a class that you manually create. Although this is not hard it’s unlikely many people will build applications that way.

 

You have to make choices

So if you want to use ASP.NET 2.0 approaches you can see there are two very distinct compilation models in ASP.NET 2.0 and you have to make some hard choices over which model to choose. Personally I think both approaches have some serious drawbacks, but if I have to choose between the two pre-compiled deployment is probably the way I have to go on this.