Déploiement automatique d’une application Web/WCF à l’aide de Release Manager for Visual Studio 2013 – Part 1

by sgross 13. mars 2014 17:46

Introduction

Cet article est le premier des 2 billets consacrés à Release Management for Visual Studio 2013.

Il s’agit d’un complément à la session que j’ai animée aux Techdays 2014 avec Jean Christophe, dont le Webcast est disponible ici, et les slides ici.

Contrairement à la session des Techdays, cette présentation s’inspire d’un cas client réel que nous venons de réaliser. Bien entendu, le nom des machines, des comptes, des applications et des acteurs a été modifié: toute ressemblance serait donc fortuite.

Les bases de Release Manager ne sont pas décrites dans cet article: le lien suivant décrit de manière très simple et complète les possibilités du produit. Il s’agit dans cet article de présenter Release Manager for Visual Studio 2013 dans un cas d’utilisation réel.

La présentation est découpée en 2 parties:

  • Problématique à résoudre, de l’installation et de la mise en place des bases
  • Réalisation des outils et composants, puis implémentation du workflow de déploiement

Contexte

L’application qui fait l’objet de cet article est l’ERP du client. Il travaille dans la grande distribution, et possède une quarantaine de magasins, pour un CA de 180M€. Cet ERP est un développement spécifique permettant de gérer les produits, les fournisseurs, les achats, les ventes, les magasins…c’est donc une application réellement vitale !

Il s’agit d’une application Web basée sur les derniers framework techniques, et utilise une couche de service WCF. L’application est répartie sur 5 serveurs, avec un dispositif de Load Balancing, un cache AppFabric. La gestion des données y joue évidemment un rôle capital.

Pour ce projet, la problématique du déploiement s’est rapidement posée. Nous avons d’abord mis en œuvre un déploiement basé sur MSBuild et MSDeploy (pour des précisions sur la mise en œuvre de MSDeploy, voir l’excellente série d’articles de Charles Barjansky).

Cependant, les déploiements restaient fastidieux à réaliser: une build par serveur rendait le processus de déploiement un peu lourd.

De plus, il est important de sécuriser ce déploiement, en prévoyant les cas où un incident se produirait. Le retour en arrière automatisé en cas de problème de déploiement est le moyen le plus rapide de revenir à une situation stable.

Voici une vision simplifiée de l’architecture d’intégration sur laquelle nous avons travaillé.

image

A noter que sur cet environnement d’intégration, les serveurs Web et WCF sont doublés.

Le processus de déploiement

Déploiement standard

Le déploiement normal doit se passer de la manière suivante :

image

Déploiement « Retour Arrière »

En cas de problème pendant le déploiement, et surtout lors d’une validation rejetée, Release Manager est capable d’effectuer un retour en arrière.

image

Contraintes et limitations

Le déploiement doit pouvoir être effectué quel que soit l’état initial de la plateforme :

  • IIS démarré ou pas
  • Cache démarré ou pas
  • Fichiers de mise à jour de base présents ou pas

Les versions successives des applications sont conservées.

Le retour en arrière se base toujours sur la version précédemment déployée, aussi bien pour la base de données, que pour les applications.

Le déclenchement d’un retour arrière, se fait par l’appréciation d’un opérateur manuel, selon qu’il approuve ou pas ce déploiement. Il n’y a pas de test automatique pour le moment.

Installation et paramétrage de base

Vue d’ensemble

Après avoir installé tous les composants, les activités pour mener à bien cette automatisation correspondent aux étapes décrites dans la documentation de Release Manager.

image

Installation

La procédure d’installation est décrite en détail dans le Guide d’installation fourni avec le produit. Il peut être téléchargé ici, ainsi que les différents composants logiciels de Release Manager 2013.

L’architecture de Release Management est la suivante :

image

Le point important est l’installation de l’outil Client Release Manager sur le serveur de Build. En effet, lors d’une Build, des appels à Release Management Server sont effectués : les outils client doivent être présents sur le serveur de Build. L’omission de ce client occasionne des erreurs lors des builds Release Manager.

Mise en place des basiques

Configuration générale

Dans un premier temps, il est nécessaire de connecter l’outil client au serveur Release Manager.

image

Lien avec TFS

Le lien avec le serveur TFS peut être mis en place, en précisant le compte de service utilisé.

image

Liste de choix

Des listes de choix sont utilisées pour caractériser les serveurs (par technologies) ou les phases (nom de phases).

imageimage

 

 

 

 

 

 

 

 

Groupes et utilisateurs

Il est pratique de se baser sur la sécurité de TFS pour simplifier le travail de maintenance des groupes. Le groupe TFS “Administrateur de Build” peut être un choix pertinent pour l’administration des déploiements Release Manager. En fonction du contexte, il conviendra de créer un groupe spécifique.

image

Les utilisateurs présents dans Release Manager proviennent:

  • Des groupes précédemment déclarés
  • Des comptes de services utilisés. Les comptes de services sont marqués en tant que Utilisateur de service.

image

Les chemins de déploiement

Les serveurs

Les serveurs doivent tous exécuter l’Agent de déploiement. Il faut par conséquent l’installer sur chaque serveur :

  • IIS / Web
  • IIS / WCF
  • SQL Server

Le choix du compte d’exécution de ce service est fait à la fin de l’installation. Ce compte devient administrateur local du poste. Il s’ajoute également à la liste des utilisateurs / Utilisateur du service de Release Manager.

La procédure d’installation des Agents est décrite dans la documentation du produit. Lorsque les serveurs sont installés, il s’agit de les déclarer dans l’outil. Le plus rapide est de lancer une détection des serveurs présents.

image

Les environnements

Les environnements sont créés en ajoutant les différents serveurs concernés.

image

 

Le chemin d’accès à la version finale

Seul le déploiement en intégration est programmé. Le Test ou la Production sont traitées différemment pour le moment.

image

L’acceptation du déploiement est automatisée, de façon à pouvoir déclencher le déploiement depuis une Build TFS directement.

Résultat

Le résultat obtenu après la programmation de ce déploiement est présenté ci dessous.

Avant cela, il y a bien sûr un peu de travail à réaliser. Ces activités seront décrites dans la deuxième partie !

image

Tags: , , , , ,

ALM | Développement

Mise en œuvre de l’outil de déploiement web IIS (Microsoft Web Deploy 3 .0) – Partie 3

by Charles BARJANSKY 31. janvier 2014 20:01

Préambule

Cet article complète la série des quatre articles pour vous présenter la solution d’automatisation de publication d’application Internet (ASP .NET, ASP .NET MVC, Silverlight, etc...) sur un serveur qui détient le rôle IIS.
Pour rappel, les quatre parties sont :

Le but de l’ensemble de ces articles est, bien entendu, de mettre en œuvre les bonnes pratiques en ce qui concerne l’un des pans de l’ALM (Application Lifecycle Management) : le déploiement d’une application.
 

Objectif de l’article "Mise en œuvre de l’outil de déploiement IIS (Microsoft Web Deploy 3 .0) – Partie 3

L’objectif de cette troisième partie est de décrire et de mettre en œuvre le fournisseur de sauvegarde automatique présent dans la solution Microsoft Web Deploy nommé BackupManager.
Cette solution permet :

  • de sauvegarder automatiquement une application web ainsi que sa base de données associée lors de chaque publication effectuée à l’aide l’outil Web Deploy ;
  • de restaurer une sauvegarde sans l’intervention d’un administrateur lors d’un échec de la publication ou lors du souhait de l’utilisateur de restaurer une ancienne version de l’application web.

Description de la solution de sauvegarde automatique IIS

Lors de chaque déploiement d’une application web via le déploiement web (voir les précédents articles), le fournisseur IIS backupManager identifie les différents fournisseurs consommés et sauvegarde automatiquement le contenu géré par ces fournisseurs.

Par exemple, si les fournisseurs lors d’un déploiement sont iisApp (gestion des fichiers du site) et dbFullSql (publication de la structure complète du schéma et des données) alors tous les fichiers du site et la base de données sont sauvegardés.

Ainsi, si besoin, l’utilisateur peut restaurer cette version précédente de l’application web à l’aide de l’outil msdeploy.


Mise en œuvre de la solution

Pré-Requis

Les pré-requis sont identiques à ceux de l’article précèdent. Pour rappel :

