1. Présentation des Http handlers

Un http Handler est un composant logiciel qui va traiter des requêtes http. Plus exactement un http Handler est une classe de code managé qui est chargée d'effectuer le rendu d'une ressource donnée. Concrètement cela signifie que lorsque IIS va recevoir une requête de la part d'un client il va la transférer filtre ISAPI d'ASP.Net (aspnet_isapi.dll) qui contient un http Handler qui effectue un certain nombre de traitements et d'opérations. Une requête ne peut être traitée que par un et un seul http Handler. Typiquement ASP.Net possède un http Handler chargé d'exécuter les requêtes vers les pages dont l'extension est .aspx. C'est le moteur d'exécution d'ASP.Net qui appelle le Handler correspondant à la ressource concernée.

Microsoft .Net



On pourra associer des requêtes avec un Handler donné en se basant sur l'extension ciblée par la requête. Par exemple l'on pourra demander à IIS de transférer les requêtes de ressources dont l'extension est ".super" vers un Handler précis. Ce paramétrage est maintenu dans le fichier Web.config.

Un HTTP Handler va intervenir à un moment précis dans le flux d'une requête, le flux va en fait passer au travers d'un certain nombre de modules, atteindre le Handler, traverser de nouveau des modules, puis être renvoyé vers IIS qui va le transmettre au client. Le schéma suivant issu de MSDN montre très bien ce processus :

Flux d'une requête dans ASP.Net. (Copyright Microsoft).
Flux d'une requête dans ASP.Net. (Copyright Microsoft).



Vous l'aurez compris, si une requête donnée ne fait appel qu'a un seul Handler le nombre de modules lui n'est pas fixe. Ainsi lorsque ASP.Net va traiter une requête vers une page .aspx le moteur d'exécution va faire appel à de nombreux modules http comme le module d'authentification, le module de cache, le module de session… Les modules sont des composants qui vont s'attacher à des évènements de l'objet HttpApplication, de cette manière ils vont pourvoir intervenir à n'importe quelle étape du traitement d'une requête, à chaque fois qu'un évènement sera levé. Les http modules sont de bas niveaux, et vont pouvoir intervenir sur toutes les requêtes entrantes d'une application Web (ASP.Net). On pourra donc utiliser un modules http pour faire de l'authentification customisée, du filtrage de contenu ou encore un log complet de ce qui se passe sur une application donnée. Comme les Handlers, les modules sont déclarés dans le fichier web.config et sont chargés dynamiquement au démarrage de l'application. Par défaut et sauf modification de la configuration les modules ont accès uniquement aux requêtes dont les extensions sont mappées vers le moteur d'exécution ASP.Net, cela écarte donc les pages statiques, les images ou d'autres ressources encore. Maintenant que vous savez dans les grandes lignes ce que sont les Handlers et les modules voyons comment développer notre propre http Handler en C#.

2. Développement d'un Http handler en C#

2.1. Quelle utilité ?

Tout d'abord pourquoi développer un Handler, quelle est son utilité puisqu'a ASP.Net en intègre déjà… En fait c'est très simple, par le http Handler qui est chargé de traiter les requêtes vers les pages .aspx est très performant quand il s'agit justement de traiter des pages .aspx… mais parfois nous voulons que le serveur renvoi à une requête donnée un flux XML ou encore une image. Il est tout à fait possible d'utiliser le http Handler des pages .aspx pour cela mais cela va engendrée une surconsommation des ressources pour finalement peut de choses, puis le contrôle que vous avez sur ce Handler est limité. Concrètement le Handler des pages ASP.Net utilise de nombreux modules qui ne vous serons d'aucune utilité, en développant votre propre Handler vous faite en sorte de ne garder que l'essentiel et de plus vous avez le contrôle total de ce que vous allez renvoyer à IIS et qui sera in fine renvoyé au client. Par exemple si vous voulez créer un flux RSS sur votre site Web le développement d'un Handler est fortement recommandé, ou encore si les images de votre application sont stockées dans une base de données le Handler pourra être utilisé pour récupérer ses images et retourné le flux binaire associé sans faire appel à tout le mécanisme de génération d'une page .aspx qui ne serait ici absolument pas adapté à nos besoins. Sans plus tarder voyons comment implémenter notre propre http Handler en C#.

2.2. Implémentation en C#

