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

Yet another pre-compile tool for ASP.NET web sites

By , 24 May 2004
 

Introduction

I know: the problem of pre-compiling an ASP.NET web site in order to avoid the classic "compilation delay" felt by the first user browsing those site's pages has been faced many times, and a lot of solutions have been proposed to solve it. But, when I was looking for these solutions to a classic problem, I didn't find the one that I liked completely. So, I decided to develop my own ASP.NET precompiler.

Of course, now you are thinking: "Uff, yet another pre-compile tool for ASP.NET web sites". And you're so right that I decided to title my article exactly with the words you have in your mind. But... before you stop reading, take a look at some peculiarities of the tool I propose.

Background

My starting point was the CodeProject article "Pre-Compile ASPX pages in .NET 1.1" by Narendra Naidu: there, the precompiling task was faced by simply adding to the web site a special ASP.NET page simulating an HttpWebRequest towards each ASPX page of the web site itself.

That was a nice and simple solution, but not suitable in my specific situation. In fact, I was looking for:

  • something not implemented as a part of the web site, but as a separate application;
  • something not forcing me to precompile all the pages of my web site, but capable to focus only on a specific subset of them (for example, the most frequently used ones);
  • something working also with web sites protected by the ASP.NET Web Form Authentication mechanism;
  • something able to simulate client web requests coming from a specific browser;
  • something with the ability to keep track of compilation errors.

The ASP.NET precompiler I wrote matches all these goals, in fact:

  • it's a Windows Forms application, that doesn't force you to include the precompiler logic inside the web site itself;
  • it doesn't retrieve the pages to visit recursively walking on the web application folders tree, but it takes them from a user-configurable list of URLs;
  • it works also with web sites protected by Web Form Authentication, supporting a specific POST of data to the Login page and correctly managing the client-side authentication cookie;
  • it can "impersonate" a specific user agent, allowing you to work also with sites where some browser checks are implemented to force a navigation restriction;
  • it logs any error occurring during HTTP requests, that is very useful if - for some reason (for example, to have a more flexible deploying strategy) - you are not compiling your site's code-behind pages into a DLL assembly (that is: you're taking advantage of the src attribute of the @Page directive).

How to use the tool

As stated before, the tool forces the compilation of ASPX files just invoking their URLs in a web request. The list of the URLs to be hit is stored in a user-editable text file, that we'll simply call "URL file". The format of the URL file is simple: it stores an URL on each line, separating with a TAB character the base URL part from the relative path of the ASPX page. This split URL paths make simpler to invoke the same set of pages on different web sites (this is useful, for example, if you have various copies of the same ASP.NET site on different environments).

To create the URL file, you can use ASP.NET precompiler itself: select the "Generate URLs" option from the "File" menu and specify: the physical location of your web site's files, the base URL that will precede the relative page path in the final URL, and the filename for your new URL file.

Generating URLs

ASP.NET precompiler will walk recursively the specified path looking for ASPX files and it will generate your URL file, that can be manually edited later (for example, to refine or limit the set of pages to be precompiled).

To make the ASP.NET precompiler less "invasive" on your site, you can adopt a trick I found in Narendra Naidu's article: by adding a Response.End() inside the pre-request event handler of Global.asax, you can abort the page processing and rendering when you call your pages with a special parameter (for example, PreCompile=true). In this way, the requests coming from ASP.NET precompiler will cause the page compilation but not the complete overhead of serving a complete web request.

  Private Sub Global_PreRequestHandlerExecute(...) _
                   Handles MyBase.PreRequestHandlerExecute
    ' Prevent processing if page was called with a "PreCompile" parameter
    If Not Request("PreCompile") Is Nothing Then Response.End()
  End Sub

If you are planning to use this trick, you'll need to check the "Include PreCompile parameter" option when generating the URLs list with ASP.NET precompiler. Also, keep in mind that the Global_PreRequestHandlerExecute() handler will be invoked for each page requested on your web application, and this might cause a little impact on the web site performance.

When the URL file is ready, before starting the pre-compilation process, you need to configure some parameters on the ASP.NET precompiler's main form:

ASP.NET Precompiler main form

  • specify the name of the URL file you are going to use;
  • if you need to simulate web request from a specific browser, fill the textbox User Agent with the correct user agent string;
  • if you plan to invoke the pages stored in the URL file substituting the original base URL path with another one, use the Alternative Web Root option;
  • if the site you're working on is protected by Web Form Authentication, use the Web Form Authentication option, specifying the relative path for the Login page and the parameters it expects; activating this option will produce a preliminary POST request to the Login page to obtain the authentication cookie for subsequent requests (don't forget to include the __VIEWSTATE parameter with a valid value in the POST params textbox);
  • if you want to log any error occurred during the compilation process, activate the Log errors option, specifying the filename for the log (that is an HTML-formatted file, for easy viewing in a browser window);
  • if you need to clear the error log or the cookies collection before compiling, use the Reset cookies or the Reset error log option respectively.

