WebStencils

De RAD Studio
Aller à : navigation, rechercher

WebStencils, un système d'intégration et de traitement côté serveur des fichiers HTML, a été introduit dans RAD Studio version 12.2 pour les technologies WebBroker et RAD Server. Cette fonctionnalité flexible permet aux développeurs de concevoir des sites web modernes basés sur n'importe quelle bibliothèque JavaScript tout en exploitant les données extraites et traitées par une application serveur RAD Studio. Cette technologie offre une grande flexibilité pour créer des sites web adaptés à vos besoins spécifiques.

WebStencils a pour objectif de faciliter la création de sites de navigation par l'adoption des technologies Web (WebBroker, DataSnap, RAD Server) en fournissant des scripts côté serveur. Il est ainsi possible de générer des pages HTML avec des outils standard et d'utiliser n'importe quelle bibliothèque CSS et JavaScript tout en ajoutant des données à partir des pages générées depuis l'application (il peut s'agir par exemple du résultat d'une requête de base de données).

De plus, WebStencils constitue une excellente base pour le développement Web avec HTMX. Les pages HTMX bénéficient de la génération de code côté serveur et peuvent se connecter à des serveurs REST pour la mise à jour du contenu. Les technologies Web de Delphi offrent des fonctionnalités de génération de page et d'API REST de très haut niveau.

Syntaxe de WebStencil

Le langage de script de WebStencils repose sur deux éléments et est relativement simple :

  • Le @
  • Les accolades { }

Utilisation du symbole @

WebStencils utilise le symbole @ comme marqueur spécial plutôt que des balises HTML/XML ou d'autres notations. Le symbole @ est suivi par :

  • Le nom d'un objet ou d'un champ.
  • Un mot clé spécial.
  • Un autre symbole @.
    Conseil: L'utilisation du symbole @ est plus souple. Ainsi, vous n'aurez pas besoin de le doubler dans certaines situations, comme dans les en-têtes.

L'accès général à une valeur est basé sur une notation par point, sous la forme object.value. C'est pourquoi vous observerez des balises comme :

@object.value

Le nom de l'objet est un nom symbolique local qui peut correspondre à un objet réel d'une application serveur, assigné à l'exécution du script via un processus de recensement. Il peut aussi être résolu dans le code lors du traitement d'un gestionnaire d'événement OnGetValue.

La valeur est composée du nom de la propriété (pour un objet générique), du nom d'un champ (si l'objet hérite de TDataSet), et d'une chaîne qui est transmise dans le gestionnaire d'événement OnGetValue associé au processeur.

Remarque: La sortie des valeurs traitées par WebStencils est chiffrée avec la méthode TNetEncoding.HTML.Encode. Vous pouvez supprimer le chiffrement en utilisant la syntaxe @\value.

Accès aux ensembles de données et objets imbriqués

Vous pouvez aussi utiliser le symbole @ pour accéder à des ensembles de données et des objets imbriqués en utilisant la syntaxe suggérée dans les scénarios suivants :

  • Objets et classes imbriqués :
    @MyObject.SubObject.ProperyName
    
  • Tables dans les ensembles de données imbriqués :
    @MyDataSet.DataSetField.SubField
    

Utilisation des accolades pour les blocs {}

La seconde notation utilise des accolades, { et }, pour indiquer les blocs conditionnels ou répétés.

Toute autre utilisation des accolades dans le fichier de code source (le fichier HTML) est ignorée. En d'autres termes, les accolades ne sont traitées que si elles sont utilisées après une instruction conditionnelle WebStencils spécifique.

Accès à des valeurs avec la notation par point

Prenons en exemple l'extrait de code HTML WebStencils ci-dessous :

<h2>GetValue</h2>
<p>Value obtained from data: @data.name</p>
<p>Value obtained with request @@data.value: @data.value</p>

Les symboles @@ sont ignorés (nous attendons un seul @ en sortie), tandis qu'un seul déclenche le traitement. Notez également que les deux symboles, le nom d'objet et le nom de valeur, doivent être des identificateurs Delphi valides et ne peuvent pas contenir d'espaces ni commencer par un chiffre. Un nom peut contenir des caractères de soulignement et des chiffres.

Gestionnaire d'événement OnValue

