Search code examples
asp.net-mvcasp.net-mvc-routingasp.net-session

.NET MVC Route to specific area controller based on a session variable


Lets say I am using MVC for my web application and I have an area that contains multiple controllers... MyController1, MyController2 and MyController3

These controllers are used by users in certain groups: UserGroup1, UserGroup2 and UserGroup3. I will store the group id in the session.

I would like the client requests to look generic like this: www.mysite.com/MyArea/MyController/SomeAction

So, how do I assign the respective controller based on the group id variable stored in session?

some pseudo code:

var id = HttpContext.Current.Session["GroupId"];
if id == 1
  use MyController1
else if id == 2 
  use MyController2
else if id == 3
  use MyController3

I know I could hit a controller and perform a redirect, but is there somewhere higher up in the stack that I can have more control over the controller assignment.


Solution

  • After reading an article on MSDN https://msdn.microsoft.com/en-us/library/cc668201(v=vs.110).aspx I came up with the following solution:

    1. Implement a custom MvcHandler that will handle the logic of choosing a controller
    2. Implement an IRouteHandler
    3. Attach the IRouteHandler to the route that is registered in the AreaRegistration

    public class MyRouteHandler : IRouteHandler
    {
            IHttpHandler IRouteHandler.GetHttpHandler(RequestContext requestContext)
            {
                    return new MyMvcHandler(requestContext);
            }
    }
    

    public class MyMvcHandler : MvcHandler, IHttpHandler
    {
            public MyMvcHandler(RequestContext requestContext) : base(requestContext)
            {
            }
    
            private string GetControllerName(HttpContextBase httpContext)
            {
                    string controllerName = this.RequestContext.RouteData.GetRequiredString("controller");
                    var groupId = httpContext.Session["GroupId"] as string;
                    if (!String.IsNullOrEmpty(groupId) && !String.IsNullOrEmpty(controllerName))
                    {
                        controllerName = groupId + controllerName;
                    }
                    return controllerName;
            }
    
            protected override IAsyncResult BeginProcessRequest(HttpContextBase httpContext, AsyncCallback callback, object state)
            {
                    RequestContext.RouteData.Values["controller"] = this.GetControllerName(httpContext);
                    return base.BeginProcessRequest(httpContext, callback, state);
            }
    }
    

    and finally, register the RouteHandler:

        public override void RegisterArea(AreaRegistrationContext context)
        {
            context.MapRoute(
                "default",
                "{controller}/{action}/{id}",
                new { action = "Index", id = UrlParameter.Optional }
            ).RouteHandler = new MyRouteHandler();            
        }