Free, Open-Source ASP.Net 2.0 Framework for Data-Driven Websites
Session and state management is a lot better in ASP.Net that it was in older technologies. However, there are still a number of hoops to jump through with each application that we wanted abstracted so we can change the implementation in the future if needed.
Specific questions we need to be able to answer or capabilities we need to support:
Let’s start with 1 and 2.
Almost every page in a user-authenticated web-application needs to answer question number 1. If the user is not logged in, or the login occurred too long ago, the user needs to be taken somewhere to log in.
A UserId or something simple can be stored in a cookie but that’s easy to spoof. A UserId could be stored in the session but you’ll need to find another solution if the client doesn’t want the user to have to log in every time the session expires and you don’t want stuff held in memory for too long.
The approach we take today is the same approach we were taking 10 years ago. Create a Session table (AppSession) in the database that is archived regularly to keep it small. Store the SessionId in the user’s cookie and when a page is requested, get the SessionId and the IPAddress and compare it with active sessions in the database. If the session is found, return it. If no session is found, create a new session. In scenarios where new sessions are created, no user is known so if the page requires authentication, other layers in the application will route the user to the correct page.
The majority of this logic can be found in the class App_Code/Domain/AppSession.vb and in the stored procedure ncAppSession_Get.
To answers questions similar to number 2, we also pass the requested page’s url to the database when we request the session. The stored procedure adds the SessionId and URL to the AppSessionActivity table creating a log of pages used by session, and when a user is logged in, by user by session. This allows us to create very detailed reports of user activity.
Issue number 3 is handled by using wrapper functions found in UnfiedASP.System.Utility.vb class. In many cases, we use the native in-memory session collections provided by .Net.
Shared Function GetSessionValue(ByVal key As String) As Object Try Return HttpContext.Current.Session(key) Catch ex As Exception Return Nothing End Try End Function Shared Sub SetSessionValue(ByVal key As String, ByVal value As Object) Try HttpContext.Current.Session(key) = value Catch ex As Exception End Try End Sub
When a page or business object needs to set or get a session value, it uses these methods instead of interacting with the session object directly.
In situations where in-memory session does not work or meet requirements, we shift to data-driven sessions keyed off the AppSession object used for user authentication/authorization. We then change the implementation for the objects to what is shown below.
Shared Function GetSessionValue(ByVal key As String) As Object
Try
Dim appSessionId As Integer = Convert.ToInt32(HttpContext.Current.Request.Cookies("xid").Value)
Dim sessionValue As New UnifiedASP.Domain.AppSessionValue
sessionValue.AppSessionId = appSessionId
sessionValue.ItemKey = key
sessionValue.LoadForItemKey()
Return sessionValue.ItemValue
Catch ex As Exception
Return Nothing
End Try
End Function
Shared Sub SetSessionValue(ByVal key As String, ByVal value As Object)
Try
Dim appSessionId As Integer = Convert.ToInt32(HttpContext.Current.Request.Cookies("xid").Value)
Dim sessionValue As New UnifiedASP.Domain.AppSessionValue
sessionValue.AppSessionId = appSessionId
sessionValue.ItemKey = key
sessionValue.ItemValue = value
sessionValue.Save()
Catch ex As Exception
End Try
End Sub