Pour implémenter un http Handler en C# c'est très simple. Il suffit de créer une classe (qui sera le Handler) qui implémente l'interface IHttpHandler. Cette interface contient une méthode et une propriété que vous allez devoir implémenter.

Méthode ProcessRequest() : c'est la méthode unique de notre Handler, c'est elle qui est exécutée quand le Handler est appelé.

Propriété IsReusable : cette propriété qui est un booléen détermine si l'instance du Handler peut être réutilisée, mais en aucun cas cela signifie qu'ASP.Net utilisera une même instance pour une autre requête. Si la valeur est positionnée à " true " cela signifie que la méthode ProcessRequest() ne fait pas appel à des variables membres qui pourraient se trouvaient dans un état incohérent en cas de double appel.

Après avoir crée un projet Web dans Visual Studio il suffit d'ajouter un nouvel élément à la solution. Visual Studio offre un template prêt à l'emploi pour cela, il s'agit du GenericHandler. Ci-dessous voici le code d'un http Handler qui effectue une opération simple, à chaque fois qu'ne requête se présente au Handler celui renvoie la date et l'heure. Ce code est volontairement simpliste, mais gardez bien à l'esprit qu'un Handler peut faire quasiment n'importe quelle opération, en effet la méthode ProcessRequest prend en paramètre l'objet HttpContext qui donne accès à l'objet Request, à l'objet Reponse ainsi qu'à tous les composants d'une requête, bref avec cet objet nous avons accès à tout ou presque.

Http handler dans un fichier .ashx
Sélectionnez

<%@ WebHandler Language="C#" Class="Demo" %>

using System;
using System.Web;

public class Demo : IHttpHandler 
{
    
    public void ProcessRequest (HttpContext context) 
    {
        context.Response.Write(string.Format("Date : {0}. Heure : {1}.", 
                                                DateTime.Now.ToLongDateString(), 
                                                DateTime.Now.ToShortTimeString()));
    }
 
    public bool IsReusable 
    {
        get 
        {
            return true;
        }
    }

}

Voilà c'est tout, il est difficile de faire plus simple. On se contente d'ajouter les informations souhaitées dans l'objet Response, qui correspond à ce qui est retournée au client. Ici c'est du texte simple, mais n'importe quel type de contenu est envisageable.

A chaque fois que l'on demandera la ressource se trouvant à cette adresse http://host/Demo.ashx alors le serveur nous renverra la date et l'heure courante.

Ici nous avons crée un Handler directement dans une application Web, dans ce cas ce n'est même pas la peine de le déclarer dans le fichier Web.config car on l'appellera directement en entrant l'URL du fichier le contenant Demo.ashx. Cette solution pourra être valable si l'on souhaite par exemple publier un flux RSS, mais maintenant faisons en sorte que chaque fois qu'une requête demandera une ressource dont l'extension est .super alors notre http Handler sera appelé.

Cette fois ci nous n'allons pas intégrer notre Handler directement dans notre application Web dans un fichier .ashx mais dans une bibliothèque de classe, en d'autres termes dans une dll .Net. Pour cela ajouter une bibliothèque de classe à la solution nommée "HttpHandlerDemo", puis ajouter une classe "MySuperHandler" au projet.

  • Ajouter une référence au projet vers System.Web.dll
  • Ajouter using System.Web; en entête de la classe
  • Implémenter l'interface IHttpHandler

Votre classe doit alors ressembler à cela :

Squelette d'un Http handler
Sélectionnez

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web;


namespace HttpHandlerDemo
{
    public class MySuperHandler: IHttpHandler   
    {
        #region IHttpHandler Members

        public bool IsReusable
        {
            get { throw new NotImplementedException(); }
        }

        public void ProcessRequest(HttpContext context)
        {
            throw new NotImplementedException();
        }

        #endregion
    }
}

Comme dans notre premier exemple ce http Handler remplira la même fonction, à savoir renvoyer la date et l'heure. Le code final de notre http Handler sera donc le suivant :

Http handler dans une dll
Sélectionnez

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web;


namespace HttpHandlerDemo
{
    public class MySuperHandler: IHttpHandler   
    {
        #region IHttpHandler Members

        public bool IsReusable
        {
            get { return true; }
        }

