Le risorse che non ci sono più e l’URL forwarding

Quando si lavora ad un sito web può capitare di dover spostare una risorsa. In questi casi non c’è niente di meglio che dire a tutti quello che stiamo facendo, implementando un forwarding verso la nuova risorsa, indicando quindi al client che ne ha fatto richiesta che è avvenuto questo cambiamento. In parole povere, il server non dovrà far altro che caricare un’altra risorsa invece che quella originariamente richiesta dal client.

Se infatti non si procedesse con un forwarding verso una nuova risorsa, una richiesta da parte del client verso un URL non esistente ritornerebbe al client un codice di errore che sta indicare che la risorsa non è stata trovata. Questo codice il famoso 404, pagina non trovata.

Come procedere in questi casi?

Esistono tre modi per fare l’URL Forwarding in ASP.Net

  1. Il Response.Redirect, che probabilmente i vecchi programmatori Classic ASP ricorderanno bene
  2. Il Server.Transfer
  3. Il Responde.RedirectLocation

Vediamoli nel dettaglio.

Il Response.Redirect

Il Response.Redirect è un metodo che il framework si trascina dietro sin da classic ASP 2.0 (a mia memoria, non ricordo l’1.0 se lo aveva, ma credo di ricordare di no). Con questo metodo, semplicemente si prende la richiesta corrente dalla pipeline e la si sposta su una nuova richiesta. La nuova richiesta (risorsa) potrà essere tanto una risorsa interna che una risorsa esterna. Quest’ultimo aspetto è da tenere in considerazione perchè ad esempio il metodo Server.Transfer non supporta reindirizzamenti esterni.
Tornano al nostro Redirect, un utilizzo intensivo di questo sistema è degradante, perchè questo discorso di aprire una nuova richiesta porta ad un overhead del server che alla lunga vedrà un calo di prestazioni. Chiaramente ci vogliono scenari distribuiti piuttosto complessi per potersene rendere contro.
Per questo motivo, con il framework 1.0 questo metodo è stato corredato di un overload che comprende un parametro boolean che serve ad indicare al metodo se persistere il thread corrente e lasciare che continui la sua esecuzione sebbene la pipeline sia stata dirottata o meno verso una nuova pagina.
In entrambe i casi, per via del fatto che all’interno del codice del framework viene fatta una chiamata al metodo Response.End, viene comunque sollevata una eccezione gestita dal framework, che non scatenerà errori nella vostra pagina, ma sarà sempre una sorta di anomalia.

Morale, evitare il Response.Redirect se proprio non se ne può fare a meno (Redirect verso un’altra risorsa). Utilizzare invece il secondo metodo.

Il Server.Transfer

Il Server.Transfer è assai più performante sebbene sia roba vecchia, nel senso che venne introdotto già a partire da Classic ASP 3.0, anzi fu una delle novità principali che io ricordi.
Il funzionamento è quasi simile al Redirect, per lo meno visivamente sembra uguale. La differenza sta nel fatto che mentre la Redirect richiede una nuova pagina, la Server.Transfer richiede l’esecuzione della risorsa e la restituisce sulla pipeline originale.
Attenzione al fatto dell’eccezione; se questo davvero vi preoccupa, sappiate che anche il Server.Transfer solleva anch’egli l’eccezione del Response.Redirect, perchè internamente fa una chiamata al metodo Response.End.

L’utilizzo di Response.End, Response.Redirect e Server.Transfer sollevano una ThreadAbortException. E’ un problema noto documentato dalla KB312629.

Se davvero non volete avere di questi problemi dovete usare il metodo Server.Execute, che è lo stesso poi richiamato dal Server.Transfer, con la differenza che il Server.Execute non chiama alcun Response.End e vi restituisce il risultato dell’esecuzione della pagina chiamata, ovvero l’esatto output che avreste chiamando direttamente quella determinata pagina dal primo fino all’ultimo (ammesso che vi siano).

Sembrerebbe il metodo migliore, tuttavia vi sono casi specifici in cui il Server.Transfer non può essere utilizzato. Non sono in grado di elencarli tutti, ma per esempio uno lo posso documentare.

Ancora un pò di chiarezza….

Oggi stavo scrivendo un HTTPHandler per gestire un sito web che deve subire un processo di transizione da statico a dinamico, e facendo alcune prove, mi sono reso conto che il Server.Transfer in questo processo di trasferimento parte dall’assunto che l’oggetto Page, con tutto quello che ne consegue, sia stato già correttamente caricato dal context corrente. In realtà, nel mio caso, agendo ancor prima che l’oggetto Page fosse stato creato, l’oggetto Session nel mio caso non esisteva, e ne risultava che la pagina a cui trasferivo la chiamata, facendo uso della Session mi generava un errore.

Non entro del merito del perchè. Magari un errore mio che comunque esula da questo post che si limita all’URL fowarding.

Questa faccenda la si può risolvere con un

Response.RedirectLocation

Il Response.RedirectLocation non c’entrerebbe niente di per se con un trasferimento automatico verso una nuova risorsa, e infatti il suo compito è solamente quello di impostare l’HTTP Location header della pagina su di un nuovo percorso.

Senza fare null’altro questo sistema non serve a niente (non in questo caso di URL Forwarding). Se però aggiungiamo immediatamente dopo una impostazione dello StatusCode, cioè alteriamo il codice restituito al client, che normalmente sarebbe 200 – Ok, e lo impostiamo su un 302 – Risorsa mossa temporaneamente o un 301 – Risorsa mossa definitivamente, quando questo codice una volta ritornato al client, farà si che il nuovo percorso specificato induca il client ad effettuare una nuova richiesta verso la risorsa indicata.

Il tutto con una grande differenza, il thread precedente sarà stato correttamente chiuso e nessuna eccezione sarà stata generata.

Un esempio per essere più concreti:

context.Response.StatusCode = (int)HttpStatusCode.MovedPermanently;
context.Response.RedirectLocation = "default.aspx";

A questo punto scegliere il sistema migliore è solo questione di analisi e capire quale sia veramente il sistema più adatto alla specifica esigenza sulla quale si sta lavorando.

3 thoughts on “Le risorse che non ci sono più e l’URL forwarding”

Comments are closed.