One of the more interesting compilation features coming in 2.0 of ASP.NET is the ability to pre-compile an entire application and deploy nothing but binary assemblies. Many people have requested the ability to do this in the past so that once an application is deployed you can rest assured that no one will change anything in your deployed application without going through your deployment process (or using dissassemblers and ilasm, in which case they probably deserve to change it :)
The way it works, is you run this new utility called aspnet_compiler.exe and point it to a virtual directory on your machine, also specifying a physical path where you would like it to dump out the binary compiled application ready for deployment.
For example, if you had a vdir on your local machine called myapp with an ASP.NET application, the following command would compile it and drop it into the c:\deploy directory:
aspnet_compiler -m /LM/W3SVC/1/ROOT/myapp c:\deploy
If you look at the output in the c:\deploy directory you will see all of the endpoints in your original application (*.aspx, *.asmx, etc.) but instead of containing the ASP.NET markup they used to have, they will be empty files containing only one line of text:
"This is a marker file generated by the precompilation tool, and should not be deleted!"
You will also see a text filed named PrecompiledApp.txt which contains the following line of text:
"This application has been precompiled by the aspnet_compiler.exe tool.
Please do not delete this file!"
and finally a /bin directory with a number of assemblies and .compiled files referencing types and which assembly they are stored in (using an XML format).
You can then deploy this directory to a server and there will be no request-time compilation, as all page types have been pre-compiled in the /bin directory. Interestingly, if you try and add a new .aspx file to this precompiled site and navigate to it, you will find that it generates an exception stating that the file is not precompiled and this application serves only precompiled content. Very slick - so no one can even add new .aspx files to your deployed application.
I was curious how they implemented this, so I dug through some System.Web.Compilation classes with Reflector and found the following property in the BuildManager class:
private bool IsPrecompiledAppInternal
{
get
{
{
}
}
}
|
The check to see whether the BuildManager is dealing with a precompiled application or not is simply a check for the presence of a file named "PrecompiledApp.txt"! (Note this is in the Beta1 Refresh and may be subject to change in the release). Just to verify that this was true, I went ahead and deleted this file (in spite of it's sincere pleading for me to not do exactly that :) and tried to access my non-precompiled .aspx file again. It failed! But the reason it failed was the _isPrecompiledAppComputed flag was set and it is not flushed when the directory changes. So I then bounced the worker process and tried again, and voila - it compiled and rendered the page no problem. In fact, if I then navigated to any of my previous .aspx pages they just rendered the 'marker file' text inside of them.
Note that the opposite is also true, you can drop a file named "PrecompiledApp.txt" into any ASP.NET 2.0 application directory and the BuildManager will serve up only pre-compiled types (meaning all .aspx pages will fail to compile and nothing will work, bwa ha ha :) If you're looking for a good April Fool's day trick to play on a colleague ... I've said enough already.
I should also note that the .aspx endpoints do not even have to be present in the deployed pre-compiled application, unless you have checked the 'verify that file exists' checkbox in IIS for the virtual directory. You can truly deploy only a /bin directory and one innocuous text file (PrecompiledApp.txt) to a server with no .aspx files whatsoever and it works fine.
Posted
Nov 11 2004, 08:17 AM
by
fritz-onion