Come creare multi redirect permanenti 301 in ASP. NET MVC

.NET MVC redirect permanenti 301

Spesso ad una nuova versione di un sito web che va online è necessario reindirizzare i vecchi url ad i nuovi url. Possiamo gestire gli url redirect anche in IIS 7 utilizzando il modulo URL Rewrite o in IIS 6 utilizzando un’ estensione di terze parti, ma in questo articolo vedremo come gestire via codice.

Considerazioni su redirect 301 multipli nlla nostra soluzione

In questo caso l’esigenza era quella di effettuare il redirect 301 di tutti i link appartenenti ad un vecchio dominio con url vecchi con .NET MVC, ma sarebbe stato possibile effettuare il 301 anche solo dei broken link quindi errori 404.

Mapping url per il redirect 301

Come prima cosa abbiamo effettuato un mapping dei vecchi url con i nuovi ed abbiamo creato un semplice file flat csv con due colonne la prima contenente il vecchio url la seconda il nuovo url al quale bisogna fare il redirect permanente 301. In questo modo è molto semplice aggiornare la lista:

/Home/Chi-siamo/chisiamo.html,/About/who-we-are
/Home/contattaci/contatti.html,/contact-us

All’interno di una nostra classe .NET MVC andiamo a scrivere il codice per leggere il nostro file csv contenente la mappatura degli url inserendola in un dictionary. Essendo un file che verrà modificato raramente mettiamo il dictionary letto dal file nella cache.

private static Dictionary<string, string> Read301CSV()
{
  string cacheKey = "getCSV301";
  Dictionary<string, string> redirect_dict = new Dictionary<string, string>();
  redirect_dict = (Dictionary<string, string>)Cache.Read(cacheKey);
  if (Cache.Exists(cacheKey))
  {
    redirect_dict = (Dictionary<string, string>)Cache.Read(cacheKey);
  }
  else
  {
    string file = "301url.csv";
    string path = System.IO.Path.Combine(AppDomain.CurrentDomain.GetData("DataDirectory").ToString(), file);

    if (File.Exists(path))
    {
      using (TextReader sr = new StreamReader(path))
      {
        string line = "";
        while ((line = sr.ReadLine()) != null)
        {
          string[] columns = line.Split(',');
          redirect_dict.Add(columns[0], columns[1]);
        }
        Cache.Insert(cacheKey, redirect_dict,  null,
          System.Web.Caching.Cache.NoAbsoluteExpiration,
          System.Web.Caching.Cache.NoSlidingExpiration, 
          System.Web.Caching.CacheItemPriority.Default,
          null);
        return redirect_dict;
      }
    }
    else
      return null;
  }
  return redirect_dict;
}

Intercettare l’inizio della richiesta dal global.asax

Ora che abbiamo il nostro elenco di url ed un modo per accedervi, abbiamo bisogno di agganciarsi nel ciclo di vita dell’ app .NET MVC per effettuare i redirect corretti. Abbiamo considerato di prendere in carico tutte le richieste che arrivano da un determinato dominio (il nostro vecchio dominio) quindi andiamo ad intercettare nel Application_BeginRequest del global.asax le nostre request. Per comodità implentiamo due metodi privati che gestisce le richieste ed effettuano i redirect. Inoltre nella nostra casistica consideriamo solo le richieste che non sono in Post:

private void PermanentRedirect(string url)
{
  Response.Clear();
  Response.Status = "301 Moved Permanently";
  Response.StatusCode = 301;
  Response.AddHeader("Location", url);
  Response.End();
}

private void OldDomainRedirect(HttpContext context)
{
  if (null == context)
    throw new ArgumentException("HttpContext");
  if (null == context.Request)
    throw new ArgumentException("Request");

  var oldDomain = "www.ilmiovecchiodomio.it";
  var request = context.Request;
  if (request.HttpMethod != "POST" && request.Url.Host == oldDomain)
  {
    var url = request.Path.TrimEnd('/');
    var redirect = Read301CSV();
    var newurl = "/";
    if (!string.IsNullOrEmpty(url) && redirect.Keys.Contains(url))
    {
      newurl = redirect.Where(x => x.Key == url).FirstOrDefault().Value;
      PermanentRedirect(newurl);
    }
  }
}

Ora abbiamo una soluzione semplice e facile per gestire i redirect permanenti degli URL in .NET MVC.