Subject: Session
Posted By: quinn Post Date: 11/11/2003 12:44:41 PM
Hi,

I have a human resource web base application in ASP.  The application is used for tracking employees' vacation and sick leave accrual or taken time.  Only our human resource personnel is authorized to use this application.  Now, I want to let each employee to view only his/her own vacation/sick leave time.  Does anyone know what are the steps I need to do to get this works.  I have heard of using session. How do I pass each employee ID to all the page if using session?

Thanks,

Quinn
Reply By: planoie Reply Date: 11/11/2003 12:56:46 PM
You'll need to create a login system so each user could login to access their data.  You could then also provide the ability for to set access levels to users so the HR people can access all users.  For the login system you can maintain the state of who the user is in the session object.  Then you use that value to query the database to access that user's data.  For the HR people, you can provide a page to view a list of users, then potentially use the same page to view individual users data as the users themselves use.  You just need to check the logged in user's access level for the operations you need to allow or dissallow.  You'll have to check the user access level at the start of each page in order to check that the logged in user is allowed to access the page (for example, the "userList" page, only HR authorized users can see that).  If the page fails access check, you can kick them out to a default page.

Sorry for such a vague answer. It's hard to answer without more specific questions.

Peter
------------------------------------------------------
Work smarter, not harder.
Reply By: quinn Reply Date: 11/11/2003 4:09:37 PM
Peter,

Would you specify what exact steps to approach the solution.  To be more detail, my question is how can I pass the user login password to each page so that only the login user data is displayed not to mention there is an employee id in the Employee table.  For example, after a user logins the system, only his/her data is populated from the database in a dropdown box so that he/she can view his/her own data only not any body else.  Like online banking system, only an authorized person can have access to his/her account.  

Thanks,

Q
Reply By: alyeng2000 Reply Date: 11/11/2003 4:43:45 PM
extension to planoie view
i see to attach the session variable (you made after logged from login page) to each query,procedure sent to the database you use, then the user will see only the data belongs to him.

Ahmed Ali
Software Developer
Reply By: kosla78 Reply Date: 11/12/2003 2:07:15 AM
The data of a Session variable are available to every page in your site..If you define a Session variable in the Global.asa file of your site you can change or retrieve its data, whenever you want..I send some code below on how Session variables are defined in the global.asa file..The other thing is the personalization..An example for this would be a query to the database for a particular user. It will look like this:
strSQL="SELECT * FROM (your table) WHERE PWD='" & Session("usrPwd") &"'"
.. This way you retrieve the data that concern the current user, because its user gets its own Session variable..Now in order to assign a value, when you check the password, if its correct, do this:
Session("usrPwd")= (users Password)

And here is some more code:

'Global.asa

<SCRIPT RUNAT=SERVER LANGUAGE=VBSCRIPT>
    SUB SESSION_ONSTART
        'Set Con2 = Server.createobject("ADODB.Connection")
        Maindb.connectionstring = "DSN=icom;pwd=hr;uid=hr"
        Maindb.Open
        Session("TmpKod_Ypal")=""
        Session("TmpEpon_ypal")=""
        Session("TmpOnom_ypal")=""
        Session("Mail_ypal")=""
        Session("Pwd_ypal")=""
    END SUB

    SUB SESSION_ONEND
        'Set Con2 = Server.createobject("ADODB.Connection")        
        Maindb.Close
        Session("TmpKod_Ypal")=""
        Session("TmpEpon_ypal")=""
        Session("TmpOnom_ypal")=""
        Session("Pwd_ypal")=""
        Session("Mail_ypal")=""

    END SUB
</SCRIPT>


I guess its a small story but hope it helps :)

Kostas Lagos

Reply By: planoie Reply Date: 11/12/2003 12:09:51 PM
If I may stand on my soapbox for a moment and add a couple points to kosla78's post:

  • You don't have to define session entries in the global to use them.  You can set and call them from anywhere without having set them to an empty string in the global.  They will simply return empty if they don't exist yet.

  • I wouldn't recommend selecting a row from SQL on only the password field. What happens if two people had the same password?  Unless the password field has a unique constraint on it (which it really shouldn't) you could have problems.  Better to select on both the userid/username and password so all you need to do is check that a row was returned.

  • I highly dissuade storing database connections, or any object in the session object in ASP.  Among other reasons, the SESSION_ONEND global handler is not reliable.  Also you will end up with a connection object for every session that's started up (and possibly not have them destroyed due the previous point.  Rule of thumb is "open late, close early".  Open the database connection as late as you can before you actually use it, and close it as soon as you are done.  Otherwise you'll have lots of wasted resources.

  • It's not necessary to re-set the session values to empty strings on the SESSION_ONEND event (even if it DID work ).  When ASP expires the session, all session entries for that session will disappear.



