views:

167

answers:

2

We are trying to remove the global.asax from our many web applications in favor of HttpModules that are in a common code base. This works really well for many application events such as BeginRequest and PostAuthentication, but there is no Application Start event exposed in the HttpModule.

I can think of a couple of smelly ways to overcome this deficit. For example, I can probably do this:

protected virtual void BeginRequest(object sender, EventArgs e)
{
    Log.Debug("Entered BeginRequest...");
    var app = HttpContext.Current.Application;
    var hasBeenSet app["HasBeenExecuted"] == null ? false : true;

    if(!hasBeenSet)
    {
        app.Lock();
        // ... do app level code

        app.Add("HasBeenExecuted", true);
        app.Unlock();
    }

    // do regular begin request stuff ...
}

But this just doesn't smell well to me.

What is the best way to invoke some application begin logic without having a global.asax?

+1  A: 

Just keep a static bool in the HttpModule:

private static bool _hasApplicationStarted = false;
private static object _locker = new object();

private void EnsureStarted()
{
    if (_hasApplicationStarted) return;

    lock (_locker)
    {
        if (_hasApplicationStarted) return;

        // perform application startup here

        _hasApplicationStarted = true;
    }
}

Then have any method that needs the application to have started just call EnsureStarted.

John Saunders
@John: This looks like a singleton pattern. I'd be a little worried about using the static because of threading issues when, say, multiple requests come in at the same time. The application object at least has some simple Lock/Unlock to help out with that.
Sailing Judo
@John: I see you added that now... :)
Sailing Judo
@Sailing: the lock has always been there. The answer hasn't been edited.
John Saunders
@John: In my head it wasnt there. But there are a lot of things missing from my head....
Sailing Judo
This appears to work very well. I like this much better than what I was planning.
Sailing Judo
A: 

HttpModules and HttpHandlers will execute on every single request, while the Global.asax App Start event is when the application starts, thus only once.

You could make a general global.asax which will load all assemblies with a specific interface, and then drop in the dll's you want executed for that specific application. Or even register them in your web.config, and have your general global.asax read the keys, and then load and execute the code you want.

I think this is better than putting app once code in a module and checking on a state variable.

Mikael Svenson
One of the goals is to remove the global.asax. If we can't do that there are other approaches we can take which will be more simple than what you describe (for example, we can make the Application_Start() call a static method in the HttpModule class).
Sailing Judo
Guess I just wondered why it's simpler to get rid of global.asax than to include a HttpModule?
Mikael Svenson
Well, I'm already using an HttpModule, which is already registered in the web.config. I would say adding a some reflection and file IO to the application start event to "load all the assmeblies with a specific interface" is not as simple as call a static method on another class.
Sailing Judo
@Sailing Judo, What I proposed is to generate a boiler plate global.asax to be used in all applications, thus you create it once. Then register the assemblies just like you do with a HttpModule. Then you don't have to think about global.asax, and you can add/change modules at will like you do with HttpModule. The difference is that you load them in the app start event of global asax. You could even create your own Visual Studio Web project template which includes your boiler plate global.asax.
Mikael Svenson
I see what you mean. The way you worded it in your answer evoked a different image in my head than how you said it in the response. Sorry for the misunderstanding.
Sailing Judo
@Sailing Judo, my mistake as my intentions didn't come across good enough :) But if you are developing third party solutions you cannot rely on modifying global.asax, so using a static instance in a HttpModule might very well be the best solution until the API's are modified.
Mikael Svenson