Creating Your Own Custom Session ID (Part 2)

Summary

In my last post, I talked about how to override the id generator of the HttpContext.Current.Session.  In this post I’m going to show how to override the methods that affect the cookie itself.

The ISessionIDManager Interface

In order to get at the methods required to manipulate the cookie, you’ll need to implement the ISessionIDManager Interface.  If you’re using Visual Studio 2015, this is an opportunity to use a new feature.  If you create a new solution and add a library project, then add a using for “System.Web.SessionState” and add the “System.Web” reference.  Now you can create a class that looks like this:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Web;
using System.Web.SessionState;

namespace MyCustomSession
{
    public class CustomSessionIDManager : ISessionIDManager
    {
    }
}

The ISessionIDManager statement will have a red wavy line under it.  If you hover over that keyword, you’ll get the following drop-down:

Now you can click on the “Show Potential Fixes” link, then click on “Implement Interface”.  Then all the necessary methods and properties will be auto-populated:

So you’ll end up with something like this:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Web;
using System.Web.SessionState;

namespace MyCustomSession
{
    public class CustomSessionIDManager: ISessionIDManager
    {
        public string CreateSessionID(HttpContext context)
        {
            throw new NotImplementedException();
        }
        public string GetSessionID(HttpContext context)
        {
            throw new NotImplementedException();
        }
        public void Initialize()
        {
            throw new NotImplementedException();
        }
        public bool InitializeRequest(HttpContext context, bool suppressAutoDetectRedirect, out bool supportSessionIDReissue)
        {
            throw new NotImplementedException();
        }
        public void RemoveSessionID(HttpContext context)
        {
            throw new NotImplementedException();
        }
        public void SaveSessionID(HttpContext context, string id, out bool redirected, out bool cookieAdded)
        {
            throw new NotImplementedException();
        }
        public bool Validate(string id)
        {
            throw new NotImplementedException();
        }
    }
}

In case you’re wondering, this is the free Visual Studio Community 2015 version.  I’m evaluating the features that are available and it appears that Microsoft has finally produced a free version of Visual Studio that can be used to produce real software.  I’m still expecting to run into a limitation at some point, but so far, I’ve been using 2015 Community as though it has the same features as my old Visual Studio 2013 Professional.

Implementing the Interface

In my last blog post, I already implemented the CreateSessionID() and Validate() methods, so I’m going to copy and paste that code over from that project.  Again, Microsoft has a sample that you can use for your template.  It can be found at this website: ISessionIDManager Interface.

The first problem that I discovered when using the code provided from Microsoft is that the GetSessionID() method give an error at the “context.Request.Cookies[pConfig.CookieName].Value;” line.  The cookie has not been created and the SaveSessionID() method does not get called before this method is called.

The second thing I noticed is that the implementation of the IHttpModule methods seems pointless.  They also never get called.  I’m betting that there are methods in IHttpModule that are handy for certain features of the Session id, but they are not needed for this demonstration.

Don’t forget to setup your web.config file to invoke your custom object:

<configuration>
    <system.web>
        <sessionState cookieName="MySessionID" 
            sessionIDManagerType="MyCustomSession.CustomSessionIDManager,  
            MyCustomSession" />
    </system.web>
</configuration>

To fix the issue with the cookie not being created on initial load, I did this:

public string GetSessionID(HttpContext context)
{
    string id = null;
    if (pConfig.Cookieless == HttpCookieMode.UseUri)
    {
        // Retrieve the SessionID from the URI.
    }
    else
    {
        if (context.Request.Cookies[pConfig.CookieName] == null)
        {
            bool redirected;
            bool cookieAdded;
            SaveSessionID(context, id, out redirected, out cookieAdded);
        }
        else
        {
            id = context.Request.Cookies[pConfig.CookieName].Value;
        }
    }

    // Verify that the retrieved SessionID is valid. If not, return null.
    if (!Validate(id))
    {
        id = null;
    }

    return id;
}

If anybody out there has the correct solution to this problem, please drop me a comment.  If I find a solution, I’ll post an update to this blog entry.  I’m assuming that the calling object is supposed to recognize when a cookie doesn’t exist and call the SaveSessionID() method automatically.  However, that doesn’t happen here for some reason.

Where to Get the Code

As usual, you can go to my GitHub account and download the working project by clicking here.

Leave a Reply