1. Présentation générale - fonctionnalités intégrées

Cette présentation générale présente les fonctionnalités principales du projet. Ces caractéristiques sont nécessaires à un portail Internet intégrant la gestion de contenu. Cette première partie se veut plus fonctionnelle que technique. Cette première partie conviendra au lecteur peu technicien mais désireux de comprendre les fonctions essentielles présentes dans ce projet.

1.1. Origine du projet initial

Le projet ASP.NET Portal Starter Kit a été initialement publié par Vertigo Software en Novembre 2002. La création de ce projet fut motivée par le besoin de fournir des projets de démonstration accompagnant la nouvelle technologie ASP.NET. Ainsi une gamme de différents Starter Kit est née.

La liste des différents "ASP.NET Starter Kit" disponibles est la suivante :

  • Issue Tracker Starter Kit : portail Internet de gestion de déploiement de logiciel
  • Time Tracker Starter Kit : portail Internet de gestion de projet
  • Reports Starter Kit : kit de construction d'états d'impression
  • Community Starter Kit : portail Internet communautaire
  • Commerce Starter Kit : portail Internet de commerce électronique
  • Portal Starter Kit : l'objet de cet article

Ces différents projets sont proposés dans les langages VB#, J# et C# et sont en téléchargement gratuit sur le portail Microsoft dédié à ASP.NET.

1.2. Portail Internet et gestion de contenu (CMS)

Dans les systèmes de gestion de contenu, CMS (Content Management System), la présentation est séparée des données.

Les deux niveaux suivants sont à distinguer :

  • la présentation (layout) : arborescence du site, charte graphique, agencement des différents modules dans une page...
  • le contenu (content) : informations présentées par les modules
  • .

La principale caractéristique du Portal Starter Kit est l'intégration en ligne de la gestion de contenu (CMS). Ainsi le portail offre deux modes de fonctionnement principaux :

  • La consultation classique : navigation "standard" ou navigation avec participation aux modules publics (discussions...)
  • La consultation avec administration en ligne de la présentation et du contenu : Dans ce mode les modules proposent des liens vers l'édition de leur contenu. La page d'administration du portail est accessible :
Image non disponible

Dephi ASP.NET Portal Starter Kit permet de créer et de maintenir un ou plusieurs portails. Les informations de contenu de plusieurs portails peuvent être stockées dans une même base de données. Le fichier de configuration "PortalCfg.xml" est associé à un portail unique.

1.3. Arborescence, page modèle et Modules

L'arborescence principale du portail est représentée via un système d'onglets. Chacun de ces onglets correspond à une page du portail. Cette arborescence est administrable en ligne via la page d'administration. Cette administration permet la gestion une d'une arborescence dynamique.

Chaque page du portail implémentée via Portal Starter Kit est composite et donc créée dynamiquement.

Une page finale est le résultat de l'assemblage dynamique de plusieurs modules.

Cet assemblage est basé sur une page modèle ou gabarit. Cette page modèle inclut trois zones : la zone gauche, la zone du centre et la zone de droite. La page d'administration de la présentation permet de positionner les modules d'une page du portail dans ces zones.

La page modèle est composée d'une partie représentant la banière du site. Dans cette banière sont présents le titre du site, les onglets... De même la partie titre des modules est extraite dans un composant. Cette décomposition des pages/composants en sous-éléments permet de maintenir facilement l'aspect général du portail.

Les éléments communs du site sont isolés et extraits dans des composants.La factorisation des parties communes via les composants (contrôle utilisateur ASP.NET) permet de simplifier la maintenance du portail et d'uniformiser le look and feel.

1.4. Liste et définition des Modules enfichables

La liste des modules disponibles est présentée ci-dessous. Ces modules sont groupés dans deux tableaux principaux en fonction de leur rôle d'administration du portail ou de leur rôle de présentation de contenu.

Liste des modules d'administrations présents sur la page de gestion du site :

Module Description Fichier du contrôle Page d'administration associée
1 Définition de Module Type gestion de la liste des modules du portail \Admin\ModuleDefs.ascx \Admin\ModuleDefinitions.aspx
\Admin\ModuleSettings.aspx
2 Rôles gestion des rôles associés à un utilisateur \Admin\Roles.ascx \Admin\SecurityRoles.aspx
3 Onglets gestion des onglets du portail \Admin\Tabs.ascx \Admin\TabLayout.aspx
4 Paramètres du site gestion des paramètres généraux du portail \Admin\SiteSettings.ascx page d'administration du site
5 Gestion des Utilisateurs gestion des utilisateurs du portail \Admin\users.ascx \Admin\manageusers.aspx

Liste des modules de présentation de contenu :