The configuration settings you just set can be saved to disk for future use. The reuse of ASP.NET Precompiler settings is accomplished by the options of the "File" menu (for the storage mechanism underlying the saving/retrieval of these data, see my article about managing configuration settings persistence).

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

Alberto Venditti
Technical Lead
Italy Italy
Member
I was born in 1970.
 
I studied Electronic Engineering (graduated in 1997).
 
Subsequently, I passed some Microsoft exams, and currently I'm certified as:
MCP, MCT, MCDBA, MCSD, MCAD, MCSD for .NET (early achiever).
 
My first computer experience dates back to early 80s, with a Sinclair ZX81.
From that time on, as many "friends" say, my IT-illness has increased year by year.

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   
GeneralEntering POST Paramsmemberdaleallenc30 Dec '08 - 7:00 
Hello, Alberto. "Homer" here again.
 
I have a couple of questions about entering values into the POST Params field (and please, I'm a sysadmin, not a developer/programmer):
 
1. The UserName (txtUserName), Password (txtPassword), and SignIn button parameters for our demo website are not the same as the default example given in the Untitled configuration file, so I assume that I need to change them to match what's given in the login page's source code. Only I'm not sure what to change them to. For example, the source code lists a label for="PC706_txtUsername", an input name="PC706$txtUsername", and an id="PC706_txtUsername". The password parameters are essentially the same. The submit button is equally problematic for me: input type="submit", name="PC706$btnLogin", value="Login", and id="PC706_btnLogin". What do I need to enter?
 
2. Your article says "don't forget to include the __VIEWSTATE parameter with a valid value in the POST params textbox" How do I do that?
 
Thanks again for your help. Even without making the authentication request, your precompiler makes our demo website extremely responsive on first request. In case you were wondering why I might be using this instead of the .NET 2.0 aspnet_compiler tool, it's because the Microsoft tool refuses to work if it finds a single error (and I don't have control or influence over the code). And there isn't any option for passing login parameters, either.
 
Have a safe and happy New Year!
GeneralRe: Entering POST ParamsmemberAlberto Venditti9 Jan '09 - 3:41 
Hi. Sorry for late reply, due to (finally!) some vacancies.
 
About your question #1:
If I'm not wrong, form POST parameters should use "name"s and not "id"s. So, you should try with:
PC706$txtUsername=yourName&PC706$txtPassword=yourPassword&PC706$btnLogin=Login
before trying with:
PC706_txtUsername=yourName&PC706_txtUsername=yourPassword&PC706_btnLogin=Login
 
About your question #2:
To retrieve a valid value for the VIEWSTATE param, you could:
a. navigate with your browser your login page
b. before logging in, inspect the HTML source
c. if you see inside your HTML form an INPUT hidden tag named "__VIEWSTATE", copy its "value" and supply it to the compiler tool concatenating it with other parameters:
...&PC706$btnLogin=Login&__VIEWSTATE=dDwtMzIyNjUxMzt0P...
I see you already inspected your login page HTML source: if you didn't see VIEWSTATE, maybe your login form doesn't include any VIEWSTATE.
 
---
 
In general:
if you still have problems in providing the right POST parameters, you could "sniff" them while navigating and logging in interactively on your login page (to "sniff", you could use the "Live HTTP Headers" add-on for Mozilla Firefox, for example).
 
Let me know if everything is okay.
 
Cheers, AV
GeneralRe: Entering POST Paramsmemberdaleallenc12 Jan '09 - 7:14 
That was perfect, Alberto. Many thanks. I was worried a little bit about the VIEWSTATE value because the hash value is over 3000 characters long, but your utility handled it without a problem.
GeneralRun from logon script or batch filememberdaleallenc4 Aug '08 - 8:12 
I actually have more than one question, but this is the scenario: I have a VMware virtual machine that our company's sales people use to demonstrate our web-enabled software. We've tried just suspending the VMs to save the website state in between demos, but that seems to break down the VM files quickly and unexpectedly leading to some embarrassing moments. I stumbled across this wonderful utility, and demos now run much smoother and with more confidence.
 
I'm normally a system administrator, not a developer, so I'm wondering:
 
1) Is it possible to run the utility, with the appropriately identified configuration file, from a logon script or batch file? (The less a sales person has to do, the better - and we'll both be happier)
 
And,
 
2) Is it possible for the pre-compiler to make more than one Web Form Authentication request?
AnswerRe: Run from logon script or batch filememberAlberto Venditti5 Aug '08 - 5:09 
Hi "daleallenc".
 
