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 share 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 two 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.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.