Jak mogę przestać ASP.Net MVC Html.ActionLink Z Wykorzystaniem Istniejących Wartości Trasy?

Strona, nad którą pracuję ma dość skomplikowane struktury routingu i doświadczamy pewnych trudności w pracy z silnikiem routingu, aby zbudować adresy URL w sposób, w jaki potrzebujemy, aby je zbudować.

Mamy stronę wyników wyszukiwania, która używa dopasowania wzorca opartego na RegEx, aby grupować kilka zmiennych w jeden segment trasy (np. www.host.com/{structuralParameters} " może być następująca: "www.host.com/variableA-variableB-variableC" - gdzie zmienne od A do C są wszystkie opcjonalnie). To działa dla nas dobrze po trochę pracy.

Problem, którego doświadczamy, rozwiązuje się wokół irytującej funkcji metody ActionLink: jeśli wskażesz ten sam kontroler / akcję, zachowa ona istniejące wartości trasy, niezależnie od tego, czy tego chcesz, czy nie. Wolimy mieć kontrolę nad tym, jak wyglądają nasze linki, a w niektórych przypadkach nie możemy zachować istniejących parametrów. Przykładem może być, gdy Główna nawigacja naszej strony prowadzi do strony z wynikami wyszukiwania bez parameters set-Domyślna strona Wyszukiwania, jeśli chcesz. Mówię, że jest to irytująca funkcja, ponieważ jest to rzadki przypadek ASP.Net Framework MVC pozornie dyktuje implementację bez oczywistego punktu rozszerzenia - wolimy nie tworzyć niestandardowego kodu ActionLink, aby napisać prosty link nawigacyjny na naszej stronie wzorcowej!

Widziałem, że niektórzy mówią, że trzeba jawnie ustawić takie parametry jako puste ciągi znaków, ale gdy spróbujemy to po prostu zmienia parametry z wartości trasy na parametry łańcucha zapytania. Nie wydaje mi się w porządku, że powinniśmy być zobowiązani do jawnego wykluczenia wartości, które nie są jawnie przekazywane jako parametry do metody ActionLink, ale jeśli jest to nasza jedyna opcja, użyjemy jej. Jednak obecnie, jeśli jest wyświetlany w łańcuchu zapytania, to jest dla nas tak samo bezużyteczny jak wprowadzanie parametrów bezpośrednio do trasy.

Zdaję sobie sprawę, że nasza struktura routingu irytuje ten problem - prawdopodobnie nie mielibyśmy żadnego problemu, gdybyśmy użyli prostszego podejście (tj. www.host.com/variableA/variableB/variableC) ale nasza struktura adresów URL nie podlega negocjacjom - została zaprojektowana, aby zaspokoić bardzo specyficzne potrzeby związane z użytecznością, SEO i udostępnianiem linków/treści.

Jak możemy używać Html.ActionLink do generowania linków do stron bez cofania aktualnych danych trasy (lub, jeśli to możliwe, konieczności jawnego wyłączenia segmentów trasy), nawet jeśli linki te prowadzą do tych samych metod działania?

Jeśli musimy wyraźnie wykluczyć odcinki trasy, jak możemy zapobiec renderowaniu tras przez metodę jako parametrów ciągu zapytania?

Ten pozornie mały problem sprawia nam zaskakującą ilość żalu i będę wdzięczny za każdą pomoc w jego rozwiązaniu.

EDIT: zgodnie z życzeniem LukLed, oto przykładowe wywołanie 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" } 
);
Author: johnnyRose, 2009-11-30

3 answers

Ustawienie wartości trasy jako null lub empty string podczas wywoływania Html.ActionLink lub Html.RouteLink (lub dowolnej metody generowania adresów URL) wyczyści wartości trasy "ambient".

Na przykład, przy standardowej trasie kontrolera MVC/action/id Załóżmy, że jesteś na "Home / Index / 123". Jeśli wywołasz Html.RouteLink(new { id = 456 }), MVC zauważy wartości trasy "ambient" z controller="Home" i action="Index". Zauważy również wartość trasy otoczenia id="123", ale zostanie ona nadpisana przez jawne "456". Spowoduje to, że wygenerowany adres URL będzie "Strona Główna/Index / 456"

Kolejność parametrów również ma znaczenie. Na przykład, powiedzmy, że zadzwoniłeś Html.RouteLink(new { action = "About" }). Akcja "About" nadpisałaby bieżącą akcję "Index" , a parametr " id " zostałby całkowicie wyczyszczony! Ale dlaczego, pytasz? Ponieważ po unieważnieniu segmentu parametru wszystkie segmenty parametru po nim zostaną unieważnione. W tym przypadku "akcja" została unieważniona przez nową jawną wartość, więc" id", który pojawia się po niej i nie ma jawnej wartości, również otrzymuje unieważnione. Tak więc wygenerowany adres URL byłby po prostu "Home / About"(bez ID).

W tym samym scenariuszu, jeśli wywołałeś Html.RouteLink(new { action = "" }), wygenerowany adres URL byłby po prostu "Home", ponieważ anulowałeś "akcję" z pustym łańcuchem, a następnie spowodowało to również unieważnienie "id", ponieważ przyszło po unieważnionej "akcji".

 20
Author: Eilon,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-03-17 13:25:21

Rozwiązanie u podstaw problemu

Wydaje się, że optymalnym rozwiązaniem (które nie pachnie obejściem) jest to, które rozwiązuje problem tam, gdzie ma korzenie i to jest w routingu.

Napisałem własną klasę Route o nazwie RouteWithExclusions, która jest w stanie zdefiniować nazwy wartości trasy, które powinny być wyłączone/usunięte podczas generowania adresów URL. Problem polega na tym, że trasa przechodzi przez tabelę tras i kolejne trasy nie mają takich samych nazw wartości trasy...

Cały problem jest szczegółowy i wyjaśniony w mój post na blogu i cały kod jest tam również. Sprawdź to, może to pomóc rozwiązać ten problem routingu. Napisałem również dwie dodatkowe metody rozszerzenia MapRoute, które przyjmują dodatkowy parametr.

 4
Author: Robert Koritnik,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-03-17 14:29:17

Jeśli chcesz mieć pełną kontrolę nad linkiem, po prostu zbuduj link samodzielnie:

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

Zastąp wszystko, czego potrzebujesz wewnątrz atrybutu href.

 1
Author: Robert Harvey,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-11-30 02:43:17