asp.net mvc complex routing for tree path

I am wondering how can I define a routing map like this:

{TreePath}/{Action}{Id} 

TreeMap is dynamically loaded from a database like this:

 'Gallery/GalleryA/SubGalleryA/View/3'

Solution 1:

You can create a custom route handler to do this. The actual route is a catch-all:

routes.MapRoute(
    "Tree",
    "Tree/{*path}",
    new { controller = "Tree", action = "Index" })
        .RouteHandler = new TreeRouteHandler();

The tree handler looks at path, extracts the last part as action, and then redirects to the controller. The action part is also removed from path. Adding the {id} part should be straightforward.

public class TreeRouteHandler : IRouteHandler
{
    public IHttpHandler GetHttpHandler(RequestContext requestContext)
    {
        string path = requestContext.RouteData.Values["path"] as string;

        if (path != null)
        {
            int idx = path.LastIndexOf('/');
            if (idx >= 0)
            {
                string actionName = path.Substring(idx+1);
                if (actionName.Length > 0)
                {
                    requestContext.RouteData.Values["action"] = actionName;
                    requestContext.RouteData.Values["path"] = 
                        path.Substring(0, idx);
                }
            }
        }

        return new MvcHandler(requestContext);
    }
}

Your controller then works as you would expect it:

public class TreeController : Controller
{
    public ActionResult DoStuff(string path)
    {
        ViewData["path"] = path;
        return View("Index");
    }
}

Now you can call URL like /Tree/Node1/Node2/Node3/DoStuff. The path that the action gets is Node1/Node2/Node3

Solution 2:

Can you switch the URL's around? If you can make your {TreePath} parameter as the last parameter, you can easily do this with one route.

   routes.MapRoute("TreeRoute", 
                    "{Action}/{id}/{*TreePath}", 
                    new TreeRouteHandler()));

The wildcard catchall parameter must be the last parameter though.

Otherwise, I think you'll be stuck with having to define multiple parameters, one to match each possible section of the TreeMap URL.

Note that you can never define two routing parameters together without some literal text between them. In other words, you can define {Action}/{Id}, but you can never define {Action}{Id}. There is no way for the routing engine to know where one parameter ends and the next one begins when pattern matching.

Solution 3:

You can have the "greedy" part within the querystring as long as you can have fixed parts after it, e.g.

/{*TreePath}/Edit/{id}
/{*TreePath}/Action/{id}

Note that the action is not variable in the above routes because the greedy parts needs to stop at some literal value (other that forward slash). I will work if you only perform a few actions on your "tree" but will cumbersome if you have many action since each will need its own route entry.

It will not work out of the box but requires a custom route. You can find a nice write on the subject including code here

Solution 4:

I'm new to MVC, but one of the requirements was this option. I'm a vb-er, so i had some trouble converting code, but got it to work an wanted to contribute a example solution: www.proovit.com/Download/MvcApplication1.zip It is a simple standard MVC project, I left the code and bin dirs out, but you can copy them from a standard project.

o, you have to use the tags app/bla/bla/bla for index and app/trade/order/view for the order page.