Solved

User logout time

Posted on 2007-03-21
15
587 Views
Last Modified: 2008-01-09
The closing of the browser is not trapped by session_end in global.asax, right? Then what's the event for trapping when a user closes the browser or leaves a site in code behind? Is there such an event as session terminate and/or session abandon? If yes, where? What's the best way to detect the logout time of a user from a site by clicking logout, closing the browser, leaving the site, or letting session time expire?
The logout time needs to be logged in a table.
0
Comment
Question by:ksfok
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 8
  • 7
15 Comments
 
LVL 37

Expert Comment

by:samtran0331
ID: 18766380
>>The closing of the browser is not trapped by session_end in global.asax, right?
Yes it is, if you're using InProc.
But you still have to wait for the timeout to be reached even if the user closes the browser.
You can put the code to log the user out of the database in the session_end event

If you're using SQLServer or StateServer (instead of the default InProc) for state management, Session_end does *not* fire.
0
 

Author Comment

by:ksfok
ID: 18766839
Please elaborate in more detail on "If you're using SQLServer or StateServer (instead of the default InProc) for state management, Session_end does *not* fire." What's SQLServer doing here? Can only Session_End be used alone?
0
 
LVL 37

Expert Comment

by:samtran0331
ID: 18766877
A user's session can be maintained 3 ways:
InProc (IIS), StateServer, or SQLServer

The default is InProc.
If you use either of the other 2 methods, the Session_End event in global.asax is ignored and any code inside that event does not get executed.

Here's an article on the 3 different ways to maintain sessions:
http://www.codeproject.com/aspnet/ASPNETSession.asp
0
Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 

Author Comment

by:ksfok
ID: 18767451
OK.
Can Session() be invoked in a class file with logout time sub used in global.asax and other pages? What is the namespace to which Session() belong? I got blue wriggly line under "Session" in the class code below :

    Public Sub UserLogoutTime()
        Dim queryString As String = _
"UPDATE UserLoginHistory SET LogoutTime = getdate() WHERE Username='" & ("UserName") & "' AND SessionID='" & Session.SessionID() & "';"
        Using connection As New SqlConnection(ConfigurationManager.ConnectionStrings("LocalSqlServer").ConnectionString)
            Try
                Dim command As New SqlCommand(queryString, connection)
                connection.Open()
                command.ExecuteNonQuery()
            Finally
                connection.Close()
            End Try
        End Using

    End Sub

0
 

Author Comment

by:ksfok
ID: 18767590
How can global.asax call sub UserLogoutTime() from AdminSubs.vb (class file)?
0
 
LVL 37

Expert Comment

by:samtran0331
ID: 18770502
the actual filename isn't important...it's the name of the class that is important...so
in "AdminSubs.vb "...if the class begins like this:

public class adminsubs
     public sub userlogouttime
....

then in global.asax, you would:
(at top of page:)
import adminsubs

(in code:)
dim myAdmin as new adminsubs
myAdmin.userlogouttime


if you don't want to dim a new instance of the class, you need to make it a public shared function; then you can skip the declaration...
0
 
LVL 37

Expert Comment

by:samtran0331
ID: 18770525
>>I got blue wriggly line under "Session" in the class code below :
well...quickest way would be to change your sub to accept one param:

 Public Sub UserLogoutTime(byval theSessionID as string)
        Dim queryString As String = _
"UPDATE UserLoginHistory SET LogoutTime = getdate() WHERE Username='" & ("UserName") & "' AND SessionID='" & theSessionID & "';"
        Using connection As New SqlConnection(ConfigurationManager.ConnectionStrings("LocalSqlServer").ConnectionString)
            Try
                Dim command As New SqlCommand(queryString, connection)
                connection.Open()
                command.ExecuteNonQuery()
            Finally
                connection.Close()
            End Try
        End Using

    End Sub

and then in global.asax:
dim myAdmin as new adminsubs
myAdmin.userlogouttime(session.sessionid)
0
 

Author Comment

by:ksfok
ID: 18777743
Is it possible that when Sub Session_End fires any session variable filled previously will have a value =  nothing? I tested with a session variable that captures a user's name upon login. That session variable is found to be nothing in Sub Session_End.  Please advise a more reliable way to record a user's departure time.
0
 
LVL 37

Expert Comment

by:samtran0331
ID: 18778867
How are you testing?

I'm using this exact same logic to log users out of a db to maintain licensing, my function to delete the users session from the db is in session_end and accepts a session variable as a parameter and the user gets logged out of the db as expected...
0
 

Author Comment

by:ksfok
ID: 18780613
I  tested with Sub Session_End in which sub UserLogoutTime() is called but so far not a single time the user logout time is updated. Seems the only thing that works is user clicking logout button but not closing the browser, leaving the site, or letting session time expire?
0
 
LVL 37

Expert Comment

by:samtran0331
ID: 18781399
can you post the relevant code?
session_end works fine for me to log a user out of the database...
this is a working session end from my app:

    Sub Session_End(ByVal sender As Object, ByVal e As EventArgs)
        If CStr(Session("ConnString")) <> "" Or CStr(Session("UserCode")) <> "" Then
            Dim oSecurity As cSecurity = New cSecurity(CStr(Session("ConnString")))
            If oSecurity.LogOut(CStr(Session("UserCode"))) = True Then
                Session("EmployeeName") = ""
                Session("UserCode") = ""
                Session("EmpCode") = ""
                Session("ConnString") = ""
                Session("admin") = False
                Session("TaskCalAccess") = False
                Session.Clear()
                Session.Abandon()
                FormsAuthentication.SignOut()

            End If
        End If

    End Sub

