Un thread nato oggi sul newsgroup Microsoft dedicato ad ASP .NET mi ha riportato alla mente un argomento spesso trascurato. Una delle FAQ più classiche riguardanti ASP .NET (o lo sviluppo web in generale) è sicuramente: "Come faccio a redirigere l'utente ad una pagina differente mediante codice lato server?" La risposta tipica è: "Usa Response.Redirect". Risposta corretta, per carità, ma con una piccola "trappola": questo metodo invia al client lo status code http 302 il cui codice mnemonico è "Found", ossia spostato temporaneamente. Questo è un classico caso nel quale lo sviluppo di applicazioni intranet (o comunque private) differisce da quello orientato a Internet. Perchè? Perchè i motori di ricerca interpretano questa informazione come "temporanea", poichè lo status code http dedicato alle redirezioni permanenti è il 301 (Moved Permanently) e quindi non aggiornano con uguale efficacia i propri indici. Come risolvere questa situazione? Considerato che la classe HttpResponse è sealed, e quindi ci scordiamo estensione e polimorfismo (sarebbe stato troppo comodo poter utilizzare sempre una ipotetica classe HttpResponseEx), non possiamo far altro che creare una classe ad hoc:
public class RequestRedirector
{
public void PermanentRedirect(string url)
{
PermanentRedirect(url, true);
}
public void PermanentRedirect(string url, bool endResponse)
{
if(url==null)
throw new ArgumentNullException("URL cannot be null");
else if(url==string.Empty)
throw new ArgumentException("URL cannot be empty");
else if(url.IndexOf("\n")>=0)
throw new ArgumentException("URL cannot contain newline");
else
{
url = new System.Uri(HttpContext.Current.Request.Url, url, true).AbsoluteUri;
HttpContext.Current.Response.ClearHeaders();
HttpContext.Current.Response.ClearContent();
HttpContext.Current.Response.StatusCode = 301;
HttpContext.Current.Response.AppendHeader("Location", url);
HttpContext.Current.Response.Write("\r\n");
HttpContext.Current.Response.Write("
Object moved to here.
\r\n");
HttpContext.Current.Response.Write("\r\n");
}
if(endResponse)
HttpContext.Current.Response.End();
}
}
Utilizzabile poi con un semplice:
RequestRedirector redirector =
new RequestRedirector();
redirector.PermanentRedirect("targetform.aspx", false);
Morale della favola: ASP .NET astrae moltissimo lo sviluppatore dai dettagli di basso livello, ma conoscere http è sempre un buon investimento. :-)