Amine Mostefai's Blog

Architecture is my passion :)

Amine

Hi and welcome to my blog. I share in this space a lot of posts related to software architecture, and software development. Content is mainly related to .NET CORE development, Angular, Sharepoint, Azure and Office 365. I hope that my articles are helpful and that you enjoy using them 😉

Tutoriel 5.1 - Création d’un service de recrutement–Partie 2

Dans la partie prĂ©cĂ©dente, nous avons crĂ©Ă© les services et les workflows nĂ©cessaires Ă  notre opĂ©ration de recrutement. Durant cette partie, nous ferons le reste : les applications clientes. Etape 7 : CrĂ©ation de l’application candidat L’objectif de cette Ă©tape est de crĂ©er l’application « Candidat » qui permettra Ă  un postulant de soumettre une candidature. Cette application sera Ă©galement serveur puisqu’elle hĂ©bergera un service de notification. Ouvrez Visual Studio dans une nouvelle fenĂȘtre en mode administrateur CrĂ©ez une nouvelle application WPF et appelez-la « CandidatApp » Ouvrez « MainWindow » en mode design Supprimez la grille Glissez un « DockPanel » sur la fenĂȘtre principale avec les propriĂ©tĂ©s « HorizontalAlignment » et « VerticalAlignment » Ă  « Stretch », supprimez les propriĂ©tĂ©s « Height » et « Width ». « LastChildFill » doit ĂȘtre «True » Glissez un « Label » sur le « StackPanel » avec la propriĂ©tĂ© « Content » Ă  « Nom : » et « Margin » Ă  3 et « DockPanel.Dock » Ă  « Top » Glissez un « TextBox » avec la propriĂ©tĂ© « Name » Ă  « txtNom » et « Margin » Ă  3 et « DockPanel.Dock » Ă  « Top » Glissez un deuxiĂšme « Label » en dessous de la « TextBox » avec la propriĂ©tĂ© « Content » Ă  « Date de naissance : » et « Margin » Ă  3 et « DockPanel.Dock » Ă  « Top » Glissez un « DatePicker » en dessous du deuxiĂšme « Label » avec les propriĂ©tĂ©s « Name » Ă  « dpDate », « Margin » Ă  3 et « DockPanel.Dock » Ă  « Top » Ajoutez un bouton en dessous du « Picker » avec « Name », « Margin », « Content » Ă  « btnSoumettre », 3 et « Soumettre » Glissez un « TextBox » en dessous du bouton  avec la propriĂ©tĂ© « Name » Ă  « txtConsole », « Margin » Ă  3, « AcceptReturn » Ă  « True » Le code XAML de la fenĂȘtre principale doit ĂȘtre comme ceci : <Window x:Class="CandidatApp.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="MainWindow" Height="350" Width="525"> <DockPanel HorizontalAlignment="Stretch" VerticalAlignment="Stretch" LastChildFill="True" > <Label Content="Nom :" Margin="3" DockPanel.Dock="Top"/> <TextBox Name="txtNom" Margin="3" DockPanel.Dock="Top"/> <Label Content="Date de Naissance :" Margin="3" DockPanel.Dock="Top"/> <DatePicker Name="dpDate" Margin="3" DockPanel.Dock="Top"/> <Button Content="Soumettre" DockPanel.Dock="Top" Margin="3" Name="btnSoumettre"/> <TextBox Name="txtConsole" Margin="3" AcceptsReturn="True" TextWrapping="Wrap" VerticalAlignment="Stretch"/> </DockPanel></Window> Lancez la boĂźte de dialogue d’ajout de nouvel Ă©lĂ©ment (au projet CandidatApp) Ă  partir de l’explorateur de solutions Dans la zone de recherche, tapez « WCF » SĂ©lectionnez « Service WCF » Dans la zone « Nom », entrez « NotificationService » Remarquez que VS crĂ©e une interface appelĂ©e « INotificationService » et son implĂ©mentation « NotificationService Ouvrez le fichier « INotificationService.cs » Supprimez la dĂ©claration de mĂ©thode « DoWork » Ajoutez une mĂ©thode de type « void » appelĂ©e « Notifier » et qui a deux paramĂštres « Nom » et « Acceptation » de type « String » et « Boolean » DĂ©corez la mĂ©thode par l’attribut « OperationContract » pour la rendre comme service Le listing de l’interface INotificationService devrait ĂȘtre comme ceci : [ServiceContract] public interface INotificationService { [OperationContract] void Notifier(string Nom, bool Acceptation); } Ouvrez le fichiez « NotificationService.cs » Supprimez le code de « DoWork » ImplĂ©mentez la mĂ©thode « Notifier » comme ceci : public void Notifier(string Nom, bool Acceptation) { string etat; if (Acceptation) etat = "acceptĂ©"; else etat = "rejetĂ©"; Console.WriteLine("Le candidat {0} a Ă©tĂ© {1} ", Nom, etat);  } Compilez l’application. Ajoutez au projet la classe « TextBoxTextWriter » crĂ©Ă© lors des tutoriaux prĂ©cĂ©dents pour rediriger les sorties de la console sur la « TextBox » txtConsole Ouvrez « MainWindow.xaml.cs » Ajoutez un using sur l’esapce de nom de la classe « TextBoxTextWriter » Ajoutez un using sur « System.ServiceModel » Ajoutez un Ă©vĂšnement de chargement « Loaded » sur le « DockPanel » Redirigez la sortie de la console// rediriger la sortie de la console Console.SetOut(new TextBoxTextWriter(txtConsole)); CrĂ©ez ensuite le hĂŽte qui permettra d’herbeger le service WCF comme ceci : // crĂ©er le hote wcf var host = new ServiceHost(typeof(NotificationService)); // lancer le hote wcf host.Open(); Console.WriteLine("service de notification dĂ©marrĂ©"); Nous allons enfin affectez une valeur par dĂ©faut Ă  la date de naissance qui est de 20 ans avant aujourd’hui// date par dĂ©faut dpDate.SelectedDate = DateTime.Now.AddYears(-20); Le listing complet de la mĂ©thode devrait ĂȘtre comme ceci : private void DockPanel_Loaded(object sender, RoutedEventArgs e) { // rediriger la sortie de la console Console.SetOut(new TextBoxTextWriter(txtConsole)); // crĂ©er le hote wcf var host = new ServiceHost(typeof(NotificationService)); // lancer le hote wcf host.Open(); Console.WriteLine("service de notification dĂ©marrĂ©"); // date par dĂ©faut dpDate.SelectedDate = DateTime.Now.AddYears(-20); } Ouvrez le fichier « App.Config » Changez la propriĂ©tĂ© « baseAddress » de l’hĂŽte Ă  http://localhost:7766/Notification Le listing de « App.Config » devrait ĂȘtre comme ceci : <?xml version="1.0" encoding="utf-8" ?><configuration> <startup> <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" /> </startup> <system.serviceModel> <behaviors> <serviceBehaviors> <behavior> <serviceMetadata httpGetEnabled="true" httpsGetEnabled="true" /> <serviceDebug includeExceptionDetailInFaults="false" /> </behavior> </serviceBehaviors> </behaviors> <services> <service name="CandidatApp.NotificationService"> <endpoint address="" binding="basicHttpBinding" contract="CandidatApp.INotificationService"> <identity> <dns value="localhost" /> </identity> </endpoint> <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" /> <host> <baseAddresses> <add baseAddress="http://localhost:7766/Notification" /> </baseAddresses> </host> </service> </services> </system.serviceModel></configuration> Lancez l’application pour tester le service Appelez la mĂ©thode « Notifier » Ă  partir du testeur « WCF » Remarquez que les messages de notifications sortent sur la console Etape 8 : CrĂ©ation du proxy vers le workflow Dans l’étape prĂ©cĂ©dente, nous avons crĂ©Ă© le serveur de notification qui permettra au workflow de notifier le candidat. Dans cette Ă©tape, nous allons nous connecter au service du workflow pour pouvoir soumettre le dossier du candidat. Revenez sur la fenĂȘtre VS qui contient le projet « Tutoriel51 » Lancez l’application « WorkflowConsoleHost » Revenez sur le projet « CandidatApp » Dans l’explorateur de solutions, cliquez sur le bouton droit sur les rĂ©fĂ©rences puis sur « ajouter une rĂ©fĂ©rence de service » Dans la zone « Adresse », entrez http://localhost:9988/EmbaucheSimple Cliquez sur « Go » Dans l’espace de noms, entrez « FormationWF » Dans les services, sĂ©lectionnez « EmbaucheSimpleService » puis « IEmbaucheService » Cliquez sur « OK » Ouvrez « MainWndow » en mode design Affectez un Ă©vĂšnement « Click » au bouton CrĂ©ons les informations Ă  transmettre Ă  partir du formulaire // crĂ©er les informations var info = new FormationWF.CandidatInfo() { Nom = txtNom.Text, DateNaissance = dpDate.SelectedDate.Value }; CrĂ©ons ensuite le proxy qui nous permettra de nous connecter au serveur// crĂ©er le proxy var client = new FormationWF.EmbaucheServiceClient(); Nous allons ensuite crĂ©er les donnĂ©es Ă  transmettre au serveur // donnĂ©es Ă  transmettre var data = new FormationWF.RecevoirCandidature(); data.pInfo = new FormationWF.CandidatInfo() { Nom = txtNom.Text, DateNaissance = dpDate.SelectedDate.Value }; Ensuite nous allons appeler le service et rĂ©cupĂ©rer le rĂ©sultat // appel du service var res = client.RecevoirCandidature(data); if (res.HasValue && !res.Value) Console.WriteLine("Candidature automatiquement rejetĂ©e"); Le listing complet du gestionnaire de clic est comme suit : private void btnSoumettre_Click(object sender, RoutedEventArgs e) { // crĂ©er les informations var info = new FormationWF.CandidatInfo() { Nom = txtNom.Text, DateNaissance = dpDate.SelectedDate.Value }; // crĂ©er le proxy var client = new FormationWF.EmbaucheServiceClient(); // donnĂ©es Ă  transmettre var data = new FormationWF.RecevoirCandidature(); data.pInfo = new FormationWF.CandidatInfo() { Nom = txtNom.Text, DateNaissance = dpDate.SelectedDate.Value }; // appel du service var res = client.RecevoirCandidature(data); // afficher rĂ©sultat si rejet auto if (res.HasValue && !res.Value) Console.WriteLine("Candidature automatiquement rejetĂ©e"); } ExĂ©cutez l’application puis remarquez comment des candidatures de moins de 30 ans sont automatiquement rejetĂ©es Etape 9 : CrĂ©ation de l’application de l’évaluateur L’objectif de cette Ă©tape est de crĂ©er une application qui va ĂȘtre utilisĂ©e par l’évaluateur pour Ă©valuer les candidatures. Ouvrez Visual Studio dans une nouvelle fenĂȘtre CrĂ©ez une nouvelle application WPF et appelez-la « EvaluateurApp » Ouvrez « MainWindow » en mode design Supprimez la grille Glissez un « StackPanel » sur la fenĂȘtre principale avec les propriĂ©tĂ©s « HorizontalAlignment » et « VerticalAlignment » Ă  « Stretch », supprimez les propriĂ©tĂ©s « Height » et « Width ». Glissez un « Label » sur le « StackPanel » avec la propriĂ©tĂ© « Content » Ă  « Nom : » et « Margin » Ă  3 Glissez un « TextBox » avec la propriĂ©tĂ© « Name » Ă  « txtNom » et « Margin » Ă  3 Glissez un deuxiĂšme « Label » en dessous de la « TextBox » avec la propriĂ©tĂ© « Content » Ă  « Note : » et « Margin » Ă  3 Glissez une « ComboBox » en dessous du deuxiĂšme « Label » avec les propriĂ©tĂ©s « Name » Ă  « cbNote », « Margin » Ă  3. La combobox contient 5 notes de 1 Ă  5 et la propriĂ©tĂ© « SelectedIndex » Ă  0 Ajoutez un bouton en dessous du « ComboBox » avec « Name », « Margin », « Content » Ă  « btnEvaluer », 3 et « Evaluer » Le XAML de la fenĂȘtre devrait ĂȘtre comme ceci : <Window x:Class="EvaluateurApp.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="MainWindow" Height="350" Width="525"> <Grid> <StackPanel> <Label Content="Nom :" Margin="3"/> <TextBox TextWrapping="Wrap" Name="txtNom" Margin="3"/> <Label Content="Note :" Margin="3"/> <ComboBox Name="cbNote" Margin="3" SelectedIndex="0"> <ListBoxItem Content="1"/> <ListBoxItem Content="2"/> <ListBoxItem Content="3"/> <ListBoxItem Content="4"/> <ListBoxItem Content="5"/> </ComboBox> <Button Content="Evaluer" Name="btnEvaluer"/> </StackPanel>  </Grid></Window> Dans l’explorateur de solutions, cliquez sur le bouton droit sur les rĂ©fĂ©rences puis sur « ajouter une rĂ©fĂ©rence de service » Dans la zone « Adresse », entrez http://localhost:9988/EmbaucheSimple Cliquez sur « Go » Dans l’espace de noms, entrez « FormationWF » Dans les services, sĂ©lectionnez « EmbaucheSimpleService » puis « IEmbaucheService » Cliquez sur « OK » Ajoutez un gestionnaire de clic au bouton « Evaluer » qui permet d’appeler la mĂ©thode « Evaluer » du service private void btnEvaluer_Click(object sender, RoutedEventArgs e) { // crĂ©er le proxy var proxy = new FormationWF.EmbaucheServiceClient(); // appeler le service proxy.Evaluer(txtNom.Text, cbNote.SelectedIndex + 1); } Compilez l’application pour vĂ©rifier d’éventuelles erreurs. Etape 10 : Finalisation du workflow L’objectif de cette Ă©tape est de finaliser le workflow de façon Ă  ce qu’aprĂšs l’évaluation, il envoie une notification au candidat. Revenez Ă  la solution « Tutoriel51 » Si l’application console est en exĂ©cution, quittez-la Glissez une activitĂ© « Send » au workflow Connectez le dernier « Assign » avec l’activitĂ© « Send » Connectez le nouveau « Send » avec le cĂŽtĂ© « False » de l’activitĂ© de dĂ©cision Dans la zone « OperationName », entrez « Notifier » Cliquez sur le bouton « Contenu » Ajoutez un paramĂštre appelĂ© « Nom » de type « String » et dont la valeur est « info .Nom » Ajoutez un deuxiĂšme paramĂštre appelĂ©e « Acceptation », de type « Boolean » et dont la valeur est « Resultat »   Cliquez sur « OK » Dans la propriĂ©tĂ© « EndPoint.AddressUri » de l’activitĂ© « Send », entrez http://localhost:7766/Notification. C’est l’adresse du service de notification. Dans la propriĂ©tĂ© « EndPoint.Binding », de l’activitĂ© « Send », sĂ©lectionnez « basicHttpBinding » Dans la propriĂ©tĂ© « ServiceContractName » entrez « INotificationService » Le workflow devrait ĂȘtre comme ceci : Etape 11 : Mise en place de la corrĂ©lation Le workflow dans l’étape prĂ©cĂ©dente est fonctionnel mais il reste un problĂšme : lorsque l'Ăąge du candidat dĂ©passe 30 ans, l’évaluateur doit lui donner une note. Le problĂšme est qu’un instant donnĂ©, plusieurs instances peuvent s’exĂ©cuter en parallĂšle. Lorsqu’un Ă©valuateur donne une note, on doit affecter cette note au bon candidat. La solution pour trouver la bonne instance du workflow est la corrĂ©lation. Nous Ă©tablirons une corrĂ©lation sur le nom du candidat. Ouvrez le workflow « EmbaucheSimpleService.xamlx » en mode design Remarquez que notre workflow contient deux activitĂ©s « Receive ». Pour assurer une cohĂ©rence d’exĂ©cution, nous relierons les deux « Receive » par une corrĂ©lation. Le premier « Receive » doit initialiser une corrĂ©lation tandis que le deuxiĂšme doit s’appliquer Ă  cette corrĂ©lation. Cliquez sur l’activitĂ© organigramme (FlowChart) parente Examinez les variables Remarquez la prĂ©sence d’une variable appelĂ©e « __handle » de type « CorrlationHandle » Si cette variable n’existe pas, crĂ©ez-la Changez la portĂ©e de la variable (Scope) pour qu’elle soit sur tout l’organigramme Renommez cette variable en « dossier » Double-cliquez sur la premiĂšre sĂ©quence du workflow Cliquez sur la propriĂ©tĂ© « CorrelationInitializers » de l’activitĂ© « Receive » de la sĂ©quence Dans la zone « Add initializer », entrez « dossier » Dans la liste dĂ©roulante au dessus de la grille « XPath Queries », sĂ©lectionnez « Query Correlation Initializer » Dans la grille, dans la colonne « Query », sĂ©lectionnez la propriĂ©tĂ© « Nom » du paramĂštre « pInfo » Remarquez que VS gĂ©nĂšre automatiquement le chemin « XPath » relatif Ă  la propriĂ©tĂ© Laissez la colonne « Key » Ă  « Key1 » Cliquez sur « OK » Nous allons maintenant corrĂ©ler la deuxiĂšme activitĂ© « Receive » avec la premiĂšre Dans la deuxiĂšme activitĂ© « Receive » (Recevoir Evaluation), cliquez sur le bouton de la propriĂ©tĂ© « CorrelateOn » Dans la zone « Correlates With », entrez « dossier » Dans la « XPath Queries », sĂ©lectionnez le paramĂštre « Nom ». Remarquez que le chemin « XPath » est automatiquement gĂ©nĂ©rĂ©. Ce que nous avons fait c’est que nous utilierons le paramĂštre « Nom » fourni par l’évaluateur pour trouver la bonne instance du workflow. Cliquez sur « OK » Le workflow est maintenant prĂȘt. Compilez pour vĂ©rifier l’absence d’erreurs. Etape 12 : ExĂ©cution et Tests L’objectif de cette Ă©tape est de tester nos services. Nous validerons les trois cas de figures : Si le candidat a moins de 30 ans, sa candidature est automatiquement rejetĂ©e. Il reçoit immĂ©diatement une notification. Si le candidat a plus de 30 ans, l’évaluateur doit l’évaluer. Lorsque l’évaluateur lui attribue une note supĂ©rieure ou Ă©gale Ă  3, il est acceptĂ©, sinon il est rejetĂ©. ProcĂ©dure : Lancez les trois applications Dans l’application « CandidatApp », entrez « Kamel » dans le nom et « 01/05/1986 » dans la date de naissance Cliquez sur « Soumettre » Remarquez que « Kamel » a Ă©tĂ© automatiquement rejetĂ© CrĂ©ez deux candidatures pour « Yazid » et pour « Racha » nĂ©s respectivement le « 25/03/1971 » et « 26/08/1978 » Remarquez que les candidatures n’ont pas Ă©tĂ© automatiquement rejetĂ©es Allez sur l’application « EvaluateurApp » Dans la zone « Nom » entrez « Racha » et sĂ©lectionnez « 4 » dans la note puis cliquez sur « Evaluer » Revenez Ă  l’application « CandidatApp », remarquez qu’une notification indiquant que « Racha » a Ă©tĂ© acceptĂ©e. La corrĂ©lation a fait qu’on trouve le bon « Workflow » malgrĂ© que « Racha » a un dossier ultĂ©rieur Ă  celui de « Yazid » Revenez Ă  l’application « EvaluateurApp » Dans la zone « Nom » entrez « Yazid », dans la zone « Note » entrez « 2 » puis cliquez sur le bouton « Evaluer » Revenez sur l’application « CandidatApp » Remarquez une notification stipulant que « Yazid » a Ă©tĂ© rejetĂ©e       Le code source complet des applications de ce tutoriel est accessible ici. Enjoy !