        public void ProcessRequest(HttpContext context)
        {
            context.Response.Write(string.Format("Date : {0}. Heure : {1}.",
                                        DateTime.Now.ToLongDateString(),
                                        DateTime.Now.ToShortTimeString()));

        }

        #endregion
    }
}

Compilez alors votre projet, vous obtenez alors une dll nommée HttpHandlerDemo.dll. Cette dll contient votre http Handler custom, il ne reste plus qu'à le déployer dans IIS et votre application ASP.Net.

3. Installation et déploiement dans IIS 7.0

Le déploiement d'un http Handler dans IIS 7.0 a été encore simplifié par rapport aux versions précédentes. Le déploiement d'un http Handler dans IIS 6.0 fera l'objet d'un autre article.

A cette étape notre application ASP.Net ne sait pas quoi faire si on lui demande une ressource dans l'extension .super. Le moteur d'IIS qui est le premier à recevoir la requête ne sait pas qu'il faut la transférer au moteur d'exécution ASP.Net, en l'état il va donc essayer d'interpréter la requête lui-même sans grand succès bien évidemment... Voyons comment faire pour configurer IIS 7.0 pour qu'il transmette la requête pour une ressource dont l'extension est .super vers ASP.Net (aspnet_isapi.dll).

Il faut tout d'abord ajouter la dll contenant votre http Handler dans le répertoire bin de votre application ASP.Net. Une fois cette étape réalisée, procéder de la manière suivante :

  • Ouvrez la console d'administration (inetmgr) d'IIS 7.0
  • Placez-vous sur le répertoire virtuel contenant votre application
  • Dans le volet de droite double cliquer sur l'icône « Handler mappings »
  • Cliquez sur « Add managed Handler »
  • Configurer les différents champs comme le montre cette capture d'écran
Ajout d'un http handler dans IIS 7.0
Ajout d'un http handler dans IIS 7.0



Paramétrage d'un http handler
Paramétrage d'un http handler
  • Path correspond en fait à l'extension qui appellera notre Handler. Ici n'importe quelle ressource ayant l'extension .super appellera notre Handler custom. Ce paramétrage sera maintenu par le moteur d'exécution d'ASP.Net au moment du démarrage de notre application.
  • Type correspond au nom complet du type de notre Handler (namespace plus classe), puis après une virgule il faudra ajouter le nom de la dll sans son extension.
  • Name est en fait le nom que nom que vous souhaitez donner à ce Handler, le nom est totalement arbitraire et n'a aucun impact

Cliquez sur le bouton "Request restrictions", il permet de configurer certains paramètres comme par exemple les verbes de requêtes qui entrainent l'appel du Handler. Comme le montre la capture suivante entrer " GET, POST ".

Cliquer sur "OK", puis sur "OK" de nouveau. A ce stade le http Handler est fonctionnel. Pour le vérifier il suffit d'ouvrir votre navigateur puis de taper : http://localhost/test.super

Et à ce moment là vous allez récupérer la réponse du Handler, à savoir la date et l'heure.

Si vous ouvrez le fichier web.config de votre application vous allez voir qu'IIS a ajouté pour vous une nouvelle entrée dans "httpHandlers", en voici une copie :

Fichier Web.config
Sélectionnez

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <system.webServer>
        <handlers>
            <add name="MySuperHandler" path="*.super" verb="GET, POST" type="HttpHandlerDemo.MySuperHandler, HttpHandlerDemo" resourceType="Unspecified" preCondition="integratedMode" />
        </handlers>
    </system.webServer>
</configuration>

Cette nouvelle entrée signale au moteur d'exécution d'ASP.Net quel est le comportement à avoir si une requête vers une ressource portant l'extension .super arrive.

4. Conclusion

Que ce soit pour exposer des flux XML, générés des contenus graphiques à la volée, faire appel à des images en base de données et encore bien d'autres applications les http Handlers offrent une grande souplesse de développement et de mise en œuvre, encore plus avec IIS en version 7.0 dans Windows Vista et Windows Server 2008. Avec une interface IHttpHandler très simple à implémenter il serait dommage de ne pas tirer parti du modèle et l'architecture d'ASP.Net. J'espère au travers de cet article vous avoir montré une partie des possibilités offertes par les http Handler, d'autres articles suivront tant les Handlers et les modules peuvent rendre de grands services aux développeurs.

Ressources