0

How to handle Session timeout if same asp.net session Id is shared across multiple asp.net web application.

We have multiple web applications. These web applications running on DNN and sharing session id. But the session for each application is created at the time application is accessed. Now i want to find a way though which we can handle session time out because traditional way (using Session_Start on globle.aspx to check existing session id and Is New session) is not working.

Please help me to know how to handle session timeout and i don't to implement it at page level.

yashpal
  • 326
  • 1
  • 3
  • 16
  • 1)http://blogs.lessthandot.com/index.php/webdev/serverprogramming/aspnet/sharing-asp-net-session-state-between-ap/ 2)http://www.codeproject.com/Articles/416137/Understanding-Session-Management-Techniques-in-ASP Check this articles i think it may be help u. – Arunprasanth K V Nov 11 '14 at 12:43

1 Answers1

0

Rather than using ASP.NET session state, you could instead use caching to achieve a similar result. You can even use it with a multiple tenant application if you like so each tenant has its own sessions. You can respond to cache timeouts using callback methods, which are more reliable than using session state events.

The downside is that it won't scale to multiple servers unless you come up with a distributed cache solution. You could use azure distributed caching to resolve this, or there are other options.

Here is what a session caching solution would typically look like:

public class ThreadSafeCache
{   
    public shared ThreadSafeCache()
    {
        if (cache == null)
        {
            cache = System.Runtime.Caching.MemoryCache.Default;
        }
        if (syncLock == null)
        {
            syncLock = new ReaderWriterLockSlim(LockRecursionPolicy.NoRecursion);
        }
    }

    private shared System.Runtime.Caching.ObjectCache cache;
    private shared ReaderWriterLockSlim syncLock;

    public shared bool Contains(string key)
    {
        syncLock.EnterReadLock();
        try
        {
            return this.cache.Contains(key);
        }
        finally
        {
            syncLock.ExitReadLock();
        }
    }

    public shared object GetOrAdd(string key, Func<object> loadFunction, Action<CacheEntryRemovedArguments> callbackFunction)
    {
        // Get or add an item to the cache
        object item = null;

        syncLock.EnterReadLock();
        try
        {
            item = cache.Get(key);
        }
        finally
        {
            syncLock.ExitReadLock();
        }

        if (item == null)
        {
            syncLock.EnterWriteLock();
            try
            {
                // Lazy lock pattern - need to check again after
                // the lock to ensure only 1 thread makes it through
                if (item == null)
                {
                    // Get the item
                    item = loadFunction();

                    var policy = new CacheItemPolicy();

                    // Set the cache expiration (from the last access).
                    policy.SlidingExpiration = TimeSpan.FromMinutes(30);

                    // Setting priority to not removable ensures an 
                    // app pool recycle doesn't unload the item, but a timeout will.
                    policy.Priority = CacheItemPriority.NotRemovable;

                    // Setup expiration callback.
                    policy.RemovedCallback = callbackFunction;

                    cache.Add(key, item, policy);
                }
            }
            finally
            {
                synclock.ExitWriteLock();
            }
        }

        return item;
    }

    public shared void Remove(string key)
    {
        syncLock.EnterWriteLock();
        try
        {
            this.cache.Remove(key);
        }
        finally
        {
            syncLock.ExitWriteLock();
        }
    }
}

Then you would use it like:

var sessionID = "1234"; // string from cookie or string that is stored in ASP.NET session state
var tenantID = "2"; // identifier for the specific tenant within the application
var key = tenantID + "_" + sessionID;

ThreadSafeCache.GetOrAdd(key, LoadItem, CacheItemRemoved);

private object LoadItem()
{
     // TODO: Load the item (from wherever you need to load it from)
     return item;
}

private void CacheItemRemoved(CacheEntryRemovedArguments arguments)
{
    // Respond here when the cache expires
}

The trick is to ensure your cache key is built up of both the user's session ID (from a cookie) and the ID of the application.

Note that I haven't tested this, so it may need some tweaking to get it working.

Community
  • 1
  • 1
NightOwl888
  • 55,572
  • 24
  • 139
  • 212
  • Thanks @Night, As we have running system so we cant make too many changes in it. I am looking for a generic solution either just by placing new page or minor changes to handle it at Application level. – yashpal Nov 12 '14 at 07:53
  • It can be done, but only if you are using the same domain name for both sites (the subdomain can be different) because cookies cannot be passed between different domains. See [this answer](http://stackoverflow.com/questions/3438912/share-session-between-two-web-sites-using-asp-net-and-state-server). – NightOwl888 Nov 12 '14 at 08:54
  • Also, check out [this](http://stackoverflow.com/questions/616046/passing-session-data-between-asp-net-applications) and [this](http://stackoverflow.com/questions/2868316/sharing-sessions-across-applications-using-the-asp-net-session-state-service). – NightOwl888 Nov 12 '14 at 08:58