Application_Start versus OnInit versus constructor - asp.net

I've gone rounds with this ever since I started programming classic ASP 12 (or so) years ago and I've never found a great solution because the architecture of ASP and ASP.NET has always been a swamp of bad practices, magic shared singletons, etc. My biggest issue is with the HttpApplication object with its non-event events (Application_Start, Application_End, etc.).
If you want to do stuff once for the entire lifespan of an HTTP application, Application_Start is the obvious place to do it. Right? Not exactly. Firstly, this is not an event per se, it's a magic naming convention that, when followed, causes the method to be called once per AppDomain created by IIS.
Besides magic naming conventions being a horrible practice, I've started to think it might be a reason there exist no such thing as a Start event on the HttpApplication object. So I've experimented with events that do exist, such as Init. Well, this isn't really an event either, it's an overridable method, which is the next best thing.
It seems that the Init() method is called for every instantiation of an HttpApplication object, which happens a lot more than once per AppDomain. This means that I might as well just put my startup logic inside the HttpApplication object's constructor.
Now my question is, why shouldn't I put my startup logic in the constructor? Why does even Init() exist and do I need to care about Application_Start? If I do, can anyone explain why there is no proper event or overridable method for this pseudo-event in the HttpApplication object?
And can anyone explain to me why in a typical ASP.NET application, 8 instances of my HttpApplication are created (which causes the constructor and Init to run just as many times, of course; this can be mitigated with locking and a shared static boolean called initialized) when my application only has a single AppDomain?

The Asp.Net runtime keeps a pool of HttpApplication objects. Every .aspx request is processed by a single object which is allocated from the pool(8 objects in your case).
The answer to your question, Application_Start event is indeed called, but only for the first instance of the HttpApplication, not subsequent ones, so you can be sure that it is called exactly once whenever your application is started or the application pool of IIS is restarted. So is Application_OnEnd event (last instance)
meanwhile, the Init() and Dispose() are called on every instance of the HttpApplication object. That will be called on each instance a.k.a. each request.
Why do they do it that way..? maybe to balance performance and memory optimizations.
Hope i answered your question.

Calling Application_Start the first time an instance of HttpApplication is created, but not on subsequent instances seems a bit of a hack. Perhaps Microsoft didn't want to explain the concept of a static constructor to people who didn't really want to know.
Application_End(), however, seems to be a necessity, as there is no C# equivalent of a static destructor/finalizer. As hacks go, this isn't that bad. It just smells a little funny.

There is one HttpApplication object created for each concurrent request. That is each thread that ASP.NET creates gets its own instance of HttpApplication. Instances are re-used for subsequent requests in the same way that threads are re-used from the thread pool.
Use the Init method to initialize instance fields on the HttpApplication as these will only be initialized one the first instance if it is done in the Application_Start event .

Related

First Web API request triggers execution of Application_Start

I'm having a Web application that also integrates a Web API. Just today I've found myself surprised to see that the first REST request on the Web API re-triggers the execution of Application_Start (although it has been run already when starting the web page). After reading ASP.NET HttpApplication lifecycle and ASP.NET Application Life Cycle Overview, it seems that the REST request is spawning a new HttpApplication.
Further, on the MSDN it says:
The first time that an ASP.NET page or process is requested in an application, a new instance of the HttpApplication class is created. However, to maximize performance, HttpApplication instances might be reused for multiple requests.
This sounds to me that each request could potentially spawn a new HttpApplication and that thus, Application_Start must be written in a re-entrant or idempotent way. Is this conclusion right?
In my concrete case, I'm initializing a log writer in Application_Start which fails the second time because the file is already being used. I guess in the case of an application pool recycling this wouldn't be a problem, as the resources are freed in-between.
You can read further down on the provided link
The Application_Start and Application_End methods are special methods that do not represent HttpApplication events. ASP.NET calls them once for the lifetime of the application domain, not for each HttpApplication instance.
So there is no need to write Application_Start in a re-entrant or idempotent way.
Furthermore Application_Start is not called on the recycling of IIS. It gets called on the first request after recycling when the application is actually loaded by IIS.
As for your error, make sure you're disposing off your logger on Application_End so the file handle gets released.

Instantiated Object Lifetime

I'm designing a new ASP.NET website (ASP.NET is somewhat new to me so forgive stupid questions) and I was wondering about the life time of an object that I would instantiate in the Global.asax's Application_Start event (i.e. new myClass()). I would refer to the object through a static pointer somewhere.
The reason why I was thinking of doing this was to create a master object for the running ASP.NET application that would track some pieces of information per user (browser), even though I'm storing much of the info in my database. In other words, I wanted to use an array of sessions indexed by a user key, and this array would be an element in myClass that, as mentioned above, gets instantiated in the Global.asax's Application_Start event. I'll regularly trim my array to account for users who have gone off or haven't done anything after NN minutes.
Or, is this just nuts because objects instantiated during the application's life are not reliable in terms of lifetime.
Thanks in advance!
Kind regards,
Derek
Why not use the application cache?
Unfortunately, msdn appears to be down right now, but the link is
http://msdn.microsoft.com/en-us/library/system.web.httpcontext.cache.aspx
It is accessible in your asp.net site through the Context property of the current HttpApplication.
Where you create the object doesn't matter, what matters is where you store the reference to the object.
If you put the reference in a static variable, the object will survive as long as the application is running.
Using static variables in a web application can have its uses, but you have to be careful as a web application is multi threaded. If you change any data in the object, you have to synchronise the access to the data, so that only one thread at a time can access it.

