Académique Documents
Professionnel Documents
Culture Documents
DevWeb2
Démos
Document à destination des formateurs
DEVWEB2
EIDPDEVB
21/09/2015
Dé monstrations DevWeb2
1. DM 1.1 : Import d'une maquette MAQ
Préparation : Copier le fichier DemoMaq.sbproj présent à la racine de «DEVBFORMARTION_DEMO»
sur le bureau, et l'ouvrir.
NB : Il s'agit de la maquette initialement fournie par l'équipe ERGO, après adaptations pour l'import
DevBooster, mais avec l'ancienne version de MAQ et avant corrections. Elle ne correspond donc pas
totalement au projet sur lequel nous allons travailler par la suite.
Déroulement :
Activer les outils Développeur (menu Fichier/Options/Préférences/Outils de
développement)
Certaines pages ont été renommées en PascalCase anglais : elles seront à importer dans
DevBooster
D'autres pages sont restées en français : il s'agit des pages qui ont été dupliquées à des fins
d'animation, qui ne seront pas importées.
Parcourir les onglets Aperçu et code Xaml, Xml, C# (et DTO lorsqu'il sera disponible)
Montrer l'onglet propriétés : cliquer sur différents éléments de la page ; les propriétés
varient selon l'objet sélectionné, et il est possible de les modifier.
Elle illustre une lightbox de confirmation. Il s'agit d'une copie de BeneficiaryList, il ne faudra
pas l'importer. Idem pour les pages Ben1liste*, qui illustrent les messages utilisateurs.
Basculer sur la partie 3 Maquette
Fenêtre de gauche
Cliquer sur un bouton et montrer les propriétés de navigation dans l'onglet Propriétés. Il est
important de contrôler/rectifier ces informations avant l'import :
Montrer les propriétés de différents éléments d'une page de liste et de création (ex :
BeneficiaryList et BeneficiaryCreate)
Déroulement :
- indiquer un code application et code produit au choix (ex: DEMO et DEMOMAQ ; l'appli ne
sera pas réutilisée)
- dans la liste des pages à importer, décocher les 4 pages Ben1listexxx et valider
Dans LivePreview, activer la navigation et parcourir l'application pour montrer que tout
fonctionne dès l'import
(certains boutons sont inopérants, car les développements spécifiques restent à faire,
comme la LightBox ou l'affichage de documents PDF)
Dans l’éditeur de code XAML, masquer les e:Table pour ne pas surcharger l’affichage.
Valoriser également IsExpanded pour montrer qu’il est possible de définir l’état initial.
Montrer que l’ensemble du titre est cliquable (et pas seulement le bouton) pour éviter aux
utilisateurs de devoir viser le bouton.
Démonstration de e:Expander
Sur la page Demo_2_1_2_Expander montrer un e:Expander dans une cellule de donnée de la fiche.
<e:Expander IsExpanded="False">
<e:Expander.Header>
Titre de la valeur
</e:Expander.Header>
blabla
</e:Expander>
Valoriser dès le début IsExpanded à False. Préciser que cette propriété sera disponible sur tous les
composants capables de faire du plier/déplier.
Mettre un lien dans la zone de titre de e:Expander (avec un e:Link avec Href=http://www.e-i.com/).
Montrer que cela semble poser problème, car le clic sur le lien fait un plier/déplier au lieu de
naviguer normalement.
Note : Pour revenir à la page lorsque le site e-i.com est affiché dans LivePreview : Click droit, puis
« Précédent ».
Démonstration de ExpanderController
Revenir à la page Demo_2_1_3_TrRowGroup, rendre toutes les ruptures restantes pliables si ce n’est
pas déjà fait.
La démo s'inspire de la page TP5, avec juste un bouton de validation qui est une copie de la méthode
d'action DoCheckNone. Elle s'intitule Demo_2_2, une entrée dans le menu.xaml a été ajoutée dans
DEVBFORMARTION_DEMO.
L'objectif est d'ajouter des messages Utilisateurs à celui déjà en place, pour explorer les cas
courants.
Démonstration de RichWarning
Dupliquer le message déjà en place, et remplacer RichInfo par RichWarning
Messages.Add(UserMessage.RichWarning(I18N.Translate("Le groupe 'none' est validé")));
- Paramètres nommés (limite le risque de décalage entre les méthodes d'action et le Prepare)
- Paramètres optionnels (évite la multiplication des Prepare)
- IntelliSense (facilité de saisie : affichage de la description des données + contrôle visuel de
l'utilisation de toutes les propriétés)
Une page Demo_4_1 a été créée, avec une entrée dans le menu DEVBFORMARTION_DEMO.
Situation de départ : La page contient un bloc de quatre clés à saisir + bouton validation
(DoValidate), et un deuxième bloc avec seulement les deux premières clés (DoValidate2). Les deux
boutons naviguent vers la page Demo_4_1_Conf, qui contient une seule méthode Prepare recevant
quatre paramètres en entrée.
Revenez en arrière (ou cliquer sur Confirmer, dans ce cas il faudra refaire les saisies), et utiliser le
deuxième bouton. Cette fois le programme plante. Le Diagnostic montre qu'il faut créer un
deuxième step Prepare() pour le deuxième bouton.
Coder le deuxième Prepare() recevant deux paramètres. Cette fois cela fonctionne
Utilisation du DTO
Montrer le DTO Demo_4_1Keys : Les deux dernières propriétés portent l'attribut
[OptionalParameter]
Coder les deux méthodes d'action en utilisant le DTO ; montrer au passage que
l'IntelliSense propose les différentes propriétés du DTO, et élimine au fur et à mesure les
propriétés déjà codées.
Comme les objets sont nommés, cela limite les risques d'erreur, évite les décalages dans
l'ordre des paramètres.
Coder ensuite le Prepare() recevant le DTO.
Exécuter l'application. Cette fois les deux boutons fonctionnent avec un seul Prepare().
Clé Valeur
/devbooster.aspx?
_pid=Demo_4_1_Conf&k_Key1=1&k_Key2=2&k_Key3=3&k_Key4=4&_fid=DoConfirm&_contentita=
et%253dEmptyPag
Objectif : montrer qu'en cas d'erreur détectée dans une méthode d'action, la page est réaffichée et
la méthode Prepare() est ré-exécutée. Il faut donc être capable de reconstruire les données,
notamment celles qui figurent dans les DropDownList, et de restituer les données qui ont pu être
saisies par l'utilisateur.
Sur la première page, indiquer un montant de virement supérieur au solde, afin d'afficher la ligne de
décision sur la page de confirmation.
Sur la page de confirmation, confirmer sans cocher la case, ce qui provoquera une erreur dans
DoValidate().
Débuguer pas à pas pour constater que l'on retourne dans le Prepare() et que toutes les infos sont
reconstruites.
Expliquer qu'il est important de prévoir un mécanisme de restauration des données, sinon les
données qui ont été saisies sur la page seront perdues (ici il n'y a pas de saisie, mais la reconstruction
est possible grâce au ClientData).
6. DM 5.2 : Session/CacheObject
Session object
Afficher la pageSession object
Afficher la page
• montrer qu’au premier chargement, lorsque l’objet de session n’est pas trouvé, la méthode
init est appelée
• montrer qu’aux chargements suivants, init n’est plus appelé car l’objet est présent en session
• faire expirer la session (ajout de _newsession=true sur l’url) (taper directement l’url
http://localhost-ni.cm-cic.fr:8080/devbooster.aspx?
_pid=Demo_5_2_SessionObject&_contentita=et%253dEmptyPage&_newsession=true)
• observer qu’on repasse alors à nouveau dans la méthode Init
• que la session expire ou non, notre session object est donc bien restauré, sans erreur
d’expiration
CacheObject
Afficher la page
• montrer qu’au premier chargement, lorsque l’objet de cache n’est pas trouvé, la méthode
Load est appelée
• montrer qu’aux chargements suivants, Load n’est plus appelé car l’objet est présent en
Cache
• montrer que la quantité reste la même car issue du cache
• cliquer sur purger le cache
• montrer qu’on est repassé par Load et que la quantité a changé
7. DM 5.3 : AlmostPreparedObject
Si il y a le temps : montrer les urls (sans portail) et montrer que la clé est absente de l’url lorsqu’il y a
l’erreur, et présente lorsque l’on n’a plus d’erreur
8. DM 7.1 : Appel d'une activité externe
Etant donné que ce sont des entiers qui sont manipulés il faut redéfinir les clés de
l’activityStep « ComputeActivityStep » afin d’éviter de devoir réaliser des conversions. Pour
cela créer une classe DTO « ComputeKeys » avec les propriétés Operand1 et Operand2 de
type int :
[DTO]
public class ComputeKeys
{
[DTOKey("operand1")]
public int Operand1 { get; set; }
[DTOKey("operand2")]
public int Operand2 { get; set; }
}
Redéfinir les clés de « ComputeActivityStep » :
[Keys]
public new ComputeKeys Keys { get; set; }
Ajouter une nouvelle méthode Prepare dans la page « Demo_7_1» qui va recevoir le
paramètre ‘résultat’ ainsi que les opérandes afin de valoriser l’instance correctement
public void Prepare(int a, int b, string result)
{
Data.A = a;
Data.B = b;
Data.Result = result;
}
Exécuter l’application
Vérifier que l’activité est bien lancée en remplacement du contenu du portail
Vérifier que les paramètres sont bien retournés et que le résultat de l’opération est correct
Vérifier qu'en annulant l'opération, on revient bien à la page appelante
Pour cela il faut aller dans l’onglet pagination de la configuration du service « GetTransfersList dans
l’éditeur de configuration et lui ajouter :
<e:Pager CurrentPageExpr="Data/Pager/CurrentPage"
PageNavigation="GoPageNavigation"
TotalPageExpr="Data/Pager/TotalPages"
TargetPageParamName="targetPage" />
PageNavigation : action déclenchée lors d’une navigation vers un des éléments du Pager, la
soumission est utilisée ici afin de transmettre le type de compte sélectionné.
TotalPageExpr : chemin XPath vers le nombre total de page s’il est connu, -1 par défaut.
TargetPageParamName : nom du paramètre qui contiendra le numéro de la page cible lors d’une
navigation.
Il faut ensuite modifier TransferList : étant donné que cette dernière a maintenant deux clés (le type
de compte sélectionné et la page visée), on va simplifier leurs utilisations en déterminant un DTO.
[DTO]
public class TransferListParameters
{
[OptionalParameter]
public string SelectedAccountType { get; set; }
[OptionalParameter]
public int? TargetPage { get; set; }
}
public void Prepare(TransferListParameters parameters)
{
if (string.IsNullOrEmpty(parameters.SelectedAccountType))
{
Keys.SelectedAccountType = "All";
}
if (!parameters.TargetPage.HasValue)
{
Keys.TargetPage = 1;
}
...
Cela permet de s’assurer que les valeurs utilisées par la suite correspondront toujours à des valeurs
attendues.
[DefaultNextStep(target: typeof(TransferList))]
[Submission]
public NextStepId DoAccountType()
{
Keys.TargetPage = 1;
Keys.SelectedAccountType = Data.SelectedAccountType;
return NextStepId.Default(Keys);
}
La page visée est valorisée à 1 car la liste est réinitialisée lors du choix du type de compte : il n’est pas
utile de conserver la page 2 alors que le type de compte a changé.
[DefaultNextStep(target: typeof(TransferList))]
public NextStepId GoPageNavigation(int targetPage)
{
Keys.TargetPage = targetPage;
return NextStepId.Default(Keys);
}
Elle valorise juste la page visée, le type de compte étant conservé d’une page à l’autre du Pager.
public class Pagination : SessionObject
{
/// <summary>
/// Nombre de pages total
/// </summary>
public int MaxPage { get; set; }
/// <summary>
/// Liste des clés de suite (des ContinuationStructure)
/// </summary>
public List<ContinuationStructure> Continuation { get; set; }
/// <summary>
/// Initialisation de l'objet.
/// </summary>
/// <param name="involvedPartyId">identifiant de tiers qui servira de clé pour
récupérer cet objet.</param>
public void Init(string involvedPartyId)
{
MaxPage = -1;
Continuation = new List<ContinuationStructure>();
}
}
Il va service à stocker en session les informations nécessaire au bon fonctionnement du Pager.
Il faut ensuite modifier TransferList.
Ajouter un import sur IWebSessionObjects, c’est lui qui sera utilisé pour le stockage en session :
[Import]
public IWebSessionObjects SessionObjects { get; set; }
// Récupération des informations de pagination en session
var pagination = SessionObjects.GetOrInit<Pagination>(involvedParty.Id);
// Récupération des clés de suite en session
int currentPage = Keys.TargetPage.Value;
if (currentPage > 1)
{
}
int previousPage = currentPage - 1;
getTransfersList.FieldLocator.Continuation = pagination.Continuation[previousP
age - 1]);
// Mise à jour des clés de suite avec celle de la page
if (getTransfersList.HasNext)
{
if (pagination.Continuation.Count == currentPage - 1)
{
// Si la continuation de la page suivante n'est pas encore connue,
// on l'ajout à la liste
pagination.Continuation.Add(getTransfersList.FieldLocator.Continuation);
}
}
// Mise à jour du nombre total de pages
else
{
pagination.MaxPage = currentPage;
}
La propriété HasNext de type bool indique si le service n’a pas encore renvoyé toutes les données.
La dernière étape est d’enregistrer les informations de paginations en session et de valoriser les
données du Pager, à la fin de la méthode Prepare :
// Enregistrement des informations de pagination en session
SessionObjects.Set(pagination);
// Valorisation des propriétés du composant Pager
Data.Pager = new PagerVM
{
CurrentPage = currentPage,
TotalPages = pagination.MaxPage
};
Dans la méthode Prepare, au niveau de la récupération des clés de suite en session il ne faut
renseigner les informations de continuation au service que s'ils existent. Dans le cas contraire on va
afficher un message à l’utilisateur à revenir sur la première page.
// Récupération des clés de suite en session
int currentPage = Keys.TargetPage.Value;
if (currentPage > 1)
{
int previousPage = currentPage - 1;
if (pagination.Continuation.Count > previousPage - 1)
{
getTransfersList.FieldLocator.Continuation = new ContinuationStructure(pag
ination.Continuation[previousPage - 1].ToIData());
}
else
{
// Retour à la page 1, on a perdu les informations de la continuation
Messages.Add(UserMessage.RichWarning(I18N.Translate("La session a expiré."
)));
currentPage = 1;
Keys.TargetPage = currentPage;
}
}
Il est possible de tester cette modification en ajoutant « &_newsession=true » au lien récupéré via un
clic-droit sur la page 2 du pager.
Exécution :
myDocContainer.MailTo("mon_mail@e-i.com");
Présision : Le document en pièce jointe a été renommé avec la ligne de code suivante :
myDoc.Filename = "File.pdf";
Exécution :
Dire qu’on upload le fichier mais qu’on ne l’utilise que pour afficher son nom.
Exécution :
Access list
Dans le projet DEVBFORMATION_DEMO_OLD, ouvrir le fichier devbappli.config.
Indiquer les ressources obligatoires et optionnelles de l’application, ainsi que la liste d’accès
positionnée sur le PID Demo_10_10 et le FID DoSomethingRestricted.
Lancer l’application et naviguer vers le PID Démo 10.1 via le menu, puis cliquer sur le bouton
« suivant » : un message d’erreur indique que vous ne possédez pas les ressources nécessaires.
Utilisation basique
Dans la méthode PreparePID du fichier Demo_10_1.cs ajouter le code suivant, qui récupère la liste
des autorisations possédées parmi celles déclarées dans le fichier devbappli.config et teste
explicitement l’autorisation TAR3002G :
var authorizations = data.Append(new Data("authorizations"));
foreach (IData authorization in GiveMe.Session.GetAuthorizations())
{
authorizations.Append("authorization", authorization.Name.ToUpperInvariant());
}
bool hasTAR3002G = GiveMe.Session.GetAuthorization("TAR3002G");
data.Append("hasTAR3002G", hasTAR3002G.ToString());
Réactualiser la page Internet Explorer avec le l’application de démo : la liste des ressources testées
s’affichent.
Utilisation avancée
Dans la méthode PreparePID du fichier Demo_10_1.cs ajouter le code suivant, qui teste
explicitement les autorisations MVT2001G et TAR3003G :
IAuthorization myAuth = AuthorizationFactory.GetAuthorizationObject(GiveMe.Session
);
string furtherInfo1, furtherInfo2;
bool hasMVT2001G = myAuth.CheckAuthorization("MVT2001G", out furtherInfo1);
data.Append("hasMVT2001G", hasMVT2001G.ToString());
bool hasTAR3003G = myAuth.CheckAuthorization("TAR3003G", out furtherInfo2);
data.Append("hasTAR3003G", hasTAR3003G.ToString());
Réactualiser la page Internet Explorer avec le l’application de démo : la liste des ressources testées
s’affichent et comporte les informations des autorisations testées.
Il existe la possibilité de mettre un point d'arrêt conditionnel. Faire clic-droit sur le point d'arrêt =>
"Condition".
Exemple :
Le résultat ne sera pas le même entre la première et les deux dernières instructions. Mais le but de
cette démonstration est de donner un ordre d'idée de ce qu'on peut faire facilement.
Exemple :
id = id +1
Si cette ligne est exécutée dans la fenêtre Watch avant l'initialisation du service dans
TransferRepository.GetTransferInfos, on se retrouve avec un mauvais identifiant et dans la majorité
des cas, l'appel du service tombera en erreur.
Cette fonctionnalité peut être très utile pour essayer de reproduire un problème signalé en
production avec des données que l'on a du mal à obtenir en test.
En double cliquant sur une ligne de la pile, il est possible de remonter dans la pile d'appel est de
disposer de la valeur des différentes variables, membres ou propriété contextuelles de chacune des
lignes de la pile d'appel
Fenêtre Locals (uniquement en Debug)
La fenêtre Locals permet de disposer de toutes les variables locales d'une méthode.
Cette fenêtre permet également de modifier des variables en double cliquant sur leurs valeurs
Cette fenêtre peut rapidement devenir illisible s'il y a beaucoup de variables locales.
Trace
Lancer l’application de démo.
Activer la trace via la case à cocher dans le menu puis cliquer sur le menu « 11.2 Liste des comptes ».
Activer les différentes catégories / niveaux afin de détailler tout ce qu’il est possible de voir avec la
trace.
Aller sur PFTL NI puis dans la recherche DEVBOOSTER et faire une recherche sur son IP avec une
recherche approximative sur la description avec les mots « Démo 11.2 ».
MNTR / METROLOGIE
Aller sur MNTR et montrer les erreurs de Strasbourg SI (ou autre site approprié).
Chercher la ligne avec le plus grand nombre d’erreurs dans les rapports DEVB.
Déplier le module afin de montrer les informations disponibles des erreurs puis cliquer sur le nombre
d’erreurs afin de pouvoir les détailler sur PFTL.
Préparation : récupérer le cookie SSON du jour même, voir doc 0990021527 « Tester un Web Service
à l'aide de SoapU », paragraphe « Ajout du cookie SSON ».
Lancer SoapUI, cliquer sur File / New SOAP Project et renseigner l'url du wsdl :
Cliquer sur « OK » puis une fois le projet généré déplier l'arbre « calculus » jusqu'à « Request 1 » et
double-cliquer dessus.
Vérifier que l'url pointe bien vers localhist-ni.cm-cic.fr et non uniquement vers localhost, la corriger
au besoin.
Fiddler
Lié à SoapUI
Lancer Fiddler, faire F12 (ou cliquer sur le rectangle en bas à droite contenant "Capturing") afin
d'éviter les captures de requêtes non souhaitées.
Dans SoapUi aller dans File / Preferences puis dans l'onglet « Proxy Settings ».
Le configurer en « Manual », Host 127.0.0.1 et Port 8888 (port par défaut de Fiddler, à modifier si
vous en avez défini un autre).
Le bouton de proxy est passé en vert.
Relancer la requête : le résultat apparaît toujours dans SoapUI mais la requête et la réponse sont
également présentes dans Fiddler.
Cliquer sur la session dans Fiddler puis dans l'onglet « Inspectors » et cliquer sur les onglets « Raw »
de la requête et de la réponse afin de les détailler.
Cliquer sur le bouton proxy dans SoapUI afin de désactiver l'utilisation de Fiddler.
Lancer le projet de démo et naviguer sur un page puis étudier dans Fiidler les sessions capturées.
Service Preview
Cliquer sur le bouton « Run » et le résultat s'affichera au bout de quelques secondes dans l'écran de
sortie.
Puis dans le menu DevBooster cliquer sur « Web Inclusion test window ».
Une fois la fenêtre ouverte, noter que le lien « Help » mène directement vers le document détaillant
la configuration.
Cliquer sur « Start » pour démarrer la Web-Inclusion Gateway » puis lancer le projet de démo via F5.
Se loguer puis appuyer sur le bouton retour du navigateur afin de parvenir avec un utilisateur
authentifié sur la première page de l’application.
Utilisation de GlobalString
Ouvrir le fichier EmptyPage.xaml et remplacer « Content » par le code suivant :
<GlobalString Key="12" MaxSize="150" Technical="False" Comments="Content of the pa
ge">
Content
</GlobalString>
Ouvrir le fichier GlobalizationData.xml et montrer que les valeurs saisies sont répercutées dans ce
fichier.
17. DM12.1 Migrer une activité en nouvelle navigation
Reproduire le bug de navigation
Afficher la liste.
Clic droit, ouvrir une nouvel page sur un autre élément de la liste
Dans la première page ouverte, cliquer sur le bouton Suivant. Vous serez sur l'onglet 2 du dernier
élément saisi.
/// <summary>
/// Activité permettant de consulter une carte
/// </summary>
[ReturnState(typeof(EmptyDTO), ActivityResult.Success, "Success")]
internal class TransferView : Activity
{
case "GoDetail":
ActivityInputParams activityInputParams = new ActivityInputParams(processedRequest, renderInfo,
preparePIDParams);
activityInputParams.InputParams["transfer_id"] = processedRequest.Data["id"];
ActivityManager.StartActivity(
"CardTransfer",
true,
activityInputParams);
break;
/// <summary>
/// Démarrage de l'activité
/// </summary>
/// <param name="transfer_id">identifiant du virement</param>
[DefaultNextStep(target: typeof(TransferView1Account))]
public NextStepId Start(string transfer_id)
{
return NextStepId.Default();
}
Tester (F5)