Question

Je créais un module http et pendant le débogage j'ai remarqué quelque chose qui, au début (au moins) semblait un comportement bizarre.

Quand je tournerai un point d'arrêt dans la méthode d'initialisation du HttpModule je peux voir que la méthode d'initialisation du module http est appelé plusieurs fois, même si je n'ai commencé le site pour le débogage et fait une demande unique (parfois il est touché seulement 1 fois, d'autres fois jusqu'à 10 fois).

Je sais que je devrais attendre plusieurs instances du HttpApplication être en cours d'exécution et pour chaque modules http seront créés, mais quand je demande une seule page il doit être manipulé par un seul objet d'application http et donc tirer que les événements associée une fois, mais il déclenche les événements à plusieurs reprises pour chaque demande qui n'a pas de sens - autre que doit avoir été ajoutée à plusieurs reprises dans ce HttpApplication - ce qui signifie qu'il est la même méthode init HttpModule qui est appelé à chaque fois et non une nouvelle application http créé à chaque fois qu'il frappe mon point de rupture (voir mon exemple de code en bas etc.).

Ce qui pourrait aller mal ici? est-ce parce que je suis le débogage et définir un point d'arrêt dans le module http?

Il a remarqué qu'il semble que si je démarre le site Web pour le débogage et l'étape rapidement sur le point d'arrêt dans le HttpModule il ne touche que la méthode d'initialisation une fois et le même pour les eventhandler. Si je laisse la place pendre au point d'arrêt pendant quelques secondes la méthode d'initialisation est appelée à plusieurs reprises (semble que cela dépend de combien de temps j'attends avant de monter sur le point d'arrêt). Peut-être que cela pourrait être une construction dans fonction pour vous assurer que le HttpModule est initialisée et l'application http peut répondre aux requêtes, mais il semble aussi quelque chose qui pourrait avoir des conséquences catastrophiques.

Cela pourrait sembler logique, car il pourrait essayer de terminer la demande et que j'ai mis le point de rupture, il pense que quelque chose a mal tourné et essayer d'appeler à nouveau la méthode init? soo il peut gérer la demande?

Mais est-ce ce qui se passe et tout va bien (je suis juste deviner), ou est-ce un vrai problème?

Qu'est-ce que je suis particulièrement préoccupé est que si quelque chose fait pendre sur le serveur « production / live » pendant quelques secondes un grand nombre de gestionnaires d'événements sont ajoutés par l'init et donc chaque demande à la page feux soudain eventhandler plusieurs fois.

Ce comportement pourrait rapidement mettre tout en bas du site.

Je l'ai regardé le code .net « original » utilisé pour les httpModules pour FormsAuthentication et etc RoleManagerModule mais mon code isnt différent que ces modules utilise.

Mon code ressemble à ceci.

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

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

ici est un exemple, comment cela se fait dans le RoleManagerModule du framework .NET

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

Est-ce que quelqu'un sait ce qui se passe?

(j'espère juste que quelqu'un là-bas peut me dire pourquoi cela se passe et me assurer que tout est parfaitement bien):)


Mise à jour:

J'ai essayé de cerner le problème et jusqu'à présent j'ai trouvé que la méthode Init étant appelée est toujours sur un nouvel objet de mon module http (contary à ce que je pensais avant).

Je semble que pour la première demande (lors du démarrage du site) tous les objets HttpApplication en cours de création et ses modules sont tous en essayant de servir la première demande et donc tous frapper la eventhandler qui est ajouté. Je ne peux pas vraiment comprendre pourquoi ce qui se passe.

Si je demande une autre page tout de l'HttpApplication créé (et leur moduless) sera à nouveau essayer de servir la demande l'amenant à frapper le eventhandler plusieurs fois.

Mais il semble aussi que si je en arrière puis sauter à la première page (ou un autre) seul HttpApplication va commencer à prendre soin de la demande et tout est comme prévu - aussi longtemps que je ne le laisser pendre à une pause Point.

Si je laisse pendreà un point d'arrêt, il commence à créer de nouveaux objets de HttpApplication et commence à ajouter HttpApplications (plus de 1) pour servir / gérer la demande (ce qui est déjà en train d'être servi par le HttpApplication qui est actuellement arrêté au point d'arrêt).

Je suppose ou espère que cela pourrait être une manière intelligente « dans les coulisses » d'aider à distribuer et gérer la charge et / ou des erreurs. Mais je n'ai aucune idée. J'espère que certains là-bas peut me assurer qu'il est parfaitement bien et comment il est censé être?

Était-ce utile?

La solution

  1. Vérifiez la HttpContext.Current.Request voir, pour ce demande est tiré init du module. Peut-être envoyer navigateur demande multiple.

  2. Si vous êtes connecté à IIS, faire vérifier les journaux IIS pour savoir si une demande est reçue pour le temps que vous restez au point de rupture.

Autres conseils

Il est normal que la méthode Init () à appeler plusieurs fois. Lorsqu'une application démarre, le processus de travail ASP.NET instanciera autant d'objets de HttpApplication car il pense qu'il a besoin, il va les mettre en commun (par exemple. Les resuse pour les nouvelles demandes, similaires à la mise en commun de connexion de base de données).

pour chaque objet HttpApplication, il sera également instancier une copie de chaque IHttpModule qui est enregistré et appeler la méthode Init que beaucoup de fois. Donc, si 5 objets HttpApplication sont créés, 5 copies de votre IHttpModule seront créés, et votre méthode Init appelé 5 fois. Sens?

Maintenant, pourquoi est-il instancié 5 objets HttpApplications dire? Eh bien peut-être votre page ASPX a des liens vers d'autres ressources que votre navigateur essayera de télécharger, css, javascript, WebResource.aspx, peut-être un iframe quelque part. Ou peut-être le processus de travail ASP.NET « est dans l'état d'esprit » pour commencer plus de 1 objet HttpApplication, c'est vraiment un détail interne / optimisation du processus ASP.NET fonctionnant sous IIS (ou VS construit serveur web).

Si vous voulez un code qui est garanti pour fonctionner une seule fois (et ne veulent pas utiliser l'événement Application_Startup dans le Global.asax), vous pouvez essayer ce qui suit dans votre 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;
            }
        }
    }
}

Je l'ai fait quelque chose de similaire et il semble fonctionner, mais je salue les critiques de mon travail au cas où je l'ai raté quelque chose.

examle verrouille au-dessus du IHttpModule pour toutes les demandes, puis, il frezes toute l'application. Si vos appels IHttpModule demande plusieurs fois est nécessaire pour appeler HttpApplication méthode CompleteRequest et éliminer l'instance HttpApplication du IHttpModule en cas EndRequest afin de supprimer l'instance de HttpApplication comme ceci:

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
    }

Si vous avez besoin que IHttpModule demande à chaque fois sans postback redemande utiliser ce sur le code ci-dessus.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top