internet - habilitar javascript en chrome en windows
Los eventos de scripting ya no se activan cuando un usuario abandona el sitio o cierra el navegador aunque la aplicación aún esté activa (1)
Llegué a la conclusión de que no hay forma de activar un evento cuando el navegador no está en el sitio. Parece que, por más ''genial'' que sea la idea de un latido del corazón, no hay una forma práctica de hacerlo funcionar desde un sitio web de aplicaciones ASP.NET que utiliza el código detrás con los Javascripts generados por páginas. Esperamos que esta publicación sea útil para otros que podrían estar considerando esto y evitar que pierdan su tiempo;)
Actualmente las rutinas de la aplicación se están volviendo a trabajar para usar el evento Session_End en su lugar. Cuando se dispara el evento Session_End, los datos de la sesión se han agotado, por lo que no puede usar variables de sesión para ninguna rutina de limpieza. En su lugar, el plan es crear algunas variables App_Code globales que se establecerán en el evento Session_Start y luego usarlas en el evento Session_End para eliminar cualquier dato de sesión inactivo y directorios temporales.
Un proyecto con el que estoy trabajando implementa tres "temporizadores" de script JAVA desde una página maestra para rastrear el tiempo de espera de la sesión y hacer un control de "latido". El temporizador "setTimerout" redirige al usuario a una página de advertencia si el conteo de tiempo de espera llega a 1 y medio minutos antes de que ocurra un tiempo de espera de la sesión. Los dos temporizadores "setInterval" se implementan para rastrear si el navegador del usuario permanece activo en el sitio. A continuación, se incluyen varios fragmentos de código que implementan los controladores de "temporizadores" y "Control de latidos" y "Control de latidos".
Código de página maestra para activar temporizadores:
Dim BaseAccountTimeout As Single = CType((CType(CurrentSessionTimeout, Single) - 1.5), Single)
If Session.Item("UseSessionTimeout") Then
Dim TimeoutAcount As String = CType(((BaseAccountTimeout * 60) * 1000), Integer).ToString
Page.ClientScript.RegisterStartupScript(Me.GetType, "TimeoutScript", "setTimeout(""top.location.href = ''" & GotoTimeoutPage & "''""," & TimeoutAcount & ");", True)
End If
If Session.Item("UseHeartBeat") Then
Dim BaseHeartBeatTimeout As Single = CType(CurrentHeartBeatTimeout, Single)
Dim BaseHeartBeatCheckTimeout As Single = CType((BaseHeartBeatTimeout + 1.5), Single)
Dim TimeoutHeartBeat As String = CType(((BaseHeartBeatTimeout * 60) * 1000), Integer).ToString
Dim TimeoutHeartBeatCheck As String = CType(((BaseHeartBeatCheckTimeout * 60) * 1000), Integer).ToString
Page.ClientScript.RegisterStartupScript(Me.GetType, "HeartBeatScript", "setInterval(""ajax.post(''/pages/heartbeat.ashx'', {id: ''" + Session.SessionID + "''}, function() {})""," & TimeoutHeartBeat & ");", True)
Page.ClientScript.RegisterStartupScript(Me.GetType, "HeartBeatCheckScript", "setInterval(""ajax.post(''/pages/heartbeatcheck.ashx'', {id: ''" + Session.SessionID + "''}, function() {})""," & TimeoutHeartBeatCheck & ");", True)
End If
Código de controlador de latido del corazón:
<%@ webhandler language="VB" class="HeartbeatHandler" %>
Imports System
Imports System.Web
Imports System.Data
Imports System.Data.SqlClient
Public Class HeartbeatHandler
Implements IHttpHandler
Public ReadOnly Property IsReusable As Boolean Implements IHttpHandler.IsReusable
Get
Return True
End Get
End Property
Public Sub ProcessRequest(ByVal ctx As HttpContext) Implements IHttpHandler.ProcessRequest
Dim sqlConnection1 As New System.Data.SqlClient.SqlConnection(ConfigurationManager.ConnectionStrings("ApplicationServices").ConnectionString)
Dim cmd As New System.Data.SqlClient.SqlCommand
Dim dreader As System.Data.SqlClient.SqlDataReader
Dim GotOne As Boolean = False
Dim ValuesString As String = ""
Dim FieldsString As String = ""
Dim id As String = ""
id = ctx.Request.Params.Item("id")
If IsNothing(id) Then id = ""
If id = "" Then GoTo EXITHEARTBEAT
cmd.Connection = sqlConnection1
cmd.CommandType = System.Data.CommandType.Text
If cmd.Parameters.Count = 0 Then
cmd.Parameters.Add("@uID", System.Data.SqlDbType.NVarChar)
cmd.Parameters.Add("@Date", System.Data.SqlDbType.DateTime)
cmd.Parameters.Add("@IP", System.Data.SqlDbType.NVarChar)
End If
cmd.Parameters("@uID").Value = id
cmd.Parameters("@Date").Value = CType(Now, DateTime)
cmd.Parameters("@IP").Value = HttpContext.Current.Request.UserHostAddress
Try
cmd.CommandText = "SELECT SessionID FROM aspnet_Sessions WHERE SessionID = @uID"
sqlConnection1.Open()
dreader = cmd.ExecuteReader()
If dreader.Read() Then GotOne = True
dreader.Close()
Catch ex As Exception
'' do nothing here
Finally
sqlConnection1.Close()
End Try
If GotOne Then
Try
ValuesString = "LastRequest = @Date"
cmd.CommandText = "UPDATE aspnet_Sessions SET " + ValuesString + " WHERE SessionID = @uID"
sqlConnection1.Open()
cmd.ExecuteNonQuery()
Catch ex As Exception
'' do nothing here
Finally
sqlConnection1.Close()
End Try
Else
Try
FieldsString = "(Record, LiveDate, SessionID, LastRequest, IPAddress)"
ValuesString = "(NEWID(), @Date, @uID, @Date, @IP)"
cmd.CommandText = "INSERT aspnet_Sessions " + FieldsString + " VALUES " + ValuesString
sqlConnection1.Open()
cmd.ExecuteNonQuery()
Catch ex As Exception
'' do nothing here
Finally
sqlConnection1.Close()
End Try
End If
EXITHEARTBEAT:
End Sub
End Class
Código de controlador de verificación Heartbeat:
<%@ webhandler language="VB" class="HeartbeatCheckHandler" %>
Imports System
Imports System.Web
Imports System.Data
Imports System.Data.SqlClient
Public Class HeartbeatCheckHandler
Implements IHttpHandler
Public ReadOnly Property IsReusable As Boolean Implements IHttpHandler.IsReusable
Get
Return True
End Get
End Property
Public Sub ProcessRequest(ByVal ctx As HttpContext) Implements IHttpHandler.ProcessRequest
Dim sqlConnection1 As New System.Data.SqlClient.SqlConnection(ConfigurationManager.ConnectionStrings("ApplicationServices").ConnectionString)
Dim cmd As New System.Data.SqlClient.SqlCommand
Dim dreader As System.Data.SqlClient.SqlDataReader
Dim GotOne As Boolean = Nothing
Dim ValuesString As String = ""
Dim FieldsString As String = ""
Dim LastRequest As DateTime = Nothing
Dim TimeDifference As Long = 0
Dim HeartBeatTimeout As Single = CommonCode.Common.DefaultHeartBeatTimeout
Dim MissedHeartBeats As Single = CommonCode.Common.DefaultMissedHeartBeats
Dim id As String = ""
id = ctx.Request.Params.Item("id")
If IsNothing(id) Then id = ""
If id = "" Then GoTo EXITHEARTBEATCHECK
cmd.Connection = sqlConnection1
cmd.CommandType = System.Data.CommandType.Text
Try
cmd.CommandText = "SELECT HeartBeatTimeout, MaximumMissedHeartBeats FROM aspnet_WebSiteSettings"
cmd.CommandType = System.Data.CommandType.Text
sqlConnection1.Open()
dreader = cmd.ExecuteReader()
If dreader.Read() Then
HeartBeatTimeout = dreader("HeartBeatTimeout")
MissedHeartBeats = dreader("MaximumMissedHeartBeats")
End If
dreader.Close()
Catch ex As Exception
'' do nothing here
Finally
sqlConnection1.Close()
End Try
Dim MaximumDifference As Single = (HeartBeatTimeout * MissedHeartBeats) + 0.5
If cmd.Parameters.Count = 0 Then cmd.Parameters.Add("@uID", System.Data.SqlDbType.NVarChar)
cmd.Parameters("@uID").Value = id
Try
cmd.CommandText = "SELECT SessionID, LastRequest FROM aspnet_Sessions WHERE SessionID = @uID"
cmd.CommandType = System.Data.CommandType.Text
sqlConnection1.Open()
dreader = cmd.ExecuteReader()
If dreader.Read() Then
If Not IsDBNull(dreader("LastRequest")) Then
If dreader("LastRequest").ToString.Trim <> "" Then
LastRequest = dreader("LastRequest")
TimeDifference = DateDiff(DateInterval.Minute, LastRequest, CType(Now, DateTime))
If TimeDifference > MaximumDifference Then GotOne = True
Else
GotOne = False
End If
Else
GotOne = False
End If
Else
GotOne = False
End If
dreader.Close()
Catch ex As Exception
'' do nothing here
Finally
sqlConnection1.Close()
End Try
If GotOne Then
Try
cmd.CommandText = "DELETE aspnet_Sessions WHERE SessionID = @uID"
cmd.CommandType = System.Data.CommandType.Text
sqlConnection1.Open()
cmd.ExecuteNonQuery()
Catch ex As Exception
'' do nothing here
Finally
sqlConnection1.Close()
End Try
CommonCode.Common.DeleteFromSessionIDCollection(id)
CommonCode.Common.SessionData(CommonCode.Common.DeleteSessionData, id)
CommonCode.Common.DisposeSession()
End If
EXITHEARTBEATCHECK:
End Sub
End Class
A continuación está el código en la página maestra:
var ajax = {};
ajax.x = function () {
try {
return new ActiveXObject(''Msxml2.XMLHTTP'')
} catch (e1) {
try {
return new ActiveXObject(''Microsoft.XMLHTTP'')
} catch (e2) {
return new XMLHttpRequest()
}
}
};
ajax.send = function (url, callback, method, data, sync) {
var x = ajax.x();
x.open(method, url, sync);
x.onreadystatechange = function () {
if (x.readyState == 4) {
callback(x.responseText)
}
};
if (method == ''POST'') {
x.setRequestHeader(''Content-type'', ''application/x-www-form-urlencoded'');
}
x.send(data)
};
ajax.get = function (url, data, callback, sync) {
var query = [];
for (var key in data) {
query.push(encodeURIComponent(key) + ''='' + encodeURIComponent(data[key]));
}
ajax.send(url + ''?'' + query.join(''&''), callback, ''GET'', null, sync)
};
ajax.post = function (url, data, callback, sync) {
var query = [];
for (var key in data) {
query.push(encodeURIComponent(key) + ''='' + encodeURIComponent(data[key]));
}
ajax.send(url, callback, ''POST'', query.join(''&''), sync)
};
Descubrí que los temporizadores de script de JAVA solo continúan activados mientras hay un navegador en el sitio. Tan pronto como el usuario cierra el navegador o se aleja del sitio, aunque la aplicación web todavía se está ejecutando, el único evento que los archivos es el evento "Session_End" de ASP.NET en Global.asax cuando la sesión expira. Ninguno de los "temporizadores" se disparará, lo cual supongo que es causado por el hecho de que la página maestra ya no está cargada, por lo que los scripts en el maestro no se disparan.
Realmente no me importa el temporizador "setTimeout", ya que no hay necesidad de redirigir a una página de tiempo de espera si el navegador ya no está activo en el sitio, por lo que el script puede permanecer en la página maestra. Sin embargo, los dos temporizadores de "setInterval" son los que trato de seguir para que la aplicación pueda detectar si el usuario abandonó el sitio y luego la aplicación puede eliminar los datos de sesión y los directorios temporales para esa sesión.
Mi pregunta es esta: ¿Alguien sabe de una manera de ejecutar estos dos guiones desde un servicio o de alguna otra forma para implementarlos, de modo que continúen disparando incluso si el navegador está cerrado o se ha ido a otro sitio?
¡Gracias! David
PD. Un pequeño trasfondo: las cuatro variables globales ''CurrentSessionTimeout'', ''CurrentHeartBeatTimeout'', ''DefaultHeartBeatTimeout'', & ''DefaultMissedHeartBeats'' y las dos variables de sesión ''UseSessionTimeout'' y ''UseHeartBeat'' se configuran cuando la aplicación comienza con valores almacenados en una base de datos SQL. Sin embargo, ninguno de los manejadores usa variables de sesión, sino que obtiene los valores que necesitan directamente de las variables globales o de la base de datos, ya que la sesión podría haber terminado antes de que el controlador dispare, es decir, si todavía se carga una página, que vuelve a la original motivo de esta publicación :)