Click here to Skip to main content
Click here to Skip to main content

Pre-Compile ASPX pages in .NET 1.1

By , 30 Mar 2004
 

Introduction

The first time a HTTP request is made for a ASPX page, then the ASP.NET runtime converts the ASPX page to a '*.cs' file and compiles it into a DLL. This DLL is typically stored in the temporary folder 'C:\WINNT\Microsoft.NET\Framework\v1.1.4322\ Temporary ASP.NET Files'. Because of this, the first response time for a page is always on the higher side. In this article, we shall see how to pre-compile the ASPX pages of an application after installation so that users of the application do not feel the initial delay during compilation of ASPX pages.

Background

The technique that we are going to use is very simple. We would simulate HTTP requests to all the ASPX pages in an application. This would result is the pages getting compiled. We would also pass a special request parameter with each request that would prevent unnecessary processing of all the code in ASPX pages.

How to make HTTP requests?

Writing code to fire HTTP requests for a web resource is very simple. We make use of the HttpWebRequest and HttpWebResponse classes available in the .NET framework. The code snippet below shows how to make a HTTP request for a ASPX page.

HttpWebRequest myHttpWebRequest = null;
HttpWebResponse myHttpWebResponse = null;
myHttpWebRequest = 
  (HttpWebRequest)WebRequest.Create("http://localhost/naren/test.aspx"); 
myHttpWebResponse = (HttpWebResponse)myHttpWebRequest.GetResponse();

About the Global.asax file

The Global.asax file contains global event handlers that get called for important events such as Session_Start, Application_Start, Application_BeginRequest etc. We are interested in the Application_BeginRequest event. This event is the first event in the HTTP pipeline chain of execution when ASP.NET responds to a request. We shall see further how we can make use of this event handler code for our pre-compilation tool.

The Pre-Compilation Tool

The Pre-Compilation tool that we are going to write is going to be a aspx page named PreCompile.aspx. This page needs to be placed in the root directory of the application we want to compile. In the Page_Load() event handler of this page, we simulate requests to all the ASPX pages in that application. This tool can be run by just pointing the browser to http://{host}/{virtual_root or application_root}/PreCompile.aspx.

Note: ASP.NET is optimized to do a batch-compile of all pages in a folder if any page in that folder is requested. But there is no guarantee that batch-compilation would always occur. It depends on the load on the server at that point of time. So it's safe to make requests to all pages in an application.

But how do we get URLs of all the pages in that application? We can get the physical path of the root folder of the current application through the PhysicalApplicationPath property of the request object. Once we get the physical folder path on the server, we can write a recursive function that would give us a list of all ASPX files in that application. The code snippet below demonstrates how this is done:

string rootDirectory = Request.PhysicalApplicationPath;
ArrayList arrayList = GetAllFiles(rootDirectory, 
  "*.aspx",true);//gets a list of all aspx files in a folder.

Then we construct URLs for each of the ASPX pages. For these HTTP requests, we make the host as 'localhost' since we are running the tool on the server. We get the virtual root of the application from the raw URI of the request. So, to construct a URL, we append the file name to 'http://localhost/{virtual_root}/". The below code snippet gives us an idea of how this can be done.

Note: Virtual folder path can be different from actual physical path of the root folder of an application.

string url = Request.RawUrl;
//Get the virtual root directory.
int index = url.LastIndexOf('/');
string virtualDirectory = url.Substring(0,index+1);
Response.Write("Virtual path is >> " + url);

Once we get the virtual path, then we construct the URL for each request as follows:

string uri = "http://localhost" + {virtualDirectory} + 
               {aspx file name} + "?PreCompile=true"

You must have observed that we are appending a HTTP request parameter (PreCompile=true) to the URL. We are doing so because on the server side, we shall check for this special request parameter. And if the request contains this special parameter, then we stop all processing and just return. This would prevent further unnecessary code processing of all ASPX pages, as we just want the pages to be compiled. And the best place to handle this is in the Application_PreRequestHandlerExecute event handler of Global.asax. The code snippet below shows how we can do this in Global.asax:

protected void Application_PreRequestHandlerExecute(Object sender, EventArgs e)
{
    string preCompile = Request["PreCompile"];
    if(preCompile != null)//If request is for Pre-Compile, just return..
    {
        Response.End();
        return;
    }
}

Using the code

To use the tool, just follow the steps below for your web application:

  1. Copy PreCompile.aspx and PreCompile.aspx.cs to the root directory of your application.
  2. Add the Application_PreRequestHandlerExecute event handler to your application's Global.asax file.
  3. Simply make a request to the PreCompile.aspx page from your web browser.

Points of Interest

This tool can be used to pre-compile any application, by just placing PreCompile.aspx and the code-behind file in the root folder of the web application.

In future releases of .NET framework, Microsoft is planning to provide developers with a similar tool to pre-compile aspx pages.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here

About the Author

Narendra Naidu
Architect
India India
Member
No Biography provided

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board.
Search this forum  
    Spacing  Noise  Layout  Per page   
GeneralAnother way to do the samememberpekadorweb29 May '07 - 6:04 
Hello everybody,
 
I've found another way to pre-compile a complete virtual directory in this URL
http://weblogs.asp.net/jgalloway/archive/2004/10/15/242677.aspx, does it do the same but more easily?
 