Module Description Fichier du contrôle Page d'administration associée
1 Annonces Annonce texte avec les champs : titre, date de d'expiration, description, lien "en savoir plus" \DesktopModules\Announcements.ascx
\MobileModules\mAnnouncements.ascx
\DesktopModules\EditAnnouncements.aspx
2 Contacts liste de contacts avec les champs : nom, rôle, email, premier contact, second contact \DesktopModules\Contacts.ascx
\MobileModules\mContacts.ascx
\DesktopModules\EditContacts.aspx
3 Discussion Discussion avec les champs : titre, date, auteur, texte \DesktopModules\Discussion.ascx \DesktopModules\DiscussDetails.aspx
4 Evénements Evénement texte avec les champs : titre, où et quand, description, date d'expiration \DesktopModules\Events.ascx
\MobileModules\mEvents.ascx
\DesktopModules\EditEvents.aspx
5 html Document html avec les champs : document html, résumé html et document html pour les mobiles \DesktopModules\HtmlModule.ascx
\MobileModules\mText.ascx
\DesktopModules\EditHtml.aspx
6 Image Image avec champs : taille de l'image affichée, chemin du fichier image \DesktopModules\ImageModule.ascx \DesktopModules\EditImage.aspx
7 Liens Lien hypertexte avec les champs : URL, URL pour les mobiles, ordre d'affichage, description \DesktopModules\Links.ascx \DesktopModules\EditLinks.aspx
8 Liens Rapides Lien hypertexte avec les champs : URL et ordre d'affichage, description \DesktopModules\QuickLinks.ascx \DesktopModules\EditLinks.aspx
9 XML/XSL Transformation XML/XSLT avec les champs : chemin d'un fichier XML et du fichier de transformation XSL/T \DesktopModules\XmlModule.ascx \DesktopModules\EditXml.aspx
10 Documents Documents avec les champs : nom de document, lien sur le document, catégorie et propriétaire \DesktopModules\Document.ascx \DesktopModules\ViewDocument.aspx

Module utilitaire :

