I. Introduction

Le framework 2.0 a implémenté une nouvelle fonctionnalité appelée Expression Builder. Cette nouveauté permet par exemple d'appeler simplement une variable du web.config côté script d'une page web :

<asp:Label ID="lblImgDir" runat="server" Text='<%$ AppSettings: imgDirectory %>' />

Elle permet également d'aller chercher les chaines de connexion :

<asp:SqlDataSource ID="SqlDataSource" Runat="server" ConnectionString="<%$ ConnectionStrings:Northwind %>" />

ou des informations des fichiers de ressources :

<asp:Literal ID="Literal" Runat="server" Text="<%$ Resources:MyResources, MyText %>" />

Au moment de l'exécution de la page, si le compilateur trouve cette expression il va créer une nouvelle instance de la classe AppSettingsExpressionBuilder et rechercher la partie de droite dans les clés de la section AppSettings. L'attribut Text contiendra alors la valeur de la clé imgDirectory.

Il est également possible de créer son propre composant Expression Builder. Cette fonctionnalité vous permet de créer des composants plus riches que ceux décrits plus haut si jamais ils ne répondent pas totalement à vos besoins. Vous pouvez par exemple :

  • Vouloir lire des informations dans un fichier XML
  • Aller chercher des variables en session sans passer par le code behind.

Dans le cas de ce tutoriel, notre composant permettra de créer le chemin d'accès aux images via une variable de configuration.

Cet article vous propose de vous expliquer comment créer ce composant.

II. La classe ExpressionBuilder

II-A. Définition

La classe ExpressionBuilder permet de générer des expressions durant l'analyse de la page.

Les ExpressionBuilder se basent sur des balises ayant la forme suivante :

<%$ prefixe  : valeur %> .

Lors de l'analyse de la page, un générateur d'expression va être instancié dès lecture de la balise <%$. Le type de générateur dépendra du préfixe. Par exemple, dans le cas suivant <%$ AppSettingsimgDirectory %>, une classe AppSettingsExpressionBuilder va être instanciée.

La seconde partie de l'expression (valeur) va être passée en paramètre de la classe de génération idoine afin d'être évaluée et de retourner la valeur attendue par le contrôle.

II-B. Exemples connus

Sans que l'on se soit vraiment douté de ce concept, la plupart des codes l'utilisent. Voici quelques exemples très communs :

<%$ AppSettingsimgDirectory %> : permet de récupérer une valeur dans la section AppSettings du Web.Config ;

<%$ ConnectionStrings : MyNorthwind %>: permet de récupérer une chaine de connexion précisée dans le Web.Config ;

<%$ Resources : Libelle, ApplicationLabel %>: permet de récupérer la valeur de la clé ApplicationLabel dans le fichier ressource Libelle.resx.

III. Mise en oeuvre du contexte de développement

III-A. Mise en situation

Pour des raisons de sécurité et de cache, certains clients demandent une mise en oeuvre particulière des répertoires du serveur Microsoft Internet Information Server. Cette mise en place implique un premier répertoire virtuel contenant le code de l'application et un second contenant toutes les images de l'application.

Les raisons de ce découpage sont multiples allant des droits sur les répertoires à la mise en cache des images.

Afin de ne pas modifier le code source avant livraison (et donc d'éviter des risques d'oubli), il est nécessaire de mettre en configuration le chemin menant au répertoire des images. Cette variable pointera sur le répertoire image de l'application durant la phase de développement et pourra pointer vers l'alias IIS lors de la qualification puis la production.

III-B. Mise en place de la configuration du répertoire

Dans le fichier web.config, il suffit de créer une section AppSettings ainsi que la variable ImgDirectory.

Web.config
Sélectionnez
<appSettings>
   <add key="imgDirectory" value="/Images" />
</appSettings>

III-C. Création du composant

Afin de réaliser son propre composant, il faut créer une classe héritant de System.Web.Compilation.ExpressionBuilder.

La classe ExpressionBuilder est une classe abstraite. Elle définit plusieurs fonctions dont une abstraite, donc à redéfinir : GetCodeExpression.

GetCodeExpression
Sélectionnez
/// <summary>
/// Cette méthode sera appelée lors de l'exécution de la page 
/// </summary>
public override CodeExpression GetCodeExpression(BoundPropertyEntry entry, object parsedData, ExpressionBuilderContext context)
{
   // OBTENIR une référence de la classe en cours
   CodeTypeReferenceExpression thisType = new CodeTypeReferenceExpression(base.GetType());
   // RECUPERER l'expression passée en paramètre 
   CodePrimitiveExpression expression = new CodePrimitiveExpression(entry.Expression.Trim().ToString());
   // NOMMER la fonction qui va être appelée
   string evaluationMethod = "FormatExpression";
   // RETOURNER l'expression qui appellera la méthode définie
   return new CodeMethodInvokeExpression(thisType, evaluationMethod, new CodeExpression[] { expression });
}

Il faut ensuite définir la méthode définition dans la variable evaluationMethod.

FormatExpression
Sélectionnez
public static string FormatExpression(string expression)
{
   // RECUPERER les deux parties
   // La première représente la clé dans le web.config, section appSettings
   // La seconde le sous-répertoire + fichier
   string[] stringParts = expression.Split(',');
   if (stringParts.Length == 2)
   {
      return ConfigurationManager.AppSettings[stringParts[0].Trim()] + stringParts[1].Trim();
   }
   if ("this.src".Equals(stringParts[2].Trim()))
   {
      return "this.src='" + ConfigurationManager.AppSettings[stringParts[0].Trim()] + stringParts[1].Trim() + "'";
   }
   return ConfigurationManager.AppSettings[stringParts[0].Trim()] + stringParts[1].Trim();
}

Cette méthode transforme la valeur en paramètre en tableau afin de récupérer la valeur à rechercher dans le ConfigurationManager et le chemin du fichier.

Ces deux valeurs seront concaténées et le résultat retourné.

III-D. Mise en place de la configuration

Une fois la classe codée, il faut définir notre nouvelle Expression Builder dans le web.config.

Web.config
Sélectionnez
<system.web>
   <compilation debug="true" targetFramework="4.0">
      <expressionBuilders>
         <add expressionPrefix="iisdir" type="MonExpressionBuilder.MonExpressionBuilder"/>
      </expressionBuilders>
   </compilation>
</system.web>

Attribut expressionPrefix : nom du tag

Attribut type : namespace.classe

III-E. Utilisation du composant

Enfin, il ne nous reste plus qu'à utiliser notre nouveau composant dans une page aspx :

Page aspx
Sélectionnez
<body>
    <form id="form1" runat="server">
    	<div>
    	<img alt="Logo" src="<asp:Literal runat='server' Text='<%$ iisdir: imgDirectory, /logo.gif %>' />" />
    	</div>
    </form>
</body

IV. Mise en oeuvre du contexte de qualification

Compiler le code et placer le site web sous IIS.

Créer un répertoire virtuel pour l'application ainsi qu'un autre pour les images.

Dans le fichier web.config positionner la variable imgDirectory sur l'alias IIS.

V. Conclusion

Il est donc très simple de créer de nouveaux composants de type Expression Builder. Cela permet de gérer dans IIS un répertoire virtuel avec toutes les images de l'application, répertoire différent de celui de l'application proprement dite.

VI. Remerciements

Je remercie toute l'équipe developpez.com pour m'avoir mis le pied à l'étrier avec ce premier article et en particulier Philippe Vialatte et Arnard pour leur relecture et leurs conseils. Merci également à Claude Leloup pour ses corrections.