Une librairie de UserControl ? Sans code (ou presque) C’est aussi possible ! ;) par Thomas Zumbrunn

Introduction

Dans cet article, nous allons tenter de voir comment nous pourrions trouver une solution alternative / complémentaire à l'excellent article de Sébastien Bouchet. Cet article complémentaire n'est pas destiné à présenter le pourquoi du comment mais plutôt à vous proposer un tutorial clé en main pour pouvoir réutiliser des contrôles utilisateur (usercontrol) facilement sans utiliser un wrapper ou un code particulier. Nous allons principalement utiliser Visual Studio.net 2003 dans ce tutorial mais vous pouvez, bien entendu, utiliser d'autres IDE ou éditeur texte.

Création du bibliothèque de user controls

Tous d'abord, nous allons créer un projet web dans visual studio qui contiendra l'ensemble des contrôles partagés dans nos différentes applications web.

 


 

Jusqu'ici pas grand chose de nouveau, nous rajoutons un contrôle contenant un calendrier ainsi que deux labels qui nous seront utiles un peu plus tard pour afficher la compagnie ainsi que la date.

Custom properties dans le code behind

Pour notre démonstration, nous allons également rajouter des properties ainsi que du custom code dans l'événement page_load du contrôle. Dans le but de montrer qu'il est possible de réutiliser l'assembly avec le code et les propriétés qu'elle contient nous allons le faire dans le code behind du contrôle, mais ceci fonctionne également si le code est directement inséré dans le fichier ascx. Je rajoute donc le code suivant dans le fichier DateBox.ascx.cs

public string Company

{
    get { return _company; }
   
set { _company = value; }
}

public string Year
{
   
get { return _year; }
   
set { _year = value; }
}

protected void Page_Load(object sender, System.EventArgs e)
{
    Response.Write("DNGControl Page Load Event successfully called!");
    lblDate.Text = Year;
    lblCompany.Text = Company;
}

private string _company,
                        _year;

Partager l'assembly des contrôles

Le seul moyen de partager une assembly entre plusieurs applications .NET est de signer une assembly et de l'enregistrer dans le GAC (Global Assembly Cache).  Pour cela nous devons créer un fichier qui contiendra les clés grâce à l'utilitaire SN : "sn.exe -k votrenomdecle.snk" . Puis nous associons le nom de ce dernier à l'attribut "AssemblyKeyFile" du fichier "AssemblyInfo.cs" de notre projet.

Nous allons maintenant compiler notre projet et installer l'assembly générée par le projet dans le GAC par un cliquer / glisser ou en utilisant l'utilitaire DOS "GacUtil.exe".

Il nous reste une dernière étape indispensable pour que le compilateur de page aspx prenne en compte l'assembly dans le GAC, modifier le fichier Machine.Config. Ce dernier se trouve par défaut dans le répertoire suivant : VotreDrive:\VotreWin\Microsoft.NET\Framework\VotreVersion\CONFIG. Il nous faut charger le fichier dans un éditeur de texte et trouver <assemblies> et rajouter un élément add avec les informations correspondantes. Dans notre cas cela donne ceci :

 <add assembly="DNGControls, Version=1.0.0.0, Culture=neutral, PublicKeyToken=29f4c43ca2dde360"/>

A noter que la valeurs des paramètres ci-dessus dependront évidemment du contexte de lequel vous vous trouverez.

Et nos contrôles ASCX ?!

Un peux de patience, nous allons y parvenir. Avant cela laissons le framework et vs.net de coté pour nous pencher sur IIS. Pourquoi IIS me direz-vous ? IIS possède la faculté de créer des répertoires virtuels. Ce mécanisme va nous permettre de créer sur le site qui désire réutiliser notre bibliothèque de contrôles, un répertoire virtuel qui mappera directement le path physique du répertoire qui contient notre projet de contrôle.

 

J'ai volontairement supprimé le mode application du répertoire mais ceci est optionnel. Il n'est non plus pas obligatoire que le répertoire où ce trouve les .ASCX soit sur le même site ou soit un répertoire référencé dans IIS. Cela peut être un simple répertoire ou un partage (share) contenant uniquement les fichier .ascx. Pour le share je m'avance peut-être un peu car je n'ai pas encore essayé. Mais je ne vois pas de raisons pour lesquelles cela ne fonctionnait pas

