Url rewriting tramite HttpHandler
Questo articolo mostra il modo in cui approfittare delle funzionalità degli HttpHandler per la creazione di un sistema di url rewriting per le vostre applicazioni web ASP.NET; questo semplice sistema ci permette di esporre al pubblico delle url più "amichevoli" , più facili quindi da memorizzare e più utili per quanto riguarda l'indicizzazione nei motori di ricerca.
Quindi, un url del genere:
http://www.peppedotnet.it/post.aspx?id=1
la possiamo far diventare ...
http://www.peppedotnet.it/post1.aspx
o addirittura
http://www.peppedotnet.it/Blog/primo_post.aspx
Questi tipi di url sono decisamente più
"user-friendly" , sia per l'utente che per i
robot dei motori di ricerca (google impazzisce per url di
questo genere ... :).
Per far ciò bisogna utilizzare quelle classi fornite
dal .NET Framework per soddisfare le richieste HTTP in
ingresso. Queste classi, che ci permettono la creazione di
HttpHandler personalizzati, derivano tutte
dall'interfaccia System.Web.IHttpHandler, e ne
implementano il metodo ProcessRequest(), utile a processare
la richiesta HTTP, e la proprietà IsReusable, che
specifica se e quando è supportata una attività
di pooling.
E' inoltre possibile implementare degli HttpHandler,
creandone un'istanza, attraverso l'implementazione
dell'interfaccia IHttpHandlerFactory, interfaccia che
permette un controllo più fine e accurato sulla
richiesta. IHttpHandlerFactory fornisce, in pratica,
l'infrastruttura che gestisce l'effettiva risoluzione
ed elaborazione delle richieste URL alle istanze
IHttpHandler.
Questa interfaccia espone due metodi:
- GetHandler - Restituisce un nuovo oggetto di tipo IHttpHandler che elabora la richiesta.
- ReleaseHandler - Permette ad altri oggetti di utilizzare un'istanza gia esistente dell'HttpHandler.
L'HttpHandler creato come esempio, è stato appunto creato implementando questa classe.
using System;
using System.IO;
using System.Web;
using System.Web.UI;
namespace Peppe.Handlers
{
public class NewsHttpHandler : IHttpHandlerFactory
{
public IHttpHandler GetHandler(HttpContext context,
string requestType,
string url,
string pathTranslated)
{
context.Items["fileName"] = Path.GetFileNameWithoutExtension(url);
return PageParser.GetCompiledPageInstance(url,
context.Server.MapPath("default.aspx"),
context);
}
Nel listato si vede effettivamente il lavoro fatto dal
metodo GetHandler, metodo che prende in input 4 parametri:
- context - Istanza della classe HttpContext della richiesta corrente.
- requestType - Il tipo della richiesta effettuata (GET o POST).
- url - L'url della richiesta.
- pathTranslated - Il percorso fisico della risorsa richiesta.
E' stato solamente aggiunto il codice necessario per
salvare il nome della pagina richiesta all'interno
dell'istanza della classe HttpContext, in modo tale da
poterlo riutilizzare nella pagina ASP.NET che effettivamente
risolve la richiesta, e la chiamata al metodo
GetCompiledPageInstance della classe
System.Web.UI.PageParser, che specifica la pagina fisica che
risolve la richiesta e ne restituisce il gestore HTTP.
Per far ciò non bisogna far altro che utilizzare,
da riga di comando, il compilatore (nel nostro caso C#)
fornito dal framework in questo modo:
csc /t:library /r:System.dll,System.Web.dll
/out:Peppe.Handlers.dll /recurse:*.cs
Una volta creato l'handler, e dopo averlo inserito tra
i riferimenti del vostro progetto, bisogna settarne le
proprietà via web.config e creare la pagina, che nel
nostro caso e la pagina default.aspx, utile a risolvere la
richiesta e a stampare a video le informazioni
desiderate.
Un HttpHandler nel file di configurazione della vostra
applicazione viene settato in questo modo:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.web>
<compilation defaultLanguage="c#" debug="true" />
<globalization requestEncoding="utf-8" responseEncoding="utf-8" />
<httpHandlers>
<add verb="*" path="News/*.aspx"
type="Peppe.Handlers.NewsHttpHandler, Peppe.Handlers" />
</httpHandlers>
</system.web>
</configuration>
Il fulcro sta nell'attributo "path"
dell'elemento "add" , il cui contenuto ci
permette di decidere il formato delle nostre nuove url. Il
nostro path (News/*.aspx) sta a significare che tutte le
url che hanno qualsiasi nome tra lo slash e il .aspx,
vengono gestite dal nostro HttpHandler. Quindi tutte le url
di questo genere:
http://www.vostrosito.it/News/qui_ci_metto_quello_che_voglio.aspx
Se, per esempio, avessimo inserito un path del genere :
News/news*.aspx, avremmo scelto di utilizzare url di questo
tipo:
http://www.vostrosito.it/News/news51.aspx
Vediamo ora come creare la pagina fisica che,
effettivamente, risolve la richiesta HTTP in ingresso.
Non dobbiamo far altro che creare una nuova Web Form
ASP.NET sotto la cartella /News, e fare in modo che
nell'evento Page_Load ci sia la lettura dell'url
richiesta e la successiva visualizzazione dei dati
relativi.
Nell'esempio sviluppato, ho scelto di avere un campo
del database che contenesse il nome della pagina riscritta,
in modo tale da fare una semplice query di equivalenza tra
il valore del campo e la pagina aspx richiesta. Magari
questa tecnica non è il massimo parlando di
sicurezza di dati, ma non era questo il punto
dell'articolo.
Vediamo quindi il codice che legge l'url richiesta e
visualizza i dati :
protected System.Web.UI.WebControls.Label lbl;
private OleDbConnection conn = null;
private void Page_Load(object sender, System.EventArgs e)
{
string pageName = Request.Url.Segments[Request.Url.Segments.Length-1];
string strConn = ConfigurationSettings.AppSettings["strConn"];
string sql = "SELECT * FROM News WHERE PageName='" +pageName+ "'";
try
{
using(conn = new OleDbConnection(strConn))
{
conn.Open();
OleDbCommand cmd = new OleDbCommand();
cmd.Connection = conn;
cmd.CommandText = sql;
cmd.CommandType = CommandType.Text;
OleDbDataAdapter adapter = new OleDbDataAdapter(cmd);
DataSet ds = new DataSet();
adapter.Fill(ds, "News");
DataTable dt = ds.Tables["News"];
foreach(DataRow riga in dt.Rows)
{
Response.Write("<h2>" +riga["Titolo"].ToString()+ "</h2>");
Response.Write(riga["Corpo"].ToString());
}
}
}
catch(Exception exe)
{
lbl.Text = exe.Message;
}
}
Chiaramente questo è solo un esempio introduttivo
all'argomento degli HttpHandler, argomento che risulta
decisamente utile a tutti gli sviluppatori ASP.NET.
- Articolo precedente Date formatting in C#
- Articolo successivo Aumentare le prestazioni di un sito web utilizzando al meglio il ViewState