2010-02-02 15 views
6

Estoy ejecutando VS 2008 y .NET 3.5 SP1.ASP.NET - IHttpModule.BeginRequest activando 2X, Application_BeginRequest disparando 1X

Quiero implementar el seguimiento de visitas en un HttpModule en mi aplicación ASP.NET. Bastante simple, pensé. Sin embargo, el evento BeginRequest de mi HttpModule se activa dos veces por cada visita a la página. El sitio es muy simple en este momento ... sin seguridad, solo un poco de trabajo en la base de datos. Debería iniciar sesión una fila por página. ¿Por qué este evento se dispara dos veces?

Además, IHttpModule.BeginRequest realmente dispara una cantidad diferente de veces para el primer hit de la página cuando se ejecuta por primera vez (desde un navegador web cerrado) ... 3 veces cuando estoy llegando al DB para proporcionar datos dinámicos para la página, y solo 1 vez para las páginas donde no se golpea la base de datos. Dispara 2 veces por cada página golpeada después de la primera, independientemente de si toco o no la base de datos.

Es interesante observar que Application_BeginRequest (en Global.asax) siempre se activa solo una vez.

Aquí está el código:

using System; 
using System.Data; 
using System.Data.Common; 
using System.Net; 
using System.Web; 
using BluHeron.BusinessLayer; 
using Microsoft.Practices.EnterpriseLibrary.Data.Sql; 

namespace BluHeron.HttpModules 
{ 
    public class SiteUsageModule : IHttpModule 
    { 
     public void Init(HttpApplication httpApp) 
     { 
      httpApp.BeginRequest += OnBeginRequest; 
     } 

     static void OnBeginRequest(object sender, EventArgs a) 
     { 
      UsageLogger.LogSiteUsage(((HttpApplication)sender).Context.Request); 
     } 

     public void Dispose() 
     { } 
    } 

    public static class UsageLogger 
    { 
     public static void LogSiteUsage(HttpRequest r) 
     { 
      string ipAddress = GetHostAddress(Dns.GetHostAddresses(Dns.GetHostName())); 
      string browserVersion = r.Browser.Type; 

      string[] urlChunks = r.RawUrl.Split('/'); 
      string page = urlChunks[urlChunks.GetLength(0)-1]; 

      SqlDatabase db = new SqlDatabase(Common.GetConnectionString()); 
      DbCommand cmd = db.GetStoredProcCommand("LogUsage"); 

      db.AddInParameter(cmd, "IPAddress", SqlDbType.NVarChar, ipAddress); 
      db.AddInParameter(cmd, "BrowserVersion", SqlDbType.NVarChar, browserVersion); 
      db.AddInParameter(cmd, "PageName", SqlDbType.NVarChar, page); 
      db.AddInParameter(cmd, "Notes", SqlDbType.NVarChar, ""); 

      db.ExecuteNonQuery(cmd); 
     } 

     private static string GetHostAddress(IPAddress[] addresses) 
     { 
      foreach (IPAddress ip in addresses) 
      { 
       if (ip.ToString().Length <= 15) 
       { 
        return ip.ToString(); 
       } 
      } 

      return ""; 
     } 
    } 
} 
+0

¿Puedes publicar el código que estás usando para el HttpModule? Parece que los eventos no están siendo enganchados correctamente. –

Respuesta

0

Una posibilidad es que hay otras peticiones en curso que no podría estar considerando. Por ejemplo, supongamos que su página ASPX hace referencia a algunas imágenes o archivos CSS. Si esas solicitudes pasan por la canalización ASP.NET, se llamará a su módulo y se registrarán como hits.

Además, cuando dice IHttpModule.BeginRequest ¿quiere decir que en IHttpModule.Init() está conectando HttpApplication.BeginRequest? De ser así, la razón por la que menciono arriba podría aplicarse.

+1

Otro ejemplo común es posible que desee agregar: 'ScriptResource.axd' o' WebResource.axd' –

+0