Pour permettre le succès du déroulement des deux mises en œuvre étudiées (dbFullSql & dbDacFx), veuillez suivre les tâches suivantes :
  1. Suivre l’article "Mise en oeuvre de l’outil de déploiement web IIS (Microsoft Web Deploy 3 .0) – Partie 1" ;
  2. Installation du package “Microsoft® System CLR Types for Microsoft® SQL Server® 2012 SP1” (disponible à l’adresse suivante : http://www.microsoft.com/en-us/download/details.aspx?id=35580) sur le/les serveurs qui détiennent le rôle IIS ;
  3. Installation du package “Microsoft® SQL Server® 2012 SP1 Shared Management Objects” (disponible à l’adresse suivante : http://www.microsoft.com/en-us/download/details.aspx?id=35580) sur le/les serveurs qui détiennent le rôle IIS ;
  4. Obtention des paramétrages de connexion d’un utilisateur SQL ayant les droits de création de base de données (dbcreator) et de modification des informations de sécurité (securityadmin) sur une instance Microsoft SQL Server (différent du paramétrage de connexion existant de l'application web).

De plus, pour la mise en œuvre de la solution du fournisseur dbDacFx, veuillez effectuer les tâches complémentaires suivantes :

  1. Installation du package “Microsoft® SQL Server® 2012 SP1 Transact-SQL ScriptDom” (disponible à l’adresse suivante : http://www.microsoft.com/en-us/download/details.aspx?id=35580) sur le/les serveurs qui détiennent le rôle IIS ;
  2. Installation du package “Microsoft® SQL Server® 2012 Data-Tier Application Framework (March 2013)” (disponible à l’adresse suivante : http://www.microsoft.com/en-us/download/details.aspx?id=36842) sur le/les serveurs qui détiennent le rôle IIS.

Activation du fournisseur backupManager

L’intégralité des opérations s’effectue à l’aide d’un script PowerShell présent dans le dossier Program Files de l’outil « Microsoft Web Deploy v3 ».

  1. A l’aide d’une console Powershell sur le serveur qui héberge le rôle IIS, exécuter les commandes :
    Set-Location "$env:ProgramFiles\IIS\Microsoft Web Deploy V3\Scripts"
    . .\BackupScripts.ps1
    Remarques : veillez à bien ajouter le point devant « .\BackupScripts.ps1 ». Ce point permet l’inclusion des fonctions présentes dans le fichier dans la session Powershell.
     
  2. Activer le fournisseur BackupManager :
    TurnOn-Backups -On $true
  3. Activer cette fonctionnalité pour l’intégralité des sites IIS :
    Configure-Backups -Enabled $true
  4. Spécifier l’emplacement des sauvegardes :
    Configure-Backups -BackupPath "{sitePathParent}\Backup_{siteName}"
    A l’aide de cette commande, les sauvegardes de l’application web « Neos-SDI.ContactManager » dont le contenu est à l’emplacement « c:\inetpub\Neos-SDI.ContactManager » seront stockés à l’emplacement « c:\inetPub\Backup_Neos-SDI.ContactManager ». Veillez à ne pas spécifier un dossier enfant à l’emplacement de l’application web sinon les sauvegardes seront supprimées à chaque déploiement.
    De plus, et dans le cas où le dossier de sauvegarde est situé sur un partage, vérifier la sécurité du dossier pour permettre aux utilisateurs IIS d’y effectuer la sauvegarde.
     
  5. Spécifier le nombre maximum de sauvegarde (recommandé) :
    Configure-Backups -NumberOfBackups 5
  6. Bloquer le déploiement des applications web si la sauvegarde échoue (recommandé) :
    Configure-Backups -ContinueSyncOnBackupFailure $false

La configuration du fournisseur BackupManager est terminée !
Dès lors, à chaque déploiement web, une sauvegarde du site est effectuée automatiquement. Il n’y a aucune manipulation supplémentaire pour les autres intervenants.

Restauration d’une sauvegarde

Dans le cas où un utilisateur souhaite restaurer une sauvegarde automatique, suivre les opérations suivantes :

  1. Pour récupérer la liste des sauvegardes disponibles, exécuter la commande suivante (remplacer les valeurs entre crochets) :
    msdeploy.exe -verb:dump -source:backupManager=[NomSiteIIS],wmsvc='[AdresseServiceGestionIIS]?site=[NomSiteIIS]',username='[NomUtilisateurIIS]',password='[MotDePasseUtilisateurIIS]' –allowUntrusted
    
    Le résultat pour notre environnement de test est le suivant :
    msdeploy.exe -verb:dump -source:backupManager=Neos-SDI.ContactManager,wmsvc='https://serveriis.neos-sdi.lan:8172/msdeploy.axd?site=Neos-SDI.ContactManager',username='Charles',password='P@ssw0rd' -allowUntrusted
    
    Remarques:
    • L’executable msdeploy se situe à l’emplacement suivant: "%ProgramFiles(x86)%\IIS\Microsoft Web Deploy V3 »
    • Le paramètre –allowUntrusted permet d’outrepasser la validation du certificat du service de gestion iis dans le cas de l’usage d’un certificat auto-généré.


  1. Pour restaurer une sauvegarde, exécuter la commande suivante (remplacer les valeurs entre crochet) :
    msdeploy.exe -verb:sync -source:backupManager -dest:backupManager=[NomSiteIIS]/[NomFichierZip],wmsvc='[AdresseServiceGestionIIS]?site=[NomSiteIIS]',username='[NomUtilisateurIIS]',password='[MotDePasseUtilisateurIIS]',connectionString=[ChaineConnexionSQL]' -skip:xpath=dirPath[@path='[DossierNonRestauré]'] -allowUntrusted
    
    Le résultat pour notre environnement de test est le suivant :
    msdeploy.exe -verb:sync -source:backupManager -dest:backupManager=Neos-SDI.ContactManager/msdeploy_2013_07_08_12_14_27.zip,wmsvc='https://10.24.0.10:8172/msdeploy.axd?site=Neos-SDI.ContactManager',username='Charles',password='P@ssw0rd',connectionString='Server=10.24.0.11;Database=ContactManager;User ID=ServerIIS;Password=P@ssw0rd' -skip:xpath=dirPath[@path='App_Data'] -allowUntrusted
    
    Remarques:
    • L’option “connectionString” est obligatoire si la sauvegarde contient une sauvegarde de base de données ;
    • Le paramètre « skip » permet de laisser en l’état un dossier lors de la restauration.

Sauvegarde manuelle

Il est possible d’effectuer une sauvegarde manuelle d’une application web et d’y associer des fournisseurs différents à ceux utilisés lors du déploiement web.
Dans notre cas, nous souhaitons effectuer une sauvegarde manuelle avec tout le contenu du site IIS ainsi que la base de données complète (schéma et données).

  1. Préparer un fichier manifest (format xml):
    <?xml version="1.0" encoding="utf-8"?>
    <m>
    <iisApp path="Neos-SDI.ContactManager" />
    <dbFullSql path="Server=10.24.0.11;Database=ContactManager;User ID=ServerIIS;Password=P@ssw0rd" IncludeHeaders="true" IncludeDatabaseContext="true" />
    </m>
    Nous avons déclaré deux fournisseurs (iisApp et dbFullSql).
    Pour le fournisseur dbFullSql, nous y spécifions la chaine de connexion de la base de données et nous y avons ajouté des options de script SMO supplémentaires.
    Par défaut, les options suivantes sont activées :
    • ScriptSchema
    • ScriptData
    • ScriptDropFirst
    • DriAll
    • Triggers
    • Indexes
    • NoFileGroup

    La liste complète des options de script SMO est disponible à l’adresse suivante : http://msdn.microsoft.com/en-us/library/Microsoft.SqlServer.Management.Smo.ScriptingOptions_properties.aspx
     
  2. Exécuter la commande suivante (remplacer les valeurs entre crochets) :
    msdeploy -verb:sync -source:backupManager=[EmplacementFichierManifest] -dest:backupManager=[NomSiteIIS],wmsvc='[AdresseServiceGestionIIS]?site=[NomSiteIIS]',username='[NomUtilisateurIIS]',password='[MotDePasseUtilisateurIIS]' –allowUntrusted
    Le résultat pour notre environnement de test est le suivant :
    msdeploy -verb:sync -source:backupManager=E:\Manifests\manifest.xml -dest:backupManager=Neos-SDI.ContactManager,wmsvc='https://10.24.0.10:8172/msdeploy.axd?site=Neos-SDI.ContactManager',username='Charles',password='P@ssw0rd' -allowUntrusted
    

 
Pour restaurer cette sauvegarde manuelle, la procédure est identique à une sauvegarde automatique.
 

Conclusion

Dans cet article, nous avons mis en œuvre une solution complète et simple de sauvegarde et de restauration des applications web hébergées sur un serveur qui possède le rôle IIS.

Pour notre dernier article, nous étudierons le déploiement d’une application web lors d’une compilation tfs (build tfs).

Tags: , , ,

Développement

Mise en œuvre de l’outil de déploiement web IIS (Microsoft Web Deploy 3 .0) – Partie 2

by Charles BARJANSKY 26. juin 2013 03:56

Préambule

Cet article complète la série des quatre articles pour vous présenter la solution d’automatisation de publication d’application Internet (ASP .NET, ASP .NET MVC, Silverlight, etc...) sur un serveur qui détient le rôle IIS.

Pour rappel, les quatre parties sont :

  • Installation de Microsoft Web Deploy (sur une instance Windows Server ayant le rôle IIS) et publication d’une application à partir de Microsoft Visual Studio 2012 ;
  • Publication d’une base de données ;
  • Sauvegarde de l’application lors de la publication ;
  • Publication d’une application lors d’un build TFS (TFS 2012).

Le but de l’ensemble de ces articles est de mettre en œuvre les bonnes pratiques en ce qui concerne l’un des pans de l’ALM (Application Lifecycle Management) : le déploiement d’une application.

Objectif de l’article "Mise en œuvre de l’outil de déploiement IIS (Microsoft Web Deploy 3 .0) – Partie 2"

L’objectif de cette seconde partie est de prendre connaissance des différentes solutions pour la création ou la mise à jour d’une base de données lors du déploiement d’une application web via l’outil Microsoft Web Deploy. Ensuite, pour certaines solutions sélectionnées, nous découvrirons la mise en œuvre.

Les solutions disponibles sont :

  • Migration Entity Framework Code First ;
  • Fournisseur Web Deploy dbDacFx ;
  • Fournisseur Web Deploy dbFullSql.

Les solutions mises en œuvre dans cet article sont :

  • Fournisseur Web Deploy dbDacFx ;
  • Fournisseur Web Deploy dbFullSql.

Description des solutions

Migration Entity Framework Code First

Lors de l’usage de la solution Entity Framework Code First (pour rappel, une solution d’ORM dans laquelle les interactions avec la base de données ainsi que les manipulations des données sont gérées uniquement par du code), le développeur peut déclarer la stratégie de création ou de mise à jour de la base de donnée à l’aide :

  • Des stratégies disponibles par défaut dans le framework Entity Framework :
    • DropCreateDatabaseAlways ;
    • DropCreateDatabaseWhenModelChanges ;
    • CreateDatabaseIfNotExists ;
    • MigrateDatabaseToLatestVersion.
  • De développements spécifiques qui définissent le processus de création ou de mise à jour de la base de données.

L’outil de déploiement Web Deploy peut, uniquement si la stratégie retenue par le développeur est "MigrateDatabaseToLatestVersion", se charger de la configuration de l’application web. Ainsi après le déploiement et lors du 1er démarrage de l’application web, la base de données sera automatiquement créé ou mise à jour avec les différentes évolutions des différentes entités que composent le contexte Entity Framework.

Cette fonctionnalité est disponible depuis la version 4.3 d’Entity Framework.

Fournisseur Web Deploy dbDacFx

Un fournisseur Web Deploy qui réalise :

  • Lors du déploiement initial, créer les tables et les objets à l’identique d’une base de données source sur la base de donnée cible ;
  • Lors des déploiements suivants, un traitement différentiel du schéma entre la base de données source et une base de données cible.

Par défaut, le fournisseur n’est pas destructeur, c’est-à-dire ne supprime pas de données en base. De plus, cette option permet l’exécution des scripts SQL complémentaires.

Fournisseur Web Deploy dbFullSql

Un fournisseur Web Deploy simple qui accomplit uniquement le déploiement initial d’une base de donnée (schéma avec ou sans données).

Mise en œuvre des solutions

Pré-Requis

Pour permettre le succès du déroulement des deux mises en œuvre étudiées (dbFullSql & dbDacFx), veuillez suivre les tâches suivantes :

  1. Suivre l’article "Mise en œuvre de l’outil de déploiement web IIS (Microsoft Web Deploy 3 .0) – Partie 1" ;
  2. Installation du package “Microsoft® System CLR Types for Microsoft® SQL Server® 2012 SP1” (disponible à l’adresse suivante : http://www.microsoft.com/en-us/download/details.aspx?id=35580) sur le/les serveurs qui détiennent le rôle IIS ;
  3. Installation du package “Microsoft® SQL Server® 2012 SP1 Shared Management Objects” (disponible à l’adresse suivante : http://www.microsoft.com/en-us/download/details.aspx?id=35580) sur le/les serveurs qui détiennent le rôle IIS ;
  4. Obtention des paramétrages de connexion d’un utilisateur SQL ayant les droits de création de base de données (dbcreator) et de modification des informations de sécurité (securityadmin) sur une instance Microsoft SQL Server (différent du paramétrage de connexion existant de l'application web).

De plus, pour la mise en œuvre de la solution du fournisseur dbDacFx, veuillez effectuer les tâches complémentaires suivantes :

  1. Installation du package “Microsoft® SQL Server® 2012 SP1 Transact-SQL ScriptDom” (disponible à l’adresse suivante : http://www.microsoft.com/en-us/download/details.aspx?id=35580) sur le/les serveurs qui détiennent le rôle IIS ;
  2. Installation du package “Microsoft® SQL Server® 2012 Data-Tier Application Framework (March 2013)” (disponible à l’adresse suivante : http://www.microsoft.com/en-us/download/details.aspx?id=36842) sur le/les serveurs qui détiennent le rôle IIS.

Remarques : veillez à redémarrer le/les serveurs qui détiennent le rôle IIS à la fin des installations des packages.

Mise en œuvre de la solution fournisseur Web Deploy dbFullSql

Création d’une délégation du fournisseur dbFullsql

  1. Dans la console "Gestionnaire des services Internet (IIS)" ("Internet Information Services (IIS)") : 
    • Sélectionner le serveur désiré ;
    • Dans la vue "Affichage des fonctionnalités" ("Features View") > "Gestion" ("Management"), sélectionner l’élément "Délégation du service de gestion" ("Management Service Delegation").
    IIS Home
  2. Dans la vue "Délégation du service de gestion" ("Management Service Delegation"), cliquer sur "Ajouter une règle... " (" Add Rule... ") ;
    Management Service Delegation
  3. Dans la fenêtre "Ajouter une règle" ("Add Rule"), sélectionner "Règle vide" ("Blank rule") et cliquer sur "OK" ;
    Add Rule
  4. Dans la fenêtre "Ajouter une règle" ("Edit Rule"):
    • Fournir les informations suivantes :
      • "Fournisseurs" ("Providers") :
        1. "dbFullSql".
      • Actions :
        1. "*".
      • "Type de chemin" ("Path Type") :
        1. "Chaîne de connexion" ("Connection String").
      • "Chemin d’accès" ("Path") :
        1. "Datasource=".
      • "Type d’identité" ("Identity Type") :
        1. "Current User".
    • Cliquer sur "OK".
    Edit Rule
  5. Dans la fenêtre "Ajouter un utilisateur à la règle" ("Add User To Rule"), saisir le nom de l’utilisateur IIS dans le champ "Nom" ("Name") puis cliquer sur "OK" ;
    Add User To Rule
  6. La règle de délégation est créée avec l’utilisateur associé.
    Management Service Delegation

Activer la publication Web Deploy pour un site IIS

  1. Suivre la procédure "Activer la publication Web Deploy pour un site IIS" de l’article "Mise en œuvre de l’outil de déploiement web IIS (Microsoft Web Deploy 3 .0) – Partie 1". Aucune information supplémentaire n’est nécessaire pour la publication à l’aide du fournisseur dbFullSql.

Configurer la publication SQL (Visual Studio 2012)

  1. Dans votre solution Visual Studio 2012, effectuer un clic droit sur le projet Web et sélectionner l’option “Propriétés ("Properties") ;
    Visual Studio 2012
  2. Dans l’onglet des propriétés de votre projet web : 
    1. Cliquer sur l’onglet "Package/Publication SQL" ("Package/Publish SQL") ;
    2. Sélectionner la configuration de solution correspondant à celle de votre déploiement web ("Release" par exemple") ;
    3. Cliquer sur le bouton "Activer cette page" ("Enable this Page") ;
      Publish SQL
    4. En fonction de votre l’application web, ajouter les entrées de base de données que vous souhaitez déployer à l’aide des boutons "Importer depuis Web.config" ("Import from Web.config") ou "Ajout” ("Add") ;
      Database Entries
    5. Spécifier pour chaque entrée de base de données ("Database Entries"):
      1. La chaine de connexion SQL (avec les informations de l’utilisateur SQL ayant les droits "dbcreator" et "security admin") sur la base de données de destination ;
         
        Remarques :
        • Celle-ci ne sera utilisée uniquement pour le déploiement de la base de données et ne remplace pas la chaîne de connexion présente dans le fichier de configuration ;
        • Cette chaîne de connexion doit fonctionner à partir du serveur qui détient le rôle IIS (car le déploiement est effectué à partir de l’instance IIS du serveur et non à partir de la machine en local).
      2. Les sources :
        1. Autogénéré (à partir de votre base de données développement) ;
        2. Script SQL (ajout d’un script SQL).
           
          Remarques :
          • Le script autogénéré est effectué à partir de l’instance Visual Studio 2012 (et non à partir fonctionner à partir du serveur qui détient le rôle IIS) ;
          • Le script autogénéré nécessite les informations supplémentaires :
            • Chaine de connexion ;
            • Type de script généré (schéma seul, schéma et données ou données uniquement).
        Pull data and or schema

Publication de l’application Internet (Visual Studio 2012)

  1. Suivre la procédure "Publication de l’application Internet (Visual Studio 2012)" de l’article "Mise en œuvre de l’outil de déploiement web IIS (Microsoft Web Deploy 3 .0) – Partie 1". Aucune information supplémentaire n’est nécessaire pour la publication à l’aide du fournisseur dbFullSql.

Mise en œuvre de la solution fournisseur Web Deploy dbDacFx

Création d’une délégation du fournisseur dbDacFx

  1. Dans la console "Gestionnaire des services Internet (IIS)" ("Internet Information Services (IIS)") : 
    • Sélectionner le serveur désiré ;
    • Dans la vue "Affichage des fonctionnalités" ("Features View") > "Gestion" ("Management"), sélectionner l’élément "Délégation du service de gestion" ("Management Service Delegation").
    IIS Home
  2. Dans la vue "Délégation du service de gestion" ("Management Service Delegation"), cliquer sur "Ajouter une règle... " (" Add Rule... ") ;
    Management Service Delegation
  3. Dans la fenêtre "Ajouter une règle" ("Add Rule"), sélectionner "Règle vide" ("Blank rule") et cliquer sur "OK" ;
    image
  4. Dans la fenêtre "Ajouter une règle" ("Edit Rule"):
    • Fournir les informations suivantes :
      • "Fournisseurs" ("Providers") :
        1. "dbDacFx".
      • Actions :
        1. "*".
      • "Type de chemin" ("Path Type") :
        1. "Chaîne de connexion" ("Connection String").
      • "Chemin d’accès" ("Path") :
        1. "Datasource=".
      • "Type d’identité" ("Identity Type") :
        1. "Current User".
    • Cliquer sur "OK".
    Edit Rule
  5. Dans la fenêtre "Ajouter un utilisateur à la règle" ("Add User To Rule"), saisir le nom de l’utilisateur IIS dans le champ "Nom" ("Name") puis cliquer sur "OK" ;
    Add User To Rule
  6. La règle de délégation est créée avec l’utilisateur associé.
    Management Service Delegation

Activer la publication Web Deploy pour un site IIS

  1. Dans la console "Gestionnaire des services Internet (IIS)" ("Internet Information Services (IIS)") :
    1. Sélectionner le serveur désiré ;
    2. Déployer le nœud "Sites" ;
    3. Effectuer un clic droit sur le site sur lequel vous souhaitez activer l’option ;
    4. Sélectionner "Déployer" ("Deploy") puis "Activer la publication Web Deploy" ("Configure Web Deploy Publishing") ;
    IIS Site
  2. La fenêtre "Activer la publication Web Deploy" ("Configure Web Deploy Publishing") s’affiche. A l’emplacement "Sélectionner un utilisateur auquel accorder les autorisations de publication", cliquer sur le bouton "..." ;
    Configure Web Deploy Publishing
  3. Dans la fenêtre "Autoriser l’utilisateur..." ("Allow User..."), sélectionner la pastille "Gestionnaire des services Internet" ("IIS Manager"), sélectionner l’utilisateur désiré et cliquer sur "OK" ;
    image
  4. A l’emplacement "Insérer la chaîne de connexion SQL Server utilisé pour la publication" ("Enter SQL Server connection string to be used for publishing", cliquer sur le bouton "..." ;
    Configure Web Deploy Publishing
  5. Dans la fenêtre "Editer la chaine de connexion" ("Edit Connection String"), utiliser les différentes options pour créer/éditer la chaîne de connexion et cliquer sur "OK" ;
    Edit Connection String
  6. Dans la fenêtre "Activer la publication Web Deploy" ("Configure Web Deploy Publishing"), vérifier les différentes informations et cliquer sur "Configurer" ("Setup") ;
    Configure Web Deploy Publishing
  7. Vérifier le résultat puis cliquer sur "Fermer" ("Close") ;
    image
  8. Vous pouvez désormais rendre disponible le fichier généré à la personne désirée.
    PublishSettings File


 
 
 
 
 
 
 
 
 
 

Publication de l’application Internet (Visual Studio 2012)

  1. Dans votre solution Visual Studio 2012, effectuer un clic droit sur le projet Web et sélectionner l’option “Publier…” ("Publish...") ;
    image
  2. L’assistant “Publier le site Web” ("Publish Web") s’affiche. Cliquer sur le bouton "Importer..." ("Import...") et sélectionner le fichier généré avec l’extension .publish ;
    image
  3. A l’étape "Connexion" ("Connection"), saisir le mot de passe, valider les informations via le bouton "Valider la connexion" ("Validate Connection") puis cliquer sur le bouton "Suivant >" ("Next >") ;
    image
  4. A l’étape "Paramètres" ("Settings"), cocher la case "Mettre à jour la base de donnée" ("Update database") et cliquer sur le bouton "Suivant >" ("Next >") ;
    image
  5. A l’étape "Aperçu" ("Preview"), vous pouvez visualiser les modifications apportées à la base de données en cliquant sur le lien “Prévisualiser la base de données” ("Preview Database") ;
  6. Pour terminer, cliquez sur “Publier” ("Publish") ;
    image
  7. A la fin de la publication, le navigateur est lancé pour permettre de vérifier le bon fonctionnement du site.
    image

Conclusion

Dans cet article, nous avons identifié et mise en œuvre les différentes solutions disponibles de déploiement d’une base de données associée à une application web à l’aide de l’outil Microsoft Web Deploy.

Nous aborderons dans le prochain article la sauvegarde automatique de l’application lors de chaque déploiement sur la plateforme IIS à l’aide de l’outil Microsoft Web Deploy.

Tags: , , ,

Développement | Infrastructure

Mise en œuvre de l’outil de déploiement web IIS (Microsoft Web Deploy 3 .0) – Partie 1

by Charles BARJANSKY 19. février 2013 02:18

Préambule

J’entame avec cet article une série de quatre articles pour vous présenter la solution d’automatisation de publication d’application Internet (ASP .NET, ASP .NET MVC, Silverlight, etc...) sur un serveur IIS.

Les quatre parties sont :

  • Installation de Microsoft Web Deploy (sur une instance Windows Server ayant le rôle IIS) et publication d’une application à partir de Microsoft Visual Studio 2012
  • Publication d’une base de données
  • Sauvegarde de l’application lors de la publication
  • Publication d’une application lors d’un build TFS (TFS 2012)

Le but de l’ensemble de ces articles est, bien entendu, de mettre en œuvre les bonnes pratiques en ce qui concerne l’un des pans de l’ALM (Application Lifecycle Management) : le déploiement d’une application.

Objectif de l’article "Mise en œuvre de l’outil de déploiement IIS (Microsoft Web Deploy 3 .0) – Partie 1"

L’objectif de cette première partie est de vulgariser la mise en œuvre de l’outil de déploiement IIS (Microsoft Web Deploy) et la publication d’une application Internet via la méthode "déploiement web" (Web Deployment) à partir de Visual Studio sur un serveur IIS.

Cette mise en œuvre comprend :

  1. L’installation de l’outil Microsoft Web Deploy 3.0 est un prérequis pour permettre la mise en place de la publication web d’une application Internet.
  2. La création d’un utilisateur IIS pour s’affranchir des problèmes de gestion d’un utilisateur Windows dans une infrastructure hétérogène.
    "Vous pouvez ajouter un compte d'utilisateur du Gestionnaire des services Internet (IIS) dans le Gestionnaire des services Internet (IIS) si vous souhaitez autoriser un utilisateur à se connecter à un site ou à une application du serveur, mais ne souhaitez pas créer un compte d'utilisateur Windows ou ajouter l'utilisateur dans un groupe Windows. Les informations d'identification du Gestionnaire des services Internet (IIS) se composent d'un nom d'utilisateur et d'un mot de passe qui sont créés dans le Gestionnaire des services Internet (IIS) et sont utilisés exclusivement pour que le Gestionnaire des services Internet (IIS) accède aux fichiers de configuration IIS."
    (source : http://technet.microsoft.com/fr-fr/library/cc732621%28v=ws.10%29.aspx)
  3. La création d’une règle de délégation qui ajoute des autorisations à un utilisateur (Windows ou IIS) de gestion de un ou plusieurs sites IIS ou de une ou plusieurs applications.
  4. L’activation de la fonctionnalité de déploiement web sur un site IIS permet:
    • D’activer l’option de déploiement web sur un site IIS
    • De désigner l’utilisateur (Windows ou IIS) qui sera autorisé à déployer
    • De générer un fichier .Publishsettings
  5. La publication d’une application Internet partir de Visual Studio grâce au fichier .PublishSettings. Dès lors, nous pourrons déployer une application Internet vers une instance IIS à partir de Microsoft Visual Studio en moins de 10 clics de souris...

Installation de l’outil de déploiement (Web Deploy 3.0)

Pré-Requis

Les pré requis pour permettre cette mise en œuvre sont :

Mise en œuvre pas à pas

  1. Exécuter l’exécutable "WebDeploy_x[platefom]_xx_xx.msi"
  2. A l’étape de démarrage "Bienvenue dans l’Assistant d’installation de Microsoft Web Deploy 3.0" ("Welcome to the Microsoft Web Deploy 3.0 Setup Wizard"), démarrer l’installation de l’outil en cliquant sur "Suivant" ("Next")
    Microsoft Web Deploy 1
  3. A l’étape "Contrat de Licence Utilisateur Final" ("End-User Licence Agreement"), accepter les termes et cliquer sur "Suivant" ("Next")
    Microsoft Web Deploy 2
  4. A l’étape "Choisissez un type d’installation" ("Choose Setup Type"), cliquer sur "Complète" ("Complete")
    Microsoft Web Deploy 3
  5. A l’étape "Prêt à installer Microsoft Web Deploy 3.0", cliquer sur "Installer" ("Install")
    Microsoft Web Deploy 4
  6. Patienter lors de l’installation du composant
    Microsoft Web Deploy 5
  7. A la fin de l’assistant, cliquer sur "Terminer" ("Finish")
    Microsoft Web Deploy 6 

Paramétrage de l’outil de déploiement web

Création d’un utilisateur IIS

  1. Dans la console "Gestionnaire des services Internet (IIS)" ("Internet Information Services (IIS)"),
    1. Sélectionner le serveur désiré
    2. Dans la vue "Affichage des fonctionnalités" ("Features View") > "Gestion" ("Management"), sélectionner l’élément "Utilisateurs du Gestionnaire des services Internet" ("IIS Manager User")
    Utilisateur 1
  2. Dans la vue "Utilisateurs du Gestionnaire des services Internet" ("IIS Manager User"), cliquer sur "Ajouter un utilisateur..." ("Add User... ")
    Utilisateur IIS 2
  3. Spécifier un "Nom d’utilisateur" ("User name"), un "Mot de passe" ("Password") et cliquer sur le bouton "OK"

    Utilisateur IIS 3

Création d’une délégation du service de gestion

  1. Dans la console "Gestionnaire des services Internet (IIS)" ("Internet Information Services (IIS)"),
    1. Sélectionner le serveur désiré
    2. Dans la vue "Affichage des fonctionnalités" ("Features View") > "Gestion" ("Management"), sélectionner l’élément "Délégation du service de gestion" Management Service Delegation")
    Delegation IIS 1
  2. Dans la vue "Délégation du service de gestion" ("Management Service Delegation"), cliquer sur "Ajouter une règle... " (" Add Rule... ")
    Delegation IIS 2
  3. Dans la fenêtre "Ajouter une règle" ("Add Rule"), sélectionner "Règle vide" ("Blank rule") et cliquer sur "OK"
    Delegation IIS 3
  4. Dans la fenêtre "Ajouter une règle" ("Add Rule"),
    1. fournir les informations suivantes :
      1. "Fournisseurs" ("Providers")
        1. "contentPath"
        2. "createApp"
        3. "iisApp"
        4. "setAcl"
      2. "Actions"
        1. "*"
      3. "Type de chemin" ("Path Type")
        1. "Préfixe du chemin d’accès" ("Prefix Path")
      4. "Chemin d’accès" ("Path")
        1. "{userScope}"
      5. "Type d’identité" ("Identity Type")
        1. "Current User"
    2. Cliquer sur "OK"
    Delegation IIS 4
  5. Dans la fenêtre "Ajouter un utilisateur à la règle" ("Add User To Rule"), saisir le nom de l’utilisateur IIS dans le champ "Nom" ("Name") puis cliquer sur "OK".
    Delegation IIS 5
  6. La règle de délégation est créée avec l’utilisateur associé
    Delegation IIS 5

Activer la publication Web Deploy pour un site IIS

  1. Dans la console "Gestionnaire des services Internet (IIS)" ("Internet Information Services (IIS)"),
    1. Sélectionner le serveur désiré
    2. Déployer le nœud "Sites"
    3. Effectuer un clic droit sur le site sur lequel vous souhaitez activer l’option
    4. Sélectionner "Déployer" ("Deploy") puis "Activer la publication Web Deploy" ("Configure Web Deploy Publishing")
    Activation 1
  2. La fenêtre "Activer la publication Web Deploy" ("Configure Web Deploy Publishing") s’affiche. A l’emplacement "Sélectionner un utilisateur auquel accorder les autorisations de publication", cliquer sur le bouton "..."
    Activation 2
  3. Dans la fenêtre "Autoriser l’utilisateur..." ("Allow User..."), sélectionner la pastille "Gestionnaire des services Internet" ("IIS Manager"), sélectionner l’utilisateur désiré et cliquer sur "OK"
    Activation 3
  4. Dans la fenêtre "Activer la publication Web Deploy" ("Configure Web Deploy Publishing"), vérifier les différentes informations et cliquer sur "Configurer" ("Setup")
    Activation 4
  5. Vérifier le résultat puis cliquer sur "Fermer" ("Close")
    Activation 5
  6. Vous pouvez désormais rendre disponible le fichier généré à la personne désirée
    Activation 6

Publication de l’application Internet (Visual Studio 2012)

  1. Dans votre solution Visual Studio 2012, effectuer un clic droit sur le projet Web et sélectionner l’option "Publish..."
    Visual Studio 1
  2. L’assistant "Publish Web" s’affiche. Cliquer sur le bouton "Importer..." ("Import...") et sélectionner le fichier généré avec l’extension .publish.
    clip_image004[10]
  3. A l’étape "Connexion" ("Connection"), saisir le mot de passe, lancer la validation des informations via le bouton "Valider la connection" ("Validate Connection") puis cliquer sur "Publier" ("Publish")
    clip_image006[10]
  4. A la fin de la publication, le navigateur est lancé pour permettre de vérifier le bon fonctionnement du site.
    clip_image008[10]

Remarques

Vérification du type de démarrage du service "Service de gestion Web" ("Web Management Service")

Pour permettre le bon fonctionnement de l’outil de déploiement, vérifier le type de démarrage (Startup Type) du service "Service de gestion Web" ("Web Management Service") est spécifié à "Automatique (début différé)" ("Automatic (Delayed Start)")

Autres 1

Règle de pare-feu

Pour permettre le bon fonctionnement du service de gestion IIS, il faut s’assurer que le port 8172 est correctement configuré.
Dans le cas inverse, exécuter cette commande dans une console Powershell avec le jeton "Administrateur" ("Run As Administrator"):

New-NetFirewallRule -DisplayName "Allow IIS Management Service In" -Direction Inbound -LocalPort 8172 -Protocol TCP -Action Allow

Activation du suivi des requêtes échouées

Vous pouvez activer le suivi des requêtes échoués si vous rencontrez des difficultés lors du paramétrage de l’outil.
Vous pouvez activer l’option "Activer le suivi de requêtes échouées" ("Enable failed request tracing") dans la vue "Service de gestion" ("Management Service").

Autres 2

Dès lors, vous pouvez consulter les différentes tentatives de publication échoués à l’emplacement suivant :

%SystemDrive%\inetpub\logs\wmsvc\TracingLogFiles

Liste des "fournisseurs de déploiement web" ("Web Deploy Providers")

La liste des fournisseurs ainsi que leur description est disponible à l’emplacement suivant : http://technet.microsoft.com/fr-fr/library/dd569040.aspx

 

A bientôt!

Tags: , , ,

Développement | Infrastructure

BizTalk - Bug sur les Delivery Notifications (BizTalk 2006 R2 et 2009) – Part 1

by srivas 1. février 2013 02:38

J’ai dernièrement rencontré un problème assez déroutant chez un client utilisant les delivery notifications (DN) sur une plateforme BizTalk 2006 R2

 

Rappel : principe des delivery notifications

Mécanisme général

BizTalk a la capacité de publier automatiquement des acquittements positifs (ACK) en cas de transmission réussie d’un message et des acquittements négatifs (NACK) en cas d’erreur. Les orchestrations peuvent utiliser les DN pour s’abonner aux acquittements pour les messages qu’elles envoient.

L’activation des DN se fait de 2 manières :

  • La plus courante est de positionner la propriété Delivery Notification d’un port logique d’envoi (dans une orchestration) à Transmitted.

image

  • Une autre méthode est de positionner la propriété de contexte BTS.AckRequired à true sur le message à envoyer.

image

NOTE : fondamentalement, les deux méthodes sont identiques puisque le positionnement de la propriété Delivery Notification à Transmitted au niveau du port indique simplement à BizTalk qu’il faut positionner la propriété BTS.AckRequired à true sur tous les messages transitant par le port.

Propriétés de contexte associées

Les ACKs et NACKs ont chacun un jeu de propriétés de contexte promues associé, qui sont les suivantes :

Propriété Description
AckType Vaut ACK en cas de succès ou NACK en cas d’erreur
AckID MessageID du message auquel est associé l’acquittement
AckOwnerID InstanceID de l’instance à laquelle est associé l’acquittement
AckSendPortID ID du port par lequel le message a été envoyé
AckSendPortName Nom du port par lequel le message a été envoyé
AckOutboundTransportLocation URL du port par lequel le message a été envoyé
AckReceivePortID  ID du port par lequel le message est arrivé
AckReceivePortName Nom du port par lequel le message est arrivé
AckInboundTransportLocation URL du port de réception

Fonctionnement détaillé

La publication des acquittements présente une particularité par rapport au fonctionnement standard de la Message Box : en effet si aucune souscription active n’existe pour un acquittement, celui-ci est simplement ignoré. La conséquence de ceci est qu’il ne peut pas y avoir d’erreur de routage sur un acquittement et qu’un acquittement ne peut être suspendu.

D’autre part, lorsqu’un message est envoyé sur un port d’envoi pour lequel la propriété Delivery Notification est positionnée à Transmitted, un correlation set est initialisé, et un jeton de correlation propriété CorrelationToken) est associé au message sortant, et sera également associée à l’acquittement (la propriété sera également promue). Lorsque l’acquittement est créé, il est automatiquement routé vers l’orchestration appelante.

Enfin lorsque l’orchestration appelante reçoit un ACK, l’orchestration sort du Scope dans lequel elle était arrêtée et reprend ses traitements suivants. Lorsqu’elle reçoit un NACK, une exception de type DeliveryFailureException est générée, qui peut alors être interceptée dans une section Catch.

 

Contexte du problème

Le contexte est le suivant :

  • Dans une orchestration, les DN sont activés sur un port d’envoi unidirectionnel
  • En cas d’erreur, l’instance de messaging est suspendue et l’orchestration intercepte bien une exception (DeliveryFailureException), le mécanisme fonctionne donc comme prévu jusque-là.
  • Dès interception de l’exception, l’orchestration est programmatiquement terminée (au moyen d’une shape Terminate)

A ce stade, il reste donc uniquement l’instance de messaging suspendue, en attente d’être résumée.

Symptômes

Une fois le problème à l’origine de l’erreur (dans le cas de mon client : les droits sur un site FTP avaient sauté), on résume l’instance de messaging.

Le comportement attendu est que cette instance passe au statut Completed, ne laissant ainsi plus aucune instance active ou suspendue.

Or l’instance de messaging est à nouveau suspendue mais pour cause d’erreur de routage, résultant donc en une instance suspendue résumable correspondant au message lui-même et une instance suspendue non résumable correspondant au rapport d’erreur de routage :

image

Le rapport d’erreur de routage nous apprend que les propriétés suivantes sont attachées au message :

image

 

Diagnostic

Les propriétés attachées au message nous indiquent que c’est tout simplement un acquittement (ACK dans notre cas) qui a été publié dans la Message Box et qui a été suspendu du fait qu’aucune souscription active n’a été trouvée.

En effet : l’orchestration appelante s’est terminée après avoir reçu un premier NACK. Puisqu’elle est terminée, sa souscription sur les acquittements n’est plus active, et le ACK ne peut être routé vers aucune instance active. Le résultat est donc une erreur de routage.

Or ce fonctionnement est en contradiction avec le principe des DN (cf plus haut) : un acquittement ne peut pas être suspendu, il devrait être ignoré.

Cause

Il s’agit bien d’un bug, apparu avec le SP1 de BizTalk 2006 R2. Il est passé au travers des 4 Cumulative Updates suivants.

Par curiosité, j’ai effectué le test sur une plateforme BizTalk Server 2009 sur laquelle le CU6 avait été appliqué, le bug était toujours présent… Reste à élargir les tests aux versions 2010 et 2013.

Solution

Il n’existe donc aucun correctif, mais on peut mettre en place une solution de contournement. Celle-ci consiste à créer une orchestration s’abonnant sur un message de type XmlDocument pour lequel la propriété AckType existe, le port de réception étant en binding direct sur la Message Box. Ainsi cette orchestration consommera systématiquement tous les acquittements, ACKs comme NACKs, ce qui évitera toute erreur de routage. L’orchestration serait comme suit :

image

D’autre part, de manière à ne pas polluer le HAT et la DTADb (après tout, cette orchestration ne fait que se substituer à la mécanique interne de BizTalk, il ne devrait donc pas y avoir de traces de son fonctionnement), il suffit de désactiver tout le tracking :

image

Néanmoins cette solution ne résout pas tout, comme nous le verrons dans un autre article (BizTalk - Bug sur les Delivery Notifications (BizTalk 2006 R2 et 2009) – Part 2), à paraitre.

Tags: , , ,

Biztalk

Créer sa première application Windows Store avec C# XAML

by acamara 16. octobre 2012 00:30

Introduction

Comment créer sa première application Modern UI, avec C# XAML?

Les applications Modern UI connaissent un véritable essor dans le monde du développement. Notamment, avec l'arrivée imminente du nouvel OS Windows 8 de chez Microsoft, ainsi qu'une multitude d’appareils et de supports tactiles, sur lesquels nous allons justement pouvoir utiliser ces applications.

Sur la toile, vous trouverez un bon nombre de tutoriels pour commencer à développer une application pour Windows 8. Je pense au blog de Loïc Rebours, que je trouve complet.

Dans cette article, j’insisterai sur la manière dont nous pouvons développer une application, en utilisant le pattern MVVM, au travers d’un exemple concret. Puis, dans un second article, je vous présenterai une manière de déployer une application sans passer par le Windows Store. Quels genres de contraintes et de restrictions allons-nous rencontrer ?

 

Prérequis

Avant de rentrer dans le vif du sujet, nous allons commencer par les prérequis.

Pour concevoir des applications Windows Store, il faut :

  • être doté d’une machine équipée de l’OS Windows 8, et d’un compte Microsoft (nécessaire et pour faciliter les déploiements)
  • avoir une licence Développeur Microsoft (gratuite) ; cette licence est proposée lors de la première compilation d’un projet Windows Store
  • être équipé de l’IDE Visual Studio 2012,  avec le Framework 4.5 (à minima)

Contexte

Notre application consiste à afficher le profil d’un utilisateur depuis un back-end existant :

 

Dans le monde de l’entreprise, on a souvent besoin de récupérer les informations depuis une base de données ou un Active Directory, par exemple.

Pour rappel, une application Modern UI évolue dans un  environnement dit « Sandbox ». C’est-à-dire qu’une telle application ne peut communiquer directement avec une application tierce.

Les applications Windows Store sont soumises à des restrictions. Et, par conséquent, elles ne peuvent interagir directement avec une base de données ou un annuaire LDAP. Pour cela, la solution du Web service va nous permettre de répondre à notre besoin.

Le but de cet article n’est pas d’apprendre comment créer un Web Service avec WCF. Je pourrais très bien créer une « data source », pour simplifier les développements. Mais, je pense qu’on passerait à côté de certaines informations.

 

Préliminaires

Nous sommes partis du principe que la partie Middleware et Back-end existaient déjà. En effet, cette partie a été précédemment développée pour les besoins d’une application interne. Il s’agit du trombinoscope de Neos-SDI développé à partir d’un des templates de Windows Store Apps (« Je dis ça, je dis rien ! »).

Voici, la solution finale avec la logique MVVM. Cette solution sera disponible en interne. 

 

Qu’est-ce que le MVVM ?

Le MVVM est un « pattern »  de conception architecturale qui permet une séparation indépendante entre les couches :

  • métier : le Model
  • de présentation : la View
  • et, on va dire le contrôleur (par analogie au design pattern MVC) : la ViewModel ; cette dernière couche va jouer le rôle du liant entre la couche métier et la couche de présentation.

 

Pour bien commencer…

Avant de mettre en place l’architecture MVVM dans notre projet, souvenez-vous qu’une application Windows Store est une application Sandbox (restrictive). Une application est soumise à des contraintes déclaratives.

Pour pouvoir communiquer avec l’extérieur, ou consommer un Web Service, il va donc falloir déclarer cette fonctionnalité dans notre application. Cela se passe dans notre fichier de manifeste, Package.appxmanifest (situé à la racine de notre projet) :

NB : Pour pouvoir faire évoluer notre application et gérer les ressources de déploiement, il faut donc passer par ce fichier de manifeste.

 
Rentrons dans le vif du sujet, il va y avoir du code…

Dans la famille MVVM, je demande le…

 ...Model :

 

 

Le Model  représente les objets métier de notre back-end (cf. Contexte).  Ici, notre source de données provient de l’annuaire LDAP de notre société. Pour notre besoin, la classe Neostee représente un utilisateur commun à Neos-SDI. Cette classe est visible dans notre projet, si et seulement si nous intégrons la référence au Web Service (Middleware).

NB : Cette classe hérite d’une classe de base qui implémente l’interface INotifyPropertyChanged. Nous verrons un exemple de code, par la suite.
 

Dans la famille ViewModel, je demande le…

ViewModel :

 

 

Le ViewModel représente la liaison entre le Model et la View. L’idée est d’implémenter aussi l’interface INotifyPropertyChanged (comme dans le Model) afin d’utiliser le mécanisme de « Binding » entre la vue et l’objet métier. Nous verrons comment faire le lien entre nos objets métier et la vue.
 

Pour détailler la classe ViewModelBase, comme pour la classe ModelBase, voici une implémentation de l’interface INotifyPropertyChanged :

 

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Threading.Tasks;

namespace AppLoadProfil.ViewModel
{
    public abstract class ViewModelBase : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;

        public void OnChangedProperty(string propertyName)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }

        public void OnChangedProperty<T>(Expression<Func<T>> expression)
        {
            MemberExpression body = expression.Body as MemberExpression;

            if (body == null)
            {
                throw new ArgumentException("erreur dans l'expression");
            }

            string propertyName = body.Member.Name;

            if (!string.IsNullOrEmpty(propertyName))
            {
                OnChangedProperty(propertyName);
            }
        }
    }
}

La classe de base implémente l’évènement : event PropertyChangedEventHandler PropertyChanged; 

Les 2 surcharges de méthodes OnChangedProperty permettent de détecter le changement de valeur d’une propriété rattachée à notre ViewModel (ou notre Model).

 

Comment allons-nous utiliser cette classe de base ?

La classe ProfilViewModel hérite de cette classe de base 

 

using AppLoadProfil.BusinessLayer.Impl;
using AppLoadProfil.BusinessLayer.Interfaces;
using AppLoadProfil.Common;
using AppLoadProfil.LdapService;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Windows.Storage;
using Windows.Storage.Streams;
using Windows.UI.Popups;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Media.Imaging;

namespace AppLoadProfil.ViewModel
{
    public class ProfilViewModel : ViewModelBase
    {

        #region properties

        private Neostee _neostee = null;

        public Neostee TheNeostee
        {
            get { return _neostee; }
            set
            {
                _neostee = value;
                //base.OnChangedProperty("TheNeostee");
                base.OnChangedProperty<Neostee>(() => this.TheNeostee);
            }
        }

        private string _commonName;

        public string CommonName
        {
            get { return _commonName; }
            set
            {
                _commonName = value;
                base.OnChangedProperty("CommonName");
            }
        }


        private ObservableCollection<Neostee> _Neostees = null;

        public ObservableCollection<Neostee> Neostees
        {
            get { return _Neostees; }
            set
            {
                _Neostees = value;
                base.OnChangedProperty("Neostees");
            }
        }
        #endregion

        #region ctors
        public ProfilViewModel()
        {
            _Neostees = new ObservableCollection<Neostee>();
            LoadAsync();
        }
        #endregion

        #region private methods

        /// <summary>
        /// Méthode asynchrone qui permet le chargement du profil du neostee
        /// </summary>
        private async void LoadAsync()
        {
            string firstName = await Windows.System.UserProfile.UserInformation.GetFirstNameAsync();
            string name = await Windows.System.UserProfile.UserInformation.GetLastNameAsync();
            var commonName = "Amadou Camara";
            byte[] flux = null;
            StorageFolder folder = null;

            try
            {
                folder = Windows.ApplicationModel.Package.Current.InstalledLocation;
            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message);
            }

            StorageFile file = await folder.GetFileAsync(@"Assets\SmallLogo.png");

            if (file != null)
            {
                flux = await GetByteFromFile(file);
            }

            var defaultNeostee = new Neostee() { CommonName = "Inconnu", DepartmentName = string.Empty, Description = string.Empty, Email = string.Empty, Login = string.Empty, Manager = string.Empty, ThumbnailPhoto = flux };

            if (!string.IsNullOrEmpty(firstName) && !string.IsNullOrEmpty(name))
            {
                commonName = string.Format("{0} {1}", firstName, name);
            }
            else
            {
                TheNeostee = defaultNeostee;
                _Neostees.Add(defaultNeostee);
                return;
            }

            INeosteeRepository _repository = new NeosteeRepository();

            try
            {
                var result = await _repository.Get(commonName);
                if (result != null)
                {
                    foreach (var item in result)
                    {
                        _Neostees.Add(item);
                        if (TheNeostee == null)//le 1er neostee qui correspond au critère de recherche
                        {
                            TheNeostee = item;
                            CommonName = _neostee.CommonName;
                            break;
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                throw new Exception("erreur dans la methode LoadAsync", ex);
            }
        }

        private async Task<byte[]> GetByteFromFile(StorageFile storageFile)
        {
            var stream = await storageFile.OpenReadAsync();

            using (var dataReader = new DataReader(stream))
            {
                var bytes = new byte[stream.Size];
                await dataReader.LoadAsync((uint)stream.Size);
                dataReader.ReadBytes(bytes);

                return bytes;
            }
        }
        #endregion
    }
}

 

Dans cette classe, nous allons définir l’ensemble des propriétés que nous souhaitons afficher dans la vue (la couche de présentation).

Il est même possible de définir des actions telles que les ICommand, qui représentent une action (une interaction), lors d’un évènement provoqué par utilisateur, tel que le clic sur un bouton. Mais ceci est une autre histoire.

Dans notre cas, j’ai défini  dans le ViewModel une méthode private async void LoadAsync()

Cette méthode permet de faire appel asynchrone au Web service.

Mais attention, je ne fais pas appel directement à ce Web service. Je passe par une couche métier :

 

 Cette classe est  responsable de la pertinence des données et va nous permettre de renseigner les propriétés à afficher dans la Vue. Cette classe définit une méthode Get qui va renvoyer les informations sur un employé de Neos-SDI en fonction de son Common Name.

 Dans la propriété TheNeostee, j’ai volontairement commenté la première surcharge de la méthode de base OnChangedProperty, au profit de la deuxième surcharge :  

 

private Neostee _neostee = null;

public Neostee TheNeostee
{
	get { return _neostee; }
	set
	{
		_neostee = value;
		//base.OnChangedProperty("TheNeostee");
		base.OnChangedProperty<Neostee>(() => this.TheNeostee);
	}
}

 

Cette surcharge prend en paramètre de type de la forme Lambda Expression. Cette méthode comporte ainsi moins de risques d’erreur de saisie, comparé à la méthode de base qui prend une chaîne de caractères en paramètres.  

Dans la famille ViewModel, je demande la…

View :

Pour afficher les données, on se base sur le concept lié au pattern MVVM : le databinding.

Ce mécanisme permet de lier une donnée entre notre couche de présentation et le ViewModel. Pour cela, il faut définir le contexte du ViewModel au niveau de la Vue et déclarer notre objet métier à l’aide du mot clé Binding.

Voici une vue partielle de la View, avec la déclaration du contexte pour le ViewModel :

 

 Voici une vue partielle de la page qui montre comment la « binder » avec notre objet métier TheNeostee.

Et la partie que je trouve intéressante dans cette vue :

Comment afficher une image dans notre vue ? Sachant que la propriété TheNeostee.ThumbnailPhoto est homogène à un flux binaire.

La solution est de passer par la classe ImageConverter :

  

 

La classe ImageConverter implémente l’interface IValueConverter qui définit 2 méthodes Converter et ConverterBack. Seule la première méthode est implémentée pour justement convertir notre source de données (qui provient de l’annuaire) en objet de type WriteableBitmap qui permettra de charger l’image dans notre application Windows Store.

        

using AppLoadProfil.Common;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Data;
using AppLoadProfil.StreamExtensions;
using Windows.UI.Xaml.Media.Imaging;

namespace AppLoadProfil.Converters
{
    public class ImageConverter : IValueConverter
    {
        WriteableBitmap _imageSource = null;
        private readonly int _pixelWidth = 1024;
        private readonly int _pixelHeight = 1024;

        /// <summary>
        /// to load an image from byte[] stream
        /// </summary>
        /// <param name="value">value which as byte[]</param>
        private async void LoadImage(object value)
        {
            var flux = value as byte[];
            
            if (flux != null)
            {
                _imageSource = new WriteableBitmap(_pixelWidth, _pixelHeight);
                var stream = flux.ToAccessStream();
                await _imageSource.SetSourceAsync(stream);
            }
        }

        public object Convert(object value, Type targetType, object parameter, string language)
        {
            LoadImage(value);
            return _imageSource;
        }

        public object ConvertBack(object value, Type targetType, object parameter, string language)
        {
            throw new NotImplementedException();
        }
    }
}

 

La méthode ToAccessStream est une méthode d’extension qui va renvoyer un objet de type IRandomAccessStream : interface de gestion des flux pour les applications Modern UI.

using AppLoadProfil.Common;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Windows.Storage.Streams;

namespace AppLoadProfil.StreamExtensions
{
    public static class MemoryStreamExtensions
    {
        public static IRandomAccessStream ToAccessStream(this byte[] flux)
        {
            return new ImageStream(flux);
        }
    }
}

 

Cette méthode d’extension renvoie une instance de la classe ImageStream qui prend en charge une implémentation de l’interface IRandomAccessStream :

 

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Windows.Storage.Streams;

namespace AppLoadProfil.Common
{
    public class ImageStream : IRandomAccessStream
    {
        private MemoryStream _memoryStream = null;
        public ImageStream()
        {

        }

        public ImageStream(byte[] inputStream)
        {
            if (inputStream != null)
            {
                _memoryStream = new MemoryStream(inputStream, 0, inputStream.Count(), true);
            }
        }

        public bool CanRead
        {
            get
            {
                if (_memoryStream != null)
                {
                    return _memoryStream.CanRead;
                }
                else
                {
                    return false;
                }
            }
        }

        public bool CanWrite
        {
            get
            {
                if (_memoryStream != null)
                {
                    return _memoryStream.CanWrite;
                }
                else
                {
                    return false;
                }
            }
        }

        public IRandomAccessStream CloneStream()
        {
            return this.MemberwiseClone() as IRandomAccessStream;
        }

        public IInputStream GetInputStreamAt(ulong position)
        {
            _memoryStream.Position = (long)position;
            return _memoryStream.AsInputStream();
        }

        public IOutputStream GetOutputStreamAt(ulong position)
        {
            _memoryStream.Position = (long)position;
            return _memoryStream.AsOutputStream();
        }

        public ulong Position
        {
            get { return (ulong)_memoryStream.Position; }
        }

        public void Seek(ulong position)
        {
            _memoryStream.Seek((long)position, SeekOrigin.Begin);
        }

        public ulong Size
        {
            get
            {
                return (ulong)_memoryStream.Length;
            }
            set
            {
                _memoryStream.SetLength((long)value);
            }
        }

        public void Dispose()
        {
            _memoryStream.Dispose();
        }

        public Windows.Foundation.IAsyncOperationWithProgress<IBuffer, uint> ReadAsync(IBuffer buffer, uint count, InputStreamOptions options)
        {
            var inputStream = this.GetInputStreamAt(0);
            return inputStream.ReadAsync(buffer, count, options);
        }

        public Windows.Foundation.IAsyncOperation<bool> FlushAsync()
        {
            var outputStream = this.GetOutputStreamAt(0);
            return outputStream.FlushAsync();
        }

        public Windows.Foundation.IAsyncOperationWithProgress<uint, uint> WriteAsync(IBuffer buffer)
        {
            var outputStream = this.GetOutputStreamAt(0);
            return outputStream.WriteAsync(buffer);
        }
    }
}

 

Et voilà, nous savons comment utiliser le pattern MVVM dans un projet Windows Store. Ce pattern a pour avantage de séparer les concernes et permet le travail avec un designer pour l’interface utilisateur.

Pour aller plus loin, comment naviguer avec le pattern MVVM ? Voici une première réponse proposé par Microsoft Services

Tags: , , ,

Développement

Contrôle WPF Bing Maps (2/2) : Utilisation du Bing Maps REST Services pour la géolocalisation et du Bing Maps Spatial Data Services pour la recherche de POI

by COlivier 12. octobre 2012 00:03

Le Bings Maps REST Services est une API de géolocalisation vous permettant de trouver un emplacement à partir de son adresse (ou de ses coordonnées GPS) et d’obtenir les données de localisation de l’emplacement recherché.

Le Bing Maps Spatial Data Services est une API de rechercher des POI (points d’intérêts) autour d’une localisation et d’obtenir les données de chaque POI tels que les coordonnées GPS, le nom, l’adresse et le  type de POI.

NB : Pour utiliser l’une de ces API, vous devrez obligatoirement posséder une clé Bing Maps (voir le billet intitulé «Contrôle WPF Bing Maps (1/2) : Présentation de l’intégration du contrôle dans votre application WPF »).

1/. Bing Maps REST Services

L’exemple de code ci-dessous, vous présente une méthode vous permettant de géolocaliser une adresse (telles que « Rue Auber, Paris », « Toulouse », etc.) et d’obtenir ses coordonnées GPS.

 

using Microsoft.Maps.MapControl.WPF;

/// <summary>
/// Permet de géocaliser une adresse (Ressource : http://msdn.microsoft.com/en-us/library/hh757509.aspx)
/// </summary>
/// <param name="addressQuery">Adresse à rechercher (par exemples: "Rue Auber, Paris" ou "Toulouse")</param>
/// <returns>Localisation de l'adresse recherchée (coordonnées GPS)</returns> 
public static Location GeocodeAddress(string addressQuery)
{
	Location addressLatitudeLongitude = null;

	// Création de la requête de géocalisation
	string geocodeRequest = string.Format("http://dev.virtualearth.net/REST/v1/Locations/{0}?o=xml&key={1}", addressQuery, YOU_BING_MAPS_KEY);

	//Envoi de la requête et récupèration de la réponse sous forme de document XML
	XmlDocument geocodeResponse = GetXmlResponse(geocodeRequest);
	if(geocodeResponse.IsNotNull())
	{
		//Création d'un namespace pour lire le document
		XmlNamespaceManager nsmgr = new XmlNamespaceManager(geocodeResponse.NameTable);
		nsmgr.AddNamespace("rest", "http://schemas.microsoft.com/search/local/ws/rest/v1");

		//On récupère tous les noeuds "Location" 
		XmlNodeList locationElements = geocodeResponse.SelectNodes("//rest:Location", nsmgr);
		if (locationElements.IsNotNull())
		{
			// On récupère les coordonnées de l'adresse recherchée
			XmlNodeList displayGeocodePoints = locationElements[0].SelectNodes(".//rest:GeocodePoint/rest:UsageType[.='Display']/parent::node()", nsmgr);
			string latitude = displayGeocodePoints[0].SelectSingleNode(".//rest:Latitude", nsmgr).InnerText;
			string longitude = displayGeocodePoints[0].SelectSingleNode(".//rest:Longitude", nsmgr).InnerText;

			addressLatitudeLongitude = new Location(Convert.ToDouble(latitude), Convert.ToDouble(longitude));
		}
	}
	
	return addressLatitudeLongitude;
}

/// <summary>
/// Permet d'obtenir la réponse d'une requête
/// </summary>
/// <param name="requestUrl">Requête à envoyer</param>
/// <returns>Réponse de la requête au format XML</returns>
private static XmlDocument GetXmlResponse(string requestUrl)
{
	XmlDocument xmlDoc = null;
	
	HttpWebRequest request = WebRequest.Create(requestUrl) as HttpWebRequest;
	using (HttpWebResponse response = request.GetResponse() as HttpWebResponse)
	{
		if (response.StatusCode != HttpStatusCode.OK)
		{
			throw new Exception(String.Format("Server error (HTTP {0}: {1}). Request URL (XML): {2}", response.StatusCode, response.StatusDescription, requestUrl));
		}
		xmlDoc = new XmlDocument();
		xmlDoc.Load(response.GetResponseStream());	
	}
	
	return xmlDoc;
}

 

Une fois que vous avez obtenu l’emplacement votre adresse, il ne vous reste plus qu’à créer la punaise qui vous permettra de la situer sur le contrôle Bing Maps.

 

/// <summary>
/// Permet de créer une punaise et de l'associer au contrôle Bing Maps
/// </summary>
/// <param name="map">Le contrôle Bing Maps</param>
/// <param name="location">La localisation de l'adresse recherchée</param>
public void CreatePushpin(Map map, Location location)
{
	// Création de la punaise
	Pushpin pushpin = new Pushpin()
	{
		Name = "Adresse recherchée",
		Location = location
	};
	
	// Association au contrôle Bing Maps
	map.Children.Add(pushpin);
}

 

Voici le résultat pour une recherche sur l’adresse « Rue Auber, Paris » :

 

NB : Sur la carte ci-dessus, vous avez la punaise par défaut du contrôle. Celle-ci est une image, vous pouvez donc créer vos propres punaises.

 

2/. Bing Maps Spatial Data Services

Maintenant que vous avez géolocalisé votre adresse, vous avez la possibilité de rechercher des points d’intérêts (POI) autour de votre adresse en précisant le ou les types que vous souhaitez rechercher. (Voir le fichier joint se trouvant en bas de page "BingMaps (Liste POIEntityType).cs" : ce fichier contient une énumération des types de POI existants et le lien vers le MSDN sur la présentation de cette liste).

L’exemple de code ci-dessous vous présente une méthode vous permettant d’obtenir une liste de POI autour d’une localisation.

 

/// <summary>
/// Permet de trouver les points d'intérets autour d'une localisation (Ressource : http://msdn.microsoft.com/en-us/library/gg585131)
/// </summary>
/// <param name="location">Une localisation permettant de servir de point de recherche</param>
/// <param name="poiEntityTypeIds">Liste des POI EntityTypeId recherchés (entier séparé par une virgule)</param>
/// <param name="nbPoiSearch">Nombre de POI max à retourner</param>
/// <param name="radiusSearch">Radius de recherche (en km)</param>
/// <returns></returns>
public static List<Tuple<Location, string, int>> GetPOIs(Location location, string poiEntityTypeIds, int nbPoiSearch, int radiusSearch)
{
	List<Tuple<Location, string, int>> retour = default(List<Tuple<Location, string, int>>);
	
	// Création de la requête Bing Spatial Data Services 
	// Ressource : http://msdn.microsoft.com/en-us/library/hh478189
	string findNearbyPOIRequest = string.Format("http://spatial.virtualearth.net/REST/v1/data/c2ae584bbccc4916a0acf75d1e6947b4/NavteqEU/NavteqPOIs?spatialfilter=nearby({0},{1},{2})&$filter=EntityTypeID in({3})&$select=EntityID,DisplayName,__Distance,Latitude,Longitude,AddressLine,Locality,AdminDistrict,PostalCode,EntityTypeID&$top={4}&key={5}",
		location.Latitude, location.Longitude, radiusSearch,
		poiEntityTypeIds,
		nbPoiSearch,
		YOU_BING_MAPS_KEY);

	XmlDocument xmlDocument = GetXmlResponse(findNearbyPOIRequest);

	if(xmlDocument.IsNotNull())
	{
		retour = ReadPoiXmlDocument(xmlDocument);
	}
	
	return retour;
}

/// <summary>
/// Permet de lire le résultat de la recherche des POI
/// </summary>
/// <param name="xmlDocument">Document XML correspondant à la réponse de la requête au service</param>
/// <returns></returns>
private static List<Tuple<Location, string, int>> ReadPoiXmlDocument(XmlDocument xmlDocument)
{
	List<Tuple<Location, string, int>> retour = default(List<Tuple<Location, string, int>>);

	XmlNamespaceManager xmlNamespaceManager = new XmlNamespaceManager(xmlDocument.NameTable);
	xmlNamespaceManager.AddNamespace("d", "http://schemas.microsoft.com/ado/2007/08/dataservices");
	xmlNamespaceManager.AddNamespace("m", "http://schemas.microsoft.com/ado/2007/08/dataservices/metadata");
	xmlNamespaceManager.AddNamespace("a", "http://www.w3.org/2005/Atom");

	// Obtient les entityID pour chaque POI 
	// Ressource : http://msdn.microsoft.com/en-us/library/hh478191.aspx
	XmlNodeList displayNameList = xmlDocument.SelectNodes("//d:DisplayName", xmlNamespaceManager);

	if (displayNameList.Count > 0)
	{
		retour = new List<Tuple<Location, string, int>>();

		XmlNodeList addressLineList = xmlDocument.SelectNodes("//d:AddressLine", xmlNamespaceManager);
		XmlNodeList localityList = xmlDocument.SelectNodes("//d:Locality", xmlNamespaceManager);
		XmlNodeList adminDistrictList = xmlDocument.SelectNodes("//d:AdminDistrict", xmlNamespaceManager);
		XmlNodeList postalCodeList = xmlDocument.SelectNodes("//d:PostalCode", xmlNamespaceManager);
		XmlNodeList latitudeList = xmlDocument.SelectNodes("//d:Latitude", xmlNamespaceManager);
		XmlNodeList longitudeList = xmlDocument.SelectNodes("//d:Longitude", xmlNamespaceManager);
		XmlNodeList distanceList = xmlDocument.SelectNodes("//d:__Distance", xmlNamespaceManager);
		XmlNodeList entityTypeIdList = xmlDocument.SelectNodes("//d:EntityTypeID", xmlNamespaceManager);

		for (int i = 0; i < displayNameList.Count; i++)
		{
			Location locationPoi = new Location(Convert.ToDouble(latitudeList[i].InnerText), Convert.ToDouble(longitudeList[i].InnerText));

			int entityTypeId = Convert.ToInt32(entityTypeIdList[i].InnerText);

			retour.Add(new Tuple<Location, string, int>(locationPoi,
				string.Format(BingMapsResource.Label_PushpinTooltip,
						displayNameList[i].InnerText, 
						Environment.NewLine,
						addressLineList[i].InnerText,
						postalCodeList[i].InnerText,
						localityList[i].InnerText,
						adminDistrictList[i].InnerText,
						Convert.ToDouble(distanceList[i].InnerText), entityTypeId));
		}
	}

	return retour;
}

 

Comme vous pouvez le voir dans le code ci-dessus, l’URL de la requête contient plusieurs critères permettant de définir le rayon de la recherche, le ou les types de POI recherchés, le nombre maximum de POI à retourner ou bien encore les informations sur les POI à retourner.

NB : Pensez à bien définir vos critères de recherche car plus vous demanderez d’information, plus le fichier XML contenant la réponse sera volumineux et par conséquent vos temps de traitement seront plus long.

Voici le résultat pour une recherche de POI autour de l’adresse « Rue Auber, Paris » et pour les types de POI correspondant à une gare ou un transport ferroviaire :

 

Comme vous l’aurez remarqué, si vous ne créez pas vos propres punaises, on n’arrive plus à distinguer l’adresse recherchée et les POI. Je vous recommande donc vivement de créer vos propres punaises pour une meilleure utilisation du contrôle.

 

 Lien utile :

 

Fichier joint :

BingMaps (Liste POIEntityType).cs (14,15 kb)

Tags: , , , , , ,

Développement

Contrôle WPF Bing Maps (1/2) : Présentation de l’intégration du contrôle dans votre application WPF

by COlivier 11. octobre 2012 23:52

Dans un premier temps, je vais vous présenter comment intégrer le contrôle Bing Maps dans votre application WPF.

Dans un second billet, je vous présenterai l’utilisation du Bing Maps REST Services permettant de géolocaliser une adresse et l’utilisation du Bing Maps Spatial Data Services permettant de rechercher des POI (points d’intérêts) autour d’une adresse.

Après avoir téléchargé le contrôle et ajouté la référence dans votre projet, vous devrez déclarer un namespace dans votre fenêtre et ajouter votre contrôle :

A l’exécution, vous obtiendrez cet écran :

 

Comme vous l’aurez remarqué, un message vous indique que vos droits sont invalides. Ce message ne vous empêche pas de travailler avec le contrôle. Vous pouvez créer et tester vos menus de navigation et d’affichage, menus qui pourront vous permettre de zoomer sur la carte, centrer la carte à partir d’une position ou bien modifier le type d’affichage pour passer d’une vue plan à une vue satellite par exemple.  

Mais, bien entendu, lors de la livraison de votre application vous devrez enlever ce message.

Pour cela, vous devez obtenir une clé d’authentification Bing Maps à partir du portail Bing Maps (Compte Windows Live ID pour la connexion).

NB : Ce portail contient aussi différentes ressources autour du contrôle Bing Maps afin de vous informer et de vous aider sur la compréhension et l’utilisation du contrôle ainsi qu’une présentation des services qui l’entourent.

Une fois que vous aurez créé votre clé d’authentification, vous n’aurez plus qu’à la copier pour la déclarer dans votre contrôle avec l’attribut CredentialsProvider :

Et voilà, vous avez créé une Bing Maps dans votre application WPF.

 

Liens utiles : 


<!--[if !supportLineBreakNewLine]-->
<!--[endif]-->

Tags: , , , ,

Développement

Utilisation du Facebook SDK C# sur une application WPF

by COlivier 8. octobre 2012 20:00

Dans cet article, je vais vous présenter mon retour d’expérience sur l’utilisation de Facebook SDK C# que j’ai pu avoir sur ma dernière mission.

Tout d’abord, si vous effectuez une recherche sur l’utilisation du Facebook SDK C#, vous avez de fortes chances de tomber sur le blog de Nathan Tottent (un évangéliste technique de chez Microsoft) qui commencera par vous dire « Développer avec Facebook, c’est comme construire une maison sur un marécage ». Rien de très encourageant, surtout quand on vous demande de créer un module de publication de biens sur Facebook sur le compte d’utilisateur.

Avant de commencer à coder votre module, vous devrez tout d’abord télécharger le SDK Facebook C#, vous renseigner sur son fonctionnement et surtout créer une application Facebook. Car, c’est par l’intermédiaire de cette application Facebook que votre application WPF va pouvoir publier des informations sur les murs.

Comme pour toute application Facebook, les « Facebookiens » devront autoriser l’accès de votre application Facebook à leur compte, ce qui vous permettra d’obtenir un AccessToken.

Cet AccessToken contiendra des permissions comme l’accès aux informations personnelles, la permission de lire la liste des amis, de publier en son nom, etc. tout dépendra de ce que vous allez définir dans votre application Facebook.

NB : tout en sachant qu’un utilisateur peut bloquer certaines permissions de votre application à n’importe quel moment après avoir autorisé l’accès de votre application.

Voici donc l’exemple d’une méthode qui permet de publier du contenu sur une page Facebook :

 

using System;
using Facebook;

public class FacebookService
{
    /// <summary>
    /// Permet de poster sur Facebook les informations contenu dans un FacebookModel 
    /// </summary>
    /// <param name="facebookModel">Information de la publication</param>
    public void SendToFacebook(FacebookModel facebookModel)
    {
        try
        {
            // Token de permission de publication sur un compte utilisateur
            // ayant accepté l'accès à votre publication.
            string facebookAccessToken = AccessToken;
 
            // L'identifiant de votre application Facebook
            string facebookAppId = AppId;

            // Création du post Facebook
            dynamic parameters = new ExpandoObject();
            parameters.message = facebookModel.Message;
            parameters.link = facebookModel.Link;
            parameters.name = facebookModel.Name;
            parameters.caption = facebookModel.Caption;
            parameters.description = facebookModel.Description;
            parameters.picture = facebookModel.uriPicture;
            parameters.actions = new
                {
                    name = facebookModel.ActionName,
                    link = facebookModel.ActionUri,
                };
        
            FacebookClient facebookClient = new FacebookClient(facebookAccessToken);

            // Dans ce cas d'un paramétrage sur une page perso l'AccessToken est composé du [AppId|AppSecret]
            // Dans le cas d'une page pro on utilise un token pour se connecter au compte Facebook propriétaire de l'application précédement créée,
            // puis récupérer un AccessToken pour la page Pro, ce qui implique que le compte propriétaire doit être Gestionnaire de la page Pro
            if (facebookAccessToken.IndexOf('|').Equals(-1))
            {
                // Obtention de la liste des compte associés au compte propriétaire
                dynamic fbAccounts = facebookClient.Get("/me/accounts");

                // Boucle sur les comptes à la recherche de l'ID qui correspond à votre ID de destination (Fan Page ID)
                foreach (dynamic account in fbAccounts.data)
                {
                    if (account.id.Equals(facebookAppId))
                    {
                        parameters.access_token = account.access_token;
                        break;
                    }
                }
            }

            // Envoi de la requête de publication sur Facebook
            dynamic result = facebookClient.Post(string.Format("/{0}/feed", facebookAppId), parameters);

        }
        catch (FacebookApiException facebookApiException)
        {
            // Permet d'intercepter une exception sur la publication Facebook
        }
        catch (Exception exception)
        {
            // Permet d'intercepter une exception sur le traitement
        }
    }
}

 

 

Et voici un exemple de résultat d’une publication :

Liens utiles :

Tags: , ,

Développement

Problèmes courants lors de la configuration du webpart « Operations Manager Dashboard Viewer »

by Guyot 13. juin 2012 15:14

Si l’installation du webpart qui permet l’affichage de tableaux de bord SCOM 2012 dans SharePoint est plutôt bien documentée (voir notamment l’article http://technet.microsoft.com/en-us/library/hh212924.aspx) et ne présente pas de difficulté majeure, sa configuration peut se heurter à quelques subtilités.

Je vous livre ci-dessous quelques retours d’expérience en espérant vous faire ainsi économiser des instants biens précieux.

  1. Lorsque je tente de configurer le webpart « Operation Manager Dashboard Viewer », SharePoint m’affiche une page « Accès refusé»

clip_image002

Et pan, accès refusé !

clip_image004

Cause :

Le panneau de configuration du webpart interroge une liste hébergée par le site de l’administration centrale en utilisant pour cela l’identité du pool d’application (du site où vous avez posé le webpart). Le compte du pool d’application doit déjà avoir le droit d’accéder à cette liste.

Résolution :

Il suffit d’octroyer des permissions de lecture au compte du pool d’application dans l’administration centrale, soit sur la collection de site (cas illustré ci-dessous), soit sur la liste en elle-même en cassant l’héritage.

clip_image006

Après cela, vous partez confiant, le sourire aux lèvres, rafraîchir votre page en vous disant intérieurement : « ça y est, ça va marcher, mon chef va être content et je vais pouvoir enfin rentrer chez moi rejoindre ceux que j’aime (mes pizzas et mes bières quoi !)… »

Eh ben non, perdu ! …

2. Le compte du pool d’application a suffisamment d’autorisations sur l’administration centrale mais lorsque je tente de configurer le webpart « Operation Manager Dashboard View », j’ai un autre message d’erreur (code 0x080131904)

clip_image008

Le même message d’erreur dans sa version « développeur » :

clip_image010

Cause :

Donner les droits de lecture au compte du pool d’application sur l’administration centrale, pas plus que le mettre administrateur de la collection de sites, ne s’avère suffisant. Le compte doit aussi avoir le droit d’exécuter une procédure stockée de la base de contenu de l’administration centrale.

Résolution :

Il faut donner à ce même compte du pool d’application, le droit d’exécution sur la procédure stockée « proc_EnumLists » dans la base de données de contenu de l’administration centrale (« SharePoint_AdminContent_... »).

image

Et là, enfin, Ô joie, vous pouvez enfin configurer votre webpart pour afficher votre dashboard SCOM (ceci dit, ça ne vous aura pas dispensé de configurer la liste de l’administration centrale conformément à la procédure du Technet mentionnée précédemment).

A moins que …

3. Tout à l’air correctement configuré, dans l’Administration Centrale et dans le webpart mais en lieu et place de mon tableau de bord SCOM, rien ne s’affiche à part un bel espace tout blanc. Le dashboard ne s’affiche pas et il n’y a pas de message d’erreur.

 

Cause :

Il doit y avoir bien d’autre raison, mais je vous livre ici celle que j’ai rencontrée :

La console web SCOM est publiée en https et l’url utilisée par le webpart ne correspond pas au certificat SSL déclaré.

Par exemple : le certificat SSL est valide pour les url https://monserveur.mondomain.local mais le webpart essaye d’afficher un dashboar à l’url https://monserveur/operationsmanager/#/dashboard(type=Microsoft...)

C’est ballot n’est-ce pas … !

Résolution :

Dans la liste « Operations Manager Web Console Environments » hébergée dans l’administration centrale, éditer l’item de configuration utilisé par le webpart et corriger le champ « HostURI » pour qu’il corresponde au domaine du certificat.

clip_image014

Bon à savoir et autres petites contrariétés…

  • Par défaut, le Webpart « Operations Manager Dashboard Viewer » n’utilise pas le compte identifié dans SharePoint mais bien le compte de la session Windows. C’est pourquoi le dashboard peut afficher « Accès refusé » même si vous avez fait « Se connecter avec un utilisateur différent… » dans SharePoint et que le compte affiché par SharePoint 2010 a bien les permissions dans la console Operations Manager. Une alternative à ce problème est d’utiliser le « Secure Store » de SharePoint.

 

  • Le Webpart « Operations Manager Dashboard Viewer » utilize l’url configure telle que, la resolution de celle-ci est donc faite sur le poste client. Assurer vous que les utilisateurs, dans un contexte extranet par exemple, peuvent bien résoudre l’adresse du site SharePoint ET l’adresse de la console web d’Operations Manager.

Tags:

Collaboratif | Infrastructure | SharePoint

Neos-SDI  Neos-SDI