Il est possible de fournir des données en utilisant un composant avec le gestionnaire d'événement OnValue. Par exemple :</br>

Delphi :

procedure TWebModule13.WebStencilsValueFromEventValue(Sender: TObject;
  const ObjectName, FieldName: string; var ReplaceText: string; 
  var Handled: Boolean)
begin
  if SameText (ObjectName, 'data') then
  begin
    Handled := True;
    ReplaceText := 'You requested ' + FieldName;
  end;
end;

Dans le code exemple ci-dessus, le code vérifie uniquement le nom d'objet (la première partie du symbole avant le point), mais il est recommandé de vérifier également la propriété FieldName (le symbole après le point).

C++ :

void __fastcall TWebModule13::WebStencilsValueFromEventValue(TObject *Sender,
  const String ObjectName, const String FieldName, String &ReplaceText, bool &Handled)
{
  if (SameText(ObjectName, "data"))
  {
    Handled = true;
    ReplaceText = "You requested " + FieldName;
  }
}

Dans l'exemple ci-dessus, String est une chaîne UnicodeString compatible Delphi dans C++ Builder. SameText est une fonction de comparaison de chaîne insensible à la casse fournie par SysUtils. Enfin, {code|&ReplaceText}} et &Handled sont transmis par référence pour pouvoir être modifiées et reproduire le comportement var de Delphi.

Utilisation d'un objet dans le dictionnaire de variables de script

Une autre approche consiste à fournir les valeurs en utilisant un objet. Dans ce cas, l'objet doit être configuré et associé à l'action du producteur.

Voici un exemple complet, supposant une classe TMyObject et sa propriété Name :</br>

Delphi :

procedure TWebModule1.WebModule1WebActionItem2Action(Sender: TObject;
  Request: TWebRequest; Response: TWebResponse; var Handled: Boolean);
begin
  WebStencilsProcessor1.InputLines.Text := '''
    <h2>GetValue</h2>
    <p>Value obtained from data: @world.Name</p>
  ''';
  var MyObj := TMyObject.Create();
  MyObj.Name := 'Hello hello';
  WebStencilsProcessor1.AddVar('world', MyObj, True);
  Response.Content := WebStencilsProcessor1.Content;
  Handled := True;
end;

Cet exemple donne le résultat suivant :

"Value obtained from data: Hello Hello"

Notez que l'objet est recensé avec le nom 'world', qui sera ensuite utilisé dans le script WebStencils.

C++ :

void __fastcall TWebModule1::WebModule1WebActionItem2Action(TObject *Sender,
  TWebRequest *Request, TWebResponse *Response, bool &Handled)
{
  WebStencilsProcessor1->InputLines->Text =
    "<h2>GetValue</h2>\n"
    "<p>Value obtained from data: @world.Name</p>";

  TMyObject *MyObj = new TMyObject();
  MyObj->Name = "Hello hello";

  WebStencilsProcessor1->AddVar("world", MyObj, true);

  Response->Content = WebStencilsProcessor1->Content;
  Handled = true;
}

Expressions

Voici la liste des expressions prises en charge :

  • @ (<expression>) - marqueurs de variable. L'expression doit être écrite entre parenthèses.
  • @if (<expression>) - commande "if". L'expression doit être écrite entre parenthèses.
  • @Import (<expression>), @LayoutPage (<expression>), @AddPage (<expression>) - commandes de fichier. L'expression doit être écrite entre accolades.

L'exemple suivant montre uniquement les différences entre les options ci-dessus :

WebStencilsProcessor1.InputLines.Text := '''
    <h2>GetExpression</h2>
    <p>Value obtained from data: @(world.value*2)</p>
  ''';
  MyObj.Value := 2;

Vous obtenez alors la sortie suivante :

"Value obtained from data: 4"

En plus des expressions simples, vous pouvez étendre le système en utilisant des appels de fonction personnalisés. Voici un exemple de code qui recense une fonction “Concat” recevant deux paramètres chaîne :</br>

Delphi :

