diff --git a/src/SqlSessionStateProviderAsync/Microsoft.AspNet.SessionState.SqlSessionStateProviderAsync.csproj b/src/SqlSessionStateProviderAsync/Microsoft.AspNet.SessionState.SqlSessionStateProviderAsync.csproj
index a527de7..3b6c90b 100644
--- a/src/SqlSessionStateProviderAsync/Microsoft.AspNet.SessionState.SqlSessionStateProviderAsync.csproj
+++ b/src/SqlSessionStateProviderAsync/Microsoft.AspNet.SessionState.SqlSessionStateProviderAsync.csproj
@@ -77,6 +77,7 @@
+
diff --git a/src/SqlSessionStateProviderAsync/SqlSessionStateProviderAsync.cs b/src/SqlSessionStateProviderAsync/SqlSessionStateProviderAsync.cs
index 7a6b3bf..c391274 100644
--- a/src/SqlSessionStateProviderAsync/SqlSessionStateProviderAsync.cs
+++ b/src/SqlSessionStateProviderAsync/SqlSessionStateProviderAsync.cs
@@ -29,6 +29,7 @@ public class SqlSessionStateProviderAsync : SessionStateStoreProviderAsyncBase
private const string RETRY_INTERVAL_CONFIGURATION_NAME = "retryInterval";
private const string CONNECTIONSTRING_NAME_CONFIGURATION_NAME = "connectionStringName";
private const string SESSION_TABLE_CONFIGURATION_NAME = "sessionTableName";
+ private const string APP_ID_CONFIGURATION_NAME = "appId";
private const string SESSIONSTATE_SECTION_PATH = "system.web/sessionState";
private const double SessionExpiresFrequencyCheckIntervalTicks = 30 * TimeSpan.TicksPerSecond;
private static long s_lastSessionPurgeTicks;
@@ -41,7 +42,7 @@ public class SqlSessionStateProviderAsync : SessionStateStoreProviderAsyncBase
private static RepositoryType s_repositoryType;
private int _rqOrigStreamLen;
-
+
///
/// Initialize the provider through the configuration
///
@@ -65,7 +66,7 @@ public override void Initialize(string name, NameValueCollection config)
}
// for unit tests
- internal void Initialize(string name, NameValueCollection config, SessionStateSection ssc, ConnectionStringSettings connectionString,
+ internal void Initialize(string name, NameValueCollection config, SessionStateSection ssc, ConnectionStringSettings connectionString,
bool shouldCreateTable = false)
{
base.Initialize(name, config);
@@ -105,27 +106,52 @@ internal void Initialize(string name, NameValueCollection config, SessionStateSe
// Initialize the repository
if (s_repositoryType == RepositoryType.InMemory || s_repositoryType == RepositoryType.InMemoryDurable)
{
- s_sqlSessionStateRepository = new SqlInMemoryTableSessionStateRepository(connectionString.ConnectionString, tableName,
- (int)ssc.SqlCommandTimeout.TotalSeconds, GetRetryInterval(config), GetMaxRetryNum(config), (s_repositoryType == RepositoryType.InMemoryDurable));
+ s_sqlSessionStateRepository = new SqlInMemoryTableSessionStateRepository(
+ connectionString.ConnectionString,
+ tableName,
+ (int)ssc.SqlCommandTimeout.TotalSeconds,
+ GetRetryInterval(config),
+ GetMaxRetryNum(config),
+ (s_repositoryType == RepositoryType.InMemoryDurable)
+ );
}
else if (s_repositoryType == RepositoryType.FrameworkCompat)
{
- s_sqlSessionStateRepository = new SqlFxCompatSessionStateRepository(connectionString.ConnectionString, tableName,
- (int)ssc.SqlCommandTimeout.TotalSeconds, GetRetryInterval(config), GetMaxRetryNum(config));
+ s_sqlSessionStateRepository = new SqlFxCompatSessionStateRepository(
+ connectionString.ConnectionString,
+ tableName,
+ (int)ssc.SqlCommandTimeout.TotalSeconds,
+ GetRetryInterval(config),
+ GetMaxRetryNum(config)
+ );
}
else
{
- s_sqlSessionStateRepository = new SqlSessionStateRepository(connectionString.ConnectionString, tableName,
- (int)ssc.SqlCommandTimeout.TotalSeconds, GetRetryInterval(config), GetMaxRetryNum(config));
+ s_sqlSessionStateRepository = new SqlSessionStateRepository(
+ connectionString.ConnectionString,
+ tableName,
+ (int)ssc.SqlCommandTimeout.TotalSeconds,
+ GetRetryInterval(config),
+ GetMaxRetryNum(config)
+ );
}
if (shouldCreateTable)
{
s_sqlSessionStateRepository.CreateSessionStateTable();
}
- var appId = AppId ?? HttpRuntime.AppDomainAppId;
+ //============================================================================ robs ==
+ // Use AppId from config if specified, otherwise use AppDomainAppId
+ //====================================================================== 2023-07-21 ==
+ string configAppId = config[APP_ID_CONFIGURATION_NAME];
+ if (string.IsNullOrEmpty(configAppId))
+ {
+ configAppId = HttpRuntime.AppDomainAppId;
+ }
+
+ string appId = AppId ?? configAppId;
Debug.Assert(appId != null);
- s_appSuffix = appId.GetHashCode().ToString("X8", CultureInfo.InvariantCulture);
+ s_appSuffix = appId.GetDeterministicHashCode().ToString("X8", CultureInfo.InvariantCulture);
s_oneTimeInited = true;
}
@@ -188,7 +214,7 @@ internal static Func GetSessionStaticO
{
int retryInterval;
var val = config[RETRY_INTERVAL_CONFIGURATION_NAME];
- if(val != null && int.TryParse(val, out retryInterval))
+ if (val != null && int.TryParse(val, out retryInterval))
{
return retryInterval;
}
@@ -214,9 +240,9 @@ public override SessionStateStoreData CreateNewStoreData(HttpContextBase context
///
public override async Task CreateUninitializedItemAsync(
- HttpContextBase context,
- string id,
- int timeout,
+ HttpContextBase context,
+ string id,
+ int timeout,
CancellationToken cancellationToken)
{
if (id == null)
@@ -259,8 +285,8 @@ public override Task GetItemAsync(HttpContextBase context, string
///
public override Task GetItemExclusiveAsync(
- HttpContextBase context,
- string id,
+ HttpContextBase context,
+ string id,
CancellationToken cancellationToken)
{
return DoGet(context, id, true, cancellationToken);
@@ -274,9 +300,9 @@ public override void InitializeRequest(HttpContextBase context)
///
public override async Task ReleaseItemExclusiveAsync(
- HttpContextBase context,
- string id,
- object lockId,
+ HttpContextBase context,
+ string id,
+ object lockId,
CancellationToken cancellationToken)
{
if (id == null)
@@ -295,10 +321,10 @@ public override async Task ReleaseItemExclusiveAsync(
///
public override async Task RemoveItemAsync(
- HttpContextBase context,
- string id,
- object lockId,
- SessionStateStoreData item,
+ HttpContextBase context,
+ string id,
+ object lockId,
+ SessionStateStoreData item,
CancellationToken cancellationToken)
{
if (id == null)
@@ -317,8 +343,8 @@ public override async Task RemoveItemAsync(
///
public override async Task ResetItemTimeoutAsync(
- HttpContextBase context,
- string id,
+ HttpContextBase context,
+ string id,
CancellationToken cancellationToken)
{
if (id == null)
@@ -337,11 +363,11 @@ public override async Task ResetItemTimeoutAsync(
///
public override async Task SetAndReleaseItemExclusiveAsync(
- HttpContextBase context,
- string id,
- SessionStateStoreData item,
- object lockId,
- bool newItem,
+ HttpContextBase context,
+ string id,
+ SessionStateStoreData item,
+ object lockId,
+ bool newItem,
CancellationToken cancellationToken)
{
byte[] buf;
@@ -368,7 +394,7 @@ public override async Task SetAndReleaseItemExclusiveAsync(
}
catch
{
- if(!newItem)
+ if (!newItem)
{
await ReleaseItemExclusiveAsync(context, id, lockId, cancellationToken);
}
@@ -393,15 +419,15 @@ private async Task DoGet(HttpContextBase context, string id, bool
throw new ArgumentException(SR.Session_id_too_long);
}
id = AppendAppIdHash(id);
-
+
SessionStateStoreData data = null;
var sessionItem = await s_sqlSessionStateRepository.GetSessionStateItemAsync(id, exclusive);
- if(sessionItem == null)
+ if (sessionItem == null)
{
return null;
}
- if(sessionItem.Item == null)
+ if (sessionItem.Item == null)
{
return new GetItemResult(null, sessionItem.Locked, sessionItem.LockAge, sessionItem.LockId, sessionItem.Actions);
}
@@ -423,14 +449,14 @@ internal static string AppendAppIdHash(string id)
return id + s_appSuffix;
}
return id;
- }
+ }
// Internal code copied from SessionStateUtility
internal static void SerializeStoreData(
- SessionStateStoreData item,
- int initialStreamSize,
- out byte[] buf,
- out int length,
+ SessionStateStoreData item,
+ int initialStreamSize,
+ out byte[] buf,
+ out int length,
bool compressionEnabled)
{
using (MemoryStream s = new MemoryStream(initialStreamSize))
@@ -518,7 +544,7 @@ private static SessionStateStoreData Deserialize(HttpContextBase context, Stream
try
{
BinaryReader reader = new BinaryReader(stream);
-
+
timeout = reader.ReadInt32();
hasItems = reader.ReadBoolean();
hasStaticObjects = reader.ReadBoolean();
@@ -527,7 +553,8 @@ private static SessionStateStoreData Deserialize(HttpContextBase context, Stream
{
sessionItems = SessionStateItemCollection.Deserialize(reader);
}
- else {
+ else
+ {
sessionItems = new SessionStateItemCollection();
}
@@ -535,7 +562,8 @@ private static SessionStateStoreData Deserialize(HttpContextBase context, Stream
{
staticObjects = HttpStaticObjectsCollection.Deserialize(reader);
}
- else {
+ else
+ {
staticObjects = GetSessionStaticObjects(context.ApplicationInstance.Context);
}
@@ -600,6 +628,6 @@ private static ConnectionStringSettings GetConnectionString(string connectionstr
String.Format(CultureInfo.CurrentCulture, SR.Connection_string_not_found, connectionstringName));
}
return conn;
- }
+ }
}
}
diff --git a/src/SqlSessionStateProviderAsync/StringExtensions.cs b/src/SqlSessionStateProviderAsync/StringExtensions.cs
new file mode 100644
index 0000000..c498d48
--- /dev/null
+++ b/src/SqlSessionStateProviderAsync/StringExtensions.cs
@@ -0,0 +1,29 @@
+namespace Microsoft.AspNet.SessionState
+{
+ internal static class StringExtensions
+ {
+ //============================================================================ robs ==
+ // This is to replace the call to GetHashCode() when appending AppId to the session id.
+ // Using GetHashCode() is not deterministic and can cause problems when used externally (e.g in SQL)
+ // Credit: https://andrewlock.net/why-is-string-gethashcode-different-each-time-i-run-my-program-in-net-core/
+ //====================================================================== 2023-07-21 ==
+ internal static int GetDeterministicHashCode(this string str)
+ {
+ unchecked
+ {
+ int hash1 = (5381 << 16) + 5381;
+ int hash2 = hash1;
+
+ for (int i = 0; i < str.Length; i += 2)
+ {
+ hash1 = ((hash1 << 5) + hash1) ^ str[i];
+ if (i == str.Length - 1)
+ break;
+ hash2 = ((hash2 << 5) + hash2) ^ str[i + 1];
+ }
+
+ return hash1 + (hash2 * 1566083941);
+ }
+ }
+ }
+}