views:

1174

answers:

4

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'
+1  A: 

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.

womp
I guess there is no other way. {Action}/{id}/{*TreePath} is not very beautiful URL.Thanks anyway
Nima
+7  A: 

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

chris166
tree word still has noise, Thanks anyway
Nima
A custom route handler is definately the way to go if you don't like womp's work around. You don't have to have the "tree" controller explicitly set as Chris has outlined... I think the basic idea is that you can do anything you want with a custom route handler.
Charlino
+1  A: 

Hi all,

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.

Erik
A: 

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

HakonB