About your question number 1:
The simplest solution is to make the tool capable of handling some command-line argument in order to understand which config file has to be loaded and if the execution has to fire immediately the precompile operation. Supposing you want to support these following execution variations:
 
  > ASPdotNETprecompiler.exe -autorun
      will automatically start the precompile operation using the default config file ("Untitled.cfg")
  > ASPdotNETprecompiler.exe MyConfig.cfg
      will automatically load the specified config file ("MyConfig.cfg")
  > ASPdotNETprecompiler.exe -autorun MyConfig.cfg
      will automatically load the specified config file ("MyConfig.cfg") and start the precompile operation
 
all you will need is to modify the MainForm_Load() procedure in the following way:
 
  Private Sub MainForm_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
    Dim ConfigFilename As String = DefaultConfigFilename
    Dim AutoRun As Boolean = False
    Dim cla As String() = Environment.GetCommandLineArgs
    If cla.Length > 1 Then
      If cla(1).ToLower = "-autorun" Or cla(1).ToLower = "/autorun" Then
        AutoRun = True
        If cla.Length > 2 Then
          ConfigFilename = cla(2)
        End If
      Else
        ConfigFilename = cla(1)
      End If
    End If
 
    ConfigOpt.Initialize(ConfigFilename)
    ReadConfigValues()
    Me.Text = Application.ProductName & " - " & ConfigFilename
    ConfigToBeSaved = False
 
    If AutoRun Then
      cmdPreCompile_Click(Nothing, Nothing)
    End If
  End Sub
 

About your question number 2:
In order to make the tool execute multiple WFA, we need to modify the current concept of "Start with this Web Form Authentication request" checkbox. Maybe the best solution is to create a special syntax for specific lines in the URLs.txt file (to be manually edited) where more [Login URL / POST parameters] combination are specified in particular point of the URLs-to-be-visited sequence. Then, a simple modification in the "Main loop for hitting web requests taken from the URLs file" procedure is needed to manage the new case.
If you need just two or three WFA (followed by - I suppose - a set of child pages to be visited), my suggestion is to:
- implement the solution for question 1;
- prepare two or three appropriate config files, equipped with corresponding "URLs" files;
- execute (in a batch) ASPdotNETprecompiler.exe more times, sequentially, with the different configurations.
 
Hope this helps.
Cheers, AV
GeneralRe: Run from logon script or batch filememberdaleallenc6 Aug '08 - 3:25 
Thank you for your excellent and timely response, Alberto. I really didn't expect one since the last post here was over two years ago.
 
I modified the MainForm_Load() procedure as written (copy-and-pasted lines from Dim ConfigFileName... to last End If) in MainForm.vb.
 
I wasn't sure if I should overwrite the existing procedure or append to it. At first, I overwrote the existing procedure and when I received the behavior listed below, I then tried appending the new code to the existing. I separately ran both with the different execution variations from the CLI. In both cases, the resulting behavior was the same.
 
Behavior:
 
1. All execution variations opened the ASP.NET precompiler GUI but did not run the application.
 
2. All execution variations loaded the Untitled configuration file, even when others were named.
 
I guess we're thinking alike as far as question number 2. Your solution is exactly what I was thinking if the tool could be made to use command-line arguments.
GeneralRe: Run from logon script or batch file [modified]memberAlberto Venditti6 Aug '08 - 3:42 
Hi.
The code included in my preceding post is intended to "replace" the original content of MainForm_Load() procedure.
Maybe you're compiling the project with a newer version of Visual Studio or of the .NET Framework? The original code was for VS2003 and .NET 1.1 (and I only tested the proposed modifications on that original target).
Let me know, and we'll address the issue.
 
Ciao, AV
 
modified on Wednesday, August 6, 2008 11:49 AM

GeneralRe: Run from logon script or batch filememberdaleallenc7 Aug '08 - 3:54 
Ah, I thought something like that might be the case. The specific .NET Framework version we're using is v2.0.50727.
 
thanks
GeneralRe: Run from logon script or batch filememberAlberto Venditti7 Aug '08 - 5:36 
I actually converted the solution to VS2005 / .NET 2.0, I applied the modifications to Form_Load, and I found it working... Hence I find strange it is not working for you.
Are you sure you're launching the EXE having set the OS default directory to the one hosting the EXE itself, so that it is able to retrieve the config and URLs files correctly?
AV
GeneralRe: Run from logon script or batch filememberdaleallenc7 Aug '08 - 8:52 
Are you familiar with "The Simpsons" in Italy? Just call me Homer. DOH!
 
Not having programmed since college, I forgot that I needed to rebuild the executable after modifying the source code.
 
After converting the solution, applying the modifications, and rebuilding (DOH!) the executable, it works as advertised.
 
Is there a way to close the Main form from the command line after it's finished pre-compiling?

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

Permalink | Advertise | Privacy | Mobile
Web02 | 2.6.130523.1 | Last Updated 25 May 2004
Article Copyright 2004 by Alberto Venditti
Everything else Copyright © CodeProject, 1999-2013
Terms of Use
Layout: fixed | fluid