c# - valid - El método HttpModule Init se llama varias veces, ¿por qué?
tag c# (4)
Estaba creando un módulo http y, mientras depuraba, noté algo que al principio (al menos) parecía un comportamiento extraño.
Cuando establezco un punto de interrupción en el método init del httpmodule puedo ver que el método init del módulo http se llama varias veces aunque solo inicié el sitio web para la depuración y realicé una única solicitud (a veces solo se atiende 1 vez) otras veces hasta 10 veces).
Sé que debería esperar varias instancias de HttpApplication en ejecución y para cada una de ellas se crearán los módulos http, pero cuando solicito una sola página, debe ser manejada por un único objeto de aplicación http y, por lo tanto, solo desencadenar los eventos asociados una vez. pero aún dispara los eventos varias veces por cada solicitud que no tiene sentido, aparte de que debe haber sido agregado varias veces dentro de esa httpApplication, lo que significa que es el mismo método init de httpmodule al que se llama cada vez y no una nueva aplicación http que se crea cada vez que llega a mi punto de ruptura (vea el ejemplo de mi código en la parte inferior, etc.).
¿Qué podría estar yendo mal aquí? ¿es porque estoy depurando y establezco un punto de interrupción en el módulo http?
Se ha dado cuenta de que parece que si inicio el sitio web para la depuración y paso rápidamente sobre el punto de interrupción en el httpmodule solo golpeará el método init una vez y lo mismo aplica para el manejador de eventos. Si, en cambio, lo dejo colgar en el punto de interrupción durante unos segundos, se llama al método init varias veces (parece que depende de cuánto tiempo espere antes de pisar el punto de interrupción). Tal vez esto podría ser una función incorporada para asegurarse de que el httpmodule se inicializa y la aplicación http puede atender solicitudes, pero también parece algo que podría tener consecuencias catastróficas.
Esto podría parecer lógico, ya que podría tratarse de finalizar la solicitud y, dado que he establecido el punto de ruptura, ¿cree que algo salió mal e intento llamar al método init nuevamente? ¿así que puede manejar la solicitud?
Pero, ¿es esto lo que está sucediendo y todo está bien (estoy adivinando) o es un problema real?
Lo que me preocupa especialmente es que si algo hace que cuelgue en el servidor "producción / en vivo" durante unos segundos, muchos controladores de eventos se agregan a través del init y, por lo tanto, cada solicitud a la página activa repentinamente el manejador de eventos varias veces.
Este comportamiento podría rápidamente derribar cualquier sitio.
He analizado el código .net "original" utilizado para los httpmodules para formsauthentication y rolemanagermodule, etc. pero mi código no es diferente de los que utilizan esos módulos.
Mi código se ve así.
public void Init(HttpApplication app)
{
if (CommunityAuthenticationIntegration.IsEnabled)
{
FormsAuthenticationModule formsAuthModule = (FormsAuthenticationModule) app.Modules["FormsAuthentication"];
formsAuthModule.Authenticate += new FormsAuthenticationEventHandler(this.OnAuthenticate);
}
}
Aquí hay un ejemplo de cómo se hace en el RoleManagerModule desde el framework .NET
public void Init(HttpApplication app)
{
if (Roles.Enabled)
{
app.PostAuthenticateRequest += new EventHandler(this.OnEnter);
app.EndRequest += new EventHandler(this.OnLeave);
}
}
¿Alguien sabe lo que está pasando?
(Solo espero que alguien pueda decirme por qué sucede esto y asegurarme de que todo está perfectamente bien) :)
ACTUALIZAR:
He tratado de reducir el problema y hasta ahora he descubierto que el método Init que se llama está siempre en un nuevo objeto de mi módulo http (en relación con lo que pensaba antes).
Parece que para la primera solicitud (al iniciar el sitio) todos los objetos de HttpApplication que se están creando y todos sus módulos intentan atender la primera solicitud y, por lo tanto, todos afectan al controlador de eventos que se está agregando. Realmente no puedo entender por qué está pasando esto.
Si solicito otra página, todas las HttpApplication''s creadas (y su moduless) volverán a intentar servir la solicitud, haciendo que golpee el controlador de eventos varias veces.
Pero también parece que si vuelvo a la primera página (u otra) solo una aplicación Http comenzará a encargarse de la solicitud y todo es como se esperaba, siempre y cuando no deje que cuelgue en un punto de quiebre.
Si lo dejo colgado en un punto de interrupción, comienza a crear nuevos objetos HttpApplication y comienza a agregar HttpApplications (más de 1) para servir / manejar la solicitud (que ya está siendo procesada por HttpApplication que actualmente está detenida en el punto de interrupción) .
Supongo o espero que pueda ser una forma inteligente "entre bastidores" de ayudar a distribuir y manejar la carga y / o los errores. Pero no tengo idea. Espero que algunos me puedan asegurar que está perfectamente bien y cómo se supone que debe ser.
Inspeccione HttpContext.Current.Request para ver qué solicitud se inicia el init del módulo. Podría ser el navegador enviando múltiples solicitudes.
Si está conectado a IIS, verifique los registros de IIS para saber si se recibió alguna solicitud para el momento en que se aloja en el punto de ruptura.
Aquí hay un poco de explicación sobre qué debe usar, cuándo y cómo funcionan. Cuándo usar Application_Start vs Init en Global.asax?
Editar: Más lectura
INFORMACIÓN: Instancias de aplicación, eventos de aplicación y estado de aplicación en ASP.NET
Es normal llamar al método Init () varias veces. Cuando se inicia una aplicación, el proceso de trabajo de ASP.NET instanciará tantos objetos HttpApplication como considere necesarios, y luego los agrupará (por ejemplo, los reutilizará para nuevas solicitudes, de forma similar a la agrupación de conexiones de bases de datos).
Ahora, para cada objeto HttpApplication, también instanciará una copia de cada IHttpModule que esté registrado y llamará al método Init muchas veces. Entonces, si se crean 5 objetos HttpApplication, se crearán 5 copias de su IHttpModule y su método Init se llamará 5 veces. ¿Tener sentido?
Ahora, ¿por qué se trata de crear instancias de 5 objetos HttpApplications? Bueno, tal vez su página ASPX tiene enlaces a otros recursos que su navegador intentará descargar, css, javascript, WebResource.aspx, tal vez un iframe en alguna parte. O tal vez el Proceso de trabajo de ASP.NET está "de humor" para iniciar más de 1 objeto HttpApplication, eso es realmente un detalle interno / optimización del proceso ASP.NET que se ejecuta bajo IIS (o el servidor web incorporado VS).
Si desea que el código se ejecute solo una vez (y no desea utilizar el evento Application_StartUp en Global.asax), puede intentar lo siguiente en su 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;
}
}
}
}
He hecho algo similar y parece funcionar, aunque agradecería las críticas de mi trabajo en caso de que me haya perdido algo.
Examinar arriba bloquea el IHttpModule para todas las solicitudes, y luego, libera toda la aplicación. Si su solicitud de llamadas IHttpModule es necesaria varias veces, llame al método HttpApplication CompleteRequest y deseche la instancia HttpApplication del IHttpModule en el evento EndRequest para eliminar la instancia de HttpApplication de esta manera:
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 necesita que las solicitudes de IHttpModule siempre, sin re-solicitud en la devolución de datos, use este código arriba.