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

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

У нас есть страница результатов поиска, которая использует сопоставление с шаблоном на основе RegEx для группировки нескольких переменных в один сегмент маршрута (т. Е. «Www.host.com/ enjstructuralParameters}» может быть следующим: «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" } 
);

Ответы [ 3 ]

20 голосов
/ 01 декабря 2009

Установка значений маршрута равными нулю или пустой строке при вызове Html.ActionLink или Html.RouteLink (или любого метода генерации URL) приведет к удалению «окружающих» значений маршрута.

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

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

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

4 голосов
/ 17 марта 2011

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

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

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

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

1 голос
/ 30 ноября 2009

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

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

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

...