Peter
------------------------------------------------------
Work smarter, not harder.
Reply By: kosla78 Reply Date: 11/17/2003 1:52:16 AM
OK.., it seems like i have to put some things in place..

a)I didn't say that Session variables are ONLY defined in global.asa. I just use them that way, that was only an example

b)The SQL was also just an example on how to use the Session variable. Besides, I dont have duplicate passwords in my db, as i create them with some kind of keygen and they are unique.

c)I dont think that I've assigned any object to my Session variables. The connection is open from the start as i need it that way. I didnt have issues so far. I know I could have used include file but I prefer the former way.

d)Yeah, you're right about the SESSION_ON_END, that was a crap of mine and forgot o get it out :)

Cheers
Kostas Lagos

Reply By: planoie Reply Date: 11/17/2003 10:16:37 AM
Kosta,

I'm curious about something... In this code:

    SUB SESSION_ONSTART
        'Set Con2 = Server.createobject("ADODB.Connection")
        Maindb.connectionstring = "DSN=icom;pwd=hr;uid=hr"
        ...
    END SUB

where is Maindb declared and where does it live?  When I skimmed this code the first time, I guess I was under the impression that you were putting this in the session object but I know see that is not written there.

Peter
------------------------------------------------------
Work smarter, not harder.
Reply By: kosla78 Reply Date: 11/18/2003 7:40:57 AM
Its declared as object in the global.asa file.The scope is Session, so if this counts as a session variable you're right. Im under the impression that this is just an initialization of the object. Here is the missing link:

<OBJECT RUNAT=Server SCOPE=Session ID=MyInfo PROGID="MSWC.MyInfo">
</OBJECT>
<OBJECT    RUNAT=SERVER SCOPE=SESSION ID=Maindb PROGID="ADODB.CONNECTION">
</OBJECT>

<SCRIPT RUNAT=SERVER LANGUAGE=VBSCRIPT>
    SUB SESSION_ONSTART
        Maindb.connectionstring = "DSN=icom;pwd=hr;uid=hr"
        Maindb.Open
        Session("TmpKod_Ypal")=""
        Session("TmpEpon_ypal")=""
        Session("TmpOnom_ypal")=""
        Session("Mail_ypal")=""
        Session("Pwd_ypal")=""
    END SUB

    </SCRIPT>


Cheers
Kostas Lagos


Reply By: planoie Reply Date: 11/18/2003 11:42:07 AM
If you can access Maindb on any ASP page without the need to instantiate it (Server.CreateObject("ADODB.CONNECTION")) or to .Open() it, than it is definately living in the session.  If you had to use the connection object that way, I'd recommend putting it in the application scope, because you at least then only have one open for everyone instead of 1 for each user.

A technique I have used in the past which kind of violates the rule of thumb that I go by (open late, close early) works pretty well for ASP pages because they are basically "one shot" executions (vs. a app that's sitting open on a desktop and in memory).  This technique is probably more efficient because it doesn't require constant opening and closing of a DB connection for one page.

I create a helper include for DB interaction.  On it is a globally declared DBConnection object.  I have a couple functions to retrieve values, basically just wrappers around .Execute().  Inside of those functions, I check the object state of that global DBConn.  If it's not an object yet, I instantiate it to the ADODB.Connection and open it.  The I execute the query.  Subsequent calls to the DB functions skip those parts and just execute the queries.  Need to make sure that the page closes the connection so there's also a function to call at the end of the page to clean up the DB: close it and deallocate the object.  This works well and is fast.

Peter
------------------------------------------------------
Work smarter, not harder.
Reply By: kosla78 Reply Date: 11/19/2003 2:36:16 AM
I ran through my books in order to clear this out. It seems that this is just an instantiation but the object is not created until is referenced..so I guess its not the same thing as declaring it to Session.Every user gets an instance but the Connection is not created until the user needs the Connection..
Maybe it would be a better idea to change the scope to Application, as you mentioned.
As far as your technique, I would like to see a coding example, so to get a grip to it :)

Cheers
Kostas Lagos

Reply By: planoie Reply Date: 11/19/2003 7:44:20 AM
This doesn't entirely make sense.  An object instantiation is an instance of the object (the object has been created).  The object tags provide that, and it seems pretty clear that those object tags indicate that the object is instanced in the scope of the session.

If you were to simply declare the object in the the onstart, then it wouldn't be instantiated until the first time it was created, but that instance would persist throughout the life of the session, and may very well live on after the session is gone.

Here's the general idea I mentioned (please excuse the code, I had to type it out of my head):


dbHelpers.inc

