Se qualcuno ha provato ad implementare un url rewrite ove già avesse utilizzato il VirtualPathProvider di ASP.NET forse si sarà già reso conto che ci sono alcuni problemi da tenere in considerazione. Innanzitutto bisogna tenere bene a mente come si comporta il runtime di ASP.NET quando compila le pagine. Poniamo ad esempio di avere una pagina ~/pippo.aspx, questa durante la compilazione darà luogo ad un assembly così denominato
App_Web_pippo.aspx.cdcab7d2.cdcaravs.dll
L'ultima parte del nome in realtà viene generata in modo casuale per evitare che possano esserci sovrapposizioni nei nomi. Questo pone un sottile problema. Nel caso di pagine di cui venga fatto il rewrite, mediante l'uso di una regular expression, come ormai abbastanza consueto, ci si può trovare di fronte al problema che venga compilato un assembly per ogni possibile combinazione di caratteri nel nome file. Ad esempio con un url fatto in questo modo:
~/articles/2837922.aspx
l'assembly diventerebbe
App_Web_2837922.aspx.cdcab7d2.cdcaravs.dll
Ma naturalmente ci sarebbe un assembly per ogni singolo articolo anche se in realtà la pagina che gestisce la visualizzazione è sempre la stessa. Personalmente mi sono trovato di fronte ad una condizione analoga implementando un VirtualPathProvider che mappa le pagine fisiche su un database. Per questo motivo alle fine ho dovuto implementare un rewrite in modo tale che l'url venisse mappato sempre e comunque su un nome pagina univoco, perchè solo in questo modo l'applicazione può essere fruibile.
Ora, dovendo realizzare un url rewriting la scelta è dovuta ricadere sull'uso di un HttpHandlerFactory per il semplice motivo che un rewrite implementato mediante HttpModule causa un comportamento anomalo della FormsAuthentication. Infatti, qualora si cerchi di accedere ad una pagina protetta, la FormsAuthentication effettua il redirect sulla pagina /login.aspx o su quella che è definita come tale in configurazione. A questo punto entra in gioco l'HttpModule che riscrive l'url convertendolo in qualcosa che tipicamente verrà riconosciuto dalla FormsAuthentication nuovamente come un url protetto e quindi avverrà dinuovo un redirect alla pagina di login causando un loop infinito.
L'unica soluzione che ho trovato è appunto realizzata mediante l'uso di una HttpHandlerFactory che però deve essere realizzata in modo molto particolare. In sostanza per realizzare questa factory occorre estendere la classe PageHandlerFactory - per inciso quella che normalmente intercetta le chiamate alle pagine aspx - perchè è proprio questa factory che contiene la logica relativa i VirtualPathProvider. Se si prova a scrivere un proprio HandlerFactory che faccia uso come di consueto del PageParser per creare l'istanza della pagina, il VirtualPathProvider non verrà più eseguito. Perciò ecco che l'unico sistema è quello di intervenire facendo l'override del metodo GetHandler() chiamando alla fine il metodo originale.
In questo modo potremo avere il meglio di entrambi i sistemi. Il VirtualPathProvider otterrà in input il virtualPath riscritto dal quale desumeremo la pagina da caricare, ma che sarà univoco e perciò darà luogo ad un solo assembly. D'altro canto l'HttpContext manterrà l'url originale e quindi saremo in grado di ingannare la FormsAuthentication e così evitare l'ingresso nel ciclo infinito nella login.