hypen в маршрутах MVC 3

Вот желаемый формат URL: / product-24-hid-35wh4-cx-dsgtx

Как я могу сопоставить этот URL-адрес с моим методом действия:

public ActionResult Product(int id)

Вот мой код маршрутизации:

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

Однако это не работает; Я использовал routedebugger Фила Хака, чтобы протестировать этот маршрут, и вот результат:

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

Только id = 24 правильно.

Одним словом, мне нужен маршрут для сопоставления:

   /product-24
   /product-24-
   /product-24-hid-35wh4-cx-dsgtx

person dfang    schedule 17.05.2012    source источник


Ответы (1)


Попробуйте добавить ограничения в свой 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" }
  );

ОБНОВЛЕНИЕ:
Наконец-то получил.
Основная проблема в том, что нельзя использовать параметры, содержащие одинаковый разделитель. Например, приведенный выше пример будет работать с /product-24-nm, но не с product-24-nm-smth.

Итак, давайте попробуем это решение:
Я выбрал маршрутизацию по умолчанию, вы можете сделать это по-своему

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

Реализация 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);
    }
}

Итак, основная идея - проверить, соответствуют ли значения нашему шаблону product-id-name в обработчике, а не пытаться сделать это в MapRoute. Надеюсь это поможет.

person Smileek    schedule 17.05.2012
comment
не работает, результат отладчика маршрута: {controller: product-26-hid-35wh11-cx-dsgtx, action: index}, если отключить маршрут по умолчанию mvc, результат отладчика будет {any: product-24-hid-35wh4-cx -dsgtx, контроллер: NotFound, действие: NotFound} - person dfang; 17.05.2012
comment
Хм ... А что, если добавить id = UrlParameter.Optional? - person Smileek; 17.05.2012
comment
Боюсь, что нет, идентификатор - это ключ к поиску продукта - person dfang; 17.05.2012
comment
Решение нашел, а с парсером что-то странно. Смотрите обновление поста. - person Smileek; 17.05.2012