WebStencils
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.
Sommaire
- 1 Syntaxe de WebStencil
- 2 Utilisation de variables de modules
- 3 Mots clés de WebStencil
- 4 Modèles WebStencils : disposition et corps
- 5 Composants de WebStencils
- 6 Intégration automatique de sessions
- 7 Liste blanche de sécurité
- 8 Utilisation de WebStencils avec RAD Server
- 9 Voir aussi
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.
@\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
@defaultest 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 :
|
@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 :
|
@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
@ExtraHeaderdé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.
- Les blocs
- @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
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 :
Truelorsqu'utilisé pour remplacer une liste blanche existante, ouFalsepour 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 :
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);