ARTICLE
Session Management in Web Garden using Custom Components and VB.NET
Tags: .NET, ArrayList, ASP.NET, CType, DateTime, GetValue, HashTable, HashValues, In-process, Out-process, Session Interface, Session Management, Session Management in VB.NET., Session Manager, Sql Server, Timer, TimerCallBack, ToString, VB.NET, Web Forms
This article provides an insight on creating a custom Session Manager component using C#.
Introduction.
'Sessions' in simple terms are nothing but information that is stored and persisted for a specific time period. Asp.net provides three ways to manage sessions. They are
- In-process Session Management (default).
- Out-process Session Management (Asp.Net state service).
- Sql-Server Session Management (using sql server).
For more information on configuring sessions (in web.config) refer.
http://msdn2.microsoft.com/library/ms178586(en-us,vs.80).aspx
As long as a web site is deployed in one server, sessions can be managed by using any one of the above-said methods. But in a real-word scenario, critical e-commerce and line-of-business applications have to be deployed in different servers that are managed and integrated using the concept of "Clustering" and "Network Load Balancing (NLB)".
For more details on clustering visit.
http://www.microsoft.com/windows2000/
techinfo/howitworks/cluster/introcluster.asp.
Why Custom Components?
In a typical web garden scenario where a particular web site has been deployed in more than one server, Sessions can be maintained using the Asp.Net state service or using the Sql server session management (which are provided by Microsoft). But there are situations where we have to take control of session management (allocating sessions, storing session data and removing sessions). This article provides an insight on creating a custom Session Manager component using c#.
Solution.
Step 1: Create the following ISessionManager and ISession interface(s)
Public Interface ISessionManager
Function createSessionId() As String
Function getSession(ByVal strSesId As String) As ISession
Function removeSession(ByVal strSesId As String) As ISession
End Interface 'ISessionManager
Public Interface ISession
Function getAttribute(ByVal strKey As String) As [Object]
Sub setAttribute(ByVal strKey As String, ByVal objValue As [Object])
Function removeAttribute(ByVal strKey As String) As [Object]
End Interface 'ISession
About ISessionManager.
The IsessionManager interface contains the list of generic methods and functionalities that can be used for creating and managing sessions.
- The createSessionId method is used to create a new session id. For instance, a new session id will be allocated when the user hits the web site for the first time.
- The getSession method is used to fetch an existing session. The method returns an object, which has implemented the Isession interface (which would be dealt in detail below).
- The removeSession method is used to remove a particular session allocated to an user and returns the session object that was removed (The session object would be the class that has implemented the Isession interface).
About ISession. The Isession interface contains the list of methods used to store and retrive individual session data/information. For e.g., an online website can store the preferences of an user, temporarily in the session object.
- The getAttribute method returns the value stored against the unique key from the session object from the hash table (all session values are stored in a hash table).
- Similarly setAttribute method is used to assign/set a key/value.
- RemoveAttribute is used to remove a particular key/value stored in the session.
Managing timeouts.
The SessionManager class (which implements the ISessionManager interface), has a timer variable, which would be instantiated when an object of the SessionManager class is created for the first time. This timer variable is liked with a timercallback thread which would be fired for every 8 seconds (which would in turn invoke the call back method). It would check for the "lastAccessedDateTime" value set, for every session and would compare the time difference with the current date time. If it is greater than or equal to 2 house the session would be removed.
Step 2: Implement the ISessionManager interface.
Public
Class SessionManager
Implements ISessionManager 'ToDo: Add Implements Clauses for implementation methods of these interface(s)
'Hashtable to store the list of sessions allocated.
Private hsSession As New Hashtable
Private Shared objSM As SessionManager 'static SINGLETON object
'a timer to manage the session timeouts
Private Shared tmrSessionTimeout As Timer
'Private Constructor-To prevent creating instaces explicitly
Private Sub New()
End Sub 'New
'Create a new object of session manager.
Public Shared Function getInstance() As SessionManager
If objSM Is Nothing Then
objSM = New SessionManager
'create a new objectof the timer class and associte //a timer call back delegate. The removesession
'method will be invoked by the timer object for //every 1000 milliseconds (change it as u like).
tmrSessionTimeout = New Timer(New TimerCallback(objSM.removesession), Nothing, 0, 100)
Return objSM
End If
Return objSM
End Function 'getInstance
'This method will be invoked by the timer call back for every 1000 milliseconds.
Private Sub removesession(ByVal state As Object)
Dim objSesEnum As IDictionaryEnumerator = hsSession.GetEnumerator()
'A temporary session object.
Dim tmpSesObj As ISession
Dim arrExpiredKeys As New ArrayList
'for each session, check the last used datetime.
While objSesEnum.MoveNext()
'The session will be removed, if the user is idle for 2 hours. (change it as u like).
tmpSesObj = CType(objSesEnum.Value, ISession)
Dim dt As DateTime = DateTime.Parse(tmpSesObj.getAttribute("lastAccessedDatetime").ToString())
Dim ts As TimeSpan = dt.Subtract(DateTime.Now)
'If the difference between the last accessed //datetime and current date time is equal to 2 hours //then the session id will be added to the arraylist.
'(ie., left idle for 2 hours)
If dt.Subtract(DateTime.Now).Hours >= 2 Then
arrExpiredKeys.Add(objSesEnum.Key)
End If
'remove the list of keys added to the array list.
Dim i As Integer = 0
While arrExpiredKeys.Count > i
'remove the session from the hashtable.
hsSession.Remove(arrExpiredKeys(i))
End While
End While
End Sub 'removesession Public Function createSessionId() As String
'Create a new guid which will act as the session id
Dim newSessionId As String = Guid.NewGuid().ToString
'create a new session object and store the object in the //hashtable against the new session id (GUID).
Dim objS As New Session
hsSession.Add(newSessionId, objS)
'Set the session id into the session object.
objS.setAttribute("SessionId", newSessionId)
'return the session id,
Return newSessionId
End Function 'createSessionId Public Function getSession(ByVal strSesId As String) As ISession
Dim objS As ISession = CType(hsSession(strSesId), ISession)
'everytime when the session object is retried, update the //lastaccesseddate variable with the latest datetime
objS.setAttribute("lastAccessedDatetime", DateTime.Now)
Return objS 'return the session object
End Function 'getSession Public Function removeSession(ByVal strSesId As String) As ISession
Dim objS As ISession = CType(hsSession(strSesId), ISession)
'remove the sessionid from the hash table.
hsSession.Remove(strSesId)
Return objS 'return the removed session
End Function 'removeSession
End Class 'SessionManager
Step 3: Implement the ISession interface. Public
Class Session
Implements ISession
'ToDo: Add Implements Clauses for implementation methods of these interface(s)
'Hashtable to store the values..
Private hsValues As New Hashtable
'Default constructor
Public Sub New()
End Sub 'New Public Function removeAttribute(ByVal strKey As String) As Object
Dim obj As Object = hsValues(strKey) 'fetch the value
hsValues.Remove(strKey)
Return obj 'return the value that is removed
End Function 'removeAttribute Public Function getAttribute(ByVal strKey As String) As Object
'get the value for the key specified
Return hsValues(strKey)
End Function 'getAttribute Public Sub setAttribute(ByVal strKey As String, ByVal objValue As [Object])
'add a new value, if the key already exists then it will //be overridden
hsValues.Add(strKey, objValue)
End Sub 'setAttribute
End Class 'Session
At any time there will be only one instance of the session manager class (as it is declared as static). It must always remain as a singleton object, as persistent storage and maintenance of multiple sessions cannot be achieved otherwise. A new static method getInstance is added into the SessionManager class to create a new instance of the SessionManager class. The constructor of the class is made private to prevent creating objects of the SessionManager component explicitly. Testing the Session Manager component.
Now we can test the session manager component. Create a new console application project and add a reference of the SessionManager component. The following code snippet creates an object of the session manager class (using the getInstance method) and assigns a value in the session object. The WriteLine method prints the value in the session object.
Imports NpSessionManager 'add the namespace
Friend Class SessionManagerTest
Private Shared strid As String
<STAThread()> _
Shared Sub Main(ByVal args As String())
'Create a new session and assign values to the session object.
Dim sm As SessionManager = SessionManager.getInstance()
'store the session id in some global variable.
strid = CStr(sm.createSessionId())
'get the session
Dim objS As ISession = CType(sm.getSession(strid), ISession)
objS.setAttribute("website", "c-sharpcorner")
Console.WriteLine(objS.getAttribute("website").ToString())
Console.ReadLine()
End Sub
End Class
Scalibility and deploying the component.
Due to the object oriented design of the session manager component, any amount of flexibility and scalability is achievable.
- The session manager component can be deployed in the following ways.
- In-process version (will run the Asp.Net Process / w3wp.exe process, just dll reference is enough).
- Out-process version (Using .net Remoting).
In-process version.
In-proc version is achievable by just adding a reference of the session manager component to the web application (can also be used with windows application). During execution the session manager component (Sessionmanager.dll) will be loaded and executed in the AspNet_wp.exe or w3wp.exe (in case of windows 2003 server) process. One of the main disadvantages is the loss of all sessions, whenever the AspNet_wp.exe or w3wp.exe process crashes or restarted. To overcome this issue, the Session Manager component can be deployed as an Out-proc version.
Out-process version.
The session manager component can be hosted in a separate process by deploying it using .net Remoting. Just create a remoting application and host the session manager component in the remote server. Using remoting (at runtime), proxy can be generated from the client by accessing the server by providing the requisite port number/path and credentials. (If you need code to host it as a remoting component, just mail me). We can also deploy the component as a Windows Service using .net Remoting.
Conclusion.
Even though Microsoft has provided various options to maintain and manage sessions, often developers are caught in scenarios where solutions have to be provided for functionalities that are too complex to solve. In a real-world application, most of the Requirements put-forth are hard to achieve using the available resources. Often, we have to develop our own custom components and techniques to overcome such hardships. The SessionManager component is one of its kinds, which is up and running successfully in a project undertaken by our company.
NOTE: THIS ARTICLE IS CONVERTED FROM C# TO VB.NET USING A CONVERSION TOOL. ORIGINAL ARTICLE CAN BE FOUND ON C# CORNER (WWW.C-SHARPCORNER.COM).