Tutoriel 5.1 - Création d’un service de recrutement–Partie 1

L’objectif de ce tutoriel (cours 5) est de mettre en place un workflow de recrutement basĂ© sur les services WCF. Pour ce, le workflow est hĂ©bergĂ© dans une application console. Le candidat dispose d’une application qui lui permet de postuler Ă  un poste et l’évaluateur a une application lui permettant d’évaluer une candidature. A la fin de l’évaluation, le candidat reçoit une notification de la note s’il a Ă©tĂ© acceptĂ© ou pas. Au dĂ©but, si l’ñge du candidat est infĂ©rieur Ă  30, sa candidature est systĂ©matiquement rejetĂ©e sans passer par l’évaluation. Etape 1 – CrĂ©ation de la solution. L’objectif est de crĂ©er une solution qui va contenir les diffĂ©rents modules du tutoriel. Lancez Visual Studio en tant qu’administrateur CrĂ©ez une nouvelle solution vide appelĂ©e « Tutoriel51 » Ajoutez Ă  la solution un projet de type « Application de service WCF Workflow » et appelez-le « EmbaucheLibrary » Remarquez que le projet contient un fichier dont l’extension est « xamlx » appelĂ©e « Service1.xamlx » Supprimez ce fichier Ajoutez au projet un nouvel Ă©lĂ©ment de type « Service Workflow WCF » et appelez-le « EmbaucheSimpleService » Remarquez que par dĂ©faut, VS 2012 crĂ©e une sĂ©quence avec une activitĂ© « Receive » et une activitĂ© « Send » Supprimez la sĂ©quence et toutes les activitĂ©s avec Etape 2 : CrĂ©ation d’un contrat de donnĂ©es L’objectif de cette Ă©tape est de crĂ©er un contrat de donnĂ©es (DataContract) qui reprĂ©sente des donnĂ©es qui vont ĂȘtre sĂ©rialisĂ©es et envoyĂ©es sur le rĂ©seau Ă  travers les services WCF. Ajoutez une nouvelle classe au projet « EmbaucheSimpleService » appelĂ©e « CandidatInfo » Ajoutez deux propriĂ©tĂ©s publiques appelĂ©es «Nom » et « DateNaissance » de type « String » et « DateTime » public DateTime DateNaissance { get; set; } public string Nom { get; set; }   Ajoutez un « using » vers l’espace de nom « System.Runtime.Serialization » DĂ©corez les deux propriĂ©tĂ©s avec l’attribut « DataMember » DĂ©core la classe avec l’attriobut « DataContract » Compilez la solution pour vĂ©rifier l’absence d’erreurs. Le listing complet devrait ĂȘtre comme suit : [DataContract] public class CandidatInfo { [DataMember] public DateTime DateNaissance { get; set; } [DataMember] public string Nom { get; set; } }   Etape 3 : CrĂ©ation du service de candidature L’objectif de cette Ă©tape est de crĂ©er un service workflow qui permettra au candidat de prĂ©senter ses informations : nom et date de naissance. Ouvrez le workflow « EmbaucheSimpleService.xamlx » Glissez un organigramme sur le workflow Glissez une activitĂ© « ReceiveAndSendReply » et connectez-la au nƓud de dĂ©marrage Cliquez sur l’organigramme parent CrĂ©ez une variable « info » dont le type est « CandidatInfo » CrĂ©ez une deuxiĂšme variable appelĂ©e « Resultat » de type « Boolean » CrĂ©ez une troisiĂšme variable appelĂ©e « Note » de type « Int32 » Double-cliquez sur la sĂ©quence Renommez la premiĂšre activitĂ© « Receive » en « Recevoir Candidature » Entrez « RecevoirCandidature » dans la zone « Nom de l’opĂ©ration » Dans la propriĂ©tĂ© « ServiceContractName », entrez « IEmbaucheService » Cochez la propriĂ©tĂ© « CanCreateInstance » Cliquez sur « Contenu », la boĂźte de dialogue ci-dessous devrait apparaĂźtre Cliquez sur le bouton radio « ParamĂštres » Cliquez sur « Ajoutez nouveau paramĂštre » Dans la zone « Nom », entrez « pInfo » Pour le type, sĂ©lectionnez « CandidatInfo » Dans la zone « Assign To », entrez « info » Cliquez sur OK Glissez une activitĂ© de type « Assign » entre l’activitĂ© « Receive » et l’activitĂ© « Send » Dans la zone « To », entrez « Resultat » Dans la zone « Value » entrez l’expression suivante :info.DateNaissance < DateTime.Today.AddYears(-30) Ajoutez une activitĂ© « WriteLine » aprĂšs « Assign » et avant « SendReplyToReceive » Affectez l’expression suivante Ă  la propriĂ©tĂ© « Text »string.Format("Candidature reçue, nom : {0}, dn : {1}",info.Nom,info.DateNaissance) Dans l’activitĂ© « SendReplyToReceive », cliquez sur « Contenu » Dans la liste dĂ©roulante « Message Type », sĂ©lectionnez « Boolean » Dans la zone « Message Data », entrez « Resultat » La sĂ©quence devrait ĂȘtre comme suit : Compilez pour vĂ©rifier la prĂ©sence d’erreurs. Etape 4 : Test du service L’objectif de cette Ă©tape est de tester le service en utilisant l’outil « WCFTestClient » fourni avec Visual Studio. Dans Visual Studio, dans l’explorateur de solution, cliquez avec le bouton droit sur le fichier « EmbaucheSimpleService.xamlx » Cliquez sur « Afficher sur le navigateur » Remarquez la dĂ©finition du service s’affichant dans le navigateur.   Copiez l’adresse du service Ă  partir de la barre d’adresse Lancez l’explorateur Windows Allez sur le rĂ©pertoire d’installation de Visual Studio Allez sur le rĂ©pertoire « Common7 Ă  IDE » ExĂ©cutez l’outil « WCFTestClient.exe » Cliquez « Fichier Ă  Ajouter Service » Dans la boĂźte de dialogue qui apparait, dans la zone de texte, collez l’URL copiĂ©e lors de l’étape 4 Remarquez la prĂ©sence du service « IEmbaucheService » avec la mĂ©thode « RecevoirCandidature » Double-cliquez sur « RecevoirCandidature » Affectez des valeurs au paramĂštre « pInfo » (utiliser l’assistant qui propose des valeurs par dĂ©faut) Cliquez sur « Invoke » Remarquez que le service renvoie « True » pour les dates de naissance de plus de 30 ans et false sinon Etape 5 : CrĂ©ation de l’application d’hĂ©bergement en mode console Une des nombreuses façons d’hĂ©berger un workflow de service est une application de console. L’objectif de cette Ă©tape est d’utiliser la classe « WorkflowServiceHost » pour hĂ©berger un workflow. Ajoutez Ă  la solution un nouveau projet de type « Application Console Workflow » et appelez-la « ConsoleWorkflowHost » A partir de l’explorateur de solution, faites de ce projet le projet de dĂ©marrage A partir de l’explorateur de solution, supprimer le workflow « Workflow1.xaml » crĂ©Ă© avec le projet Ajoutez une rĂ©fĂ©rence vers « EmbaucheLibrary » Ouvrez le fichier « Program.cs » Supprimez le contenu de la mĂ©thode « Main » Ajoutez un using vers « System.ServiceModel.Activities » Ajoutez un using vers « System.Xaml » Ajoutez un using vers « System.ServiceModel.Description » La premiĂšre Ă©tape consiste Ă  charger le service Ă  partir du fichier :// charger le service Ă  partir du fichier WorkflowService service = XamlServices.Load(@"F:\FormationWF\Tutoriaux\Chapitre 5\Tutoriel51\EmbaucheLibrary\EmbaucheSimpleService.xamlx") as WorkflowService; Remplacez le chemin indiquĂ© par le chemin dans lequel se trouve votre code source La deuxiĂšme Ă©tape consiste Ă  compiler le service :// compiler le service Compile(service); Nous fournirons l’implĂ©mentation de la mĂ©thode « Compile » dans une prochaine Ă©tape La prochaine Ă©tape consiste Ă  dĂ©finir l’adresse du service :// dĂ©finir l'adresse du service Uri address = new Uri("http://localhost:9988/EmbaucheSimple"); Ensuite, nous lancerons l’hĂŽte en utilisant le workflow et l’adresse :// crĂ©er le hĂŽte WorkflowServiceHost host = new WorkflowServiceHost(service, address); Nous paramĂ©trerons le service de façon Ă  ce qu’il communique ses mĂ©tadonnĂ©es via HTTP :// communiquer mĂ©tadonnĂ©es via HTTP host.Description.Behaviors.Add(new ServiceMetadataBehavior { HttpGetEnabled = true }); Nous supprimerons ensuite le comportement de dĂ©bogage du service// supprimer le comportement de dĂ©bogage host.Description.Behaviors.Remove(typeof(ServiceDebugBehavior)); Nous ajouterons ensuite le comportement qui inclut les informations des exceptions avec les messages. Ce comportement est trĂšs utile pour le dĂ©bogage.// inclure les dĂ©tails des exception dans les messages host.Description.Behaviors.Add(new ServiceDebugBehavior { IncludeExceptionDetailInFaults = true }); Maintenant que l’hĂŽte est configuĂ©, il faut le lancer// dĂ©marrer le service host.Open(); Ajoutons une instruction qui lit une touche Ă  partir du clavier (Console.ReadKey()) et afficher un message avantConsole.WriteLine("Service dĂ©marrĂ©"); Console.ReadKey(); Le listing complet de la mĂ©thode « Main » devraĂźt ĂȘtre comme suit : static void Main(string[] args) { // charger le service Ă  partir du fichier WorkflowService service = XamlServices.Load(@"F:\FormationWF\Tutoriaux\Chapitre 5\Tutoriel51\EmbaucheLibrary\EmbaucheSimpleService.xamlx") as WorkflowService; // compiler le service Compile(service); // dĂ©finir l'adresse du service Uri address = new Uri("http://localhost:9988/EmbaucheSimple"); // crĂ©er le hĂŽte WorkflowServiceHost host = new WorkflowServiceHost(service, address); // communiquer mĂ©tadonnĂ©es via HTTP host.Description.Behaviors.Add(new ServiceMetadataBehavior { HttpGetEnabled = true }); // supprimer le comportement de dĂ©bogage host.Description.Behaviors.Remove(typeof(ServiceDebugBehavior)); // inclure les dĂ©tails des exception dans les messages host.Description.Behaviors.Add(new ServiceDebugBehavior { IncludeExceptionDetailInFaults = true }); // dĂ©marrer le service host.Open(); Console.WriteLine("Service dĂ©marrĂ©"); Console.ReadKey(); } Ajoutez un using vers « System.Activities.XamlIntegration » Ajoutez un using vers « System.Activities.Expressions » Ajoutez la mĂ©thode « Compile » comme suit : static void Compile(WorkflowService workflowService) { TextExpressionCompilerSettings settings = new TextExpressionCompilerSettings { Activity = workflowService.Body, Language = "C#", ActivityName = workflowService.Name + "_CompiledExpressionRoot", ActivityNamespace = string.Join(".", "CompiledExpressions"), RootNamespace = null, GenerateAsPartialClass = false, ForImplementation = false, // Important tip - ForImplementation should only be true when compiling an ActivityBuilder, it must be false when compiling an Activity such as a WorfkflowService body. };  TextExpressionCompilerResults results = new TextExpressionCompiler(settings).Compile();  if (results.HasErrors) { throw new Exception("Compilation failed."); }  ICompiledExpressionRoot compiledExpressionRoot = Activator.CreateInstance(results.ResultType, new object[] { workflowService.Body }) as ICompiledExpressionRoot;  CompiledExpressionInvoker.SetCompiledExpressionRoot( workflowService.Body, compiledExpressionRoot); }   L’implĂ©mentation de « Compile a Ă©tĂ© tirĂ©e du service de « Microsoft » (https://connect.microsoft.com/VisualStudio/feedback/details/743870/workflow-foundation-4-5-workflowservicehost-xamlx-expression-activity-type-csharpvalue1-requires-compilation-in-order-to-run ) Etape 6 : CrĂ©ation du service d’évaluation L’objectif de cette Ă©tape est d’ajouter le service permettant Ă  la commission technique d’évaluer un candidat. Ouvrez le workflow « EmbaucheSimpleService.xaml » Ouvrez l’organigramme principal qui contient la sĂ©quence Ajoutez une activitĂ© « FlowDecision » et connectez-la Ă  la sĂ©quence Entrez « Resultat » dans l’expression de la condition de la dĂ©cision Ajoutez une activitĂ© « Receive » et appelez-la « Recevoir Evaluation » Connectez l’activitĂ© au label « True » de la dĂ©cision Entrez « IEmbaucheService » dans la propriĂ©tĂ© « ServiceContractName » Entrez « Evaluer » dans la zone « Nom de l’opĂ©ration » Cliquez sur le bouton « Contenu » de l’activitĂ© « Receive » Cliquez sur le bouton radio « ParamĂštres » Ajoutez un paramĂštre appelĂ© « nom » de type « String » Ajoutez un paramĂštre appelĂ© « note » de type « Int32 » affectĂ©e Ă  la variable « Note » Cliquez sur « OK » Ajoutez une activitĂ© « Assign » et connectez-la au dernier « Receive » Dans la zone « To » entrez « Resultat » Dans la zone expression, entrez « Note >=3) Le workflow devrait ĂȘtre comme suit : Compilez pour vĂ©rifier les erreurs. Vous pouvez accĂ©der Ă  la suite du tutoriel ici.