Init() se está llamando una sola vez. BeginRequest() se llama varias veces. Tendré que pensar en qué más podría estar causando las llamadas adicionales. Gracias. – birdus

+0

@birdus - ¿Te refieres a este init solo una vez? 'public void Init (HttpApplication httpApp)', en caso afirmativo, Application Init, una vez que se inicia la aplicación ... nada es específico, solo debe ejecutarse una vez. –

1

Esto es interesante. Eliminé la referencia al archivo CSS de la página maestra y obtuve menos hits repetidos en el HttpModule para ciertos navegadores (como se sugirió), pero aún obtengo repeticiones. Tengo 6 navegadores instalados y obtengo alguna variación entre ellos.

de referencia, esta es la URL que estoy enchufando a mis navegadores para estas pruebas:

http://localhost/BluHeron

default.aspx se establece como la página de inicio y es, de hecho, ser devueltos para la URL antes mencionada. Estoy usando HttpRequest.RawUrl para informar a qué página llegó el usuario. Específicamente, estoy dividiendo la cadena RawUrl y solo estoy informando el último elemento en la matriz de cadenas (ver código).

  • Todos y cada uno de los buscadores informan al presionar default.aspx, como se esperaba (RawUrl = /BluHeron/default.aspx).
  • 4 de los 6 buscadores también informan BluHeron (RawUrl =/BluHeron).
  • 3 de los 6 navegadores también están grabando un espacio en blanco en la base de datos (RawUrl =/BluHeron /).

Hay varias maneras de obtener informes precisos de cuántas personas están accediendo a cada página.

  1. de selección de la base de datos sólo las filas que realmente Lista Uno de mis páginas (ignorar/BluHeron y espacios en blanco)
  2. sólo tiene que utilizar Application_BeginRequest en el mundial.asax archivo (que parece consistentemente ser llamado una sola vez por página hit)
  3. Obtener esta resuelto

Por lo tanto, tengo opciones para conseguir buenos informes, incluso con los datos de mierda en la base de datos. Sin embargo, preferiría no tener basura en la base de datos y entender qué está pasando aquí.

¡Gracias por mirar a todos!

3

Esto puede ser demasiado tarde para la respuesta pero puede ser útil para otra persona. Me enfrenté con el mismo problema. El evento BeginRequest se desencadena dos veces para cada solicitud. Depuré el código y me di cuenta de que el primer activador para la solicitud de recursos real, pero el segundo es el resultado de la solicitud "favicon.ico". Al comienzo del evento BeginRequest, una simple comprobación de la solicitud favicon.ico elimina la segunda ejecución del método.

public void Application_BeginRequest(object sender, EventArgs e) { 
    HttpApplication app = (HttpApplication)sender; 
    HttpContext ctx = app.Context; 

    if (ctx.Request.Path == "/favicon.ico") { return; } 
1

bastante tarde en esto, pero se encontró con el mismo problema. En nuestro caso, fue debido a la solicitud anónima que devuelve el 401 por RFC. La segunda solicitud se autentica.

0

Nos lo resolvió mediante el uso de

HttpContext.Current.ApplicationInstance.CompleteRequest(); 

Esto debe evitar que el fuego dos veces el que está viendo.

0

La parte "Documento predeterminado" de IIS parece desencadenar un segundo evento BeginRequest. Si ha determinado que Request.Path es igual para HttpApplication en ambos controladores de eventos y su url termina con una barra inclinada, intente agregar una regla de reescritura de URL para atajar el procesamiento de "Documento predeterminado".

-1

Desactive Browser Link en Visual Studio 2013 en adelante, lo que provoca la segunda solicitud.

VS Snapshot

Esto produce cuando una aplicación se ejecuta desde Visual Studio.

+0

Debería ser evidente que una característica nueva en VS 2013 no podría haber causado problemas en VS 2008, por lo que es casi seguro que esta es la pregunta incorrecta para que se publique esta respuesta. –

Cuestiones relacionadas