Tired of looking for errors in log files? Use OneTrueError - Automatic exception management for .NET.

Get an unique session in each browser tab

I got a lot to do at work, hence the silence. I got a lot to blog about, but so little time ;/ I found an interesting question at stackoverflow which this answer is for (also to show you that the blog is not forgotten).

A user wanted to store browser tab specific data which can be a problem since most browsers shares a session between different tabs. The solution is to create a new route which generates a GUID and then
use that guid to fetch and store session information. Keep in mind that you need to routes: One that works for users which just surfed into the site, and one that loads an existing guid.

Here is the route class:

public class GuidRoute : Route
{
	private readonly bool _isGuidRoute;

	public GuidRoute(string uri, object defaults)
		: base(uri, new RouteValueDictionary(defaults), new MvcRouteHandler())
	{
		_isGuidRoute = uri.Contains("guid");

		DataTokens = new RouteValueDictionary();
	}

	public override RouteData GetRouteData(HttpContextBase httpContext)
	{
		var routeData = base.GetRouteData(httpContext);
		if (routeData == null)
			return null;

		if (!routeData.Values.ContainsKey("guid") || routeData.Values["guid"].ToString() == "")
			routeData.Values["guid"] = Guid.NewGuid().ToString("N");

		return routeData;
	}

	public override VirtualPathData GetVirtualPath(RequestContext requestContext, RouteValueDictionary values)
	{
		return !_isGuidRoute ? null : base.GetVirtualPath(requestContext, values);
	}
}

Replace the default route in global.asax with it:

/*routes.MapRoute(
	"Default", // Route name
	"{controller}/{action}/{id}", // URL with parameters
	new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults
);*/

routes.Add("Default", new GuidRoute(
	"{controller}/{action}/{id}", 
	new { controller = "Home", action = "Index", guid = "", id = UrlParameter.Optional }));

routes.Add("GuidRoute", new GuidRoute(
	"g/{guid}/{controller}/{action}/{id}", 
	new { controller = "Home", action = "Index", guid = "", id = UrlParameter.Optional }));

And finally some extension methods to make life easier in the controllers:

public static class ControllerExtensionMethods
{
	public static string GetGuid(this Controller controller)
	{
		return controller.RouteData.Values["guid"].ToString();
	}

	public static void SetGuidSession(this Controller controller, string name, object value)
	{
		controller.Session[controller.GetGuid() + "_" + name] = value;
	}

	public static object GetGuidSession(this Controller controller, string name)
	{
		return controller.Session[controller.GetGuid() + "_" + name];
	}
}

One thing left though: Any browser bookmarks will use an old GUID. Should not be a problem in most cases (unless the user opens the bookmark in multiple tabs = sharing the session between the tabs). Same
thing goes for opening a link in a new tab = shared.

This entry was posted in Architecture, CodeProject and tagged . Bookmark the permalink.
  • shyam

    Thanks a lot for the explanation.. It really bring some ray of hope to my problem that is in asp.net. (without MVC).

    Can you please guide me on hw to implement this fix in asp.net?

  • DaMi

    I’ve created a nuget package which simplifies session handling in tabbed browsing scenarios. http://blog.micic.ch/net/asp-net-mvc-conversational-session Maybe you will find it useful.

    • JonasGauffin

      Nice.

  • Anjan

    Nice Article. Is there any way to avoid appending GUID in URL and managing from route data during the postbacks.

  • Mohamed Asane

    Could you please guid me, How I can use with mvc area registration?

    context.MapRoute(

    “Test_default”,

    “Test/{controller}/{action}/{id}”,

    new { action = “Index”, id = UrlParameter.Optional }

    );

  • Chuck Bryan

    Nice article. Everything worked fine until I went back to Home/Index. I ended up swapping the routes registration and it worked!

  • csteinmueller

    Thank you for this nice solution. Helped me a lot in a earlier project. But now it has to be extended and handle a HttpGet parameter. But the parameter doesn’t get into my MVC action. Here’s already a stackoverflow question I asked yesterday. Can you help out? http://stackoverflow.com/questions/20517293/querystring-of-httpget-are-gone-in-multisession-mvc4-application

  • Moeg

    Hi, is there a sample solution which implements this? I can’t seem to get it to work – although my routeData gets populate with a GUID my URL doesn’t, i.e. my URL is always http://localhost:51179/ or http://localhost:51179/Home/Index. I was expecting to have the GUID appended to the URL? A working solution would be great to be able to go through. Here’s hoping..

    • http://blog.gauffin.org/ jgauffin

      Did you register the custom route first before the default one?

      • Moeg

        I got it working thanks. Is there a way to access the Guid stored in the RouteData from within another project, say, for example, a WCF service layer?

      • Moeg

        Is the best way to get the GUID from a separate project (e.g. class library) to just retrieve it from the query string?

      • http://mzangweicttraining.azurewebsites.com/ Siyabulela Mooi

        This is what I have done in my application:

        RouteConfig.RegisterRoutes(RouteTable.Routes); in the “Application_Start() of the Global.asax file.

        public static void RegisterRoutes(RouteCollection routes)

        {

        //routes.IgnoreRoute(“{resource}.axd/{*pathInfo}”);

        //routes.MapRoute(

        // name: “Default”,

        // url: “{controller}/{action}/{id}”,

        // defaults: new { controller = “DeviceManager”, action = “DeviceDetails”, id = UrlParameter.Optional }

        //);

        routes.Add(“Default”, new GuidRoute(

        “{controller}/{action}/{id}”,

        new { controller = “DeviceManager”, action = “DeviceDetails”, guid = “”, id = UrlParameter.Optional }));

        routes.Add(“GuidRoute”, new GuidRoute(

        “g/{guid}/{controller}/{action}/{id}”,

        new { controller = “Home”, action = “Index”, guid = “”, id = UrlParameter.Optional }));

        }

        This still doesn’t append the Giuid in the URL.

  • http://mzangweicttraining.azurewebsites.com/ Siyabulela Mooi

    When or where do the “ControllerExtensionMethods” methods get called?