What code whould be placed in the application_start and the session_start events in global.asax?

Can you give an example of what might be best suited to place in the Application_Start and Session_Start subroutines?
I know when each subroutine is called.
Application_Start when the first user first accesses the web application.
Session_Start when a user opens a session with the application.
But what code belongs in each of these subroutines. What should the code in each subroutine do?
Just any examples? Well, in an MVC site the routes are registered in Application_Start. That's also a good place to initialize an IoC container such as StructureMap. Maybe initialize some singletons you have in your application if you want them to be readily available rather than late-bound when a user accesses them (like if they have a high initialization cost and you'd rather do one slow initial hit on the website yourself than bother a customer or two with it).
Session_Start is generally used less often, but could be a good place for per-user (or per-session, realistically) tracking of some kind.
Application_Start is often used to initialize application wide settings which need to be done once per application domain like registering object containers, reading some config initialization values, ... In Session_Start you could place some code which is tied to the specific user who started the session.
Be careful with exception handling in Application_Start. In IIS7 Integrated mode you won't have the response object or HTTPContext. See this thread: Request is not available in this context

Advanced: How many times does HttpModule Init() method get called during application's life?

Web application initialization is as follows:
As we know when IIS receives the first request for a particular Asp.net application resource, IIS creates an instance of a HttpApplication (defined in global.asax codebehind).
When this new instance is created it's initialization happens that also checks all configured HTTP modules.
All modules are then instantiated and put in the application's Modules collection (of type HttpModuleCollection)
modules are looped through and their Init() method is called (when they register for request events)
As far as I understand it the above scenario happens when a web application is started/initialized (hence application start event).
What happens with modules?
Are they (re)instatiated on each request or reused from the Modules property on each consecutive request while the web application is alive? As I understand IIS and Asp.net they are reused through the whole life of a web application.
If they are reused, can we assume that their Init() method is actually a pseudo event handler for application start event? The thing is we can't attach to application level events within http modules. But if they are being reused we could use Init() as application start event and do whatever we'd put in global.asax instead.
Question
Can we assume that module's Init() method is called only on application start event? Could we use this assumption to i.e. register routes for applications whose global.asax codebehind we can't change? web.config is usually accessible and we can change it the way we want.
Would this actually work?
Additional info
We can check HttpApplication code and check its InitModulesCommon() method. This one actually calls Init() of each registered HTTP module. What is more interesting is that this method is only used by InitIntegratedModules() and InitModules() methods. Which are both used only in HttpApplication.InitInternal() method. This is the basis of my assumptions, but I would like to know whether someone has abused IHttpModule.Init() for application start event.
Init() is called only once (per HttpApplication instance)
After I tested this the inner workings of IHttpModule initialization are as follows:
Every IHttpModule is initialized at web application start by instatiating and a call to Init() method
HttpApplication stores all module instances in its Modules property
Modules are then reused for the whole life of an HttpApplication and are not discarded/reinitialized as long as the application is alive
So the best outcome is
You can't attach an IHttpModule to application level events, but you can use its Init() method as pseudo application start event delegate. Inside it you can execute any code that you'd usually put inside Application_Start delegate in your Global.asax.
You can also read detailed information about it in my blog post.
But be careful in real-life web server environment
But IIS uses something called application pools. And each pool can have an arbitrary number of HttpApplication instances. Yes multiple. Application starting creates all these instances. Every one of them initializes their own list of modules but only the first one executes the Application_OnStart event handler.
So whenever your module modifies some common shared resource, you should take extra measures to indicate that the first module has done that and others won't do it again. Read an additional blog post about it that will show you how and when to use thread locking with your module to make it actually act as an Application_OnStart event handler. BTW: It's also possible to handle Application_OnEnd event if you need to. ;)
Detailed blog post links
Writing a custom IHttpModule that handles Application_OnStart event
How to correctly use IHttpModule to handle Application_OnStart event
Application_Start is only run once for the lifetime of your application.
IHttpModule.Init is run for each instance of HttpApplication, before request processing begins. See the walkthrough. Init is where you can register events used to process the request.
An instance of HttpApplication can be reused for multiple requests. ASP.Net pools HttpApplication objects, so the Init will be called once for every new instance of HttpApplication

Why is HttpApplication constructor called several times

Can somebody explain why the constructor of a custom class derived from HttpApplication is called several times upon application startup?
My code structure is the following:
- My Global class in global.asax derives from CustomApp class.
- The CustomApp class derives from HttpApplication class
The Global class is created at startup, but when I place a breakpoint in the constructor, it is invoked several times! I thought there should be only one instance of Application class created?
Am I wrong?
UPD: the web server can indeed create several HttpApplication instances to process multiple requests coming in at the same time. This becomes especially apparent when you place a breakpoint in the constructor of your HttpApplication descendant. Several requests will be pending from the client (http content, CSS files, etc) and to serve each of them the web server will create new instances of HttpApp. So, beware of this, when writing the application initialization logic.
I believe the ASP.NET runtime may create more than one HttpApplication per application domain. So HttpApplication.Init and the Ctor may get called more than once.
If you want to have initialization code that only runs once, you should use the Application_Start event which will only be called once per app.
Please have a look at a post global.asax in ASP.NET - it explains why there are multiple instances of the HttpApplication. Basically there are two pools: special and normal. Normal pool contains instances of the HttpApplication which are used by the requests (each requests has its own HttpApplication instance). Special pool contains HttpApplication objects used for application-level events (like Application_Start, Application_Error).

Resources