<%
Dim m_objConn 'This will be the global DB connection

Function CheckDBConn()
    If IsNothing(m_objConn) Then
        Set m_objConn = Server.CreateObject("ADODB.Connection")
        m_objConn.ConnectionString = "<myconnection string>"
        m_objConn.Open()
    End If
End Function

Function Execute(sSQL)
    CheckDBConn
    Dim objRS : Set objRS = Server.CreateObject("ADODB.RecordSet")
    Set objRS = m_objConn.Execute(sSQL)
    Set Execute = objRS
End Function
%>


You can expand on this idea. I think in the actual version I use, I set some recordset properties and maybe do some additional error handling, but this is the general concept.  I actually created a VBScript class to wrap around the db connection object so that I only need to call 1 method on that class and it does everything internally like what I have here.  If I can remember later, I'll see if I can dig it up.

Peter
------------------------------------------------------
Work smarter, not harder.
Reply By: planoie Reply Date: 11/19/2003 9:42:37 AM
Here's that class I was talking about


<%
Class DBInterface

    '******************************************************
    ' Internal Variables and their Public Properties
    '******************************************************

    Private mobjConn
    Private mstrConnectionString

    Public Property Let ConnectionString(vData)
        mstrConnectionString = vData
    End Property

    '******************************************************


    '******************************************************
    ' Public Functions
    '******************************************************

    Public Function GetRows(strSQL)

        Dim objRS
        Set objRS = Server.CreateObject("ADODB.Recordset")

        Call CheckState()

        objRS.CursorLocation = 3 'adUseClient
        objRS.CursorType = 0 'adOpenForwardOnly
        objRS.LockType = 1 'adLockReadOnly
        On Error Resume Next
        Set objRS = mobjConn.Execute(strSQL)
        If Err.number <> 0 Then
            Call ErrorHandler(strSQL)
        End If
        
        If Not (objRS.BOF And objRS.EOF) Then
            GetRows = objRS.GetRows()
        Else
            GetRows = Array()
        End If

    End Function

    Public Function GetRS(strSQL)

        Dim objRS
        Set objRS = Server.CreateObject("ADODB.Recordset")

        Call CheckState()

        objRS.CursorLocation = 3 'adUseClient
        objRS.CursorType = 0 'adOpenForwardOnly
        objRS.LockType = 1 'adLockReadOnly
        On Error Resume Next
        Set objRS = mobjConn.Execute(strSQL)
        If Err.number <> 0 Then
            Call ErrorHandler(strSQL)
        End If
        Set GetRS = objRS

    End Function

    Public Sub Execute(strSQL)
        On Error Resume Next
        Call CheckState()
        mobjConn.Execute strSQL
        If Err.number <> 0 Then
            Call ErrorHandler(strSQL)
        End If
    End Sub

    '******************************************************


    '******************************************************
    ' Private Functions
    '******************************************************
    Private Sub CheckState()
        If mobjConn.State = adStateClosed Then
            mobjConn.ConnectionString = mstrConnectionString
            mobjConn.Open
        End If
    End Sub

    Private Sub ErrorHandler(strSQL)
        Response.Write "<pre>" & vbcrlf
        Response.Write "DB Interface Object encounted an error while trying to execute the following SQL:" & vbcrlf
        Response.Write vbcrlf & vbtab & strSQL & vbcrlf & vbcrlf
        Response.Write "Error Number: " & Err.number & vbcrlf
        Response.Write "Error Description: " & Err.description & vbcrlf
        Response.Write "Error Source: " & Err.source & vbcrlf
        Response.Write "</pre>" & vbcrlf
        Err.Clear
    End Sub

    '******************************************************


    '******************************************************
    ' Class Constructor/Destructor Functions
    '******************************************************

    Private Sub Class_Initialize
        mintCursorType = adOpenStatic
        mstrConnectionString = ""

        Set mobjConn = Server.CreateObject("ADODB.Connection")

    End Sub

    Private Sub Class_Terminate

        If mobjConn.State = adStateOpen Then mobjConn.Close
        Set mobjConn = Nothing

    End Sub

    '******************************************************

End Class
%>

Notice at the end, the Class_Terminate.  When the ASP finishes execution and goes out of scope, the instance of this class should also go out of scope, thus calling the termination method which closes and deallocates the connection object.  I honestly can't recall if I confirmed that this actually does happen. You know ASP, thing you *think* will happen don't necessarily really happen.


Peter
------------------------------------------------------
Work smarter, not harder.

Go to topic 6603

Return to index page 1002
Return to index page 1001
Return to index page 1000
Return to index page 999
Return to index page 998
Return to index page 997
Return to index page 996
Return to index page 995
Return to index page 994
Return to index page 993