Module Description Fichier du control (répertoire \Admin Position
1 Connexion au portail Module de connexion au portail (nom de connexion, mot de passe, bouton valider et s'enregistrer) Signin.ascx premier onglet du portail

A chacun de ces modules de présentation de contenu est associé un objet métier implémentant l'accès aux informations de contenu. Ces informations de contenu sont stockées dans une base de données (SQL Server ou FireBird). Il est ainsi possible d'interfacer une base de données existante avec le portail.

Le paramétrage du contenu présenté par les modules Images et XML/XSL, n'est pas stocké dans la base de données. Dans ce cas ces paramètres sont stockés dans la configuration XML.

D'autres modules peuvent-être ajoutés (pluggable) via le module "définition de Module Type". Un module spécifique est facilement intégrable à l'ensemble du portail. Par exemple un module "Blogs" est simple à développer et ne présente aucune difficulté d'intégration dans le portail. L'ensemble reste cohérent grâce à ce système de modules enfichables.

1.5. Sécurité via les rôles

Le projet ASP.NET Portal Starter Kit intègre les notions de sécurité permettant une intervention sur le portail de plusieurs intervenants (travail collaboratif). Par exemple, un portail réalisé avec ce projet convient à un portail de communauté de communes dans lequel chaque commune est responsable de sa rubrique mais ne doit pas intervenir sur la rubrique de la commune voisine.

Chacun des onglets du portail correspond à une page ayant des droits d'accès en consultation. Ainsi par exemple l'onglet Administration ne sera proposé qu'aux utilisateurs possédant le rôle d'administrateur. Le même principe de sécurité est valable pour les modules composant les pages. Il est donc possible de distribuer des rôles sur les pages mais aussi sur les modules. Ces rôles sont affectés à deux actions principales :

  • Consultation ("AccessRoles") : La liste des rôles autorisés à consulter une page
  • Edition de contenu ("EditRoles") : La liste des rôles autorisés à éditer le contenu

Le basculement du mode consultation vers le mode administration de contenu est effectué via la connexion au portail et via le(s) rôle(s) associé(s) au compte de connexion. Un utilisateur lambda (public) lors de sa connexion au site ne se verra pas proposer la maintenance du site alors qu'un utilisateur connecté par exemple comme Administrateur (rôle admin) disposera d'une interface lui permettant de maintenir en ligne le portail.

Il est possible de définir de nouveaux rôles via le module d'administration. Ces rôles sont stockés dans une table de la base de données. Ils sont croisés avec les utilisateurs. Par exemple à l'utilisateur Administrateur est associé le rôle "Admin". Lors de l'administration, le rôle associé à une page ou à un module est copié dans le fichier de configuration "PortalCfg.xml".

1.6. Accès pour les périphériques mobiles

Le projet ASP.NET Portal Starter Kit permet de communiquer avec un public important grâce aux fonctionnalités intégrées d'accès aux périphériques Mobiles. Par exemple, le portail Internet d'un office de tourisme peut offrir l'accès à la liste des événements locaux via la connexion des téléphones mobiles des touristes en vacances.

Chaque page (onglet) et chaque module possèdent une option ShowMobile. Cette option, en mode administration, permet de définir si la page et/ou le module sont affichés pour les périphériques mobiles. Tous les modules ne sont pas implémentés pour permettre un affichage pour les périphériques mobiles (cf. liste des modules 1.4).

Les modules "mixtes" disponibles pour les périphériques mobiles sont :

  1. Annonces
  2. Contacts
  3. Evénements
  4. Html

Les caractéristiques d'un périphérique mobile ne sont pas forcément compatibles avec le contenu publié sur un ordinateur. En conséquence, deux zones distinctes (spécifiques aux périphériques de type Desktop ou de type Mobile) permettent de saisir le contenu présenté par le module.

Les informations publiées par un module mixte (ordinateur et mobile) sont spécifiques au périphérique du client cible.

1.7. Qualité de service (QOS) et Cache

Un système de cache configurable dans l'administration du portail permet d'offrir un temps de réponse stable. Via ce système de cache paramètrable, les modules lors de leur création initiale sont automatiquement inscrits dans le cache du système. Leur construction complète n'est pas nécessaire à la prochaine requête. Le HTML correspondant au module est automatiquement restitué à partir du cache du système. Le temps de réponse (accès à la base, présentation des infos...) est ainsi optimisé au minimum.

Ce cache peut provoquer une désynchronisation avec la base de données. Dans le cas où les informations de contenu sont modifiées dans la base, cette modification ne sera pas visible par le client car la chaîne correspondant au module (cache) avant la modification sera renvoyée.

2. Présentation technique du projet Delphi

Le projet Delphi ASP.NET Portal Starter Kit est un projet important de part sa taille. Néanmoins la complexité de l'ensemble est moindre. Avec les contrôles utilisateurs ASP.NET (ascx), les pages (aspx) mais aussi les contrôles ASP.NET ressemblent à des poupées russes. Ceci rend le code plus digeste mais l'appréhension de l'ensemble plus complexe. Dans cette présentation, les points clés sont abordés. Le code étant important (environ 20 000 lignes) il est ambitieux de décrire l'ensemble dans le détail.

2.1. Composantes logicielles

2.2. Pourquoi une traduction Delphi ?

Avec .NET, il est très simple d'utiliser avec Delphi les classes définies initialement en C#. Par exemple une inclusion (uses) du namespace "ASPNET.StarterKit.Portal" permet de définir un nouveau module héritant de la classe C# "PortalModuleControl" initiale :

Composant Delphi 'TWebUserDelphiCalendrier' héritant de la classe C# via l'inclusion du namespace C#
Sélectionnez

unit CalendarDelphi;

interface

uses System.Data, System.Drawing, System.Web, System.Web.UI,
     System.Web.UI.WebControls, System.Web.UI.HtmlControls,
     System.ComponentModel,
     System.Globalization,
     ASPNET.StarterKit.Portal; //  namespace PortalModuleControl/C#

type

  TWebUserDelphiCalendrier = class(PortalModuleControl) //  héritage

Via .NET, il est également possible d'étendre une classe avec les Class Helpers ("class helper for ...").

Afin de profiter du code C#, la traduction du projet n'est donc pas forcément nécessaire. Plusieurs raisons cependant encouragent à faire cette traduction :

  • Le projet initial ne couvre pas toutes vos exigences et l'extension des classes du projet C# ne permet pas de pallier à ce besoin. Le moteur du projet initial doit donc être modifié.
  • Des erreurs/problèmes sont présents dans le code C#. La maintenance du code original est à prévoir.
  • Vous voulez diffuser votre produit contenu dans votre assemblage sans dépendance à d'autres assemblages .
  • Delphi est votre "langage maternel" et il n'existe (à ma connaissance) aucun Framework .NET de création de portail Internet en Delphi .NET.

2.3. Configuration XML

Les informations de présentation (onglets, composition des onglets), de sécurité (rôles associés...) du portail ainsi que l'index du portail (PortalId) sont stockées dans le fichier Portal.XML. A ce fichier correspond un mappage objet de type Stronged Typed DataSet défini dans l'unité "PortalCfg.pas". Dans le code C# original, ce mappage (PortalCfg.cs) est automatiquement obtenu via l'utilitaire XSD.EXE du framework.

Utilisation de XSD.EXE : mappage d'un schéma XML vers un Stronged Typed DataSet en langage C#
Sélectionnez

C:\Program Files\Microsoft.Net\SDK\v1.1\Bin\XSD.EXE PortalCfg.xsd /language:CS /D

Cependant avec l'utilitaire "XSD.exe", il n'est pas possible d'utiliser le provider de code Delphi (DelphiCodeProvider). Cet utilitaire ne sait pas utiliser le fournisseur de code Delphi. Dans ce projet, après une longue recherche pour pallier à ce problème, le fichier "PortalCfg.pas" est la traduction du fichier C# original (PortalCfg.cs) via BabelClient.

Ce service de traduction automatique de C# vers Delphi n'est pas totalement efficace, des corrections manuelles sont ajoutées dans le source du fichier "PortalCfg.pas".

Cet exemple avec FireBird réalise un mappage via une base de données vers un Stronged Typed DataSet en langage Delphi.

Un outils de réflexion peut être utile pour réaliser rapidement la traduction d'un assembly initialement en C# vers Delphi. Le reflector de Lutz Roeder est performant dans cette tâche. Il est d'une aide précieuse dans la traduction (recherche de namespaces correspondant à une classe...).

Structure de "PortalCfg.XML" : noeuds, pages et contrôles principaux impliqués :

Image non disponible
Aperçu de la configuration 'PortalCfg.XML' et page et composant impliqués

Un portail est référencé par un index (PortalId) présent dans le fichier de configuration du portail (PortalCfg.xml). Chaque page correspondante à un onglet est référencé dans un noeud "Tab". A chacun de ces noeuds correspondent les noeuds enfants des modules assemblés par cette page. Comme pour la partie haute (bannière) de la page modèle, les modules sont eux-mêmes composites. La partie titre est implémentée dans un composant spécial. Pour les modules standards, ce contrôle est "DesktopModuleTitle.ascx". Pour les modules spécifiques aux mobiles, le titre du module est implémenté par "MobileModuleTitle.ascx".

2.4. Modules enfichables

La notion de contrôle utilisateur ASP.NET (extension ASCX) permet de créer un site résultant de l'assemblage de composants. Cette notion objet nouvellement intégrée à ASP.NET est très utilisée dans ce projet. Chaque entité du portail correspond à un contrôle utilisateur. Cette notion est identique aux principes des composants dans Delphi.


Les modules de présentation de contenu sont composés de deux parties principales correspondant à un contrôle de présentation et une page d'administration :

  • le contrôle de présentation du contenu (par exemple "Announcements.ascx")
  • la page d'administration du contenu (par exemple "EditAnnouncements.aspx")

Le contrôle utilisateur ASP.NET de présentation de contenu (ascx) propose le lien vers l'édition. Ce lien (Modifier, Editer, Nouvelle annonce...) est présent dans la partie titre (contrôle utilisateur ASP.NET "DesktopModuleTitle.ascx") du module.

Extrait du contrôle utilisateur 'DesktopModuleTitle.ascx' - lien vers l'édition de contenu du module
Sélectionnez

<asp:hyperlink id=EditButton enableviewstate="false" 
                       cssclass="CommandButton" runat="server">
        </asp:hyperlink>

Les modules spécifiques aux mobiles n'implémentent pas l'édition en ligne. Pour modifier le contenu présenté par un module mobile, il est nécessaire d'utiliser la partie "Desktop" du portail.

Chacun des modules de présentation de contenu hérite d'un contrôle générique "TPortalModuleControl". Cet héritage permet d'implémenter les règles communes au portail (charte graphique, sécurité...). Ces modules implémentent également des règles métiers spécifiques à leurs tâches (polymorphisme).

Les unités dans lesquelles sont implémentés les objets métiers d'accès au contenu sont postfixées de "DB" (par exemple ContactDB.pas). Ces unités sont dans le répertoire : "\Components". Un objet encapsule ces fonctionnalités. Voici par exemple la définition de l'objet métier du module "Contacts" :

Extrait de l'unité '\Components\ContactDB.pas' : Encapsulation des fonctionnalités métier du module Contacts
Sélectionnez

  ContactsDB = class
  public
    constructor Create;
    function AddContact(moduleId: Integer; itemId: Integer; userName: Widestring; 
	name: Widestring; role: Widestring; email: Widestring; contact1: Widestring; contact2: Widestring): Integer;
    procedure DeleteContact(itemID: Integer);
    function GetContacts(moduleId: Integer): DataSet;
    {$IFDEF SQLSERVEUR}
    function GetSingleContact(itemId: Integer): SqlDataReader;
    {$ELSE}
    function GetSingleContact(itemId: Integer): FbDataReader;
    {$ENDIF}
    procedure UpdateContact(moduleId: Integer; itemId: Integer; userName: Widestring; 
	name: Widestring; role: Widestring; email: Widestring; contact1: Widestring; contact2: Widestring);
  end;

Le fichier "Portal.XML" ne contient aucune donnée relative au contenu d'un module (sauf pour le cas particulier des modules "Image" et "XML/XSL"). Seuls les index et les rôles associés aux modules sont présents dans la configuration "PortalCfg.xml". Les données correspondantes au contenu d'un module sont stockées dans une base de données (Microsoft SQL Server ou FireBird). L'index du module est utilisé pour indexer ce contenu dans la base de données.

2.5. Utilisateur et Rôle : sécurité

Lors de l'ajout et de la composition d'une page dans le partie administration du site, les droits de consultation (AccessRoles) de cette page ainsi que les droits en édition des modules (EditRoles) sont fixés. Ces droits sont sauvegardés dans le fichier "PortalCfg.XML" :

Image non disponible

L'objet "PortalSecurity" défini dans l'unité \Components\security.pas possède trois méthodes permettant de tester les paramètres de sécurité définis dans la configuration :

Extrait de l'unité \Components\security.pas - Classe PortalSecurity : Sécurité et Configuration
Sélectionnez

PortalSecurity = class
  public
    constructor Create;
    class function Encrypt(cleanString: Widestring): Widestring; static;
    class function HasEditPermissions(moduleId: Integer): boolean; static;
    class function IsInRole(role: Widestring): boolean; static;
    class function IsInRoles(roles: Widestring): boolean; static;
  end;

2.6. ASP.NET Mobile

Un article d'introduction à ASP.NET Mobile est disponible sur le site pchapuis.developpez.com.

L'accès aux périphériques mobiles utilise une page typée ASP.NET Mobile héritant de la classe .NET "MobilePage". Comme pour les pages des périphériques de type "Desktop", une page modèle est définie : "MobileDefault.aspx" spécifiquement pour ces périphériques.

La redirection en fonction du type de périphérique n'est pas automatique. Elle est prise en charge par le code suivant :

Redirection dans la page par défaut (Default.aspx) des périphériques en fonction de leur type
Sélectionnez

procedure TWebFormDefault.Page_Load(sender: System.Object; e: System.EventArgs);
begin
  if (Request.Browser['IsMobileDevice']= 'true' )
  then Response.Redirect(DEFAULT_MOBILEINDEX)
  else Response.Redirect(DEFAULT_DESKTOPINDEX);
end;

La page "MobileDefault.aspx" inclut une fiche spécifique au mobile ("System.Web.UI.MobileControls.Form") et un contrôle "TabbedPanel" défini dans l'unité "MobileControls".

Ce contrôle MobileControls.TabbedPanel est équivalent aux onglets des pages pour "Desktop". Il implémente les spécificités d'un contrôle dédié aux périphériques mobiles. Il gère par exemple l'arborescence, la pagination ainsi que le type de vue de la page (SummaryView).

Ce contrôle "TabbedPanel" est encapsulé dans différents adaptateurs. Ces adaptateurs permettent la prise en charge spécifique des différents formats (HTML 3.2, WML 1.1, cHTML) disponibles avec ASP.NET Mobile.

Extrait de l'unité 'MobileControls' - adaptateurs spécifiques
Sélectionnez

 HtmlTabbedPanelAdapter = class(HtmlControlAdapter)
  strict protected
  public
    procedure Render(writer: HtmlMobileTextWriter); override;
    function get_Control: TabbedPanel; reintroduce;
    property Control: TabbedPanel read get_Control;
  strict private
    class function GetColorString(color: Color; defaultColor: Widestring): Widestring;static;
  end;


  WmlTabbedPanelAdapter = class(WmlControlAdapter)
  strict private
    _menu: List;
    procedure OnListItemCommand(sender: &Object; e: ListCommandEventArgs);
  strict protected
    function get_Control: TabbedPanel; reintroduce;
    property Control: TabbedPanel read get_Control;
  public
    procedure OnInit(e: EventArgs); override;
    procedure OnLoad(e: EventArgs); override;
    procedure Render(writer: WmlMobileTextWriter); override;
  end;

  ChtmlTabbedPanelAdapter = class(HtmlControlAdapter)
  strict protected
    function get_Control: TabbedPanel; reintroduce;
    property Control: TabbedPanel read get_Control;
  public
    procedure Render(writer: HtmlMobileTextWriter); override;
  end;

Pour être instanciés par le site (dans le source des pages ASPx), ces contrôles spécifiques doivent-être enregistrés dans le fichier de configuration "Web.config.XML" du site :

Image non disponible

Ce recensement dans "web.config.xml" fixe la relation entre un format spécifique (HtmlDeviceAdapters, ChtmlDeviceAdapters, WmlDeviceAdapters) , un composant spécifique prenant en charge ce format et l'assemblage implémentant ce composant.

Dans ce projet Delphi, une ligne de code est ajoutée dans l'unité "MobileDefault.pas" pour supprimer la répétition des éléments de menu WML pour le premier élément. Cette ligne de code n'est pas présente dans le projet C# initial. Ce code spécifique au projet Delphi est le suivant :

if Assigned(WmlTabbedPanelAdapter(TabView.Adapter)) and (TabIndex=0) then exit;

2.7. Fonctionnement du cache

Actuellement les sites Internet sont rarement adaptés pour répondre aux montées en charge. Lors d'une vague de connexion massive, le site dans le meilleur des cas ne répond plus ou dans le pire des cas la machine/le système passent hors service. Pour faire face à ce type de problème, un système de cache est implémenté dans le projet.

L'objet TCachedPortalModuleControl stocke automatiquement dans le cache du système la chaîne HTML correspondant à un module.

Définition de l'objet 'TCachedPortalModuleControl' défini dans l'unité 'DesktopControls.pas'
Sélectionnez

TCachedPortalModuleControl = class(Control)
// Private field variables
private
  _moduleConfiguration: ModuleSettings;
  _cachedOutput   : Widestring;
  _portalId       : integer;
strict protected
  procedure CreateChildControls; override;
  procedure Render(output: HtmlTextWriter); override;
public
    function get_CacheKey: Widestring;
    function get_ModuleId: Integer;
  // Methods
  public constructor Create;
published
  // Properties
  property CacheKey: Widestring read get_CacheKey;
  property ModuleConfiguration: ModuleSettings read _ModuleConfiguration write _ModuleConfiguration;
  property ModuleId: Integer read get_ModuleId;
  property PortalId: Integer read _PortalId write _PortalId;
end;

L'objet TCachedPortalModuleControl est mis en oeuvre dans la page par défaut (DesktopDefault.aspx). Lors de la construction de la page correspondant à l'onglet selectionné, le cache est créé. Chaque module inséré dans une page peut définir le temps d'expiration de ce cache (CacheTimeout) :

configuation XML d'un module 'Liens rapides' avec le cache activé (CacheTimeout=120)
Sélectionnez

<Module ModuleId="1" 
	ModuleTitle="QuickLinks" 
	EditRoles="Admins;Participants;" 
	ModuleDefId="8" 
	PaneName="leftPane" 
	CacheTimeout="120" 
	ModuleOrder="7" 
	ShowMobile="false"/>

Cet objet de gestion du cache est mis en oeuvre par le framework via les méthodes "Render" (capture) et "CreateChildControls" (restitution). La méthode "Render" surchargée permet (dans le cas ou CacheTime est différent de 0) de "capturer" le contenu HTML correspondant à un module. Cette chaîne HTML est alors insérée dans le cache du contexte avec le timeout correspondant au cache du module correspondant :

DesktopControls.TCachedPortalModuleControl.Render : capture dans la cache de la chaîne HTML correspondant à un module
Sélectionnez

procedure TCachedPortalModuleControl.Render(output: HtmlTextWriter);
var
tempWriter : TextWriter;
begin
  if (_moduleConfiguration.CacheTime = 0) then
  begin
      inherited Render(output);
      exit;
  end
  else
  begin
    if (_cachedOutput = '') then
    begin
      tempWriter := stringWriter.Create();
      inherited Render(HtmlTextWriter.Create(tempWriter));
      _cachedOutput := tempWriter.ToString();
      Context.Cache.Insert(	CacheKey,_cachedOutput, 
	  				nil, 
	  				DateTime.Now.AddSeconds(_moduleConfiguration.CacheTime), 
	  				TimeSpan.Zero);
    end;
    output.Write(_cachedOutput);
  end;
end;

Dans la méthode surchargée "CreateChildControls", la chaîne correspondant au module est restituée via son chargement à partir du cache du contexte. Si la chaîne n'est pas trouvée alors le module est entièrement recréé (timeout).

DesktopControls.TCachedPortalModuleControl.CreateChildControls : restitution d'un module via le cache
Sélectionnez

var
module : TPortalModuleControl;
begin
  if (_moduleConfiguration.CacheTime > 0) then
                _cachedOutput := Widestring(Context.Cache[CacheKey]);
  if (_cachedOutput='') then
  begin
    inherited CreateChildControls();
    module := TPortalModuleControl(Page.LoadControl(_moduleConfiguration.DesktopSrc));
    module.ModuleConfiguration := Self.ModuleConfiguration;
    module.PortalId := Self.PortalId;
    Self.Controls.Add(module);
  end;

3. Carences de cette version

Delphi ASP.NET Portal Starter Kit correspond à une stricte traduction du projet C# original. Bien que le projet initial soit mature, il subsiste néanmoins quelques problèmes mineurs.

3.1. Configuration "PortalCfg.XML" et HttpContext.Current

Problème : La configuration "PortalCfg.XML" du portail est stockée dans le cache du contexte http (unité "uConfiguration.pas" : HttpContext.Current.Cache). Lors de l'administration du site, la sauvegarde/restitution de cette configuration est parfois erronée. Ainsi les modifications ne sont pas prises en compte immédiatement. Il peut se produire une erreur suite à la désynchronisation des informations de configuration.

Solution proposée : La configuration "PortalCfg.XML" peut être stockée dans une table de la base de données. Ce stockage offre l'avantage d'un accès transactionnel. L'inconvénient de cette solution est un temps d'accès supérieur à celui d'un accès au cache.

Dans le source du projet, des modifications (HttpContext.Current.Application) ont été apportées pour résoudre le problème de la désynchronisation de la configuration du cache. Ces modifications ne sont pas suffisantes (cf. unité uConfiguration.pas et commentaire "PC++").

3.2. Ordre des onglets et des modules

Problème : Il peut être difficile de changer la position d'un onglet ou d'un module. Ceci est principalement causé par l'algorithme simplet d'incrémentation/décrémentation de l'index de l'élément. Les tests concernant ce problème doivent prendre en compte le problème connexe énoncé dans le point 3.1.

Solution proposée : l'algorithme de modification des index et/ou de déplacement d'un élément doit-être amélioré.

3.3. Accès ADO à différentes bases de données

Problème : Pour un besoin de code source unique et de simplicité, l'accès à la base SQL Server ou Interbase est conditionné par la directive de compilation "SQLSERVEUR". Les composants ADO permettant cet accès sont typés et donc différents en fonction de la base de données utilisée.

Solution proposée : Il existe des composants ADO permettant un accès générique. La mise en oeuvre de tels composants permet de supprimer la directive de compilation et ainsi d'alléger le code source d'accès à la base. Avec de tels composants, seule la chaîne de connexion conditionne le type de base de données couplée avec le portail.

3.5. Divers

Autres imperfections diverses :

  • La suppression d'un élément (onglet, modules...) n'est pas précédée d'une confirmation de suppression.
  • Dans le module Discussion, la suppression n'est pas proposée. Après un nouveau message, le retour à la discussion n'est pas implémenté.

4. Améliorations proposées

De nombreuses fonctions nécessaires à un portail professionnel ne sont pas implémentées dans le projet. Certaines de ces améliorations sont en cours de développement par l'auteur de cette version. Ces améliorations impliquent des modifications dans les objets principaux du projet.

4.1. Edition de contenu et granularité des primitives d'édition

Carence : L'édition du contenu d'un module est en mode "tout ou rien". L'utilisateur possédant le rôle d'administrateur accède à toutes les fonctions (insertion, édition, suppression). Les autres utilisateurs ne possédant pas ce droit d'administration n'ont accès à aucune fonction d'édition de contenu. Il serait intéressant de dégrader cet accès en édition pour offrir par exemple un accès "opérateur de suppression" ou encore "modérateur"...

Solution proposée : Une table énumère les différentes actions possibles en mode édition (insertion, édition, suppression, modération). Les rôles sont associés avec les éléments de cette table. Le problème majeur de cette solution est de ne pas définir de droits relatifs aux modules. Par exemple l'opérateur de suppression devient opérateur de suppression pour tous les modules.

4.2. Validation de la publication : modérateur

Carence : Actuellement en mode administration de contenu, les données insérées/modifiées sont immédiatement publiées. Il est uniquement possible de modérer un module via la consultation régulière et la suppression d'un élément indésirable. Cependant un élément indésirable peut être potentiellement consulté avant d'avoir été supprimé.

Solution proposée : Ce besoin n'est pas vraiment une exigence pour tous les modules. En conséquence, une extension des fonctions métiers des modules concernés règlent ce problème. Par exemple pour les discussions, l'ajout d'un nouveau champ (Approuved) de type booléan permet de vérifier si l'élément peut être publié. La valeur de ce champ est fixée à FALSE à l'insertion. Un bouton permet de basculer l'état de ce champ à Vrai (Approuved). Ce bouton est uniquement disponible pour les utilisateurs possédant le rôle de "modérateur". Une extension à cette solution est de stocker l'historique des modifications d'un élément. Ceci permet de suivre les différentes interventions faites par les différents opérateurs sur un élément.

4.3. Portail Multilingue

Carence : Le portail ne propose pas le choix de la langue de publication des informations. La structure des tables et de la configuration n'anticipe pas cette fonctionnalité de globalisation.

Solution proposée : Cette fonctionnalité est implémentée au niveau du module. Le module générique dont hérite les modules, implémente cette fonctionnalité. Un attribut supplémentaire permet de définir la langue dans laquelle est disponible l'information. Ce choix d'un langage parmis les langages disponibles est proposé par le module générique à l'utilisateur et à l'administrateur de contenu. Le changement de langue d'un module doit être propagé à l'ensemble des modules de la page en cours. Ceci est effectué par une variable de session qui stocke les préférences utilisateur.

4.4. Personnalisation de la charte graphique

Carence : Une fonctionnalité standard dans les "portails Internet modernes" est la personnalisation de la charte graphique (skins). Dans le projet Delphi ASP.NET Portal Starter Kit seule une feuille de style (ASPNETPortal.css) permet de modifier l'aspect général du portail. Il serait intéressant d'ajouter une fonctionnalité de personnalisation graphique.

Solution proposée : La factorisation d'un module en plusieurs parties (entête, pied de page, bordure) résout en grande partie ce problème. Ces nouvelles parties communes à tous les modules sont sélectionnées parmi une liste composée d'éléments de styles différents. Ces différents styles sont obtenus via l'association à des feuilles de styles distinctes et/ou via une personnalisation du style HTML de l'élément factorisé.

4.5. Arborescences et onglets (tabs)

Carence : L'arborescence du site associée à des onglets est limitée. C'est une simple liste. Il n'est pas possible de hierarchiser un élément de façon à avoir un sous-menu.

Solution proposée : Pour obtenir un arborescence plus hierarchisée, le système offre le choix du contrôle permettant la sélection de la page en cours. Les différents choix pour ce contrôle sont : onglets ou menu. Le choix d'une arborescence de type menu entraine une modification de la structure du fichier de configuration du site (PortalCfg.xml). Une liste de listes à n niveaux permet de proposer une arborescence de type simple (onglets) ou complexe (menu). Associé à cette nouvelle structure, un contrôle utilisateur ASP.NET doit offrir une interface utilisateur de type correspondant (Menu).

4.6. Modules supplémentaires

Carence : Actuellement certaines fonctionnalités classiques ne sont pas implémentées. Par exemple, un module recherche n'est pas proposé. De même, un module "lettre d'informations" serait le bienvenu. L'implémentation actuelle du portail ne traite pas l'aspect courrier électronique...

Solution proposée : L'implémentation d'un module de recherche est assez complexe car cette recherche doit être limitée au contenu du portail autorisé à l'utilisateur (AccessRoles) effectuant cette recherche. Ainsi la recherche est dépendante de la configuration du portail associé à l'utilisateur en cours. C'est la configuration qui donne le référentiel de recherche. Rechercher sur les modules de type "annonce, documents ou autre" semble être un critère supplémentaire intéressant pour restreindre la recherche. La recherche sur les documents (doc, xls...) suppose l'utilisation d'un moteur de recherche permettant la recherche fulltext dans des formats variés. Microsoft Index Server est indiqué pour ce type d'exigence.

4.7. Modules pluggables de Dot Nuke Net et Interfaces

Les fonctionnalités d'un module ne sont pas forcément nécessaires à tous les modules. Par exemple, la fonction de recherche est inutile pour une image. Ce constat est appréhendé dans Dot Nuke Net (DNN) via les interfaces. Les nouvelles fonctions associées aux portails sont déclarées et implémentées via des interfaces. Seul le moteur (page) est éventuellement modifié pour prendre en charge ces nouvelles fonctionnalités. Par exemple l'interface "ISearchable" est utilisée pour invoquer une recherche sur les modules l'implémentant. Cette figure de style conceptuelle (design pattern) correspond au "décorator" ou "wrapper". Dans le cadre de l'évolution du produit ce modèle de conception sera utilisé.

5. Conclusion

Le projet Delphi ASP.NET Portal Starter Kit est un projet important de part sa taille. C'est un excellent exemple pour découvrir la technologie du futur que constitue Microsoft ASP.NET. Les différents points forts de cette technologie sont inclus dans ce projet. La partie Mobile permet d'imaginer des applications Internet jusque là difficiles à réaliser avec Delphi. Outre ce coté pédagogique, ce projet permet de réaliser simplement un portail Internet. Un produit réellement professionnel est largement envisageable moyennant quelques jours de développement afin de compléter cette solution séduisante.

6. Références

6.1. Microsoft ASP.NET

6.2. Delphi ASP.NET Portal Starter Kit

6.3. Autres projets de portail Internet

7. Remerciements

L'auteur du projet Delphi ASP.NET Portal Starter Kit, remercie très sincérement Norbert Saint Georges pour son soutien concernant ce projet Delphi ainsi que pour l'hébergement de la démonstration du projet gracieusement offert sur Delphinaute.be.

Merci également à Bestiol pour la relecture de cet article.