How to: Sample Session-State Store Provider
Demonstrates a session-state store provider implementation.
The following example shows how to implement a session-state store provider. For more information details about how to build this provider and use it in an ASP.NET application, see Sample Session-State Store Provider.
Example
Imports System
Imports System.Web
Imports System.Web.Configuration
Imports System.Configuration
Imports System.Collections.Specialized
Imports System.Web.SessionState
Imports System.Data
Imports System.Data.Odbc
Imports System.Diagnostics
Imports System.IO
' This session state store provider supports the following schema:' ' CREATE TABLE Sessions' (' SessionId Text(80) NOT NULL,' ApplicationName Text(255) NOT NULL,' Created DateTime NOT NULL,' Expires DateTime NOT NULL,' LockDate DateTime NOT NULL,' LockId Integer NOT NULL,' Timeout Integer NOT NULL,' Locked YesNo NOT NULL,' SessionItems Memo,' Flags Integer NOT NULL,' CONSTRAINT PKSessions PRIMARY KEY (SessionId, ApplicationName)' )' ' This session state store provider does not automatically clean up ' expired session item data. It is recommended' that you periodically delete expired session information from the' data store with the following code (where 'conn' is the OdbcConnection' for the session state store provider):' ' Dim commandString As String = "DELETE FROM Sessions WHERE Expires < ?"' Dim conn As OdbcConnection = New OdbcConnection(connectionString)' Dim cmd As OdbcCommand = New OdbcCommand(commandString, conn)' cmd.Parameters.Add("@Expires", OdbcType.DateTime).Value = DateTime.Now' conn.Open()' cmd.ExecuteNonQuery()' conn.Close()Namespace Samples.AspNet.Session
PublicNotInheritableClass OdbcSessionStateStore
Inherits SessionStateStoreProviderBase
Private pConfig As SessionStateSection = NothingPrivate connectionString AsStringPrivate pConnectionStringSettings As ConnectionStringSettings
Private eventSource AsString = "OdbcSessionStateStore"Private eventLog AsString = "Application"Private exceptionMessage AsString = _
"An exception occurred. Please contact your administrator."Private pApplicationName AsString
' ' If False, exceptions are thrown to the caller. If True, ' exceptions are written to the event log. 'Private pWriteExceptionsToEventLog AsBoolean = FalsePublicProperty WriteExceptionsToEventLog AsBooleanGetReturn pWriteExceptionsToEventLog
EndGetSet
pWriteExceptionsToEventLog = value
EndSetEndProperty
' ' The ApplicationName property is used to differentiate sessions ' in the data source by application. 'PublicReadOnlyProperty ApplicationName AsStringGetReturn pApplicationName
EndGetEndProperty
' ' ProviderBase members 'PublicOverridesSub Initialize(name AsString, config As NameValueCollection)
' ' Initialize values from web.config. 'If config IsNothingThen _
ThrowNew ArgumentNullException("config")
If name IsNothingOrElse name.Length = 0 Then _
name = "OdbcSessionStateStore"IfString.IsNullOrEmpty(config("description")) Then
config.Remove("description")
config.Add("description", "Sample ODBC Session State Store provider")
EndIf
' Initialize the abstract base class.MyBase.Initialize(name, config)
' ' Initialize the ApplicationName property. '
pApplicationName = _
System.Web.Hosting.HostingEnvironment.ApplicationVirtualPath
' ' Get <sessionState> configuration element. 'Dim cfg As System.Configuration.Configuration = _
WebConfigurationManager.OpenWebConfiguration(ApplicationName)
pConfig = _
CType(cfg.GetSection("system.web/sessionState"), SessionStateSection)
' ' Initialize OdbcConnection. '
pConnectionStringSettings = _
ConfigurationManager.ConnectionStrings(config("connectionStringName"))
If pConnectionStringSettings IsNothingOrElse _
pConnectionStringSettings.ConnectionString.Trim() = ""ThenThrowNew HttpException("Connection string cannot be blank.")
EndIf
connectionString = pConnectionStringSettings.ConnectionString
' ' Initialize WriteExceptionsToEventLog '
pWriteExceptionsToEventLog = FalseIfNot config("writeExceptionsToEventLog") IsNothingThenIf config("writeExceptionsToEventLog").ToUpper() = "TRUE"Then _
pWriteExceptionsToEventLog = TrueEndIfEndSub
' ' SessionStateStoreProviderBase members 'PublicOverridesSub Dispose()
EndSub
' ' SessionStateProviderBase.SetItemExpireCallback 'PublicOverridesFunction SetItemExpireCallback( _
expireCallback As SessionStateItemExpireCallback) AsBooleanReturnFalseEndFunction
' ' SessionStateProviderBase.SetAndReleaseItemExclusive 'PublicOverridesSub SetAndReleaseItemExclusive(context As HttpContext, _
id AsString, _
item As SessionStateStoreData, _
lockId AsObject, _
newItem AsBoolean)
' Serialize the SessionStateItemCollection as a string.Dim sessItems AsString = Serialize(CType(item.Items, SessionStateItemCollection))
Dim conn As OdbcConnection = New OdbcConnection(connectionString)
Dim cmd As OdbcCommand
Dim deleteCmd As OdbcCommand = NothingIf newItem Then ' OdbcCommand to clear an existing expired session if it exists.
deleteCmd = New OdbcCommand("DELETE FROM Sessions " & _
"WHERE SessionId = ? AND ApplicationName = ? AND Expires < ?", conn)
deleteCmd.Parameters.Add("@SessionId", OdbcType.VarChar, 80).Value = id
deleteCmd.Parameters.Add( _
"@ApplicationName", OdbcType.VarChar, 255).Value = ApplicationName
deleteCmd.Parameters.Add( _
"@Expires", OdbcType.DateTime).Value = DateTime.Now
' OdbcCommand to insert the New session item.
cmd = New OdbcCommand("INSERT INTO Sessions " & _
" (SessionId, ApplicationName, Created, Expires, " & _
" LockDate, LockId, Timeout, Locked, SessionItems, Flags) " & _
" Values(?, ?, ?, ?, ?, ? , ?, ?, ?, ?)", conn)
cmd.Parameters.Add("@SessionId", OdbcType.VarChar, 80).Value = id
cmd.Parameters.Add( _
"@ApplicationName", OdbcType.VarChar, 255).Value = ApplicationName
cmd.Parameters.Add( _
"@Created", OdbcType.DateTime).Value = DateTime.Now
cmd.Parameters.Add( _
"@Expires", OdbcType.DateTime).Value = DateTime.Now.AddMinutes(CDbl(item.Timeout))
cmd.Parameters.Add( _
"@LockDate", OdbcType.DateTime).Value = DateTime.Now
cmd.Parameters.Add("@LockId", OdbcType.Int).Value = 0
cmd.Parameters.Add( _
"@Timeout", OdbcType.Int).Value = item.Timeout
cmd.Parameters.Add("@Locked", OdbcType.Bit).Value = False
cmd.Parameters.Add( _
"@SessionItems", OdbcType.VarChar, sessItems.Length).Value = sessItems
cmd.Parameters.Add("@Flags", OdbcType.Int).Value = 0
Else
' OdbcCommand to update the existing session item.
cmd = New OdbcCommand( _
"UPDATE Sessions SET Expires = ?, SessionItems = ?, Locked = ? " & _
" WHERE SessionId = ? AND ApplicationName = ? AND LockId = ?", conn)
cmd.Parameters.Add("@Expires", OdbcType.DateTime).Value = _
DateTime.Now.AddMinutes(CDbl(item.Timeout))
cmd.Parameters.Add("@SessionItems", _
OdbcType.VarChar, sessItems.Length).Value = sessItems
cmd.Parameters.Add("@Locked", OdbcType.Bit).Value = False
cmd.Parameters.Add("@SessionId", OdbcType.VarChar, 80).Value = id
cmd.Parameters.Add( _
"@ApplicationName", OdbcType.VarChar, 255).Value = ApplicationName
cmd.Parameters.Add("@LockId", OdbcType.Int).Value = lockId
EndIfTry
conn.Open()
IfNot deleteCmd IsNothingThen _
deleteCmd.ExecuteNonQuery()
cmd.ExecuteNonQuery()
Catch e As OdbcException
If WriteExceptionsToEventLog Then
WriteToEventLog(e, "SetAndReleaseItemExclusive")
ThrowNew Exception(exceptionMessage)
ElseThrow e
EndIfFinally
conn.Close()
EndTryEndSub
' ' SessionStateProviderBase.GetItem 'PublicOverridesFunction GetItem(context As HttpContext, _
id AsString, _
ByRef locked AsBoolean, _
ByRef lockAge As TimeSpan, _
ByRef lockId AsObject, _
ByRef actionFlags As SessionStateActions) _
As SessionStateStoreData
Return GetSessionStoreItem(False, context, id, locked, lockAge, lockId, actionFlags)
EndFunction
' ' SessionStateProviderBase.GetItemExclusive 'PublicOverridesFunction GetItemExclusive(context As HttpContext, _
id AsString, _
ByRef locked AsBoolean, _
ByRef lockAge As TimeSpan, _
ByRef lockId AsObject, _
ByRef actionFlags As SessionStateActions) _
As SessionStateStoreData
Return GetSessionStoreItem(True, context, id, locked, lockAge, lockId, actionFlags)
EndFunction
' ' GetSessionStoreItem is called by both the GetItem and ' GetItemExclusive methods. GetSessionStoreItem retrieves the ' session data from the data source. If the lockRecord parameter ' is True (in the case of GetItemExclusive), then GetSessionStoreItem ' locks the record and sets a New LockId and LockDate. 'PrivateFunction GetSessionStoreItem(lockRecord AsBoolean, _
context As HttpContext, _
id AsString, _
ByRef locked AsBoolean, _
ByRef lockAge As TimeSpan, _
ByRef lockId AsObject, _
ByRef actionFlags As SessionStateActions) _
As SessionStateStoreData
' Initial values for Return value and out parameters.Dim item As SessionStateStoreData = Nothing
lockAge = TimeSpan.Zero
lockId = Nothing
locked = False
actionFlags = 0
' Connection to ODBC database.Dim conn As OdbcConnection = New OdbcConnection(connectionString)
' OdbcCommand for database commands.Dim cmd As OdbcCommand = Nothing ' DataReader to read database record.Dim reader As OdbcDataReader = Nothing ' DateTime to check if current session item is expired.Dim expires As DateTime
' String to hold serialized SessionStateItemCollection.Dim serializedItems AsString = "" ' True if a record is found in the database.Dim foundRecord AsBoolean = False ' True if the returned session item is expired and needs to be deleted.Dim deleteData AsBoolean = False ' Timeout value from the data store.Dim timeout AsInteger = 0
Try
conn.Open()
' lockRecord is True when called from GetItemExclusive and ' False when called from GetItem. ' Obtain a lock if possible. Ignore the record if it is expired.If lockRecord Then
cmd = New OdbcCommand( _
"UPDATE Sessions SET" & _
" Locked = ?, LockDate = ? " & _
" WHERE SessionId = ? AND ApplicationName = ? AND Locked = ? AND Expires > ?", conn)
cmd.Parameters.Add("@Locked", OdbcType.Bit).Value = True
cmd.Parameters.Add("@LockDate", OdbcType.DateTime).Value = _
DateTime.Now
cmd.Parameters.Add("@SessionId", OdbcType.VarChar, 80).Value = id
cmd.Parameters.Add("@ApplicationName", OdbcType.VarChar, _
255).Value = ApplicationName
cmd.Parameters.Add("@Locked", OdbcType.Int).Value = False
cmd.Parameters.Add( _
"@Expires", OdbcType.DateTime).Value = DateTime.Now
If cmd.ExecuteNonQuery() = 0 Then ' No record was updated because the record was locked or not found.
locked = TrueElse ' The record was updated.
locked = FalseEndIfEndIf
' Retrieve the current session item information.
cmd = New OdbcCommand( _
"SELECT Expires, SessionItems, LockId, LockDate, Flags, Timeout " & _
" FROM Sessions " & _
" WHERE SessionId = ? AND ApplicationName = ?", conn)
cmd.Parameters.Add("@SessionId", OdbcType.VarChar, 80).Value = id
cmd.Parameters.Add("@ApplicationName", OdbcType.VarChar, _
255).Value = ApplicationName
' Retrieve session item data from the data source.
reader = cmd.ExecuteReader(CommandBehavior.SingleRow)
DoWhile reader.Read()
expires = reader.GetDateTime(0)
If expires < DateTime.Now Then ' The record was expired. Mark it as not locked.
locked = False ' The session was expired. Mark the data for deletion.
deleteData = TrueElse
foundRecord = TrueEndIf
serializedItems = reader.GetString(1)
lockId = reader.GetInt32(2)
lockAge = DateTime.Now.Subtract(reader.GetDateTime(3))
actionFlags = CType(reader.GetInt32(4), SessionStateActions)
timeout = reader.GetInt32(5)
Loop
reader.Close()
' If the returned session item is expired, ' delete the record from the data source.If deleteData Then
cmd = New OdbcCommand("DELETE FROM Sessions " & _
"WHERE SessionId = ? AND ApplicationName = ?", conn)
cmd.Parameters.Add("@SessionId", OdbcType.VarChar, 80).Value = id
cmd.Parameters.Add("@ApplicationName", OdbcType.VarChar, _
255).Value = ApplicationName
cmd.ExecuteNonQuery()
EndIf
' The record was not found. Ensure that locked is False.IfNot foundRecord Then _
locked = False
' If the record was found and you obtained a lock, then set ' the lockId, clear the actionFlags, ' and create the SessionStateStoreItem to return.If foundRecord AndAlsoNot locked Then
lockId = CInt(lockId) + 1
cmd = New OdbcCommand("UPDATE Sessions SET" & _
" LockId = ?, Flags = 0 " & _
" WHERE SessionId = ? AND ApplicationName = ?", conn)
cmd.Parameters.Add("@LockId", OdbcType.Int).Value = lockId
cmd.Parameters.Add("@SessionId", OdbcType.VarChar, 80).Value = id
cmd.Parameters.Add("@ApplicationName", OdbcType.VarChar, 255).Value = ApplicationName
cmd.ExecuteNonQuery()
' If the actionFlags parameter is not InitializeItem, ' deserialize the stored SessionStateItemCollection.If actionFlags = SessionStateActions.InitializeItem Then
item = CreateNewStoreData(context, pConfig.Timeout.TotalMinutes)
Else
item = Deserialize(context, serializedItems, timeout)
EndIfEndIfCatch e As OdbcException
If WriteExceptionsToEventLog Then
WriteToEventLog(e, "GetSessionStoreItem")
ThrowNew Exception(exceptionMessage)
ElseThrow e
EndIfFinallyIfNot reader IsNothingThen reader.Close()
conn.Close()
EndTryReturn item
EndFunction
' ' Serialize is called by the SetAndReleaseItemExclusive method to ' convert the SessionStateItemCollection into a Base64 string to ' be stored in an Access Memo field. 'PrivateFunction Serialize(items As SessionStateItemCollection) AsStringDim ms As MemoryStream = New MemoryStream()
Dim writer As BinaryWriter = New BinaryWriter(ms)
IfNot items IsNothingThen _
items.Serialize(writer)
writer.Close()
Return Convert.ToBase64String(ms.ToArray())
EndFunction
' ' Deserialize is called by the GetSessionStoreItem method to ' convert the Base64 string stored in the Access Memo field to a ' SessionStateItemCollection. 'PrivateFunction Deserialize(context As HttpContext, _
serializedItems AsString, timeout AsInteger) As SessionStateStoreData
Dim ms As MemoryStream = _
New MemoryStream(Convert.FromBase64String(serializedItems))
Dim sessionItems As SessionStateItemCollection = _
New SessionStateItemCollection()
If ms.Length > 0 ThenDim reader As BinaryReader = New BinaryReader(ms)
sessionItems = SessionStateItemCollection.Deserialize(reader)
EndIfReturnNew SessionStateStoreData(sessionItems, _
SessionStateUtility.GetSessionStaticObjects(context), _
timeout)
EndFunction
' ' SessionStateProviderBase.ReleaseItemExclusive 'PublicOverridesSub ReleaseItemExclusive(context As HttpContext, _
id AsString, _
lockId AsObject)
Dim conn As OdbcConnection = New OdbcConnection(connectionString)
Dim cmd As OdbcCommand = _
New OdbcCommand("UPDATE Sessions SET Locked = 0, Expires = ? " & _
"WHERE SessionId = ? AND ApplicationName = ? AND LockId = ?", conn)
cmd.Parameters.Add("@Expires", OdbcType.DateTime).Value = _
DateTime.Now.AddMinutes(pConfig.Timeout.TotalMinutes)
cmd.Parameters.Add("@SessionId", OdbcType.VarChar, 80).Value = id
cmd.Parameters.Add("@ApplicationName", OdbcType.VarChar, _
255).Value = ApplicationName
cmd.Parameters.Add("@LockId", OdbcType.Int).Value = lockId
Try
conn.Open()
cmd.ExecuteNonQuery()
Catch e As OdbcException
If WriteExceptionsToEventLog Then
WriteToEventLog(e, "ReleaseItemExclusive")
ThrowNew Exception(exceptionMessage)
ElseThrow e
EndIfFinally
conn.Close()
EndTryEndSub
' ' SessionStateProviderBase.RemoveItem 'PublicOverridesSub RemoveItem(context As HttpContext, _
id AsString, _
lockId AsObject, _
item As SessionStateStoreData)
Dim conn As OdbcConnection = New OdbcConnection(connectionString)
Dim cmd As OdbcCommand = New OdbcCommand("DELETE * FROM Sessions " & _
"WHERE SessionId = ? AND ApplicationName = ? AND LockId = ?", conn)
cmd.Parameters.Add("@SessionId", OdbcType.VarChar, 80).Value = id
cmd.Parameters.Add("@ApplicationName", OdbcType.VarChar, _
255).Value = ApplicationName
cmd.Parameters.Add("@LockId", OdbcType.Int).Value = lockId
Try
conn.Open()
cmd.ExecuteNonQuery()
Catch e As OdbcException
If WriteExceptionsToEventLog Then
WriteToEventLog(e, "RemoveItem")
ThrowNew Exception(exceptionMessage)
ElseThrow e
EndIfFinally
conn.Close()
EndTryEndSub
' ' SessionStateProviderBase.CreateUninitializedItem 'PublicOverridesSub CreateUninitializedItem(context As HttpContext, _
id AsString, _
timeout AsInteger)
Dim conn As OdbcConnection = New OdbcConnection(connectionString)
Dim cmd As OdbcCommand = New OdbcCommand("INSERT INTO Sessions " & _
" (SessionId, ApplicationName, Created, Expires, " & _
" LockDate, LockId, Timeout, Locked, SessionItems, Flags) " & _
" Values(?, ?, ?, ?, ?, ? , ?, ?, ?, ?)", conn)
cmd.Parameters.Add("@SessionId", OdbcType.VarChar, 80).Value = id
cmd.Parameters.Add("@ApplicationName", OdbcType.VarChar, _
255).Value = ApplicationName
cmd.Parameters.Add("@Created", OdbcType.DateTime).Value = _
DateTime.Now
cmd.Parameters.Add("@Expires", OdbcType.DateTime).Value = _
DateTime.Now.AddMinutes(CDbl(timeout))
cmd.Parameters.Add("@LockDate", OdbcType.DateTime).Value = _
DateTime.Now
cmd.Parameters.Add("@LockId", OdbcType.Int).Value = 0
cmd.Parameters.Add("@Timeout", OdbcType.Int).Value = timeout
cmd.Parameters.Add("@Locked", OdbcType.Bit).Value = False
cmd.Parameters.Add("@SessionItems", OdbcType.VarChar, 0).Value = ""
cmd.Parameters.Add("@Flags", OdbcType.Int).Value = 1
Try
conn.Open()
cmd.ExecuteNonQuery()
Catch e As OdbcException
If WriteExceptionsToEventLog Then
WriteToEventLog(e, "CreateUninitializedItem")
ThrowNew Exception(exceptionMessage)
ElseThrow e
EndIfFinally
conn.Close()
EndTryEndSub
' ' SessionStateProviderBase.CreateNewStoreData 'PublicOverridesFunction CreateNewStoreData( _
context As HttpContext, _
timeout AsInteger) As SessionStateStoreData
ReturnNew SessionStateStoreData(New SessionStateItemCollection(), _
SessionStateUtility.GetSessionStaticObjects(context), _
timeout)
EndFunction
' ' SessionStateProviderBase.ResetItemTimeout 'PublicOverridesSub ResetItemTimeout(context As HttpContext, _
id AsString)
Dim conn As OdbcConnection = New OdbcConnection(connectionString)
Dim cmd As OdbcCommand = _
New OdbcCommand("UPDATE Sessions SET Expires = ? " & _
"WHERE SessionId = ? AND ApplicationName = ?", conn)
cmd.Parameters.Add("@Expires", OdbcType.DateTime).Value = _
DateTime.Now.AddMinutes(pConfig.Timeout.TotalMinutes)
cmd.Parameters.Add("@SessionId", OdbcType.VarChar, 80).Value = id
cmd.Parameters.Add("@ApplicationName", OdbcType.VarChar, _
255).Value = ApplicationName
Try
conn.Open()
cmd.ExecuteNonQuery()
Catch e As OdbcException
If WriteExceptionsToEventLog Then
WriteToEventLog(e, "ResetItemTimeout")
ThrowNew Exception(exceptionMessage)
ElseThrow e
EndIfFinally
conn.Close()
EndTryEndSub
' ' SessionStateProviderBase.InitializeRequest 'PublicOverridesSub InitializeRequest(context As HttpContext)
EndSub
' ' SessionStateProviderBase.EndRequest 'PublicOverridesSub EndRequest(context As HttpContext)
EndSub
' ' WriteToEventLog ' This is a helper function that writes exception detail to the ' event log. Exceptions are written to the event log as a security ' measure to ensure Private database details are not returned to ' browser. If a method does not Return a status or Boolean ' indicating the action succeeded or failed, the caller also ' throws a generic exception. 'PrivateSub WriteToEventLog(e As Exception, action AsString)
Dim log As EventLog = New EventLog()
log.Source = eventSource
log.Log = eventLog
Dim message AsString = _
"An exception occurred communicating with the data source." & vbCrLf & vbCrLf
message &= "Action: " & action & vbCrLf & vbCrLf
message &= "Exception: " & e.ToString()
log.WriteEntry(message)
EndSubEndClassEndNamespace
using System;
using System.Web;
using System.Web.Configuration;
using System.Configuration;
using System.Configuration.Provider;
using System.Collections.Specialized;
using System.Web.SessionState;
using System.Data;
using System.Data.Odbc;
using System.Diagnostics;
using System.IO;
/*
This session state store provider supports the following schema:
CREATE TABLE Sessions
(
SessionId Text(80) NOT NULL,
ApplicationName Text(255) NOT NULL,
Created DateTime NOT NULL,
Expires DateTime NOT NULL,
LockDate DateTime NOT NULL,
LockId Integer NOT NULL,
Timeout Integer NOT NULL,
Locked YesNo NOT NULL,
SessionItems Memo,
Flags Integer NOT NULL,
CONSTRAINT PKSessions PRIMARY KEY (SessionId, ApplicationName)
)
This session state store provider does not automatically clean up
expired session item data. It is recommended
that you periodically delete expired session information from the
data store with the following code (where 'conn' is the OdbcConnection
for the session state store provider):
string commandString = "DELETE FROM Sessions WHERE Expires < ?";
OdbcConnection conn = new OdbcConnection(connectionString);
OdbcCommand cmd = new OdbcCommand(commandString, conn);
cmd.Parameters.Add("@Expires", OdbcType.DateTime).Value = DateTime.Now;
conn.Open();
cmd.ExecuteNonQuery();
conn.Close();
*/namespace Samples.AspNet.Session
{
publicsealedclass OdbcSessionStateStore : SessionStateStoreProviderBase
{
private SessionStateSection pConfig = null;
privatestring connectionString;
private ConnectionStringSettings pConnectionStringSettings;
privatestring eventSource = "OdbcSessionStateStore";
privatestring eventLog = "Application";
privatestring exceptionMessage =
"An exception occurred. Please contact your administrator.";
privatestring pApplicationName;
//// If false, exceptions are thrown to the caller. If true,// exceptions are written to the event log.//privatebool pWriteExceptionsToEventLog = false;
publicbool WriteExceptionsToEventLog
{
get { return pWriteExceptionsToEventLog; }
set { pWriteExceptionsToEventLog = value; }
}
//// The ApplicationName property is used to differentiate sessions// in the data source by application.//publicstring ApplicationName
{
get { return pApplicationName; }
}
publicoverridevoid Initialize(string name, NameValueCollection config)
{
//// Initialize values from web.config.//if (config == null)
thrownew ArgumentNullException("config");
if (name == null || name.Length == 0)
name = "OdbcSessionStateStore";
if (String.IsNullOrEmpty(config["description"]))
{
config.Remove("description");
config.Add("description", "Sample ODBC Session State Store provider");
}
// Initialize the abstract base class.base.Initialize(name, config);
//// Initialize the ApplicationName property.//
pApplicationName =
System.Web.Hosting.HostingEnvironment.ApplicationVirtualPath;
//// Get <sessionState> configuration element.//
Configuration cfg =
WebConfigurationManager.OpenWebConfiguration(ApplicationName);
pConfig =
(SessionStateSection)cfg.GetSection("system.web/sessionState");
//// Initialize connection string.//
pConnectionStringSettings =
ConfigurationManager.ConnectionStrings[config["connectionStringName"]];
if (pConnectionStringSettings == null ||
pConnectionStringSettings.ConnectionString.Trim() == "")
{
thrownew ProviderException("Connection string cannot be blank.");
}
connectionString = pConnectionStringSettings.ConnectionString;
//// Initialize WriteExceptionsToEventLog//
pWriteExceptionsToEventLog = false;
if (config["writeExceptionsToEventLog"] != null)
{
if (config["writeExceptionsToEventLog"].ToUpper() == "TRUE")
pWriteExceptionsToEventLog = true;
}
}
//// SessionStateStoreProviderBase members//publicoverridevoid Dispose()
{
}
//// SessionStateProviderBase.SetItemExpireCallback//publicoverridebool SetItemExpireCallback(SessionStateItemExpireCallback expireCallback)
{
returnfalse;
}
//// SessionStateProviderBase.SetAndReleaseItemExclusive//publicoverridevoid SetAndReleaseItemExclusive(HttpContext context,
string id,
SessionStateStoreData item,
object lockId,
bool newItem)
{
// Serialize the SessionStateItemCollection as a string.string sessItems = Serialize((SessionStateItemCollection)item.Items);
OdbcConnection conn = new OdbcConnection(connectionString);
OdbcCommand cmd;
OdbcCommand deleteCmd = null;
if (newItem)
{
// OdbcCommand to clear an existing expired session if it exists.
deleteCmd = new OdbcCommand("DELETE FROM Sessions " +
"WHERE SessionId = ? AND ApplicationName = ? AND Expires < ?", conn);
deleteCmd.Parameters.Add("@SessionId", OdbcType.VarChar, 80).Value = id;
deleteCmd.Parameters.Add
("@ApplicationName", OdbcType.VarChar, 255).Value = ApplicationName;
deleteCmd.Parameters.Add
("@Expires", OdbcType.DateTime).Value = DateTime.Now;
// OdbcCommand to insert the new session item.
cmd = new OdbcCommand("INSERT INTO Sessions " +
" (SessionId, ApplicationName, Created, Expires, " +
" LockDate, LockId, Timeout, Locked, SessionItems, Flags) " +
" Values(?, ?, ?, ?, ?, ? , ?, ?, ?, ?)", conn);
cmd.Parameters.Add("@SessionId", OdbcType.VarChar, 80).Value = id;
cmd.Parameters.Add
("@ApplicationName", OdbcType.VarChar, 255).Value = ApplicationName;
cmd.Parameters.Add
("@Created", OdbcType.DateTime).Value = DateTime.Now;
cmd.Parameters.Add
("@Expires", OdbcType.DateTime).Value = DateTime.Now.AddMinutes((Double)item.Timeout);
cmd.Parameters.Add
("@LockDate", OdbcType.DateTime).Value = DateTime.Now;
cmd.Parameters.Add("@LockId", OdbcType.Int).Value = 0;
cmd.Parameters.Add
("@Timeout", OdbcType.Int).Value = item.Timeout;
cmd.Parameters.Add("@Locked", OdbcType.Bit).Value = false;
cmd.Parameters.Add
("@SessionItems", OdbcType.VarChar, sessItems.Length).Value = sessItems;
cmd.Parameters.Add("@Flags", OdbcType.Int).Value = 0;
}
else
{
// OdbcCommand to update the existing session item.
cmd = new OdbcCommand(
"UPDATE Sessions SET Expires = ?, SessionItems = ?, Locked = ? " +
" WHERE SessionId = ? AND ApplicationName = ? AND LockId = ?", conn);
cmd.Parameters.Add("@Expires", OdbcType.DateTime).Value =
DateTime.Now.AddMinutes((Double)item.Timeout);
cmd.Parameters.Add("@SessionItems",
OdbcType.VarChar, sessItems.Length).Value = sessItems;
cmd.Parameters.Add("@Locked", OdbcType.Bit).Value = false;
cmd.Parameters.Add("@SessionId", OdbcType.VarChar, 80).Value = id;
cmd.Parameters.Add("@ApplicationName", OdbcType.VarChar,
255).Value = ApplicationName;
cmd.Parameters.Add("@LockId", OdbcType.Int).Value = lockId;
}
try
{
conn.Open();
if (deleteCmd != null)
deleteCmd.ExecuteNonQuery();
cmd.ExecuteNonQuery();
}
catch (OdbcException e)
{
if (WriteExceptionsToEventLog)
{
WriteToEventLog(e, "SetAndReleaseItemExclusive");
thrownew ProviderException(exceptionMessage);
}
elsethrow e;
}
finally
{
conn.Close();
}
}
//// SessionStateProviderBase.GetItem//publicoverride SessionStateStoreData GetItem(HttpContext context,
string id,
outbool locked,
out TimeSpan lockAge,
outobject lockId,
out SessionStateActions actionFlags)
{
return GetSessionStoreItem(false, context, id, out locked,
out lockAge, out lockId, out actionFlags);
}
//// SessionStateProviderBase.GetItemExclusive//publicoverride SessionStateStoreData GetItemExclusive(HttpContext context,
string id,
outbool locked,
out TimeSpan lockAge,
outobject lockId,
out SessionStateActions actionFlags)
{
return GetSessionStoreItem(true, context, id, out locked,
out lockAge, out lockId, out actionFlags);
}
//// GetSessionStoreItem is called by both the GetItem and // GetItemExclusive methods. GetSessionStoreItem retrieves the // session data from the data source. If the lockRecord parameter// is true (in the case of GetItemExclusive), then GetSessionStoreItem// locks the record and sets a new LockId and LockDate.//private SessionStateStoreData GetSessionStoreItem(bool lockRecord,
HttpContext context,
string id,
outbool locked,
out TimeSpan lockAge,
outobject lockId,
out SessionStateActions actionFlags)
{
// Initial values for return value and out parameters.
SessionStateStoreData item = null;
lockAge = TimeSpan.Zero;
lockId = null;
locked = false;
actionFlags = 0;
// ODBC database connection.
OdbcConnection conn = new OdbcConnection(connectionString);
// OdbcCommand for database commands.
OdbcCommand cmd = null;
// DataReader to read database record.
OdbcDataReader reader = null;
// DateTime to check if current session item is expired.
DateTime expires;
// String to hold serialized SessionStateItemCollection.string serializedItems = "";
// True if a record is found in the database.bool foundRecord = false;
// True if the returned session item is expired and needs to be deleted.bool deleteData = false;
// Timeout value from the data store.int timeout = 0;
try
{
conn.Open();
// lockRecord is true when called from GetItemExclusive and// false when called from GetItem.// Obtain a lock if possible. Ignore the record if it is expired.if (lockRecord)
{
cmd = new OdbcCommand(
"UPDATE Sessions SET" +
" Locked = ?, LockDate = ? " +
" WHERE SessionId = ? AND ApplicationName = ? AND Locked = ? AND Expires > ?", conn);
cmd.Parameters.Add("@Locked", OdbcType.Bit).Value = true;
cmd.Parameters.Add("@LockDate", OdbcType.DateTime).Value
= DateTime.Now;
cmd.Parameters.Add("@SessionId", OdbcType.VarChar, 80).Value = id;
cmd.Parameters.Add("@ApplicationName", OdbcType.VarChar,
255).Value = ApplicationName;
cmd.Parameters.Add("@Locked", OdbcType.Int).Value = false;
cmd.Parameters.Add
("@Expires", OdbcType.DateTime).Value = DateTime.Now;
if (cmd.ExecuteNonQuery() == 0)
// No record was updated because the record was locked or not found.
locked = true;
else// The record was updated.
locked = false;
}
// Retrieve the current session item information.
cmd = new OdbcCommand(
"SELECT Expires, SessionItems, LockId, LockDate, Flags, Timeout " +
" FROM Sessions " +
" WHERE SessionId = ? AND ApplicationName = ?", conn);
cmd.Parameters.Add("@SessionId", OdbcType.VarChar, 80).Value = id;
cmd.Parameters.Add("@ApplicationName", OdbcType.VarChar,
255).Value = ApplicationName;
// Retrieve session item data from the data source.
reader = cmd.ExecuteReader(CommandBehavior.SingleRow);
while (reader.Read())
{
expires = reader.GetDateTime(0);
if (expires < DateTime.Now)
{
// The record was expired. Mark it as not locked.
locked = false;
// The session was expired. Mark the data for deletion.
deleteData = true;
}
else
foundRecord = true;
serializedItems = reader.GetString(1);
lockId = reader.GetInt32(2);
lockAge = DateTime.Now.Subtract(reader.GetDateTime(3));
actionFlags = (SessionStateActions)reader.GetInt32(4);
timeout = reader.GetInt32(5);
}
reader.Close();
// If the returned session item is expired, // delete the record from the data source.if (deleteData)
{
cmd = new OdbcCommand("DELETE FROM Sessions " +
"WHERE SessionId = ? AND ApplicationName = ?", conn);
cmd.Parameters.Add("@SessionId", OdbcType.VarChar, 80).Value = id;
cmd.Parameters.Add("@ApplicationName", OdbcType.VarChar,
255).Value = ApplicationName;
cmd.ExecuteNonQuery();
}
// The record was not found. Ensure that locked is false.if (!foundRecord)
locked = false;
// If the record was found and you obtained a lock, then set // the lockId, clear the actionFlags,// and create the SessionStateStoreItem to return.if (foundRecord && !locked)
{
lockId = (int)lockId + 1;
cmd = new OdbcCommand("UPDATE Sessions SET" +
" LockId = ?, Flags = 0 " +
" WHERE SessionId = ? AND ApplicationName = ?", conn);
cmd.Parameters.Add("@LockId", OdbcType.Int).Value = lockId;
cmd.Parameters.Add("@SessionId", OdbcType.VarChar, 80).Value = id;
cmd.Parameters.Add("@ApplicationName", OdbcType.VarChar, 255).Value = ApplicationName;
cmd.ExecuteNonQuery();
// If the actionFlags parameter is not InitializeItem, // deserialize the stored SessionStateItemCollection.if (actionFlags == SessionStateActions.InitializeItem)
item = CreateNewStoreData(context, pConfig.Timeout.TotalMinutes);
else
item = Deserialize(context, serializedItems, timeout);
}
}
catch (OdbcException e)
{
if (WriteExceptionsToEventLog)
{
WriteToEventLog(e, "GetSessionStoreItem");
thrownew ProviderException(exceptionMessage);
}
elsethrow e;
}
finally
{
if (reader != null) { reader.Close(); }
conn.Close();
}
return item;
}
//// Serialize is called by the SetAndReleaseItemExclusive method to // convert the SessionStateItemCollection into a Base64 string to // be stored in an Access Memo field.//privatestring Serialize(SessionStateItemCollection items)
{
MemoryStream ms = new MemoryStream();
BinaryWriter writer = new BinaryWriter(ms);
if (items != null)
items.Serialize(writer);
writer.Close();
return Convert.ToBase64String(ms.ToArray());
}
//// DeSerialize is called by the GetSessionStoreItem method to // convert the Base64 string stored in the Access Memo field to a // SessionStateItemCollection.//private SessionStateStoreData Deserialize(HttpContext context,
string serializedItems, int timeout)
{
MemoryStream ms =
new MemoryStream(Convert.FromBase64String(serializedItems));
SessionStateItemCollection sessionItems =
new SessionStateItemCollection();
if (ms.Length > 0)
{
BinaryReader reader = new BinaryReader(ms);
sessionItems = SessionStateItemCollection.Deserialize(reader);
}
returnnew SessionStateStoreData(sessionItems,
SessionStateUtility.GetSessionStaticObjects(context),
timeout);
}
//// SessionStateProviderBase.ReleaseItemExclusive//publicoverridevoid ReleaseItemExclusive(HttpContext context,
string id,
object lockId)
{
OdbcConnection conn = new OdbcConnection(connectionString);
OdbcCommand cmd =
new OdbcCommand("UPDATE Sessions SET Locked = 0, Expires = ? " +
"WHERE SessionId = ? AND ApplicationName = ? AND LockId = ?", conn);
cmd.Parameters.Add("@Expires", OdbcType.DateTime).Value =
DateTime.Now.AddMinutes(pConfig.Timeout.TotalMinutes);
cmd.Parameters.Add("@SessionId", OdbcType.VarChar, 80).Value = id;
cmd.Parameters.Add("@ApplicationName", OdbcType.VarChar,
255).Value = ApplicationName;
cmd.Parameters.Add("@LockId", OdbcType.Int).Value = lockId;
try
{
conn.Open();
cmd.ExecuteNonQuery();
}
catch (OdbcException e)
{
if (WriteExceptionsToEventLog)
{
WriteToEventLog(e, "ReleaseItemExclusive");
thrownew ProviderException(exceptionMessage);
}
elsethrow e;
}
finally
{
conn.Close();
}
}
//// SessionStateProviderBase.RemoveItem//publicoverridevoid RemoveItem(HttpContext context,
string id,
object lockId,
SessionStateStoreData item)
{
OdbcConnection conn = new OdbcConnection(connectionString);
OdbcCommand cmd = new OdbcCommand("DELETE * FROM Sessions " +
"WHERE SessionId = ? AND ApplicationName = ? AND LockId = ?", conn);
cmd.Parameters.Add("@SessionId", OdbcType.VarChar, 80).Value = id;
cmd.Parameters.Add("@ApplicationName", OdbcType.VarChar,
255).Value = ApplicationName;
cmd.Parameters.Add("@LockId", OdbcType.Int).Value = lockId;
try
{
conn.Open();
cmd.ExecuteNonQuery();
}
catch (OdbcException e)
{
if (WriteExceptionsToEventLog)
{
WriteToEventLog(e, "RemoveItem");
thrownew ProviderException(exceptionMessage);
}
elsethrow e;
}
finally
{
conn.Close();
}
}
//// SessionStateProviderBase.CreateUninitializedItem//publicoverridevoid CreateUninitializedItem(HttpContext context,
string id,
int timeout)
{
OdbcConnection conn = new OdbcConnection(connectionString);
OdbcCommand cmd = new OdbcCommand("INSERT INTO Sessions " +
" (SessionId, ApplicationName, Created, Expires, " +
" LockDate, LockId, Timeout, Locked, SessionItems, Flags) " +
" Values(?, ?, ?, ?, ?, ? , ?, ?, ?, ?)", conn);
cmd.Parameters.Add("@SessionId", OdbcType.VarChar, 80).Value = id;
cmd.Parameters.Add("@ApplicationName", OdbcType.VarChar,
255).Value = ApplicationName;
cmd.Parameters.Add("@Created", OdbcType.DateTime).Value
= DateTime.Now;
cmd.Parameters.Add("@Expires", OdbcType.DateTime).Value
= DateTime.Now.AddMinutes((Double)timeout);
cmd.Parameters.Add("@LockDate", OdbcType.DateTime).Value
= DateTime.Now;
cmd.Parameters.Add("@LockId", OdbcType.Int).Value = 0;
cmd.Parameters.Add("@Timeout", OdbcType.Int).Value = timeout;
cmd.Parameters.Add("@Locked", OdbcType.Bit).Value = false;
cmd.Parameters.Add("@SessionItems", OdbcType.VarChar, 0).Value = "";
cmd.Parameters.Add("@Flags", OdbcType.Int).Value = 1;
try
{
conn.Open();
cmd.ExecuteNonQuery();
}
catch (OdbcException e)
{
if (WriteExceptionsToEventLog)
{
WriteToEventLog(e, "CreateUninitializedItem");
thrownew ProviderException(exceptionMessage);
}
elsethrow e;
}
finally
{
conn.Close();
}
}
//// SessionStateProviderBase.CreateNewStoreData//publicoverride SessionStateStoreData CreateNewStoreData(
HttpContext context,
int timeout)
{
returnnew SessionStateStoreData(new SessionStateItemCollection(),
SessionStateUtility.GetSessionStaticObjects(context),
timeout);
}
//// SessionStateProviderBase.ResetItemTimeout//publicoverridevoid ResetItemTimeout(HttpContext context,
string id)
{
OdbcConnection conn = new OdbcConnection(connectionString);
OdbcCommand cmd =
new OdbcCommand("UPDATE Sessions SET Expires = ? " +
"WHERE SessionId = ? AND ApplicationName = ?", conn);
cmd.Parameters.Add("@Expires", OdbcType.DateTime).Value
= DateTime.Now.AddMinutes(pConfig.Timeout.TotalMinutes);
cmd.Parameters.Add("@SessionId", OdbcType.VarChar, 80).Value = id;
cmd.Parameters.Add("@ApplicationName", OdbcType.VarChar,
255).Value = ApplicationName;
try
{
conn.Open();
cmd.ExecuteNonQuery();
}
catch (OdbcException e)
{
if (WriteExceptionsToEventLog)
{
WriteToEventLog(e, "ResetItemTimeout");
thrownew ProviderException(exceptionMessage);
}
elsethrow e;
}
finally
{
conn.Close();
}
}
//// SessionStateProviderBase.InitializeRequest//publicoverridevoid InitializeRequest(HttpContext context)
{
}
//// SessionStateProviderBase.EndRequest//publicoverridevoid EndRequest(HttpContext context)
{
}
//// WriteToEventLog// This is a helper function that writes exception detail to the // event log. Exceptions are written to the event log as a security// measure to ensure private database details are not returned to // browser. If a method does not return a status or Boolean// indicating the action succeeded or failed, the caller also // throws a generic exception.//privatevoid WriteToEventLog(Exception e, string action)
{
EventLog log = new EventLog();
log.Source = eventSource;
log.Log = eventLog;
string message =
"An exception occurred communicating with the data source.\n\n";
message += "Action: " + action + "\n\n";
message += "Exception: " + e.ToString();
log.WriteEntry(message);
}
}
}
See Also
Concepts
Sample Session-State Store Provider
Implementing a Session-State Store Provider