2 Stimmen

Wie kann ein HttpModule auf NUR EINEN Anruf pro Anfrage begrenzt werden?

Hier ist mein HttpModule-Implementierung:

Datei mit Modul:

public class HttpModuleRewriter : IHttpModule
{
    #region IHttpModule

    public void Init(HttpApplication app)
    {
        app.BeginRequest += ProcessRequest;
    }

    public void Dispose()
    {
    }

    #endregion

    #region Protected Methods

    protected void ProcessRequest(object sender, EventArgs e)
    {
        ...
    }
}

web.config:

Ich habe einen Breakpoint in der 'Init'-Methode der HttpModuleRewriter-Klasse gesetzt. Die Methode wird beim Start der Anwendung das erste Mal aufgerufen... und für jede Anfrage an Seiten wird das Modul nur einmal aufgerufen.

Wenn ich Anfragen an Seiten schnell durchführe (die zweite Anfrage erfolgt, bevor die erste Anfrage verarbeitet wird), wird die 'Init'-Methode zusätzlich einige Male aufgerufen und für jede folgende Anfrage an Seiten verursachen 2-3 Aufrufe meines Moduls...

Warum? Wie kann ich das vermeiden?

Danke.

P.S. Ich habe einen öffentlichen Konstruktor in HttpModuleRewriter hinzugefügt, um die Anzahl der Referenzen zu berechnen, und während meinen Anfragen wurden 5 Module erstellt... und für jede Anfrage an die Seite werden tatsächlich 2 Module aufgerufen... aber nur für die erste aufgerufene Seite, für alle folgenden Seiten (ich habe 3 weitere überprüft) werden die Module nur einmal aufgerufen (nur 1 Instanz wird aufgerufen)...

Warum wird die erste Seite zweimal verarbeitet? Die vorgeschlagene Antwort (die Verwendung der 'initialisierten' Flagge) hilft auch nicht.

5voto

Øyvind Punkte 1600

Wenn Init() nicht vor dem Eintreffen des zweiten Requests abgeschlossen ist, ist Ihr HttpModule noch nicht bereit. Wenn Sie Code in Ihrer Init()-Methode haben, der nur einmal ausgeführt werden soll, können Sie ein Flag (bool initialisiert) setzen und einen Sperrmechanismus verwenden, um zu verhindern, dass der Code von mehr als einem Thread ausgeführt wird, z. B .:

private static bool initialisiert;
private static object lockObject = new object();

public void Init(HttpApplication app)
{
    lock(lockObject)
    {
        if(!initialisiert)
        {
            app.BeginRequest += ProcessRequest;
            // ... anderer Code hier
            initialisiert = true;
        }
    }
}

Update: Wie dieser Artikel erklärt, kann ASP.NET mehr als eine Instanz Ihres HttpModules erstellen, daher kann Init() mehrmals aufgerufen werden. Dies ist so konzipiert. Daher müssen Sie das Modul so gestalten, dass Code, der nur einmal ausgeführt werden soll, nur einmal ausgeführt wird - durch Anwendung einer Sperrvorrichtung wie oben.

3voto

Paul Suart Punkte 6284

Ich würde sagen, die offensichtliche Antwort ist, dass Ihr Handler wahrscheinlich mehr als eine Anfrage verarbeitet, wahrscheinlich für Stylesheets oder Bilder.

Fügen Sie das folgende in Ihren ProcessRequest-Ereignishandler ein und fügen Sie einen Watch zu context.Request.PhysicalPath hinzu, um dies zu bestätigen.

HttpApplication application = (HttpApplication)sender;
HttpContext context = application.Context;

string filename = Path.GetFileName(context.Request.PhysicalPath);

Wenn Sie nicht möchten, dass Ihr Handler für Anfragen nach Bildern usw. ausgeführt wird, müssen Sie nur überprüfen, ob der Pfad mit ".aspx" oder ähnlichem endet.

1voto

user2173353 Punkte 4062

Wenn Sie Init() zweimal ausführen, wird das BeginRequest-Ereignis zweimal Ihren Verarbeitungsprozess aufrufen, weil es zwei Ereignishandler darin hat. Der += Operator fügt den neuen Ereignishandler in eine Liste ein, er ersetzt nicht den alten Handler.

Øyvind hat eine korrekte Lösung.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X