Подтвердить что ты не робот

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

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

У нас есть страница результатов поиска, которая использует сопоставление шаблонов на основе RegEx для группировки нескольких переменных в один сегмент маршрута (например, "www.host.com/{structuralParameters" ), может быть следующим: "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 для создания ссылок на страницы без возврата к текущим данным маршрута (или, если возможно, для явного исключения сегментов маршрута), даже если эти ссылки приводят к тем же методам действий?

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

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

EDIT: по просьбе 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" } 
);
4b9b3361

Ответ 1

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

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

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

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

Ответ 2

Решение в корне задачи

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

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

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

Ответ 3

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

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

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