uses
  System.Bindings.EvalProtocol, System.Bindings.Methods;

  TBindingMethodsFactory.RegisterMethod(
   TMethodDescription.Create(
    MakeInvokable(function(Args: TArray<IValue>): IValue
    begin
     Result := TValueWrapper.Create(
      Args[0].GetValue.AsString + Args[1].GetValue.AsString);
    end),
    'Concat', 'Concat', '', True, '', nil));

Dans un script WebStencils, vous pouvez l'utiliser dans une expression comme :

@(Concat('aaa', 'bbb']]

C++ :

#include <System.Bindings.EvalProtocol.hpp>
#include <System.Bindings.Methods.hpp>
#include <System.Rtti.hpp>
#include <System.SysUtils.hpp>

using namespace System::Bindings::EvalProtocol;
using namespace System::Bindings::Methods;
using namespace System::Rtti;

class TValueWrapper : public TInterfacedObject, public IValue
{
private:
    TValue FValue;

public:
    __fastcall TValueWrapper(const TValue &AValue) : FValue(AValue) {}

    virtual TValue __fastcall GetValue() { return FValue; }

    // Implement other IValue methods as needed...
};

void RegisterCustomBindingMethod()
{
    TBindingMethodsFactory::RegisterMethod(
        new TMethodDescription(
            MakeInvokable([](const TArray<IValue*> &Args) -> IValue*
            {
                String s1 = Args[0]->GetValue().ToString();
                String s2 = Args[1]->GetValue().ToString();
                return new TValueWrapper(TValue::From<String>(s1 + s2));
            }),
            "Concat", "Concat", "", true, "", nullptr));
}


Instruction Switch

En plus de l'instruction @if, les utilisateurs peuvent choisir d'utiliser les instructions @switch ou @case.</br>

Voici un exemple de syntaxe :

@switch(@user.role) {
  @case "admin" { 
    <div>Admin Panel</div>
  } @case "moderator" { 
    <div>Moderator Tools</div>
  } @default { 
    <div>Regular User View</div>
  }
}

A partir de l'exemple ci-dessus, notez que :

  • Les valeurs des "case" peuvent être des littéraux ou des expressions utilisant @(expression).
  • Seul le premier "case" correspondant est exécuté.
  • L'utilisation de @default est facultative et s'exécute s'il n'y a pas de correspondance avec "case"'.

Utilisation d'un ensemble de données

Une alternative consiste à utiliser l'enregistrement en cours d'un ensemble de données plutôt qu'un objet. Dans ce cas, votre code sera comme suit :</br>

Delphi :

procedure TWebModule13.WebModule13waCompanyAction(Sender: TObject;
    Request: TWebRequest; Response: TWebResponse;
    var Handled: Boolean];
  begin  
   ClientDataSet1.Open;
   if not WebStencilsValueFromObject.InVars  ('dataset'] then
    WebStencilsValueFromObject.AddVar(
      'dataset', ClientDataSet1, False]; // False = do not destroy
  Response.Content := WebStencilsValueFromObject.Content;
  ClientDataSet1.Close;
end;

C++ :

void __fastcall TWebModule13::WebModule13waCompanyAction(TObject *Sender,
  TWebRequest *Request, TWebResponse *Response, bool &Handled)
{
  ClientDataSet1->Open();

  if (!WebStencilsValueFromObject->InVars("dataset"))
  {
    WebStencilsValueFromObject->AddVar("dataset", ClientDataSet1, false); // false = do not destroy
  }

  Response->Content = WebStencilsValueFromObject->Content;

  ClientDataSet1->Close();
}

Le code HTML correspondant peut contenir des références à certains champs de l'enregistrement. Voici un exemple de résultat :

<div class="list-group w-50">
  @foreach dataset {
    <a href="/[email protected]" class="list-group-item  
        list-group-item-action" aria-current="true">
    <div class="d-flex w-100 justify-content-between">
      <h5 class="mb-1">@loop.company</h5>
      <small>@loop.country</small>
    </div>
    <p class="mb-1">@loop.city</p>
    <small>@loop.state</small>
  </a>
}

Accès aux propriétés de l'ensemble de données

La notation WebStencils @ relative à un ensemble de données permet d'accéder aux propriétés de l'ensemble de données, en plus de ses champs. Les utilisateurs peuvent utiliser @data.RecordCount pour accéder à la propriété RecordCount. En cas de conflit, les champs de l'ensemble de données ont priorité sur les propriétés portant le même nom.

