Una delle caratteristiche in assoluto più interessanti del routing su ASP.NET è la facilità con la quale possiamo estenderne le funzionalità, modificandone il comportamento per coprire delle nostre esigenze specifiche.
Immaginiamo, ad esempio, di voler fare in modo che le pagine del nostro sito presentino un URL del formato seguente:
localhost/id_pagina/titolo-pagina.aspx
Una simile tecnica ha il pregio di rendere gli indirizzi facilmente comprensibili per gli utenti, che sono in grado di identificare immediatamente il contenuto della risorsa a cui essi puntano.
Già con l'infrastruttura standard di routing è possibile realizzare una route che supporti il pattern che abbiamo visto, sfruttando il codice in basso per introdurre i due parametri {id} e {title} nell'indirizzo:
routes.MapPageRoute( "article-route", "articles/{id}/{title}.aspx", "~/articles.aspx");
Il parametro {title} svolge una funzione "decorativa", generando quindi un URL comprensibile per soddisfare il requisito di leggibilità che ci siamo dati, mentre {id} contiene invece il vero e proprio identificativo della risorsa, e sarà effettivamente utilizzato dalla pagina per recuperare quest'ultima dal database.
Una simile soluzione, pur perfettamente funzionante, presenta un difetto insidioso in ottica SEO, che rischia di penalizzare molto il nostro sito web per ciò che concerne l'indicizzazione nei motori di ricerca: l'unico parametro utilizzato dalla pagina, di fatto, è il solo {id}, e pertanto il contenuto mostrato sarà il medesimo per qualsiasi valore di {title}. Il risultato a lungo termine è una frammentazione degli hit e delle page view su diversi indirizzi ammissibili, con conseguente diminuzione del page rank.
Per risolvere il problema, la soluzione più elegante consiste nella generazione di una route personalizzata, che chiameremo TitledRoute, in grado di riconoscere un valore errato per il parametro {title} e di effettuare un redirect permanente verso l'indirizzo corretto. Per utilizzarlo dobbiamo scrivere su global.asax del codice leggermente più complesso di quello standard, come mostrato in basso.
routes.Add( new TitledRoute( "articles/{id}/{title}.aspx", "title", // titleParameter r => ArticlesService.GetTitleById(r.Values["id"]), // checkFunction new PageRouteHandler("~/default.aspx")));
Il costruttore di questa route, infatti, accetta due parametri addizionali:
- titleParameter, che indica il nome del parametro di route contenente il titolo che, come spiegato in precedenza, dovremo validare per generare eventualmente un redirect permanente;
- checkFunction è invece un delegate, nel nostro esempio valorizzato con una lambda expression, tramite il quale possiamo restituire il valore corretto per il titolo a partire dai dati di routing; ArticleService è un ipotetico servizio in grado di interrogare la cache (o, in extremis, il database) per recuperare il titolo corrispondente all'id di ingresso.
Internamente, TitledRoute sfrutta questi due parametri all'interno del metodo GetRouteData, che viene utilizzato per determinare se la route può gestire la richesta:
public override RouteData GetRouteData(HttpContextBase httpContext) { var result = base.GetRouteData(httpContext); // il risultato è != null se la route è // in grado di gestire la richiesta if (result != null) { var actual = result.Values[titleParameter]; var expected = checkFunction(result); if (!object.Equals(actual, expected)) { result.Values[titleParameter] = expected; var newUrl = this.GetVirtualPath( new RequestContext(httpContext, result), result.Values); httpContext.Response.RedirectPermanent("~/" + newUrl.VirtualPath); } } return result; }
Come possiamo notare, questo metodo, oltre a richiamare l'implementazione della classe base, effettua una verifica addizionale sulla corrispondenza del titolo rilevato nell'URL e il risultato restituito dall'invocazione di checkFunction. Nel caso questi non corrispondano, TitledRoute determina l'indirizzo corretto tramite il metodo GetVirtualPath, verso cui effettua poi un RedirectPermanent. Questo metodo, come abbiamo avuto già modo di vedere, restituisce uno status code 301, che indica lo spostamento definitivo della risorsa verso il nuovo indirizzo, e provoca l'aggiornamento delle tabelle di indicizzazione dei motori di ricerca.
Commenti
Per inserire un commento, devi avere un account.
Fai il login e torna a questa pagina, oppure registrati alla nostra community.
Approfondimenti
Filtrare i dati di una QuickGrid in Blazor con una drop down list
Usare lo spread operator con i collection initializer in C#
Path addizionali per gli asset in ASP.NET Core MVC
Configurare il nome della run di un workflow di GitHub in base al contesto di esecuzione
Applicare un filtro per recuperare alcune issue di GitHub
Creare una libreria CSS universale: Cards
Creare una custom property in GitHub
Ordine e importanza per @layer in CSS
Triggerare una pipeline su un altro repository di Azure DevOps
Evitare il flickering dei componenti nel prerender di Blazor 8
Eseguire operazioni sui blob con Azure Storage Actions
I più letti di oggi
- Simulare Azure Cosmos DB in locale con Docker
- Utilizzare il metodo Index di LINQ per scorrere una lista sapendo anche l'indice dell'elemento
- ecco tutte le novità pubblicate sui nostri siti questa settimana: https://aspit.co/wkly buon week-end!
- .NET Conference Italia 2024 - Milano
- .NET Conference Italia 2023 - Milano e Online