Best regards.
GeneralThe third step.memberjhtang11 Jan '06 - 3:36 
3.Simply make a request to the PreCompile.aspx page from your web browser.
 
according to your step 3, how do you make a request?
Questiondoes this solution actually do anything?memberTimRobinson3316 Aug '05 - 6:52 
First I wondered why it still said "precompiled ok" even when the page had syntax errors in.
 
Having a quick look at the code I notice it does not check the HTTP status code after requesting the pages, so I changed it to do this.
 
However, even with the status check in, I notice the HTTP status still returns 200 even if the page has a syntax error. Requesting a page with a syntax error usually returns 500.
 
Therefore my assumption is that the effect of the code in global.asax is to complete the HTTP request before any attempt has been made to compile the page. I suspect that the overall effect of running precompile.aspx is absolutely nothing.

 
--- Tim

AnswerRe: does this solution actually do anything?memberTimRobinson3322 Aug '05 - 1:36 
OK, I have got to the bottom of the problem and I feel a (partial) apology is in order.
 
The issue is not error checking itself - it is to do with forms authentication. Whenever the PreCompile.aspx makes a request for a page that needs to be authenticated, it is redirected to the login page. Because myHttpWebRequest has AllowAutoRedirect=true (the default) this causes it to retrieve the login page which, of course, succeeds. Hence if you run this on a site with forms authentication you will simply have precompiled the login page 200 times but it will appear to have worked.
 
The solution is rather more complicated. first you need to set myHttpWebRequest.AllowAutoRedirect=false which will allow you to see all the 302 errors. Then you will need to add a special page to your project (say PrecompileLogin.aspx) which logs the user in for the purposes of precompilation. In the main process, create a CookieContainer and request PrecompileLogin.aspx which will establish a forms authentication context on the server. Use the same cookie container whenever firing off the other URLs and they should be executed within this forms authentication context and hence will load OK.
 
There is another bug in the code where it tries to calculate the application path by doing string mnipulation on the raw URL. This only works if the Precompile.aspx is in the top level of the project. The solution is simply to use Request.ApplicationPath which returns the correct application path.
 
I'm afraid I cannot post updated source code as I have had to hack it extensively to make it work with my specific app, but I hope this helps anyone else who is trying to precompile forms authentication apps.
GeneralRunning this on forms authenticated foldersmemberwindust4 Jan '05 - 10:56 
This runs like it worked when requesting pages from forms-authenticated folders, but I'm not too sure if it's really running, or simply requesting the login page. I have two questions
 
- How can we make sure it's actually precompiling the intended page instead of the login page (by breakpointing global.asa?)
- If it's not really hitting the precompiled page, how can we impersonate?
 

GeneralTrapping Compilation ErrorssussAnonymous2 Jul '04 - 8:28 
If there was a compilation error on one of the pages, would this technique alert the person running the compilations script of the error?
 
We have been having issues with hung compilation processes locking files (vbc.exe). We are getting messages like this following our builds:
 
Cannot execute a program. The command being executed was "c:\winnt\microsoft.net\framework\v1.1.4322\vbc.exe" @"C:\WINNT\Microsoft.NET\Framework\v1.1.4322\Temporary ASP.NET Files\upg2\070f16ae\d3813c27\pvrbwmog.cmdline".
 
The only way around it is to restart IIS, or kill the VBC.EXE processes. I am going to try the technique described here to force a precompile of everything, but I think I will probably need to trap HTTP return codes in order to detect errors.


GeneralWhy not just be hardcore and ...memberleppie21 Jan '04 - 6:15 
write everything in the backend like me? Smile | :)
 
leppie::AllocCPArticle("Zee blog");
Seen on my Campus BBS: Linux is free...coz no-one wants to pay for it.

GeneralRe: Why not just be hardcore and ...memberRabidKangaroo21 Jan '04 - 8:03 
Doesn't everyone do it like this? I thought the whole point of separating the back-end logic and the front-end presentation was to get away from the "spaghetti"code of old school ASP...
 

 
"Those that say a task is impossible shouldn't interrupt the ones who are doing it." - Chinese Proverb
GeneralRe: Why not just be hardcore and ...memberpartyganger21 Jan '04 - 8:22 
Same here, there's probably one line of code in each aspx page, that transforms the XML using XLST..
GeneralRe: Why not just be hardcore and ...sussAnonymous1 Apr '04 - 3:43 
Hardcore or re-inventing the wheel - it's nice that you use XSLT and XML - but then you're rather missing the point of ASP.NET are you not? No matter how little you do in your ASP.NET page, there's still a delay for the compilation of the class on startup (actually it varies, in 'release' mode, a batch compile of all the ASPX pages in the same directory occurs, only in debug mode does it compile a single ASPX file only...). Whidbey does let you precompile all ASP.NET pages and deploy only a very minimal set of content over and above the assemblies to the server - which is especially useful as you can catch all of the compile-time errors in your ASP.NET page.

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Permalink | Advertise | Privacy | Mobile
Web01 | 2.6.130523.1 | Last Updated 31 Mar 2004
Article Copyright 2004 by Narendra Naidu
Everything else Copyright © CodeProject, 1999-2013
Terms of Use
Layout: fixed | fluid