Cela inclut l'accès aux informations des champs, comme suit :

@foreach field in customers.fields

Ainsi que l'accès aux propriétés des champs :

@foreach customer in customers {
    @customer.address.visible
    @customer.phone.displaylabel
}

Utilisation de variables de modules

Alternativement, pour recenser un objet spécifique pour un WebStencilsProcessor, vous pouvez ajouter un “module” avec plusieurs objets. Dans ce contexte, un 'module' est une collection d'objets ou de fonctions liés entre eux. N'importe quel champ ou n'importe quelle propriété du module peut être décoré avec l'attribut [WebStencilsVar], qui vous permet de spécifier comment le WebStencilsProcessor doit traiter les données.

Par exemple, supposons que votre module de données a un composant FDMemTable1 de type TFDMemTable marqué comme [WebStencilsVar], et un champ LastName, vous pouvez écrire :

  WebStencilsProcessor1.InputLines.Text := '''
    <h2>GetTableData</h2>
    <p>Value obtained from table: @(FDMemTable1.LastName)</p>
  ''';
  WebStencilsProcessor1.AddModule(self);

L'exemple ci-dessous renvoie la valeur de LastName dans le premier enregistrement. Utilisez une boucle @for pour afficher tous les enregistrements.

Utilisation de variables supplémentaires

Ajoutez des variables supplémentaires au moteur de script à l'extérieur des modèles d'objet et d'ensemble de données. Plutôt que d'ajouter une structure de données spécifique, ce mécanisme propose une méthode anonyme qui permet d'implémenter une recherche personnalisée dans une structure de données personnalisée. Il s'agit des méthodes suivantes :

TWebStencilsDataVars.Add(LookupFunc), AddInitFunc(LookupFunc)
TWebStencilsProcessor.AddVar(LookupFunc), AddInitFunc(LookupFunc)
TWebStencilsEngine.AddVar(LookupFunc), AddInitFunc(LookupFunc)

Voici un exemple :

type
  TMap = TDictionary<string, string>;
var
  LDict: TMap;
begin
  LDict := TMap.Create;
  LDict.Add('APP_VERSION', '1.0.0');
  LDict.Add('APP_NAME', 'WebStencils demo');
  LDict.Add('COMPANY_NAME', 'Embarcadero Inc.');
  LDict.Add('DEBUG_MODE', 'True');

  FWebStencilsProcessor.AddVar('env', LDict, True,
    function(AVar: TWebStencilsDataVar; const APropName: string; 
      var AValue: string): Boolean
    begin
      Result := TMap(AVar.TheObject).TryGetValue(APropName.ToUpper, AValue);
    end);

Vous pouvez aussi l'utiliser dans un modèle, comme suit :

 @env.APP_NAME - @env.APP_VERSION
 @if env.DEBUG_MODE {
   <div>Debug mode active</div>
 }

Mots clés de WebStencil

Le moteur WebStencils utilise les balises suivantes sous forme de mots clés (notez que ces noms ne peuvent pas être utilisés pour des variables de script).

