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 <%$ AppSettings: imgDirectory %>, 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 :
<%$ AppSettings: imgDirectory %> : 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.
<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.
///
<
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.
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.
<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 :
<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.