1

Here is my desired url format: /product-24-hid-35wh4-cx-dsgtx

How can I map this URL to my action method:

public ActionResult Product(int id)

Here is my routing code:

  routes.MapRoute(
       "ProductDetail",
       "product-{id}-{name}",
        new { controller = "product", action = "detail", name = UrlParameter.Optional },
        new string[] { "SphereLight.Controllers" }
  );

However, it does not work; I used phil haack's routedebugger to test this route, and below is the result:

 Key    Value
 name   dsgtx 
 id         24-hid-35wh4-cx 
 controller product 
 action detail 

Only id = 24 is correct.

In one word, I need a route to match:

   /product-24
   /product-24-
   /product-24-hid-35wh4-cx-dsgtx
dfang
  • 1,366
  • 15
  • 41

1 Answers1

2

Try to add constraints in your MapRoute:

  routes.MapRoute(
       "ProductDetail",
       "product-{id}-{name}",
        new { controller = "product", action = "detail", name = UrlParameter.Optional },
        new { id = @"\d+" }, // <-- change it for @"[^-]+", if it can be non-digit
        new string[] { "SphereLight.Controllers" }
  );

UPDATE:
Finally got it.
The main problem is that you can't use parameters which contains the same separator. For example, the example above will work with /product-24-nm, but not with product-24-nm-smth.

So, let's try this solution:
I've made it on the default routing, you can make it your way

    routes.MapRoute(
        "Default",
        "{controller}/{action}/{id}",
        new { controller = "Home", action = "Index", id = UrlParameter.Optional }, 
        new MyRouteHandler()
        ).RouteHandler = new MyRouteHandler();

Implementation of MyRouteHandler:

public class MyRouteHandler : MvcRouteHandler
{
    private static readonly Regex ProductPattern = new Regex(@"product\-(\d+)\-?(.*)");

    protected override IHttpHandler GetHttpHandler(RequestContext requestContext)
    {
        var match = ProductPattern.Match(requestContext.RouteData.Values["controller"].ToString());
        if (match.Length > 0)
        {
            requestContext.RouteData.Values["controller"] = "Home";
            requestContext.RouteData.Values["action"] = "Detail";
            requestContext.RouteData.Values["id"] = match.Groups[1].Value;
            requestContext.RouteData.Values["name"] = match.Groups[2].Value;
        }
        return base.GetHttpHandler(requestContext);
    }
}

So, the main idea is to check if the values matches our pattern product-id-name in the handler, and not trying to make it in MapRoute. Hope this helps.

Smileek
  • 2,702
  • 23
  • 26
  • does not work , route debugger result is {controller:product-26-hid-35wh11-cx-dsgtx,action:index} , if disable mvc's default route , the debugger result is {any:product-24-hid-35wh4-cx-dsgtx , controller:NotFound ,action:NotFound} – dfang May 17 '12 at 08:47
  • Hmm... And what if add `id = UrlParameter.Optional`? – Smileek May 17 '12 at 08:56
  • i'm afraid not , id is the key to find the product – dfang May 17 '12 at 09:36
  • Find a solution, but it's something strange with parser. See update of post. – Smileek May 17 '12 at 09:56