Как я могу остановить ASP.Net MVC Html.ActionLink от использования существующих значений маршрута?

StackOverflow https://stackoverflow.com/questions/1817421

  •  08-07-2019
  •  | 
  •  

Вопрос

Веб-сайт, над которым я работаю, имеет несколько довольно сложных структур маршрутизации, и мы испытываем некоторые трудности при работе с механизмом маршрутизации для создания URL-адресов так, как нам нужно их создавать.

У нас есть страница результатов поиска, которая использует сопоставление с шаблоном на основе RegEx для группировки нескольких переменных в один сегмент маршрута (т. е. "www.host.com/ {StructureParameters}" может быть следующим: "www.host. com / variableA-variableB-variableC "- где переменные от A до C являются необязательными). Это работает для нас хорошо после небольшой работы.

Проблема, с которой мы сталкиваемся, решается вокруг раздражающей функции метода ActionLink: если вы укажете на тот же контроллер / действие, он сохранит существующие значения маршрута, хотите вы их или нет. Мы предпочитаем контролировать то, как выглядят наши ссылки, и в некоторых случаях нельзя сохранять существующие параметры. Примером может служить то, что основная навигация нашего сайта ведет на страницу результатов поиска без заданных параметров - страницу поиска по умолчанию, если хотите. Я говорю, что это раздражающая функция, потому что это редкий экземпляр ASP.Net MVC Framework, который, по-видимому, диктует реализацию без очевидной точки расширения - мы бы предпочли не создавать пользовательский код ActionLink для записи простой навигационной ссылки на нашей главной странице!

Я видел, как некоторые говорили, что вам нужно явно установить такие параметры, чтобы они были пустыми строками, но когда мы пытаемся это сделать, это просто изменяет параметры из значений маршрута в параметры строки запроса. Мне кажется неправильным, что мы должны явно исключать значения, которые мы явно не передаем в качестве параметров методу ActionLink, но если это наша единственная опция, мы будем ее использовать. Однако в настоящее время, если он отображается в строке запроса, он для нас настолько же бесполезен, как и ввод параметров непосредственно в маршрут.

Я знаю, что наша структура маршрутизации усугубляет эту проблему - у нас, вероятно, не было бы никаких проблем, если бы мы использовали более простой подход (например, www.host.com/variableA/variableB/variableC), но наша структура URL не подлежит обсуждению - он был разработан для удовлетворения особых потребностей, связанных с юзабилити, SEO и обменом ссылками / контентом.

Как мы можем использовать Html.ActionLink для генерации ссылок на страницы, не обращаясь к текущим данным маршрута (или, если возможно, без необходимости явно исключать сегменты маршрута), даже если эти ссылки приводят к одним и тем же методам действий?

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

Эта, казалось бы, небольшая проблема вызывает у нас удивительное количество горя, и я буду благодарен за любую помощь в ее решении.

РЕДАКТИРОВАТЬ: по запросу LukLed, вот пример вызова ActionLink:

// I've made it generic, but this should call the Search action of the 
// ItemController, the text and title attribute should say "Link Text" but there
// should be no parameters - or maybe just the defaults, depending on the route.
// 
// Assume that this can be called from *any* page but should not be influenced by
// the current route - some routes will be called from other sections with the same
// structure/parameters.
Html.ActionLink( 
    "Link Text",
    "Search", 
    "Item", 
    new { }, 
    new { title = "Link Text" } 
);
Это было полезно?

Решение

Установка значения маршрута в нулевую или пустую строку при вызове Html.ActionLink или Html.RouteLink (или любого метода генерации URL) удалит " ambient " значения маршрута.

Например, со стандартным маршрутом контроллера / действия / идентификатора MVC предположим, что вы находитесь на "Home / Index / 123". Если вы вызываете Html.RouteLink (new {id = 456}) , тогда MVC заметит " ambient " значения маршрута controller = " Home " и action = " Index " . Он также заметит значение окружающего маршрута id = "123" , но оно будет перезаписано явным " 456 " ;. Это приведет к тому, что сгенерированный URL будет «Home / Index / 456».

Порядок параметров также имеет значение. Например, скажем, вы назвали Html.RouteLink (new {action = " About "}) . & Quot; О " действие перезапишет текущий " индекс " действие и " идентификатор " параметр будет полностью очищен! Но почему, спросите вы? Потому что как только вы сделаете недействительным сегмент параметра, все сегменты параметра после него станут недействительными. В этом случае «действие» был признан недействительным новым явным значением, поэтому «id», который идет после него и не имеет явного значения, также становится недействительным. Таким образом, сгенерированный URL будет просто "Home / About" (без удостоверения личности).

В этом же сценарии, если вы вызвали Html.RouteLink (new {action = " "}) , сгенерированный URL будет просто " Home " потому что вы аннулировали действие " action " с пустой строкой, а затем это вызвало " id " быть также признанным недействительным, потому что оно пришло после недействительного " действия ".

Другие советы

Решение в корне проблемы

Похоже, что оптимальное решение (которое не пахнет как обходной путь) - это то, которое решает проблему там, где у него есть корни, а именно в маршрутизации.

Я написал собственный класс Route с именем RouteWithExclusion , который может определять имена значений маршрутов, которые следует исключать / удалять при создании URL-адресов. Проблема заключается в том, что при маршрутизации не выполняется таблица маршрутов, а последующие маршруты не имеют одинаковых имен значений маршрутов ...

Вся проблема подробно описана и объяснена в мой пост в блоге и весь код там тоже есть. Проверьте это, это может помочь вам решить эту проблему маршрутизации. Я также написал два дополнительных метода расширения MapRoute , которые принимают дополнительный параметр.

Если вы хотите полностью контролировать ссылку, просто создайте ее самостоятельно:

<a href="~/variableA/variableB/<%= Html.Encode(Model.Target) %>">Click Here</a>

Замените все, что вам нужно, в атрибуте href .

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top