and here's my logout function in my cSecurity class:
    Public Function LogOut(ByVal UserID As String) As Boolean

        ' Add Parameters to SPROC
        Dim parameterUserID As New SqlParameter("@UserID", SqlDbType.VarChar, 100)
        parameterUserID.Value = UserID

        Try
            oSql.ExecuteNonQuery(mConnString, CommandType.StoredProcedure, "usp_wv_User_Logout", parameterUserID)
        Catch
            Return False
        End Try

        Return True

    End Function
0
 

Author Comment

by:ksfok
ID: 18781681
I tested and found UserLogoutTime() works OK with a Logout button click event, but somehow doesn't get called in Session_End() of global.asax. Here's my code:

   Sub Session_End(ByVal sender As Object, ByVal e As EventArgs)
        ' Code that runs when a session ends.
        ' Note: The Session_End event is raised only when the sessionstate mode
        ' is set to InProc in the Web.config file. If session mode is set to StateServer
        ' or SQLServer, the event is not raised.
       
        Dim adc As New AdminClass
        adc.UserLogoutTime()
       
    End Sub

=================================================
Imports Microsoft.VisualBasic
Imports System.Data.SqlClient
Imports System.Web.HttpContext


Public Class AdminClass

    Public Sub New()
    End Sub

    Public Sub UserLogoutTime()
        Dim queryString As String = _
"UPDATE UserLoginHistory SET LogoutTime = getdate() WHERE Username='" & Current.Session("UserName") & "' AND SessionID='" & Current.Session.SessionID() & "';"
        Using connection As New SqlConnection(ConfigurationManager.ConnectionStrings("LocalSqlServer").ConnectionString)
            Try
                Dim command As New SqlCommand(queryString, connection)
                connection.Open()
                command.ExecuteNonQuery()
            Finally
                connection.Close()
            End Try
        End Using

    End Sub

End Class
0
 
LVL 37

Accepted Solution

by:
samtran0331 earned 500 total points
ID: 18782803
the only real difference I can see between what you're doing and what I posted is that session_end has to go back to the class and the sub in the class gets the session...
where in my code....i'm getting the session in global.asax and passing it back to the class....
...and i'm not 100% sure that the session object is still alive when it goes back to your class...


try this:

Public Class AdminClass

    Public Sub New()
    End Sub

    Public Sub Overloads UserLogoutTime()
        Dim queryString As String = _
"UPDATE UserLoginHistory SET LogoutTime = getdate() WHERE Username='" & Current.Session("UserName") & "' AND SessionID='" & Current.Session.SessionID() & "';"
        Using connection As New SqlConnection(ConfigurationManager.ConnectionStrings("LocalSqlServer").ConnectionString)
            Try
                Dim command As New SqlCommand(queryString, connection)
                connection.Open()
                command.ExecuteNonQuery()
            Finally
                connection.Close()
            End Try
        End Using

    End Sub

    Public Sub Overloads UserLogoutTime(byval TheUserName as string, byval TheUserSession as string)
        Dim queryString As String = _
"UPDATE UserLoginHistory SET LogoutTime = getdate() WHERE Username='" & TheUserName & "' AND SessionID='" &  TheUserSession & "';"
        Using connection As New SqlConnection(ConfigurationManager.ConnectionStrings("LocalSqlServer").ConnectionString)
            Try
                Dim command As New SqlCommand(queryString, connection)
                connection.Open()
                command.ExecuteNonQuery()
            Finally
                connection.Close()
            End Try
        End Using

    End Sub


End Class

and then in global.asax:
   Sub Session_End(ByVal sender As Object, ByVal e As EventArgs)
        ' Code that runs when a session ends.
        ' Note: The Session_End event is raised only when the sessionstate mode
        ' is set to InProc in the Web.config file. If session mode is set to StateServer
        ' or SQLServer, the event is not raised.
       
        Dim adc As New AdminClass
        adc.UserLogoutTime(session("userid").tostring,session.sessionid.tostring)
       
    End Sub

0
 

Author Comment

by:ksfok
ID: 18782990
Would State Server Mode or SQL Server Mode be better alternatives?
0
 

Author Comment

by:ksfok
ID: 18784153
samtran0331,
I tested your code with leaving site and letting time out. It works! Thanks! I haven't tested with closing browser yet because I'm working on localhost. When I close the browser, the app stops. By the way, can  I set cookieless="false" in <sessionState mode="InProc"  cookieless="true"  timeout="20" />? What would be the impact of cookie on the site if we want to have sessionState mode="InProc"  and users want to use cookie to remember their credentials?
0

Featured Post

MS Dynamics Made Instantly Simpler

Make Your Microsoft Dynamics Investment Count  & Drastically Decrease Training Time by Providing Intuitive Step-By-Step WalkThru Tutorials.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Just a quick little trick I learned recently.  Now that I'm using jQuery with abandon in my asp.net applications, I have grown tired of the following syntax:      (CODE) I suppose it just offends my sense of decency to put inline VBScript on a…
Sometimes in DotNetNuke module development you want to swap controls within the same module definition.  In doing this DNN (somewhat annoyingly) swaps the Skin and Container definitions to the default admin selections.  To get around this you need t…
There are cases when e.g. an IT administrator wants to have full access and view into selected mailboxes on Exchange server, directly from his own email account in Outlook or Outlook Web Access. This proves useful when for example administrator want…
There's a multitude of different network monitoring solutions out there, and you're probably wondering what makes NetCrunch so special. It's completely agentless, but does let you create an agent, if you desire. It offers powerful scalability …

617 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question