Необязательный строковый параметр маршрутизации MVC и некрасивые URL-адреса

Я использую mvc 5.2.3 на 4.5.1 и хочу эти URL-адреса

  • /Nike обувь
  • /Nike/Обувь/Бег
  • /Nike/Рубашки/2002342345
  • /Nike/Обувь/Бег/98765432234

Мой контроллер имеет:

[HttpGet]
[Route("{brand}/{category}/{subcategory}/{page:int?}", Name="ProductIndex")]
public ActionResult Index(string brand, string category, int? page, string subcategory = "")

и дает /Nike/Обувь/Бег, но не /Nike/Обувь, но /Products?brand=Nike&category=Обувь

Когда я добавляю

[HttpGet]
[Route("{brand}/{category}/{page:int?}")]
public ActionResult Index(string brand, string category, int? page)

/Nike/Shoes/ работает, но у меня также есть /Nike/Shoes/?subcategory=Running

и мой метод деталей:

[HttpGet]
[Route("{brand}/{category}/{subcategory}/{productid:int:min(9000)}", Name="ProductDetails")]
public ActionResult Details(int productid)

дает:

Текущий запрос неоднозначен между следующими методами действия: System.Web.Mvc.ActionResult Index(System.String, System.String, System.Nullable`1[System.Int32], System.String) для типа shopmvc.Controllers.ProductsController System.Web.Mvc.ActionResult Index(shopvc.ViewModels.ProductsViewModel) по типу shopmvc.Controllers.ProductsController System.Web.Mvc.ActionResult Details(Int32) по типу shopmvc.Controllers.ProductsController

Значит, что-то не так с моей ссылкой на продукт и маршрутами категорий/подкатегорий. или с тем, как я пытаюсь его достичь:

<a href="@Url.RouteUrl("ProductDetails", new { brand = item.Brand, category = item.Category, subcategory = item.SubCategory, productid = item.ID })">test</a>
<a href="@Url.Action("Details", "Products", new { brand = item.Brand, category = item.Category, subcategory = item.SubCategory, productid = item.ID })">
<a href="@Url.Action("Index", "Products", new { brand = c.Brand, category = c.Category, subcategory = c.SubCategory })">@c.DisplayName</a>

person JP Hellemons    schedule 20.05.2015    source источник


Ответы (2)


Как насчет получения верхнего общего уровня и определения остальных оттуда?

[HttpGet]
[Route("{brand}/{category}/{*subdivision}", Name="ProductIndex")]
public ActionResult Index(string brand, string category, string subdivision)

Затем определить, содержит ли разделение вашего подразделения более глубокий путь или идентификатор продукта, и вызвать правильные методы на основе этого выбора.

person Razieltje    schedule 20.05.2015
comment
моя подкатегория является необязательным параметром, но, похоже, не работает. что делают звездочки в шаблоне URL *subcategory? - person JP Hellemons; 20.05.2015
comment
Это предотвратит дальнейший синтаксический анализ остальной части URL-адреса шаблоном (кратко объяснено) можно найти больше ссылка - person Razieltje; 20.05.2015
comment
Итак, вы предлагаете использовать msdn.microsoft .com/en-us/library/, а затем вручную проанализируйте строку в вашем единственном методе httpget. если он заканчивается на int, превышающем 10000, перенаправление на детали и разделение на / для категорий и т. д. Я не знаю, лучший ли это подход. хотя спасибо за ваше предложение. возможно, другие пользователи могут поручиться за этот подход? - person JP Hellemons; 20.05.2015
comment
это было бы предложение. Хотя это может показаться дополнительной работой, я думаю, что избыточный контроль над действиями может оказаться полезным. Если есть лучшие варианты, я тоже с нетерпением жду их :) - person Razieltje; 20.05.2015

Пробовали ли вы упорядочивать маршруты в Global.asax от наиболее конкретных к наиболее общим? Ваше приложение не знает, в каком порядке проверять маршруты, поэтому что-то вроде brand/category/subcategory/nnnnn может быть либо страницей nnnn, либо продуктом nnnnn.

Сначала вам нужно проверить этот маршрут:

[HttpGet]
[Route("{brand}/{category}/{subcategory}/{productid:int:min(9000)}", Name="ProductDetails")]
public ActionResult Details(int productid)

Тогда этот:

[HttpGet]
[Route("{brand}/{category}/{subcategory}/{page:int?}", Name="ProductIndex")]
public ActionResult Index(string brand, string category, int? page, string subcategory = "")

В качестве альтернативы вы можете изменить маршрут так, чтобы маршрут страницы выглядел примерно так:

`brand/category/subcategory/p-n`

e.g. /Nike/Shoes/Running/p-2

РЕДАКТИРОВАТЬ: Что произойдет, если вы сделаете это? Любое число меньше 9000 будет интерпретироваться как номер страницы, хотя это может ввести пользователя в заблуждение!

[HttpGet]
[Route("{brand}/{category}/{subcategory}/{page:int?:max:8999}", Name="ProductIndex")]
public ActionResult Index(string brand, string category, int? page, string subcategory = "")
person Tom Chantler    schedule 20.05.2015
comment
Я предпочитаю маршрутизацию атрибутов, а не global.asax, я также могу использовать маршрутизацию в маршрутизации атрибутов. blogs.msdn.com/b/webdev/archive/2013/10/17/ - person JP Hellemons; 20.05.2015
comment
установка необязательного параметра страницы на максимальное значение 8999 работает для страницы сведений, но это нарушает URL-адреса категорий (с подкатегорией и без нее), поскольку это больше не является необязательным целым числом. - person JP Hellemons; 20.05.2015
comment
Можете ли вы сделать это необязательным и при этом установить максимальное значение? {page:int?:max:8999} Я думаю, что вы выбрали маршруты, которые могут быть неоднозначными. Вам лучше изменить маршрут, возможно, чтобы номер страницы был p-nnnn или что-то в этом роде. - person Tom Chantler; 20.05.2015
comment
URL-адреса типа /Nike/Shoes/Running/1 работают тогда, а /Nike/Shoes/1 со вторым методом в контроллере. И необязательный, и максимальный недействителен: The inline constraint resolver of type 'DefaultInlineConstraintResolver' was unable to resolve the following inline constraint: 'int?' - person JP Hellemons; 20.05.2015