Rise of the controls

A ce stade nous avons presque tous les ingrédients pour pouvoir utiliser nos ASCX. Il nous manque encore une page de test qui va utiliser les ASCX. Pour cela j'ai crée un nouveau projet web DNGConsumer auquel je rajoute une référence a l'assembly qui contient le code de nos contrôles.

A titre d'exemple nous allons nous contenter d'une page créée par défaut "webform1.aspx" dans laquelle nous rajoutons les quelques lignes de code suivantes pour pouvoir utiliser nos contrôles.

Pour faire appel à un contrôle, il est nécessaire d'ajouter la directive Register dans la page ASPX. Attention l'astuce pour charger le contrôle ce situe ici !

  <% Register    TagPrefix="DNG"
                            TagName="DateBox"
                            Src="~/Controls/DateBox.ascx" %>

Mais quel est donc ce ~ ? Il est très important car il permet à un path d'être basé sur son vrai répertoire racine et non sur le path virtuel tout en étant considéré comme virtuel. Il est intéressant ici de noter qu'en temps normal ASP.net rejette l'expression précédente avec un message "maps to another application, which is not allowed" en raison du répertoire virtuel étranger, SAUF dans ce cas ou il ne détecte pas que le répertoire choisi est quand même un répertoire virtuel déclaré dans IIS. Qu'importe ! Cela fais bien nos affaires et nous avons désormais le champ libre pour charger notre contrôle.

Nous pouvons dés à présent l'utiliser et remplir nos paramètres l'esprit tranquille avec le code ci-dessous.

  <DNG:DateBox id="DateBox1" Company="DNG" Year="1984" runat="server" />

IL ne nous reste plus qu'a compiler le projet et si tout c'est bien passé, nous devrions avoir le contrôle apparaître de manière magique sur notre page aspx.

Ça n'a pas l'air si mal :).

Utilisations depuis le code behind de la page aspx

Pour pouvoir utiliser notre contrôle depuis le code behind de la page aspx, il nous suffit de déclarer une variable comme nous le ferions pour n'importe quel autre contrôle ainsi qu'un ordre using afin de référencer notre classe.


using
DNGControls;

namespace DNGConsumer
{

    public class WebForm1 : System.Web.UI.Page
    {
       
protected DateBox DateBox1;
       
private void Page_Load(object sender, System.EventArgs e)
        {
            DateBox1.Company = "Amiga";
            DateBox1.Year = "1985";
        }
    }

}

Pour les amoureux du dynamique nous pouvons également utiliser la méthode loadcontrol.


using
DNGControls;

namespace DNGConsumer
{

    public class WebForm1 : System.Web.UI.Page
    {
       
       
private void Page_Load(object sender, System.EventArgs e)
        {

DateBox dynDateBox = (DateBox) LoadControl("~/Controls/DateBox.ascx");
dynDateBox.Company = "Commodore";
dynDateBox.Year = "1980";
PlaceHolder1.Controls.Add(dynDateBox);

        }
    }

}


Conclusion

Pour des raisons évidentes de démonstration, cet article ne montre qu'un chemin et une seule application cliente du usercontrol mais vous pouvez bien entendu en rajouter un nombre X en suivant pour chaque application le même processus que pour l'exemple ci-dessus.

Par ailleurs, cette solution souffre peut-être d'une petite lourdeur de déploiement et elle ne permet pas d'inclure le fichier ASCX en resource embarquée , en revanche elle est entièrement intégrée a l'existant et se conforme aux différents outils et à la logique de partage .NET avec le GAC ainsi qu'avec d'IIS. Je ne sais pas si le ~ était prévu dans le loadcontrol mais si c'était le cas il serait probablement intéressant de le documenter ;) (message à destination de Microsoft bien entendu).

Le but principal de cet article était de vous faire connaître une autre façon, qui à ma connaissance n'a pas encore été publiée, de partager des usercontrols sans passer par du custom code ou sans refaire les internals de System.Web. J'espère vous avoir convaincu de l'intérêt d'une telle approche.


Auteur : Thomas Zumbrunn

Téléchargez le code source de l'article

Solution VS.NET : Comming soon

Copyright © Juillet 2003