views:

1381

answers:

4

I was creating a http module and while debugging I noticed something which at first (at least) seemed like weird behaviour.

When i set a breakpoint in the init method of the httpmodule i can see that the http module init method is being called several times even though i have only started up the website for debugging and made one single request (sometimes it is hit only 1 time, other times as many as 10 times).

I know that I should expect several instances of the HttpApplication to be running and for each the http modules will be created, but when i request a single page it should be handled by a single http application object and therefore only fire the events associated once, but still it fires the events several times for each request which makes no sense - other than it must have been added several times within that httpApplication - which means it is the same httpmodule init method which is being called every time and not a new http application being created each time it hits my break point (see my code example at the bottom etc.).

What could be going wrong here ? is it because i am debugging and set a breakpoint in the http module?

It have noticed that it seems that if i startup the website for debugging and quickly step over the breakpoint in the httpmodule it will only hit the init method once and the same goes for the eventhandler. If I instead let it hang at the breakpoint for a few seconds the init method is being called several times (seems like it depends on how long time i wait before stepping over the breakpoint). Maybe this could be some build in feature to make sure that the httpmodule is initialised and the http application can serve requests , but it also seems like something that could have catastrophic consequences.

This could seem logical, as it might be trying to finish the request and since i have set the break point it thinks something have gone wrong and try to call the init method again ? soo it can handle the request ?

But is this what is happening and is everything fine (i am just guessing), or is it a real problem ?

What i am specially concerned about is that if something makes it hang on the "production/live" server for a few seconds a lot of event handlers are added through the init and therefore each request to the page suddenly fires the eventhandler several times.

This behaviour could quickly bring any site down.

I have looked at the "original" .net code used for the httpmodules for formsauthentication and the rolemanagermodule etc but my code isnt any different that those modules uses.

My code looks like this.

    public void Init(HttpApplication app)
 {
  if (CommunityAuthenticationIntegration.IsEnabled)
  {
   FormsAuthenticationModule formsAuthModule = (FormsAuthenticationModule) app.Modules["FormsAuthentication"];   

   formsAuthModule.Authenticate += new FormsAuthenticationEventHandler(this.OnAuthenticate);
  }
 }

here is an example how it is done in the RoleManagerModule from the .NET framework

    public void Init(HttpApplication app)
 {
  if (Roles.Enabled)
  {
   app.PostAuthenticateRequest += new EventHandler(this.OnEnter);
   app.EndRequest += new EventHandler(this.OnLeave);
  }
 }

Do anyone know what is going on?

(i just hope someone out there can tell me why this is happening and assure me that everything is perfectly fine) :)


UPDATE:

I have tried to narrow down the problem and so far i have found that the Init method being called is always on a new object of my http module (contary to what i thought before).

I seems that for the first request (when starting up the site) all of the HttpApplication objects being created and its modules are all trying to serve the first request and therefore all hit the eventhandler that is being added. I cant really figure out why this is happening.

If i request another page all the HttpApplication's created (and their moduless) will again try to serve the request causing it to hit the eventhandler multiple times.

But it also seems that if i then jump back to the first page (or another one) only one HttpApplication will start to take care of the request and everything is as expected - as long as i dont let it hang at a break point.

If i let it hang at a breakpoint it begins to create new HttpApplication's objects and starts adding HttpApplications (more than 1) to serve/handle the request (which is already in process of being served by the HttpApplication which is currently stopped at the breakpoint).

I guess or hope that it might be some intelligent "behind the scenes" way of helping to distribute and handle load and / or errors. But I have no clue. I hope some out there can assure me that it is perfectly fine and how it is supposed to be?

+1  A: 

Here is a bit of explanation as to what you should use, when, and how they work. When to use Application_Start vs Init in Global.asax?

Edit: More reading

The ASP Column: HTTP Modules

INFO: Application Instances, Application Events, and Application State in ASP.NET

Greg Ogle
Thanks for your reply.I dont use any of them. Init in the global asax is overriding the init in HttpApplication. My problem is that the Init method in my httpmodule is being called several times.As far as i understand it, it should create the http modules for each http application. On each request one of the instanciated HttpApplication's will handle the request, and fire the events added, but of some reason the eventhandler *sometimes* get added more than once as the init method on the same http module (not one of the new created for other httpapplication's) is called serveral times.
MartinF
More to read added.
Greg Ogle
+1  A: 
  1. Inspect the HttpContext.Current.Request to see, for what request the module's init is fired. Could be browser sending multiple request.

  2. If you are connected to IIS, do check IIS logs to know whether any request is received for the time you are staying at the break point.

Ramesh
Correct. It happens because all requests (for any resource) hits the module. In my case because of the routing module it seems.
MartinF
A: 

It's normal for the Init() method to be called multiple times. When an application starts up, the ASP.NET Worker process will instantiate as many HttpApplication objects as it thinks it needs, then it'll pool them (eg. resuse them for new requests, similar to database connection pooling).

Now for each HttpApplication object, it will also instantiate one copy of each IHttpModule that is registered and call the Init method that many times. So if 5 HttpApplication objects are created, 5 copies of your IHttpModule will be created, and your Init method called 5 times. Make sense?

Now why is it instantiating 5 HttpApplications objects say? Well maybe your ASPX page has links to other resources which your browser will try to download, css, javascript, WebResource.aspx, maybe an iframe somewhere. Or maybe the ASP.NET Worker Process 'is in the mood' for starting more than 1 HttpApplication object, that's really an internal detail/optimisation of the ASP.NET process running under IIS (or the VS built in webserver).

If you want code that's guaranteed to run just once (and don't want to use the Application_StartUp event in the Global.asax), you could try the following in your IHttpModule:

private static bool HasAppStarted = false;
private readonly static object _syncObject = new object();

public void Init(HttpApplication context)
{
    if (!HasAppStarted)
    {
        lock (_syncObject)
        {
            if (!HasAppStarted)
            {
                // Run application StartUp code here

                HasAppStarted = true;
            }
        }
    }
}

I've done something similar and it seems to work, though I'd welcome critiques of my work in case I've missed something.

Sunday Ironfoot
A: 

Examle above locks the IHttpModule for all requests, and then, it frezes the whole application. If your IHttpModule calls request several times is needed to call HttpApplication method CompleteRequest and dispose the HttpApplication instance of the IHttpModule in EndRequest event in order to remove instance of the HttpApplication like this:

public class TestModule :IHttpModule
    {
        #region IHttpModule Members

        public void Dispose()
        {

        }

        public void Init(HttpApplication context)
        {
            context.BeginRequest += new EventHandler(context_BeginRequest);
            context.EndRequest += new EventHandler(context_EndRequest);
        }

        void context_EndRequest(object sender, EventArgs e)
        {
            HttpApplication app = sender as HttpApplication;
            app.CompleteRequest();
            app.Dispose();
        }

        void context_BeginRequest(object sender, EventArgs e)
        {
            //your code here
        }

        #endregion
    }

If you need that IHttpModule requests every time without rerequest on postback use this code above.

kinki