Scenario: Your customers need to have their own name in your application URL.

eg. http://www.yourapp.com/GOODCUSTOMERNAME

Usually in MVC you have to define your route table, but to have a dynamic route table based on your customer names is not that easy. That is where the custom route handler comes in to play.

Step 1: Changes in Global.asax.cs

We pass all the calls through our CustomRouteHandler.

public static void RegisterRoutes(RouteCollection routes)
{
   routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
   var b = new {controller = "Home", action = "Index", id = UrlParameter.Optional, area = ""};
   routes.Add("Default", new Route("{controller}/{action}/{id}", new RouteValueDictionary(b),
   new CustomRouteHandler()));
}

Step 2: Writing the CustomRouteHandler

Note: MyService is one of my business layer service to resolve the URLs. And I will send the resolved value to “Home/Index” with a parameter name called “name”. Cool! I have only one value to resolve.

public class CustomRouteHandler : MvcRouteHandler
{
   protected override IHttpHandler GetHttpHandler(RequestContext requestContext)
   {
      string customerName= string.Empty;
      var controller = requestContext.RouteData.Values["controller"].ToString().Replace("-", "_");
      if (string.IsNullOrWhiteSpace(controller))
      {
          controller = "Home";
          // The initial call sometimes does not carry the controller name
      }
       if (!string.IsNullOrWhiteSpace(controller))
       {
           customerName = controller;
           var s = MyService.ResolveUrl(customerName);
           //YOUR BUSINESS LOGIC TO RESOLVE THE URL GOES HERE, IF YOU HAVE MULTIPLE VALUES IN THE URL USE STRING MANIPULATION AS YOU WANT.
           if (s == null) // CANNOT RESOLVE, LEAVE THE CONTROLLER NAME ALONE
           {
               customerName= string.Empty;
           }
           else
           {
               controller = "Home";
               requestContext.RouteData.Values["name"] = customerName; //My Index method in HomeController is accepting a parameter called "name", that is the resolved customer name.
           }
       }
       requestContext.RouteData.Values["controller"] = controller; //Update the Controller Name
       var action = requestContext.RouteData.Values["action"].ToString().Replace("-", "_");
       if (string.IsNullOrWhiteSpace(action))
       {
           action = "Index"; //The initial call sometimes does not carry the action name
       }   
       //Since I don't have much to resolve in action name, I just pass the value. But if you have multiple resolution to the action (methods to refer), I think you can figure out how to change this code.
       requestContext.RouteData.Values["action"] = action;
       //At this moment you should have a correct/resolved values to the route data values, otherwise you will get a error page.
       return base.GetHttpHandler(requestContext);
    }
}

That is all, everything will be handled by the custom route handler. If you want more logics to resolve, just put them inside the handler.
Just keep in mind the actual controller classes must have a way to get the resolved values from the URL. Just like I have used the “name” parameter.
With this approach the URL entered in the browser would look more customer specific, and will not change, but the back end custom route handler resolve the URL for our app.

Pretty neat. eh!

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

w

Connecting to %s