簡體   English   中英

即使應用仍處於活動狀態,當用戶離開網站或關閉瀏覽器時,腳本事件也不會觸發

[英]Scripting events no longer fire when a user leaves site or closes browser even though app is still active

我正在使用的項目從母版頁實現三個JAVA腳本“計時器”,以跟蹤會話超時並進行“心跳”檢查。 如果超時計數達到1分半鍾(會話超時之前),則“ setTimerout”計時器會將用戶重定向到警告頁面。 實現了兩個“ setInterval”計時器來跟蹤用戶的瀏覽器是否在站點上處於活動狀態。 以下是實現“計時器”以及“心跳”和“心跳檢查”處理程序的幾個代碼段。

激活計時器的母版頁代碼:

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

心跳處理程序代碼:

<%@ 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

心跳檢查處理程序代碼:

<%@ 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

以下是“母版”頁面上的代碼:

        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)
    };

我發現JAVA腳本計時器僅在網站上存在瀏覽器時才繼續觸發。 一旦用戶關閉瀏覽器或導航離開站點,即使Web應用程序仍在運行,則會話超時時,文件的唯一事件就是Global.asax中的ASP.NET“ Session_End”事件。 我認為不會觸發“計時器”,這是因為不再加載母版頁,因此母版上的腳本不會被觸發。

我真的不在乎“ setTimeout”計時器,因為如果瀏覽器不再在站點上處於活動狀態,則無需重定向到超時頁面,因此腳本可以保留在“母版”頁面上。 但是,兩個“ setInterval”計時器是我要保持運行的計時器,因此該應用程序可以檢測用戶是否已離開該站點,然后該應用程序可以刪除該會話的會話數據和臨時目錄。

我的問題是:是否有人知道從服務運行這兩個腳本的方法或其他實現這些腳本的方法,以便即使瀏覽器已關閉或已轉到另一個站點,它們也將繼續啟動?

謝謝! 大衛

PS。 背景知識:當應用程序從存儲在SQL數據庫中的值開始時,將設置四個全局變量'CurrentSessionTimeout','CurrentHeartBeatTimeout','DefaultHeartBeatTimeout','DefaultMissedHeartBeats'以及兩個會話變量'UseSessionTimeout'和'UseHeartBeat'。 但是,這兩個處理程序都不使用會話變量,而是直接從全局變量或數據庫中獲取它們需要的任何值,因為會話可能在處理程序觸發之前已經結束,也就是說,如果頁面仍在加載,則可以返回原始狀態。這篇文章的原因。 :)

我得出的結論是,當瀏覽器不在站點上時,沒有辦法觸發事件。 似乎像心跳加速的想法一樣“酷”,沒有一種切實可行的方法可以使ASP.NET應用程序網站正常工作,該網站在頁面生成的Javascripts后面使用代碼。 希望這篇文章對其他正在考慮的人有所幫助,並避免他們浪費時間;)

當前,正在重新編寫應用程序的例程以使用Session_End事件。 當Session_End事件觸發時,會話數據實質上消失了,因此您不能將會話變量用於任何清理例程。 相反,計划是創建一些將在Session_Start事件中設置的全局App_Code變量,然后在Session_End事件中使用它們,以刪除所有不活動的會話數據和臨時目錄。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM