Overview
While working on a recent conversion effort to migrate an ASP.Net application to DotNetNuke, I ran into a very tricky problem. I needed to be able to run some code during the Application_Start event. The code to be run is basic initialization code and should only be called one time when first starting the application. This seemed like a simple enough task. Like every module, I am limited in how I can tie into the DotNetNuke framework and the underlying ASP.Net pipeline. My module must be able to run in a stock DotNetNuke installation without any modification to the core code. Unfortunately for me, Application_Start is not a normal event. In fact, it is not an event at all. It is just a method in Global.asax that follows a standard naming convention, and that is called by the ASP.Net framework at a specified point in the application lifecycle.
DotNetNuke, as far as I know, does not allow me to tap into this "event" and therefore I needed to find some other method for initializing my module. During this conversion, I am trying to minimize the architectural changes, since both the standalone application and the DotNetNuke version will continue to be actively developed. The goal is to keep the two codebases as close as possible. My challenge was to come up with a method for executing a method one time as close to application startup as possible.
Solution
After doing some research on the web, I did not come up with any straight forward solutions. Most of the recommendations would have required extensive changes to the way the application being converted performed its initialization. One suggestion however, if given a little extra effort, looked like it just might do the trick. The suggested solution was to use a class constructor (also known as a static initializer) to execute the desired code.
Every class has two sets of constructors available: 1) an instance constructor (that may or may not have parameters) and which is called to instantiate a new class instance. 2) a class constructor (it has no parameters) and which is used to initialize static members of the class. The class constructor is guaranteed to only be called one time for the life of the application. It will be called the first time the class is instantiated, or the first time any static Field or Method is accessed. Because it can only be called one time during the life of the application, it exhibits some of the same characteristics as the Application_Start method in Global.asax.
To make this work, I created a simple class that includes a class constructor and a stub static method.
class AppStart
{
static AppStart()
{
System.Diagnostics.Debug.WriteLine("AppStart.Initialized");
AppLogic.ApplicationStart();
}
public static void Execute()
{
System.Diagnostics.Debug.WriteLine("AppStart.Execute");
}
}
This solved one part of my problem: I now had a method to guarantee that code would only be executed once. Now I needed an event that I could use that would occur before any other code would run for my module. A quick review of the "Asp.Net Application Life Cycle Overview" showed me that the Init event of an HttpModule was the first code accessible event in the lifecycle. This event is guaranteed to fire before any page access occurs. So now I just needed to create an HttpModule and add a call to AppStart.Execute() in the Init event. This will cause the class constructor for the AppStart class to execute one time, and to run before any other code in my module.
I still have some more testing to do to ensure everything is running smoothly, but so far everything looks good. I would be interested to hear what other module developers are doing to solve this problem.
NOTE: On further inspection, it appears that I might be able to use the DotNetNuke event framework to tap into the Application_Start event. I will need to investigate this avenue some more. In the meantime, I have a method that appears to work.