Mot clé Description
@query Utilisé pour lire des paramètres de requête HTTP.
@page Fournit l'accès au nom de la page et aux arguments de l'URL (voir la propriété PathTemplate pour plus d'informations). Il est possible d'accéder au chemin de l'URL en utilisant l'une de ces valeurs :
  • @page.request_path
  • @page.request_segment
@lang Utilisé pour la prise en charge de la traduction, déclenche un événement OnLang distinct plutôt que l'événement OnValue.
@* .. *@ Utilisé pour ajouter des commentaires dans le script, qui seront omis dans le HTML résultant.
@if object.value { … } [@else { … }] Exécute le bloc suivant entre accolades uniquement si la valeur vaut true.
@if (<expression>) Utilisé pour restituer du contenu de façon conditionnelle. Si l'expression est évaluée à true, le contenu associé est inclus dans la sortie ; sinon il est omis.
@if not object.value { ... } [@else { … }] Exécute le bloc suivant entre accolades uniquement si la valeur ne vaut pas true.
Par exemple :
 @if obj1.ValueBelowTen {
	  <p>@obj1.name <span> has a value of </span> @obj1.value</p>
	}
@ForEach (var object in list) { … } Exécute le bloc entre accolades suivant aussi souvent qu'il y a d'éléments dans l'énumérateur.
Supporte actuellement :
  • Les ensembles de données
  • TObjectList, doit être ajouté au dictionnaire de processeur.
  • Tout objet possédant la méthode GetEnumerator, où l'énumérateur renvoie une valeur d'objet.
@ForEach object { … } Exécute le bloc entre accolades suivant aussi souvent qu'il y a d'éléments dans l'énumérateur.
Supporte actuellement les ensembles de données et TObjectList, qui doivent être ajoutés en tant que variables de script.
@loop Utilisez à l'intérieur d'un bloc pour faire référence à l'élément en cours de l'énumération (liste ou ensemble de données). Il doit être suivi du nom d'une propriété ou d'un champ sans utiliser de nom d'objet.
@Import Permet de fusionner un fichier externe à un emplacement spécifique du fichier externe. Suppose toutefois que le nom de fichier ait l'extension .HTML.
Le format doit être comme suit :
@import filename [ {<alias1> = <var1> [..., <aliasN> = <varN>]} ]
@Scaffolding Espace réservé pour le scaffolding. Ce mécanisme permet de générer dynamiquement du code HTML à partir de la structure de données d'une application (les propriétés d'un objet et les champs d'une base de données). Le code HTML généré côté serveur peut inclure d'autres balises pour accéder aux données.
Le code suivant est un exemple de disposition HTML simple générée dans le gestionnaire d'événement OnScaffolding pour chacun des champs de la base de données :
procedure TWebModule1.ProcessorCompanyScaffolding(Sender: TObject;
  const AQualifClassName: string; var AReplaceText: string);
begin
  if SameText (AQualifClassName, 'Company') then
  begin
    AReplaceText := '';
    for var I := 0 to ClientDataSet1.Fields.Count -1 do
      AReplaceText := AReplaceText + '<p>'+ 
        ClientDataSet1.Fields[I].FieldName +
        ': @dataset.' + ClientDataSet1.Fields[I].FieldName + '</p>';
  end;
end;
@switch, @case, et @default Effectue un rendu conditionnel à branches multiples. Après avoir évalué une expression, la met en correspondance avec les valeurs définies avec @case, en restituant le bloc correspondant. La directive @default est utilisée si aucune correspondance n'est trouvée pour @case.
@LoginRequired Arrête l'exécution si une connexion est requise alors que l'utilisateur n'est pas connecté.
@LoginRequired (<role>) Le moteur vérifie que l'utilisateur est connecté, mais aussi qu'il dispose du rôle spécifique actif, ce qui restreint l'accès à la page selon la permission.
Par exemple : @LoginRequired (admin)

Alias d'importation

L'exemple ci-dessous illustre comment utiliser des alias d'importation.

@import one {@o1 = @object, @d1 = @data} Hello

Dans ce code, @object et @data sont les véritables variables dans le script exécuté. Les alias @o1 et @d1 sont des variables de script pour le script "one" et sont accessibles dans ce script comme des variables normales. Ainsi, vous pouvez transmettre au script QA des variables portant des noms différents, en fournissant comme alias le nom attendu par le script.

Modèles WebStencils : disposition et corps

La capacité à fusionner un modèle HTML partagé avec le contenu d'une page compte parmi les fonctionnalités indispensables d'un moteur de modèle. Cette opération s'effectue (comme dans la version .NET) en utilisant quatre symboles spéciaux :

  • @LayoutPage filename : cette commande est utilisée dans une page HTML spécifique (généralement en haut de page) pour indiquer le fichier de modèle à utiliser comme structure de la page. Plusieurs pages peuvent partager un même modèle, mais toutes les pages d'un projet (même en utilisant TWebStencilsEngine) ou d'un dossier virtuel n'ont pas nécessairement besoin d'utiliser le même modèle.
Remarque: Cette commande ne doit être utilisée qu'une seule fois par page. Si vous tentez d'utiliser plusieurs fois @LayoutPage, une exception se déclenche et bloque la commande.
  • @RenderBody : cette commande sans paramètre est une marque de réservation dans un fichier de modèle qui indique où placer le contenu d'une page spécifique.

Voici un exemple d'utilisation de @LayoutPage et de @RenderBody :

Test.html

@LayoutPage BaseTemplate
   <h2>Page Test3</h2>
   <p>Local data param one is @page.name (the page name)</p>

BaseTemplate.html

<html lang="en">
  <head>
    <!-- Bootstrap CSS 
    <link href="https://.../bootstrap.min.css" rel="stylesheet">
  </head>
  <body>
    <nav class="navbar navbar-expand-md bg-dark mb-4">...
    <main class="container">
      <div class="bg-light p-5 rounded">
      @RenderBody
      </div>
    </main>
  </body>
</html>


De plus, vous pouvez injecter des en-têtes supplémentaires du document spécifié vers le modèle (par exemple, un fichier JavaScript requis à inclure dans la page ou le CSS supplémentaire d'une page spécifique). Dans ce cas, le mécanisme est inversé :

  • @ExtraHeader { ... } : Utilisé dans la page HTML spécifique pour indiquer un bloc de code à ajouter en tant qu'information d'en-tête supplémentaire.</br>Il supporte aussi la propagation de contenu sur l'ensemble des hiérarchies de disposition imbriquées :
    • Les blocs @ExtraHeader définis dans les pages se propagent automatiquement à travers plusieurs niveaux de disposition.
    • Le contenu est injecté dans la sortie finale quelles que soient les dispositions intermédiaires.
    • Permet une composition de disposition flexible, avec des dispositions de base, intermédiaires et spécifiques à la page.
  • @RenderHeader : indique à quel emplacement du fichier de modèle (généralement dans la section d'en-tête HTML) ajouter l'en-tête supplémentaire de la page, si disponible
Remarque: Les deux options sont facultatives.

Exemple:

<!-- page.html -->
@extends layouts/intermediate
@ExtraHeader {
  <style>.highlight { color: green; }</style>
}

<!-- layouts/intermediate.html -->
@extends layouts/base
@ExtraHeader {
  <meta name="viewport" content="width=device-width, initial-scale=1">
}

<!-- layouts/base.html -->
<head>
  @RenderHeader
</head>

Dans l'exemple ci-dessus, le CSS de page.html et la balise meta de intermediate.html sont injectés dans la sortie finale de @RenderHeader.

Composants de WebStencils

Le package WebStencils installe deux composants différents : un processeur de fichier unique et un moteur qui instancie des processeurs individuels et fournit une configuration globale pour les processeurs autonomes ou ceux auxquels ils sont manuellement connectés.

Le composant principal prend un fichier HTML, incorpore la notation WebStencils et le convertit en HTML brut après avoir traité les balises @.

La classe TWebStencilsProcessor traite un fichier individuel (généralement ayant une extension HTML) et son modèle associé, le cas échéant. Le processeur peut être utilisé de façon autonome et assigné au TWebActionItem.Producer, ou être créé et appelé par TWebStencilsEngine en tant que post-processeur de fichiers texte renvoyés par un répartiteur de fichiers.

Composant WebStencilsEngine

Le composant Engine peut être utilisé dans les deux scénarios suivants :

  • Pour le connecter à un ou plusieurs composants WebStencilsProcessor et fournir des comportements et des paramètres partagés.
  • Pour créer des composants WebStencilsProcessor lorsque cela est nécessaire, et placer uniquement ce composant sur vos modules web.

Intégration automatique de sessions

Lorsqu'elles sont disponibles, WebStencils peut automatiquement s'intégrer à des sessions web. Aucune configuration supplémentaire n'est nécessaire. Tout se fait automatiquement dès lors que WebRequest.Sessions existe.

Les données des sessions sont accessibles via @session.property. Tous les objets dans WebRequest.Session.DataVars sont automatiquement recensés en tant que variables de modèles. De même, UserLoggedIn et UserRoles sont automatiquement remplis à partir de WebRequest.Session.User.

En voici un exemple :

@if session.Authenticated { 
  <div>User authenticated</div>
  @session.sessionid
}

@if session.UserHasRole(‘admin’) { 
  <div>User is an Admin</div>
}

Liste blanche de sécurité

Pour des raisons de sécurité, WebStencils implémente un mécanisme de liste blanche de propriétés pour éviter l'exposition d'informations sensibles comme les chaînes de connexion aux bases de données. Par défaut, seules les propriétés sécurisées sont accessibles. Voici la liste des propriétés sécurisées :

  • Pour les TDataSet : Active, FieldByName, First, Last, Next, Prior, Bof, Eof, FieldCount, Fields, Found, RecordCount, RecNo.
  • Pour les TStrings : Contains, ContainsName, IndexOf, IndexOfName, CommaText, Count, IsEmpty, DelimitedText, Names, KeyNames, Values, ValueFromIndex, Strings, Text.

Personnalisation de la liste blanche

La liste blanche peut être personnalisée en utilisant la propriété TWebStencilsProcessor.Whitelist. La méthode de configuration permet aux utilisateurs de spécifier les membres autorisés et ceux bloqués. Voir l'exemple ci-dessous :

procedure Configure(const AClass: <PTypeInfo, TClass, TObject>; 
                    const AAllowedMembers: TArray<string>;
                    const ABlockedMembers: TArray<string>; 
                    AReset: Boolean);
  • AClass : le type PTypeInfo/TClass/TObject pour configurer des éléments tels que des TDataSet, TStrings.
  • AAllowedMembers : un tableau de propriétés ou de noms de méthodes que l'utilisateur souhaite autoriser.
  • AAllowedMembers : un tableau de propriétés ou de noms de méthodes que l'utilisateur souhaite autoriser.
  • AReset :True lorsqu'utilisé pour remplacer une liste blanche existante, ou False pour l'ajouter à la liste.

Voici un exemple qui illustre comment ajouter des membres autorisés supplémentaires à une liste blanche existante :

TWebStencilsProcessor.Whitelist.Configure(TMyClass, 
  ['CustomProp'], nil, False);

Voici un exemple qui illustre comment remplacer la totalité d'une liste blanche (AReset = True) :

TWebStencilsProcessor.Whitelist.Configure(TDataSet, 
  ['RecordCount', 'RecNo'], nil, True);

Voici un exemple qui illustre comment bloquer certains membres :

TWebStencilsProcessor.Whitelist.Configure(MyObject, 
  nil, ['CustomProp'], False);

La liste blanche s'applique à l'ensemble de l'application et à tous les WebStencils.

Utilisation de WebStencils avec RAD Server

La bibliothèque de modèles WebStencils peut aussi être utilisée dans une application RAD Server. Il est recommandé de combiner le composant TEMSFileResource' existant avec un composant TWebStencilsEngine. Le premier permet de mapper le système de fichiers, alors que le second gère le mappage HTTP et le traitement des modèles. Les composants sont connectés en utilisant la propriété Dispatcher du moteur WebStencil.

L'exemple ci-dessous illustre la configuration nécessaire pour ajouter deux composants à un module web RAD Server :

 object html: TEMSFileResource
    PathTemplate = '..\..\html\{filename}'
  end
  object WebStencilsEngine1: TWebStencilsEngine
    Dispatcher = html
    PathTemplates = <
      item
        Template = '/'
        Redirect = '/test1.html'
      end
      item
        Template = '/list'
        Redirect = '/companylist.html'
      end
      item
        Template = '/company'
        OnPathInit = WebStencilsEngine1PathTemplates2PathInit
      end
      ...>
  end

Les PathTemplates sont utilisés pour mapper les URL entrantes à des fichiers. En mode conception, la configuration se présente comme suit :

=link

En plus, il est nécessaire de configurer le mappage de plus haut niveau dans le module de données :

type
  [ResourceName('testfile')]
  TTestfileResource1 = class(TDataModule)
    [ResourceSuffix('./')]
    [ResourceSuffix('get', './')]
    [EndpointProduce('get', 'text/html')]
    html: TEMSFileResource;

Pour mapper plusieurs chemins différents (à la différence de l'exemple ci-dessus, ajoutez des composants TEMSFileResource. Le composant TWebStencilsEngine peut comporter un seul dispatcher dans la propriété correspondante. Pour associer davantage de dispatchers, utilisez le code suivant :

AddProcessor(html2, WebStencilsEngine1);

Voir aussi