L'un des grands points forts de Asp.net 2.0, c'est la simplicité avec laquelle ont peut étendre le système. Parmis les nombreuses possibilités d'extensions possible, je vous propose de nous servir des HttpModules et des VirtualPathProviders pour effectuer une chose toute simple : la redirection de certains path de votre site web vers d'autres dossiers.
Imaginons par exemple, que vous ayez un très grand nombre d'images de produits : vous souhaitrez certainement ne pas les stocker directement dans votre application web - les mises à jours devenant vite des galères ingérables dans le cas contraire - mais plutôt dans un autre dossier. Vous avez alors deux possibilités :
- écrire un HttpHandler qui accèdera au fichier et l'enverra dans la stream de sortie
- écrire un VirtualPathProvider dont le but est de de "virtualiser" - ah bah, tiens, VirtualPathProvider, Virtualiser, j'l'avais pas vu :) - l'accès aux fichiers.
Les blogs et forums regorgeant d'exemples pour la premiere solution, c'est l'utilisation d'un VirtualPathProvider qui sera détaillé dans la suite de ce billet.
Si l'on regarde la signature - simplifiée pour ne présenter que ce qui nous interesse ici - de la classe VirtualPathProvider nous trouvons 4 méthodes très intéressantes :
En implementant ces méthodes, nous allons pouvoir rediriger l'accès à un fichier 'virtuel' (disons par exemple ~/Factures/F200601003.pdf) vers un path "reel" (e:\data\legal\factures\200601003.pdf). Pour cela, il est indispensable de surcharger FileExists et GetFile, les méthodes concernant les directory n'étant ici pas très utiles. Voici le code de la classe :
Comme vous pouvez le constater, celle-ci est assez simple : le constructeur permet de définir le path virtuel à remplacer et le path réel correspondant, la méthode ToRealPath se charge de convertir le path, FileExists retourne simplement true si le fichier reel existe, seule la méthode GetFile est un tout petit peu plus complexe, puisqu'elle fait appel à une autre classe MyVirtualFile. Un certain nombre de points sont à prendre en compte lors de l'écriture de cette classe :
- Comme nous le verrons d'ici peu, les VirtualPathProvider sont enregistrés globalement pour une application et ne sont pas montés/associés à un path particulier, il convient donc de ne répondre qu'aux demandes pour lesquelles nous avons quelque-chose à dire.
- Toutes les requêtes qui ne nous concerne pas doivent être passées au VirtualPathProvider suivant -ooops, "précédent" - dans la pile. Celui-ci est disponible par l'intermédiaire de la propriété Previous.
- Il est aussi nécessaire d'écrire une classe dérivant de VirtualFile qui se chargera de l'accès effectif au fichier. La seule méthode à surcharger importante de cette classe est la méthode Open qui doit renvoyer une Stream sur les données du fichier.
Pour que tout cela fonctionne, il ne nous reste plus qu'à "enregistrer" un MyVirtualPathProvider auprès du moteur de asp.net. Cela est assez simple, mais doit être fait à certains endroits très précis : il faut qu'il soit enregistré avant toute requête. Pour cela, le plus simple est certainement de le faire au sein de la méthode Application_Start du global.asax
Et voila ! Maintenant, toutes les requêtes pour un fichier sous le dossier virtuel ~/Factures sera intercepté par notre VirtualPathProvider et le fichier obtenu depuis un autre dossier. Il est bien entendu possible d'utiliser d'autres systèmes de stockage : en base de données, dans un coffre-fort numérique, en génération dynamique - le choix d'un VirtualPathProvider étant alors quelque peu discutable -, les possibilités ne sont peut-être pas infinies mais devraient correspondre à la plupart des besoins.