Come posso impedire ad ASP.Net MVC Html.ActionLink di utilizzare i valori di route esistenti?

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

  •  08-07-2019
  •  | 
  •  

Domanda

Il sito Web su cui sto lavorando ha alcune strutture di routing piuttosto complicate e stiamo riscontrando alcune difficoltà a lavorare con il motore di routing per creare URL nel modo in cui ne abbiamo bisogno per essere costruiti.

Abbiamo una pagina dei risultati di ricerca che utilizza la corrispondenza dei pattern basata su RegEx per raggruppare diverse variabili in un singolo segmento di route (ad es. com / variabile A-variabileB-variabileC "- dove le variabili da A a C sono tutte facoltative). Questo funziona bene per noi dopo un po 'di lavoro.

Il problema che stiamo riscontrando si risolve in una fastidiosa funzionalità del metodo ActionLink: se punti allo stesso controller / azione, manterrà i valori di route esistenti, che tu li voglia o no. Preferiamo avere il controllo su come appaiono i nostri collegamenti e, in alcuni casi, non possiamo mantenere i parametri esistenti. Un esempio potrebbe essere quello in cui la navigazione principale del nostro sito porta a una pagina dei risultati di ricerca senza parametri impostati, se lo desideri una pagina di ricerca predefinita. Dico che questa è una caratteristica fastidiosa perché è una rara istanza di ASP.Net MVC Framework che sembra dettare l'implementazione senza un ovvio punto di estensione - preferiremmo non creare un codice ActionLink personalizzato per scrivere un semplice collegamento di navigazione nella nostra pagina principale!

Ho visto alcuni dire che è necessario impostare esplicitamente tali parametri come stringhe vuote, ma quando ci proviamo cambia semplicemente i parametri dai valori di route in parametri di stringa di query. Non mi sembra giusto che dovremmo essere tenuti ad escludere esplicitamente i valori che non stiamo esplicitamente passando come parametri al metodo ActionLink, ma se questa è la nostra unica opzione lo useremo. Tuttavia, al momento, se viene visualizzato nella stringa di query, per noi è inutile quanto inserire i parametri direttamente nella route.

Sono consapevole che la nostra struttura di routing esaspera questo problema - probabilmente non avremmo alcun problema se utilizzassimo un approccio più semplice (ad es. www.host.com/variableA/variableB/variableC) ma la nostra struttura URL non è negoziabile - è stato progettato per soddisfare esigenze molto specifiche relative a usabilità, SEO e condivisione di link / contenuti.

Come possiamo usare Html.ActionLink per generare collegamenti a pagine senza ricorrere ai dati del percorso corrente (o, se possibile, necessità di escludere esplicitamente i segmenti del percorso) anche se tali collegamenti portano agli stessi metodi di azione?

Se dobbiamo escludere esplicitamente i segmenti di route, come possiamo impedire al metodo di visualizzare le route come parametri della stringa di query?

Questo apparentemente piccolo problema ci sta causando una quantità sorprendente di dolore e sarò grato per qualsiasi aiuto nel risolverlo.

EDIT: come richiesto da LukLed, ecco un esempio di chiamata 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" } 
);
È stato utile?

Soluzione

L'impostazione dei valori di route su una stringa nulla o vuota quando si chiama Html.ActionLink o Html.RouteLink (o qualsiasi metodo di generazione dell'URL) cancellerà " ambient " valori di rotta.

Ad esempio, con il controller MVC standard / azione / percorso id supponiamo che tu sia su " Home / Index / 123 " ;. Se chiami Html.RouteLink (nuovo {id = 456}) , MVC noterà il "quot" ambiente " valori di rotta di controller = " Home " e action = " Index " . Noterà anche il valore della rotta ambientale di id = "123" ma che verrà sovrascritto dall'esplicito "456". Ciò farà sì che l'URL generato sia " Home / Index / 456 " ;.

Anche l'ordinamento dei parametri è importante. Ad esempio, supponiamo che tu abbia chiamato Html.RouteLink (new {action = " About "}) . Il " Informazioni " l'azione sovrascriverà l'attuale "Indice" azione e " id " il parametro verrebbe completamente cancellato! Ma perché, chiedi? Perché una volta invalidato un segmento di parametro, tutti i segmenti di parametro dopo verranno invalidati. In questo caso, "azione" è stato invalidato da un nuovo valore esplicito, pertanto viene invalidato anche "id", che viene dopo di esso e che non ha alcun valore esplicito. Pertanto, l'URL generato sarebbe solo " Home / Informazioni " (senza ID).

In questo stesso scenario se hai chiamato Html.RouteLink (new {action = " "}) , l'URL generato sarebbe solo " Home " perché hai annullato l'azione " " con una stringa vuota e quindi ciò ha causato l '"id" essere invalidato anche perché è arrivato dopo l'azione "quotata" non valida.

Altri suggerimenti

Soluzione alla radice del problema

Sembra che la soluzione ottimale (che non ha l'odore di una soluzione alternativa) sia quella che risolve il problema in cui ha radici e che è nel routing.

Ho scritto una classe personalizzata Route chiamata RouteWithExclusions in grado di definire i nomi dei valori delle route che dovrebbero essere esclusi / rimossi durante la generazione di URL. Il problema è quando il routing rientra nella tabella delle rotte e le rotte successive non hanno gli stessi nomi dei valori delle rotte ...

L'intero problema è dettagliato e spiegato in il mio post sul blog e tutto il codice viene fornito anche lì. Dai un'occhiata, può aiutarti a risolvere questo problema di routing. Ho anche scritto due metodi di estensione MapRoute aggiuntivi che accettano un parametro aggiuntivo.

Se vuoi il controllo totale del link, crealo tu stesso:

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

Sostituisci tutto ciò di cui hai bisogno all'interno dell'attributo href .

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top