WCF et IIS 8.5, Régler le problème de l’erreur 404.17

AprĂšs quelques recherches internet et bien sĂ»r, des maux de tĂȘte, j’ai rĂ©ussi Ă  dĂ©bloquer le problĂšme d’erreur 404.17 faisant suite Ă  l’hĂ©bergement d’un service WCF sur IIS 8.5. Sachant que j’utilise IIS 8.5 sous Windows 8.1, la solution est relativement simple : Lancer le panneau de configuration Lancer “Programmes et FonctionnalitĂ©s” Activer ou DĂ©sactiver des FonctionnalitĂ©s Windows” Services .NET Framewok 4.5 avancĂ© Service WCF Activation HTTP                   Le problĂšme devrait ĂȘtre logiquement rĂ©solu

Tutoriel 7.1: Intégration d’AJAX dans les applications web

L’objectif de ce tutoriel (associĂ© au module 7) est de montrer comment intĂ©grer les technologies AJAX dans les applications ASP.NET. La premiĂšre partie, utilise les dates pour montrer comment UpdatePanel permet uniquement Ă  des portions de page d’ĂȘtre actualisĂ©es. La deuxiĂšme partie consiste en la crĂ©ation d’un service web et son invocation depuis le client en utilisant JavaScript et JQuery. PrĂ©requis : Ce tutoriel requiert que la base de donnĂ©es « AdventureWorks » soit installĂ©e dans la machine. Cette base peut ĂȘtre tĂ©lĂ©chargĂ©e sur http://sqlserversamples.codeplex.com/ . Etape 1 – PrĂ©paration L’objectif de cette Ă©tape est de prĂ©parer l’application. CrĂ©er une nouvelle application ASP.NET vide appelĂ©e « TestAJAX » CrĂ©ez trois pages dans la nouvelle application « Default.aspx », « Partiel.aspx » et « Service.aspx » Dans la page web « Default.aspx » ajoutez deux liens pointant respectivement sur « Partiel.aspx » et « Service.aspx » avec la propriĂ©tĂ© « Text » Ă©gale Ă  : « Chargement Partiel » et « Service Web » respectivement. Ajoutez un modĂšle EntityFramework appelĂ© « AdventureModel » pointant sur la base de donnĂ©es « AdventureWorks ». Le nom du contexte doit ĂȘtre « AdventureContext ». Pour plus de dĂ©tails voir « Module 6 ». N’oubliez pas de cochez « Mettre au plusieurs ou au singulier les entitĂ©s gĂ©nĂ©rĂ©es ». Le modĂšle inclut une seule table « Product » et gĂ©nĂšre une seule entitĂ© « Product » Ajoutez une feuille de style appelĂ©e « Site.css » Ajoutez les rĂšgles suivantes Ă  la feuille de style : body { font-family: 'Gill Sans' , 'Gill Sans MT' , Calibri, 'Trebuchet MS' , sans-serif; } .asideBar { border: thin solid #919191; float: left; margin: 5px; background-color: #F8E9AD; padding : 5px; min-width : 200px; min-height : 400px; }   div.content { border: thin solid #0D86FF; float: left; margin: 5px; padding: 5px; }   div.clear { float : left; }   .loading { text-align: center; background-color: #C24B4B; color: #FFFFFF; margin-top: 2px; padding: 3px; } Ouvrez la page « Partiel.aspx » en mode source InsĂ©rez les balises suivantes aprĂšs la balise « div » du formulaire (« form ») : <div> <aside class="asideBar"> </aside> <div class="content"> </div> <div class="clear" /> </div> Ouvrez la page « Partiel.aspx » en mode design Faites glisser le fichier « Site.css » sur la page afin d’appliquer le style. Ouvrez la console du gestionnaire de paquets « Nuget » Installez « JQuery » en entrant « Install-Package JQuery » Etape 2 : ImplĂ©mentation de chargement partiel L’objectif de cette Ă©tape de permettre au dĂ©veloppeur de voir l’effet du chargement partiel en comparant entre le contenu de deux libellĂ©s. Elle montre aussi l’utilisation de l’UpdatePanel en conjonction avec l’UpdateProgress. Ouvrez la page « Partiel.aspx » en mode design Cliquez sur la barre latĂ©rale « aside » puis insĂ©rer un « Label » dedans A partir de la barre Ă  outils, ajoutez un « ScriptManager » (onglet extensions AJAX) en dĂ©but de page Ajoutez une source de donnĂ©es « EntityDataSource » et pointez-la sur l’ensemble « Products » du contexte « AdventureContext ». Si vous n’arrivez pas Ă  voir le contexte, compilez la solution en appuyant sur « F6 » Ajoutez un « UpdatePanel » dans la « div » dont la classe est « content » InsĂ©rez un deuxiĂšme « Label » Ă  l’intĂ©rieur de l’UpdatePanel que vous venez d’ajouter Ajoutez un « GridView » Ă  l’intĂ©rieur du composant « UpdatePanel » que vous venez d’ajouter. Configurez la source de donnĂ©es pour pointer sur la source de donnĂ©es « EntityDataSource » ajoutĂ©e prĂ©cĂ©demment. Configurez le « GridView » de façon Ă  ce qu’il ne contienne que les colonnes « ProductID », « Name » et « Color » Configurez la pagination du GridView en affectant « True » Ă  la propriĂ©tĂ© « AllowPaging » Ajoutez un composant « UpdateProgress » en dessous du « UpdatePanel » Dans la propriĂ©tĂ© « DisplayAfter », entrez 50 Dans la propriĂ©tĂ© « AssociatedUpdatepanelID » entrez « UpdatePanel1 » Affichez la page « Partiel.aspx » en mode source Dans la propriĂ©tĂ© « ProgressTemplate » de l’UpdateProgress insĂ©rez un div et du texte comme suit : <asp:UpdateProgress ID="UpdateProgress1" runat="server" DisplayAfter="50" AssociatedUpdatePanelID="UpdatePanel1"> <ProgressTemplate> <div class="loading">Chargement en cours...</div> </ProgressTemplate> </asp:UpdateProgress> La page en mode design doit ĂȘtre comme suit :   Le code ASPX gĂ©nĂ©rĂ© doit ĂȘtre comme celui-ci : <form id="form1" runat="server"> <div>   <asp:ScriptManager ID="ScriptManager1" runat="server"> </asp:ScriptManager> <asp:EntityDataSource ID="EntityDataSource1" runat="server" ConnectionString="name=AdventureContext" DefaultContainerName="AdventureContext" EnableFlattening="False" EntitySetName="Products"> </asp:EntityDataSource> <aside class="asideBar"> <asp:Label ID="Label1" runat="server" Text="Label"></asp:Label> </aside> <div class="content"> <asp:UpdatePanel ID="UpdatePanel1" runat="server" AssociatedUpdatePanelID="UpdatePanel1" UpdateMode="Conditional"> <ContentTemplate> <asp:Label ID="Label2" runat="server" Text="Label"></asp:Label> <br /> <asp:GridView ID="GridView1" runat="server" BackColor="LightGoldenrodYellow" BorderColor="Tan" BorderWidth="1px" CellPadding="2" ForeColor="Black" GridLines="None" AllowPaging="True" AutoGenerateColumns="False" DataKeyNames="ProductID" DataSourceID="EntityDataSource1"> <AlternatingRowStyle BackColor="PaleGoldenrod" /> <Columns> <asp:BoundField DataField="ProductID" HeaderText="ProductID" ReadOnly="True" SortExpression="ProductID" /> <asp:BoundField DataField="Name" HeaderText="Name" SortExpression="Name" /> <asp:BoundField DataField="Color" HeaderText="Color" SortExpression="Color" /> </Columns> <FooterStyle BackColor="Tan" /> <HeaderStyle BackColor="Tan" Font-Bold="True" /> <PagerStyle BackColor="PaleGoldenrod" ForeColor="DarkSlateBlue" HorizontalAlign="Center" /> <SelectedRowStyle BackColor="DarkSlateBlue" ForeColor="GhostWhite" /> <SortedAscendingCellStyle BackColor="#FAFAE7" /> <SortedAscendingHeaderStyle BackColor="#DAC09E" /> <SortedDescendingCellStyle BackColor="#E1DB9C" /> <SortedDescendingHeaderStyle BackColor="#C2A47B" /> </asp:GridView> </ContentTemplate> </asp:UpdatePanel>   <asp:UpdateProgress ID="UpdateProgress1" runat="server" DisplayAfter="50" AssociatedUpdatePanelID="UpdatePanel1"> <ProgressTemplate> <div class="loading">Chargement en cours...</div> </ProgressTemplate> </asp:UpdateProgress>   </div> <div class="clear" />   </div> </form> Passez en mode « Code Behind » en appuyant sur « F7 » Dans la mĂ©thode « Page_Load », affectez la date en cours aux deux libellĂ©s comme suit : protected void Page_Load(object sender, EventArgs e) { Label1.Text = DateTime.Now.ToString(); Label2.Text = DateTime.Now.ToString(); } ExĂ©cutez en appuyant sur « F5 » et naviguez jusqu’à la page « Partiel.aspx » Remarquez qu’en changeant la page en cours dans la grille, la date ne change que pour un seul libellĂ© alors que la page devait changer les deux Remarquez que le « UpdateProgress » s’affiche Ă  chaque fois qu’un lien de pagination est cliquĂ© Etape 3 : CrĂ©ation d’un service web WCF Dans le projet « TestAJAX », cliquez sur « Ajouter un Nouvel ElĂ©ment » Dans le modĂšle sĂ©lectionnez « Service WCF AJAX » Dans la zone « Nom », entrez « ProductService » Appuyez sur « OK » Remarquez que VS gĂ©nĂšre une classe de service avec une seule mĂ©thode « DoWork » comme suit : [ServiceContract(Namespace = "")] [AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)] public class ProductService { // To use HTTP GET, add [WebGet] attribute. (Default ResponseFormat is WebMessageFormat.Json) // To create an operation that returns XML, // add [WebGet(ResponseFormat=WebMessageFormat.Xml)], // and include the following line in the operation body: // WebOperationContext.Current.OutgoingResponse.ContentType = "text/xml"; [OperationContract] public void DoWork() { // Add your operation implementation here return; }   // Add more operations here and mark them with [OperationContract] } Supprimez la mĂ©thode « DoWork » de la classe Ajoutez une mĂ©thode « GetProduct » dĂ©corĂ©e par l’attribut « OperationContract » L’attribut « OperationContract » stipule que la mĂ©thode peut ĂȘtre appelĂ©e comme service Changez le code de la mĂ©thode comme suit :   [OperationContract] public Product GetProduct(int id) { using (var context = new AdventureContext()) { return context.Products.FirstOrDefault(e => e.ProductID == id); } } Compilez en appuyant sur « F6 » et vĂ©rifiez qu’il n’y a pas d’erreur Ouvrez la page « Default.aspx » ExĂ©cutez en appuyant sur « F5 » Dans la barre d’adresse du navigateur, remplacez « Default.aspx » par « ProductService.svc » Remarquez les informations donnĂ©es sur le service permettant aux clients de l’invoquer. Etape 4 : Invocation du service web depuis JavaScript Le but de cette Ă©tape est d’utiliser le composant « ScriptManager » afin qu’il gĂ©nĂšre les proxies nĂ©cessaires Ă  l’invocation du service « ProductService ». Pour invoquer le services, des Ă©vĂšnements JQuery seront utilisĂ©s. Ouvrez la page « Service.aspx » en mode design Glissez un « ScriptManager » sur la page Cliquez sur la propriĂ©tĂ© « Services » du « ScriptManager » puis sur le bouton en pointillĂ©s qui apparaĂźt Cliquez sur le bouton « Ajouter » A droite, dans la propriĂ©tĂ© « Path », entrez « ~/ProductService.svc » Cliquez sur « OK » Ouvrez la page « Service.aspx » en mode source Ajoutez trois paragraphes (« <p> ») dont les deux derniers ont l’attribut « class » Ă  « info » Dans le premier paragraphe, ajoutez une balise « label » contenant le texte « NumĂ©ro : » Dans le premier paragraphe, ajoutez un contrĂŽle HTML (pas ASP.NET) de type bouton avec la propriĂ©tĂ© « ID » pour « btnChercher » et l’attribut « value » Ă  « Trouver Produit » Dans le deuxiĂšme paragraphe, ajoutez une balise « label » avec le texte « Nom : » Dans le deuxiĂšme paragraphe, ajoutez un contrĂŽle HTML « input (Text ») avec la propriĂ©tĂ© « ID » Ă  « txtNom » Dans le troisiĂšme paragraphe ajoutez une balise « label » avec le texte « Couleur : » Dans le deuxiĂšme paragraphe, ajoutez un contrĂŽle HTML « input (Text ») avec la propriĂ©tĂ© « ID » Ă  « txtNom » Le code devra ressembler au code qui suit : <form id="form1" runat="server"> <div> <asp:ScriptManager ID="ScriptManager1" runat="server"> <Services> <asp:ServiceReference Path="~/ProductService.svc" /> </Services> </asp:ScriptManager> <p> <label> Trouver : <input id="txtNumero" type="text" /></label> <input id="btnChercher" type="button" value="Trouver Produit" /> </p> <p class="info"> <label> Nom : </label> <input id="txtNom" type="text" />   </p> <p class="info"> <label> Couleur : </label> <input id="txtCouleur" type="text" /> </p> </div> En mode source toujours, faites glisser le fichier « JQuey-x.y.z.js » dans la page juste avant la balise «/head » fermante oĂč x.y.z est la version installĂ©e de JQuery En mode source, ajoutez le script « JavaScript » suivant : <script type="text/javascript"> $(function () { $(".info").hide(); $("#btnChercher").click(function () { var numero = $("#txtNumero").val(); ProductService.GetProduct(numero, function (data) { if (data == null) { alert('non trouvĂ© !'); $(".info").hide(); } else { $("#txtNom").val(data.Name); $("#txtCouleur").val(data.Color); $(".info").show(); } }); }); }); </script> La ligne suivante permet d’invoquer l’opĂ©ration « GetService » du service « GetProduct » avec comme paramĂštre la variable « numero ». Le deuxiĂšme paramĂštre est la fonction Ă  appeler lorsque l’appel rĂ©ussit. AJAX est bĂąti sur ce genre d’appel car le services s’exĂ©cutent d’une maniĂšre asynchrone, la fonction passĂ©e en paramĂštre est appelĂ©e « callback ». ProductService.GetProduct(numero, function (data) { if (data == null) { alert('non trouvĂ© !'); $(".info").hide(); } else { $("#txtNom").val(data.Name); $("#txtCouleur").val(data.Color); $(".info").show(); } }); ExĂ©cutez l’application en appuyant sur « F5 » Pour tĂ©lĂ©charger le code du tutoriel, cliquez ici