X. Quelques astuces▲
X-A. utiliser des tables maîtres/détails avec DatasetTableProducer▲
Une petite astuce toute bête que j'ai trouvée en retravaillant mon moteur de recherche NgScan et qui peut rendre de grands services.
Quand on utilise des Pageproducer orientés données, un des problèmes que l'on rencontre, lorsque l'on utilise des tables, est la difficulté d'afficher des champs provenant de tables détails. On peut utiliser des lookupfields, mais dans certaines circonstances ce n'est pas indiqué.
Pour s'affranchir de cette contrainte, il suffit de surcharger la propriété 'custom' de la colonne du DatasetTableProducer. En effet, cette propriété surcharge les paramètres de la balise <TD>. Elle agit ainsi : <TD custom>. Il nous suffit donc de commencer la chaîne custom par le caractère > pour fermer la balise et d'ajouter ensuite n'importe quel champ d'une table détail. Le code exemple :
Columns[0
].Custom := '><FONT SIZE=-1><A HREF="/ng/ngscan.dll/images/basket?id='
+ TDetail.FieldByName('p_key'
).AsString + '" target="droite">'
+ '<IMG SRC="/ng/images/bask.gif" border=0></A'
;
// Ne pas mettre le >, c'est le producteur de page qui s'en charge
X-B. Pour rediriger une page▲
Response.SendRedirect(MonNouvelURL);
X-C. Qui envoie la requête ?▲
Si vous voulez avoir des informations sur qui envoie la requête, regardez les propriétés RemoteAddret UserAgent de TwebRequest.
X-D. champ Memo▲
Si le Tag d'un PageProducer est à remplacer par un champ Memo, faites :
ReplaceText := Field.AsString
X-E. Récupérer la valeur d'un Checkbox▲
Si vous voulez récupérer la valeur d'un Checkbox :
if
Request.ContentFields.IndexOfName('CBox'
) <> -1
X-F. Renvoyer un fichier en téléchargement▲
Si vous voulez renvoyer un fichier en téléchargement, rajoutez cette info afin que le nom du fichier apparaisse dans la boîte de dialogue :
Response.SetCustomHeader('Content-Disposition'
, 'filename='
+LeNomDuFichier);
X-G. Créer un splashscreen▲
Vous créez un fichier HTM d'attente (ex. TPageProducer)
procedure
TWebModule1.WebModule1SplashAction(Sender: TObject;
Request: TWebRequest; Response: TWebResponse; var
Handled: Boolean
);
var
I: Integer
;
S: string
;
begin
Response.SendResponse;
S := PPageProducer.Content;
Request.WriteString(S);
// Donner le temps de lire quoi :-)
for
I := 1
to
3
do
Sleep(3000
);
// On envoie la page finale
Request.WriteString('<META HTTP-EQUIV="refresh" CONTENT="0; URL=http://www.ornella.com">'
);
end
;
X-H. S'assurer de poster dans une table avec clé primaire sans concurrence grâce aux criticalsections▲
Un exemple d'intégration d'enregistrements dans un SGBD client/serveur à partir d'une ISAPI.
Il s'agissait en fait d'évaluer les cours par des étudiants d'une école. Plusieurs cours (une vingtaine d'étudiants) ont été utilisés pour remplir un questionnaire (7 questions par cours, 1 champ de remarque libre et 27 cours + 4 champs de remarques libres) et chaque réponse était inscrite dans une table de Mssql7.
Le problème était évidemment d'éviter les erreurs lors de l'attribution de clés primaires. Une première version, basée sur une p_key auto-incrémentée par MsSQL n'arrivait pas à supprimer les concurrences dans l'attribution des clés primaires: deux utilisateurs arrivaient parfois à s'attribuer la même clé.
La solution a été de :
- créer une table des nouveaux enregistrements, et pour la p_key des réponses et pour celle des remarques ;
- protéger l'attribution de cette clé primaire par un « criticalsection » (merci JJM pour la suggestion :-)))
Dans l'unité du Webmodule, il suffit d'intégrer au fond de cette unit, avant le dernier end.
var
FLock: TCriticalSection;
initialization
if
not
Assigned(fLock) then
fLock := TCriticalSection.Create;
finalization
fLock.Free;
end
.
Puis dans le OnNewRecord de chaque table, la valeur id_newrec+1 de la table des enregistrements est attribuée au nouvel enregistrement en « l'entourant » d'un criticalsection :
procedure
TWebEvalM.ReponsesNewRecord(DataSet: TDataSet);
begin
try
FLock.Enter;
NewRec.Open;
NewRec.Edit;
Reponses.FieldByName('ClefRéponse'
).AsInteger := NewRec.FieldByName('id_newRec'
).AsInteger + 1
;
NewRec.FieldByName('id_NewRec'
).AsInteger := Reponses.FieldByName('ClefRéponse'
).AsInteger;
NewRec.Post;
NewRec.Close;
finally
FLock.Release;
end
;
end
;
14 822 enregistrements insérés en 1h30 sans aucun message d'erreur, avant, c'était « presque » la cata :-)
X-I. Afficher un MessageBox dans une ISAPI▲
MessageBox(0
,PChar(sDialogCaption), PChar(sDialogMessage),
MB_SERVICE_NOTIFICATION or
MB_TOPMOST);
À noter que cette boîte de dialogue s'affichera sur le serveur, non le client.
X-J. Désactiver le cache du browser▲
Rajouter avant d'envoyer la réponse :
Response.Expires := -1
;
Response.CustomHeaders.Values['Cache-Control'
] := 'no-cache'
;
Response.CustomHeaders.Values['Pragma'
] := 'no-cache'
;