Application_Start versus OnInit versus constructor
Asked Answered
G

3

8

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?

Goodrich answered 23/7, 2010 at 12:31 Comment(2)
Probably needs to be done in Application_Start so the framework can setup all those magic shared objects. Perhaps the class is touched before that and the static constructor would be run too early. – Purusha
@JoeKoberg, that's a good point. You have less control of when a static constructor is invoked than an explicit method call, of course. I still don't see the need for Init(), though. And Application_Start and Application_End should still be proper events. – Hautevienne
P
3

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.

Procarp answered 31/5, 2011 at 2:13 Comment(2)
I agree Application_End() is needed, but why isn't it (nor Application_Start) a proper event you can listen to? I understand the background compatibility with classic ASP, but not exposing the event doesn't make much sense to me. – Hautevienne
I think maybe the reason we have Application_Start is for initializations you can't perform in a static constructor - for example, if what you're initializing has a dependency on configuration value or something, that isn't available yet when the static constructor is called. That might be why. (It's a confusing mess either way. πŸ™„) – Methodize
D
5

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.

Danford answered 23/7, 2010 at 13:6 Comment(2)
Thanks for your answer. You didn't mention the constructor in your response, though. Why would you need Init() when you can do the same in the constructor with the added benefit of changing private fields to readonly? And why isn't Application_Start and Application_End proper events that can be hooked into with proper event handlers? Plus, will these be called once per worker process, per app domain or what? – Hautevienne
Once per worker process, right? Because you can create AppDomains in your own worker process without Application_Start firing. Often though, if you don't create your own app domains, then yes, it should be per AppDomain as well as worker processes, afaik. – Charcuterie
P
3

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.

Procarp answered 31/5, 2011 at 2:13 Comment(2)
I agree Application_End() is needed, but why isn't it (nor Application_Start) a proper event you can listen to? I understand the background compatibility with classic ASP, but not exposing the event doesn't make much sense to me. – Hautevienne
I think maybe the reason we have Application_Start is for initializations you can't perform in a static constructor - for example, if what you're initializing has a dependency on configuration value or something, that isn't available yet when the static constructor is called. That might be why. (It's a confusing mess either way. πŸ™„) – Methodize
M
0

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 .

Milks answered 23/7, 2010 at 12:39 Comment(1)
But why would you use the Init() method and not the constructor? What does the Init() method give you that the constructor doesn't? – Hautevienne

© 2022 - 2024 β€” McMap. All rights reserved.