/// <summary>
        /// Checks if any items have changed in the Session, and stores the results to Redis
        /// </summary>
        /// <param name="context">The HttpContext of the current web request</param>
        /// <param name="id">The Session Id and Redis key name</param>
        /// <param name="item">The Session properties</param>
        /// <param name="lockId">The object used to exclusively lock the Session (there shouldn't be one)</param>
        /// <param name="newItem">Whether or not the Session was created in this HttpContext</param>
        public override void SetAndReleaseItemExclusive(HttpContext context, string id, SessionStateStoreData item, object lockId, bool newItem)
        {
            try
            {
                string currentRedisHashId = RedisSessionStateStoreProvider.RedisHashIdFromSessionId(
                    new HttpContextWrapper(context),
                    id);

                LocalSharedSessionDictionary    sharedSessDict = new LocalSharedSessionDictionary();
                RedisSessionStateItemCollection redisItems     =
                    sharedSessDict.GetSessionForEndRequest(currentRedisHashId);

                if (redisItems != null)
                {
                    RedisSessionStateStoreProvider.SerializeToRedis(
                        new HttpContextWrapper(context),
                        redisItems,
                        currentRedisHashId,
                        this.SessionTimeout);
                }
            }
            catch (Exception e)
            {
                if (RedisSessionConfig.SessionExceptionLoggingDel != null)
                {
                    RedisSessionConfig.SessionExceptionLoggingDel(e);
                }
            }
        }
        /// <summary>
        /// This method is called when the Session decides that no element has been modified. Due to
        ///     the implementation of RedisSessionProvider.RedisSessionStateItemCollection, this method
        ///     is never called (because the .Dirty property always returns true). The reason is because
        ///     we always dirty-check the collection in SetAndReleaseItemExclusive to ensure Session
        ///     correctness.
        /// </summary>
        /// <param name="context">The HttpContext of the current web request</param>
        /// <param name="id">The SessionId of the current request</param>
        /// <param name="lockId">A lock around the current Session so no other web request can modify it
        ///     simultaneously</param>
        public override void ReleaseItemExclusive(HttpContext context, string id, object lockId)
        {
            // if, for some reason, we are in this method we still want to record that we are no
            //      longer going to use a session in local cache
            LocalSharedSessionDictionary sharedSessDict = new LocalSharedSessionDictionary();

            sharedSessDict.GetSessionForEndRequest(RedisHashIdFromSessionId(new HttpContextWrapper(context), id));
        }
        /// <summary>
        /// Gets a Session from Redis, indicating a non-exclusive lock on the Session. Note that GetItemExclusive
        ///     calls this method internally, meaning we do not support locks at all retrieving the Session.
        /// </summary>
        /// <param name="context">The HttpContext of the current request</param>
        /// <param name="id">The Session Id, which is the key name in Redis</param>
        /// <param name="locked">Whether or not the Session is locked to exclusive access for a single request
        ///     thread</param>
        /// <param name="lockAge">The age of the lock</param>
        /// <param name="lockId">The object used to lock the Session</param>
        /// <param name="actions">Whether or not to initialize the Session (never)</param>
        /// <returns>The Session objects wrapped in a SessionStateStoreData object</returns>
        public override SessionStateStoreData GetItem(HttpContext context, string id, out bool locked, out TimeSpan lockAge, out object lockId, out SessionStateActions actions)
        {
            locked  = false;
            lockAge = new TimeSpan(0);
            lockId  = null;
            actions = SessionStateActions.None;
            if (id == null)
            {
                return(this.CreateNewStoreData(context, Convert.ToInt32(this.SessionTimeout.TotalMinutes)));
            }
            try
            {
                string parsedRedisHashId = RedisSessionStateStoreProvider.RedisHashIdFromSessionId(
                    new HttpContextWrapper(context),
                    id);

                LocalSharedSessionDictionary sharedSessDict = new LocalSharedSessionDictionary();

                RedisSessionStateItemCollection items = sharedSessDict.GetSessionForBeginRequest(
                    parsedRedisHashId,
                    (redisKey) => {
                    return(RedisSessionStateStoreProvider.GetItemFromRedis(
                               redisKey,
                               new HttpContextWrapper(context),
                               this.SessionTimeout));
                });

                return(new SessionStateStoreData(
                           items,
                           SessionStateUtility.GetSessionStaticObjects(context),
                           Convert.ToInt32(this.SessionTimeout.TotalMinutes)));
            }
            catch (Exception e)
            {
                if (RedisSessionConfig.SessionExceptionLoggingDel != null)
                {
                    RedisSessionConfig.SessionExceptionLoggingDel(e);
                }
            }

            return(this.CreateNewStoreData(context, Convert.ToInt32(this.SessionTimeout.TotalMinutes)));
        }
        /// <summary>
        /// Checks if any items have changed in the Session, and stores the results to Redis
        /// </summary>
        /// <param name="context">The HttpContext of the current web request</param>
        /// <param name="id">The Session Id and Redis key name</param>
        /// <param name="item">The Session properties</param>
        /// <param name="lockId">The object used to exclusively lock the Session (there shouldn't be one)</param>
        /// <param name="newItem">Whether or not the Session was created in this HttpContext</param>
        public override void SetAndReleaseItemExclusive(HttpContext context, string id, SessionStateStoreData item, object lockId, bool newItem)
        {
            try
            {
                string currentRedisHashId = RedisSessionStateStoreProvider.RedisHashIdFromSessionId(
                    new HttpContextWrapper(context),
                    id);

                LocalSharedSessionDictionary    sharedSessDict = new LocalSharedSessionDictionary();
                RedisSessionStateItemCollection redisItems     =
                    sharedSessDict.GetSessionForEndRequest(currentRedisHashId);

                // we were unable to pull it from shared cache, meaning either this is the first request or
                //      something went wrong with the local cache. We still have all the parts needed to write
                //      to redis, however, by looking at SessionStateStoreData passed in from the Session module
                //      and the current hash key provided by the id parameter.
                if (redisItems == null)
                {
                    redisItems = (RedisSessionStateItemCollection)item.Items;
                }

                if (redisItems != null)
                {
                    RedisSessionStateStoreProvider.SerializeToRedis(
                        new HttpContextWrapper(context),
                        redisItems,
                        currentRedisHashId,
                        this.SessionTimeout);
                }
            }
            catch (Exception e)
            {
                if (RedisSessionConfig.SessionExceptionLoggingDel != null)
                {
                    RedisSessionConfig.SessionExceptionLoggingDel(e);
                }
            }
        }
        private static RedisSessionStateItemCollection GetSessionItems(HttpContext context, string id)
        {
            var sharedSessDict = new LocalSharedSessionDictionary();

            return(sharedSessDict.GetSessionItems(new HttpContextWrapper(context), RedisHashIdFromSessionId(new HttpContextWrapper(context), id)));
        }
        /// <summary>
        /// Checks if any items have changed in the Session, and stores the results to Redis
        /// </summary>
        /// <param name="context">The HttpContext of the current web request</param>
        /// <param name="id">The Session Id and Redis key name</param>
        /// <param name="item">The Session properties</param>
        /// <param name="lockId">The object used to exclusively lock the Session (there shouldn't be one)</param>
        /// <param name="newItem">Whether or not the Session was created in this HttpContext</param>
        public override void SetAndReleaseItemExclusive(HttpContext context, string id, SessionStateStoreData item, object lockId, bool newItem)
        {
            try
            {
                string currentRedisHashId = RedisSessionStateStoreProvider.RedisHashIdFromSessionId(
                    new HttpContextWrapper(context), 
                    id);

                LocalSharedSessionDictionary sharedSessDict = new LocalSharedSessionDictionary();
                RedisSessionStateItemCollection redisItems = 
                    sharedSessDict.GetSessionForEndRequest(currentRedisHashId);

                // we were unable to pull it from shared cache, meaning either this is the first request or
                //      something went wrong with the local cache. We still have all the parts needed to write
                //      to redis, however, by looking at SessionStateStoreData passed in from the Session module
                //      and the current hash key provided by the id parameter.
                if (redisItems == null)
                {
                    redisItems = (RedisSessionStateItemCollection)item.Items;
                }

                if (redisItems != null)
                {
                    RedisSessionStateStoreProvider.SerializeToRedis(
                        new HttpContextWrapper(context),
                        redisItems,
                        currentRedisHashId,
                        this.SessionTimeout);
                }
            }
            catch (Exception e)
            {
                if (RedisSessionConfig.SessionExceptionLoggingDel != null)
                {
                    RedisSessionConfig.SessionExceptionLoggingDel(e);
                }
            }
        }
        /// <summary>
        /// Gets a Session from Redis, indicating a non-exclusive lock on the Session. Note that GetItemExclusive
        ///     calls this method internally, meaning we do not support locks at all retrieving the Session.
        /// </summary>
        /// <param name="context">The HttpContext of the current request</param>
        /// <param name="id">The Session Id, which is the key name in Redis</param>
        /// <param name="locked">Whether or not the Session is locked to exclusive access for a single request 
        ///     thread</param>
        /// <param name="lockAge">The age of the lock</param>
        /// <param name="lockId">The object used to lock the Session</param>
        /// <param name="actions">Whether or not to initialize the Session (never)</param>
        /// <returns>The Session objects wrapped in a SessionStateStoreData object</returns>
        public override SessionStateStoreData GetItem(HttpContext context, string id, out bool locked, out TimeSpan lockAge, out object lockId, out SessionStateActions actions)
        {
            locked = false;
            lockAge = new TimeSpan(0);
            lockId = null;
            actions = SessionStateActions.None;
            if (id == null)
            {
                return this.CreateNewStoreData(context, Convert.ToInt32(this.SessionTimeout.TotalMinutes));
            }
            try
            {
                string parsedRedisHashId = RedisSessionStateStoreProvider.RedisHashIdFromSessionId(
                    new HttpContextWrapper(context),
                    id);

                LocalSharedSessionDictionary sharedSessDict = new LocalSharedSessionDictionary();
            
                RedisSessionStateItemCollection items = sharedSessDict.GetSessionForBeginRequest(
                    parsedRedisHashId,
                    (redisKey) => {
                        return RedisSessionStateStoreProvider.GetItemFromRedis(
                            redisKey, 
                            new HttpContextWrapper(context),
                            this.SessionTimeout);
                    });

                return new SessionStateStoreData(
                    items,
                    SessionStateUtility.GetSessionStaticObjects(context),
                    Convert.ToInt32(this.SessionTimeout.TotalMinutes));
            }
            catch(Exception e)
            {
                if (RedisSessionConfig.SessionExceptionLoggingDel != null)
                {
                    RedisSessionConfig.SessionExceptionLoggingDel(e);
                }
            }

            return this.CreateNewStoreData(context, Convert.ToInt32(this.SessionTimeout.TotalMinutes));
        }
        /// <summary>
        /// This method is called when the Session decides that no element has been modified. Due to
        ///     the implementation of RedisSessionProvider.RedisSessionStateItemCollection, this method
        ///     is never called (because the .Dirty property always returns true). The reason is because
        ///     we always dirty-check the collection in SetAndReleaseItemExclusive to ensure Session
        ///     correctness.
        /// </summary>
        /// <param name="context">The HttpContext of the current web request</param>
        /// <param name="id">The SessionId of the current request</param>
        /// <param name="lockId">A lock around the current Session so no other web request can modify it 
        ///     simultaneously</param>
        public override void ReleaseItemExclusive(HttpContext context, string id, object lockId)
        {
            // if, for some reason, we are in this method we still want to record that we are no
            //      longer going to use a session in local cache
            string currentRedisHashId = RedisSessionStateStoreProvider.RedisHashIdFromSessionId(
                    new HttpContextWrapper(context),
                    id);

            LocalSharedSessionDictionary sharedSessDict = new LocalSharedSessionDictionary();
            sharedSessDict.GetSessionForEndRequest(currentRedisHashId);
        }