Domanda

stavo creando un modulo HTTP e durante il debug ho notato una cosa che in un primo momento (almeno) sembrava strano comportamento.

quando ho impostato un punto di interruzione nel metodo init della HttpModule posso vedere che il metodo di modulo http init viene chiamato più volte, anche se ho solo iniziato il sito web per il debug e fatto una sola richiesta (a volte viene colpito solo 1 volta, altre volte ben 10 volte).

Lo so che devo aspettarmi diverse istanze del HttpApplication per essere in esecuzione e per ogni verrà creato i moduli HTTP, ma quando chiedo una singola pagina che dovrebbe essere gestita da un unico oggetto di applicazione HTTP e quindi sparare solamente gli eventi associata una volta, ma ancora genera gli eventi più volte per ciascuna richiesta che non ha senso - altro che deve essere stato aggiunto diverse volte all'interno di tale HttpApplication - che significa che è lo stesso metodo init HttpModule che viene chiamato ogni volta e non un nuova applicazione http si crea ogni volta che colpisce il mio punto di rottura (vedi il mio esempio di codice in basso, ecc.).

Che cosa potrebbe andare male qui? è perché io sono il debug e impostare un punto di interruzione nel modulo http?

E 'notato che sembra che se mi STARTUP il sito web per il debug e rapidamente un passo sopra il punto di interruzione nel HttpModule sarà solo colpire il metodo init una volta e lo stesso vale per l'EventHandler. Se io invece lasciarlo al punto di interruzione per alcuni secondi il metodo init viene chiamato più volte (sembra che dipende da quanto tempo i attendere prima di salire sopra il punto di interruzione). Forse questo potrebbe essere un po 'di costruire in funzione per assicurarsi che il HttpModule viene inizializzato e l'applicazione HTTP può servire le richieste, ma sembra anche come qualcosa che potrebbe avere conseguenze catastrofiche.

Questo potrebbe sembrare logico, in quanto potrebbe essere cercando di finire la richiesta e dal momento che ho impostato il punto di interruzione si pensa qualcosa di essere andato storto e provare a chiamare di nuovo il metodo init? soo in grado di gestire la richiesta?

Ma è questo ciò che sta accadendo ed è tutto bene (io sono solo indovinando), o si tratta di un problema reale?

quello che sono particolarmente preoccupati è che se qualcosa fa pendere sulla "produzione / live" server per alcuni secondi un sacco di gestori di eventi sono aggiunte attraverso l'init e quindi ogni richiesta alla pagina spara improvvisamente l'EventHandler diversi volte.

Questo comportamento potrebbe portare rapidamente qualsiasi sito verso il basso.

Ho guardato il codice "originale" .net utilizzato per i httpModules per FormsAuthentication e l'etc rolemanagermodule ma il mio codice isnt qualsiasi diverso che quei moduli utilizza.

Il mio codice simile a questo.

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

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

qui è un esempio di come si è fatto nel RoleManagerModule dal framework .NET

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

Do qualcuno sa cosa sta succedendo?

(spero solo che qualcuno là fuori mi può dire perché questo sta accadendo e mi assicuro che tutto è perfettamente bene):)


UPDATE:

Ho cercato di circoscrivere il problema e finora ho trovato che il metodo Init essere chiamato è sempre su un nuovo oggetto del mio modulo HTTP (contary a quello che ho pensato prima).

Mi sembra che per la prima richiesta (all'avvio del sito) tutti gli oggetti HttpApplication in fase di creazione ed i suoi moduli sono tutti cercando di servire la prima richiesta e quindi tutti colpire l'EventHandler che viene aggiunto. Non posso davvero capire perché questo sta accadendo.

Se chiedo un'altra pagina tutte le funzionalità del HttpApplication creato (e la loro moduless) tenterà di nuovo di servire la richiesta inducendolo a colpire l'EventHandler più volte.

Ma sembra anche che se poi tornare alla prima pagina (o un altro) una sola HttpApplication inizierà a prendersi cura della richiesta e tutto è come previsto - fino a quando io non lasciarlo in una pausa punto.

Se ho lasciato penderead un punto di interruzione inizia a creare oggetti di nuova HttpApplication e inizia l'aggiunta HttpApplications (più di 1) per servire / gestire la richiesta (che è già in procinto di essere servito dalla HttpApplication che attualmente è fermato al punto di interruzione).

Credo o spero che potrebbe essere un po 'intelligente "dietro le quinte" modo di contribuire a distribuire e gestire il carico e / o errori. Ma non ho idea. Spero che un là fuori mi può assicurare che è perfettamente bene e come si suppone che sia?

È stato utile?

Soluzione

  1. Controllare la HttpContext.Current.Request per vedere, per quello che chiedere init del modulo è sparato. Potrebbe essere il browser l'invio di richiesta multipla.

  2. Se si è connessi a IIS, fare controllare i registri IIS per sapere se ogni richiesta viene ricevuto per il momento si alloggia presso il punto di rottura.

Altri suggerimenti

E 'normale che il metodo Init () per essere chiamato più volte. Quando un'applicazione si avvia, il processo ASP.NET Worker sarà istanziare come molti oggetti HttpApplication come si pensa di cui ha bisogno, allora sarà li all'aperto (ad es. Li resuse per le nuove richieste, simili a pool di connessione al database).

Ora, per ogni oggetto HttpApplication, sarà anche istanziare una copia di ciascuna IHttpModule che viene registrato e chiamare il metodo Init che molte volte. Quindi, se vengono creati 5 oggetti HttpApplication, verranno creati 5 copie del tuo IHttpModule, e il metodo Init chiamato 5 volte. Dare un senso?

Ora perché è istanziare 5 oggetti HttpApplications dire? Beh, forse la pagina ASPX ha link ad altre risorse che il vostro browser cercherà di scaricare, CSS, JavaScript, WebResource.aspx, forse un iframe da qualche parte. O forse il processo di ASP.NET Worker 'è in vena' per l'avvio oggetto più di 1 HttpApplication, che è davvero un dettaglio / ottimizzazione interna del processo di ASP.NET in esecuzione in IIS (o il VS costruita nel web server).

Se si vuole il codice che è garantito per funzionare solo una volta (e non vogliono utilizzare l'evento Application_Startup nel Global.asax), si potrebbe provare quanto segue nel 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;
            }
        }
    }
}

Ho fatto qualcosa di simile e sembra funzionare, anche se mi piacerebbe benvenuto critiche del mio lavoro in caso ho perso qualcosa.

examle sopra blocca l'IHttpModule per tutte le richieste, e poi, si frezes l'intera applicazione. Se le chiamate IHttpModule richiedere più volte che è necessario chiamare il metodo HttpApplication CompleteRequest e smaltire l'istanza HttpApplication del IHttpModule nell'evento EndRequest al fine di rimuovere istanza del HttpApplication in questo modo:

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
    }

Se è necessario che IHttpModule richiede ogni volta senza rerequest su postback utilizzare questo codice di cui sopra.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top