Blog - Title

August, 2011

  • Stéphanie Hertrich

    Développer un projet aujourd’hui : L’application CaveAVins pour Windows Phone 7.1

    • 6 Comments

    Update 18/10/2011: l’url du service OData devient http://stephecaveavins.cloudapp.net/CaveAVinsDataService.svc

    Cet article décrit le fonctionnement de la première maquette de l’application Cave A Vins pour Windows Phone. Il explique les points sensibles de l’application et détaille leur réalisation, sans rentrer autant dans le détail qu’un tutoriel.

    Pas si basique que cela, notre application va mettre en œuvre les concepts suivants:

    Nous allons également modifier le service WCF Data Services pour le rendre plus intelligent et effectuer automatiquement la transformation d’une adresse en coordonnées latitude/longitude que l’on ajoutera aux informations sur le vin.

    Ampoule L’application est développée pour Windows Phone 7.1. Pour découvrir les nouveautés par-rapport à la version 7.0, c’est ici.
    Prérequis :
    Windows Phone SDK 7.1 Release Candidate

    Un petit aperçu du résultat:

    Get Microsoft Silverlight

     

     

    Résumé des épisodes précédents

    Articles:

    Tutoriels:

    Présentation des écrans

    Voilà à quoi ressemble notre application de gestion de Cave A Vins.
    L’application utilise un contrôle Panorama, avec un en-tête déroulant affichant autant d’images de bouteilles que vous avez de vins différents dans votre cave. Si vous avez des yeux de lynx (‘achement dur ne pas écrire Linq ou Lync Extra-terrestre), vous remarquerez qu’elles portent le nom du vin sur leur étiquette. Bon c’est pas fait pour être lisible, juste décoratif : les bouteilles défilent quand vous passez d’un item panorama à un autre Tire la langue (cf vidéo).

    1 image 2 image 3 image

    1 - La première page affiche la liste des vins présents dans la cave triés par date décroissante d’achat.

    2 - La seconde utilise le contrôle LongListSelector du toolkit Silverlight pour WP7 pour afficher la même liste, groupée par année. On pourrait imaginer ajouter les informations sur les cépages et proposer le même type de vue groupée ce qui serait très pratique.

    3 - La troisième page utilise le contrôle Bing Maps pour afficher l’origine des vins et le nombre de bouteilles associées. Cela permet de repérer facilement ce qu’il manque à la cave pour être suffisamment variée géographiquement parlant.

    4 image 5 image

    4 – le menu contextuel permet de décrémenter le nombre de bouteilles du vin sélectionné, d’ajouter/éditer/supprimer un vin de sa cave.

    5 – l’édition d’un vin permet de saisir les informations qui lui sont relatives ainsi que de prendre la photo de son étiquette

    Architecture de la solution

    Rappel de l’architecture existante après la migration dans Azure:

    image48

    Et l’architecture qui sera mise en place dans le contexte de cet article :

    image

    Ampoule Le service proxy d’authentification “CaveAVins Blob Authentifier” est facultatif mais conseillé pour ne pas divulguer les clés d’accès au storage Azure.

    A ce stade, plusieurs questions restent encore en suspens :

    • Quelle architecture vais-je mettre en place dans mon application WP ?
    • Comment identifier le propriétaire de la cave pour retrouver quelles sont ses bouteilles dans la base de données ?
    • Comment situer géographiquement mes vins sur un contrôle Bing Map à partir d’une simple adresse ?
    • Comment accéder aux blobs Azure depuis le téléphone, pour y stocker les photos ?
    • Comment modifier la structure des données créée avec Entity Framework Code First pour y ajouter de nouvelles informations ?
    • Existe-t-il des contrôles gratuits pour faciliter le développement ? Liste groupée, contrôle rating pour la note associée à la bouteille, menu contextuel, animations …

    L’architecture logique de mon application WP

    De mon point vue, la question est moins triviale pour une application Silverlight WP7 que pour du Silverlight classique.

    Pour ma part, en Silverlight je pars toujours sur du “MVVM-like” plus ou moins strict, selon l’importance et la durée de vie de mon application. Je pars soit de mes classes de base et méthodes d’extension qui constituent ma boite à outils que j’ai créé au fil des projets, soit d’un framework ou partie de framework existant type MVVMLight, Caliburn, Prism…

    AmpouleEn 3 mots, si vous ne savez pas ce qu’est MVVM (Model – View – ViewModel) : c’est une architecture 3-tiers avec

    • Model = le modèle (les données)
    • View = une vue (une page ou morceau de page, contrôle, …bref, un truc qui s’affiche à l’écran et se décrit en xaml Tire la langue)
    • ViewModel = un cas d’utilisation associé à une ou plusieurs vues. Un ViewModel est une classe qui présente des propriétés “notifiables” et bindables à la vue. En principe il n’y a pas ou peu de code-behind dans les vues et ainsi tout le code lié au cas d’utilisation exprimé par la vue est concentré dans la classe ViewModel qui lui est associé.

    La bible de ce qu’est l’architecture MVVM, avec un petit exemple et le code associé qui va bien : http://msdn.microsoft.com/en-us/magazine/dd419663.aspx

    Le choix est moins immédiat sur WP7 qu’en Silverlight classique ou WPF, car beaucoup de contrôles standards “metro styled” n’intègrent pas complètement les bindings (ex : les boutons de la barres de menu). Heureusement, plusieurs variantes de frameworks MVVM ont été portées pour WP7, comme MVVMLight, Caliburn, …

    Dans mon cas, je n’utiliserai pas de framework prêt à l’emploi – ce n’est pas le sujet de cet article -, mais je reste sur une architecture de type MVVM, sans être trop stricte, en conservant du code behind, notamment pour la navigation, et la gestion des boutons de la barre de menus.

    image

    La couche View est composée de vues : MainView qui contient le panorama à 3 items et EditWineView qui permet d’éditer un vin.

    La couche ViewModel contient les 2 ViewModels  associés aux vues : MainViewModel et EditWineViewModel.

    La couche Model est composée de la classe CaveAVinsModel qui est générée automatiquement lors de l’ajout du service CaveAVins, à partir des metadata, ce qui fait gagner un temps fou. D’autant plus que ces classes proxy implémentent déjà les mécanismes de notification (INotifyPropertyChanged). Du coup, mon MainviewModel va pouvoir directement exposer ces collections à la vue, sans passer par une classe WineViewModel intermédiaire. C’est un premier raccourci par-rapport à du MVVM.strict, mais dans ce cas là, c’est nettement plus productif.

    La classe métier UploadPhoto prend en charge la sauvegarde des photos dans l’Azure Blob Storage, permettant ainsi que les couches Viewmodel et View ne soient pas couplées au mécanisme des blobs. On pourrait ainsi facilement stocker les photos ailleurs sans retoucher aux couches de présentation.

    La couche DAL correspond à l’accès aux données : aux blobs Azure et à notre service WCF Data Services hébergé lui aussi dans Azure.

    Identifier le propriétaire de la cave

    Pour pouvoir associer des bouteilles à un propriétaire, plusieurs options s’offrent à nous et en l’occurrence, c’est la plus simple qui a été retenue.

    Le téléphone stocke un numéro associé au Live Id du propriétaire (renseigné dès le téléchargement de la première application sur le MarketPlace). Nous pouvons donc utiliser cet identifiant pour rattacher un vin à son propriétaire, sans pour autant lui demander d’informations d’authentification ou de connexion. Et si vous changez de téléphone, vous ne perdez pas pour autant votre cave à vins.

    Voici un exemple de code permettant d’accéder au numéro de l’utilisateur:

     public string GetUserAnId()
            {
                string myId = string.Empty;
                string anid = UserExtendedProperties.GetValue("ANID") as string;
                if (anid != null)
                { 
                    myId = anid.Substring(2, 32);
                }
    
                return myId;
            }

    Une autre solution serait d’utiliser la fédération d’identité, en utilisant Azure Access Control Services (ACS) et un compte provenant d’un fournisseur d’identité comme Hotmail, Facebook, Google,… Cela évite à l’utilisateur de créer un énième compte dédié à l’application de cave à vins et ça permet au développeur de ne pas réinventer la roue en créant un mécanisme de gestion de comptes qui lui est propre.

    Le Toolkit Azure pour Windows Phone permet de simplifier cette opération en fournissant un template tout prêt pour ce genre d’applications. Benjamin a réalisé une vidéo de quelques minutes pour vous montrer comment utiliser le toolkit pour la gestion des authentifications.

    Localiser les vins sur un contrôle Bing Map

    Une des vues de mon panorama est une carte Bing Map matérialisant les quantités restantes de chacun des vins de ma cave. C’est une bonne aide à l’achat pour garantir une cave variée et cela me permet de vérifier rapidement si je ne manque pas de vin d’Alsace !

    Le contrôle Bing Map fait cela très bien en affichant des punaises correspondant à une liste de coordonnées géographiques (latitude, longitude). Dans notre cas, la fiche d’un vin contient une adresse et il faut donc passer par une étape intermédiaire avant de pouvoir afficher la punaise : la transformation de l’adresse en latitude et longitude. Bing Map fournit un service de résolution utilisable avec un compte développeur gratuit. Pour plus d’information sur les conditions d’utilisation : http://www.microsoft.com/maps/product/licensing.aspx.

    L’application Windows Phone pourrait réaliser cette résolution dynamiquement lors du lancement de l’application, mais cela signifie que je ferais autant de résolutions que de vins dans ma cave, à chaque chargement des données. Une meilleure idée serait de modifier directement la fiche du vin lors de l’ajout ou de la modification d’un vin. Mais si c’est mon application WP7 qui s’en charge, cela signifie que tout autre client potentiel qui ajouterait des vins dans la cave ne disposerait pas de la latitude et longitude. L’idéal serait que quiconque utilise le service bénéficie de cette résolution d’adresse, même un simple client http.

    Nous allons donc déporter cette résolution au niveau du service WCF Data Services à l’aide d’”intercepteurs”'. Voici comment cela se met place dans notre solution, dans la classe CaveAVinsDataService :

     public class CaveAVinsDataService : DataService<CaveAVins.Db.CaveAVinsContext>
        {
            // This method is called only once to initialize service-wide policies. public static void InitializeService(DataServiceConfiguration config)
            {
                config.SetEntitySetAccessRule("Wines", EntitySetRights.All);
                config.SetEntitySetAccessRule("Bottles", EntitySetRights.All);
                config.DataServiceBehavior.MaxProtocolVersion = DataServiceProtocolVersion.V3;
            }
    
    
            // Define a change interceptor for the Products entity set. [ChangeInterceptor("Wines")]
            public void OnChangeProducts(Wine updatedWine, UpdateOperations operations)
            {
                CurrentDataSource.ChangeTracker.DetectChanges();
                foreach (var uw in CurrentDataSource.ChangeTracker.Entries<Wine>())
                {
                    string oldValue = null;
                    if (operations == UpdateOperations.Change)
                    {
                        oldValue = CurrentDataSource.ChangeTracker.Entries<Wine>().First().OriginalValues.GetValue<string>("Address");
                    }
    
                    if (oldValue != updatedWine.Address)
                    {
                        // Update Latitude & longitude var geoloc = MakeGeocodeRequest(updatedWine.Address);
                        if (geoloc != null)
                        {
                            uw.Entity.Latitude = geoloc.Latitude;
                            uw.Entity.Longitude = geoloc.Longitude;
                        }
                    }
                }
    
            }

    On ajoute une méthode préfixée d’un custom attribute ChangeInterceptor("Wines")qui permet d’intercepter les requêtes de modification et d’ajout sur la table Wine. Si cette opération concerne un ajout ou qu’une modification de la propriété Address a été détectée, on appelle le service BingMap qui nous renverra une latitude et une longitude à partir de l’adresse. Ces informations sont alors répercutées directement dans l’entité Wine.

    C’est tout côté serveur.

    Dans l’application, il suffit de binder la collection de vins au contrôle Bing Map.

         <my:Map CredentialsProvider="Your credentials"
                 Center="46.642000079154968,2.3379997909069061"
                 ZoomLevel="5">
              <my:MapItemsControl ItemsSource="{Binding Model.Bottles}">
                   <my:MapItemsControl.ItemTemplate>
                        <DataTemplate>
                             <my:Pushpin Location="{Binding Converter={StaticResource BottlesToLocationConv}}"                                             
                                         Tap="Image_Tap"
                                         Background="DarkRed" FontWeight="Bold">
                                        
                                 <TextBlock HorizontalAlignment="Center" VerticalAlignment="Center" 
                                            Text="{Binding Count}"/>
        
                                 <my:Pushpin.Template>
                                      …
                                 </my:Pushpin.Template>
                             </my:Pushpin>
                        </DataTemplate>
                  </my:MapItemsControl.ItemTemplate>
              </my:MapItemsControl>
          </my:Map>
    
    

    Pour cela, j’utilise un converter qui me renvoit une instance de Geocoordinates (latitude, longitude) à partir d’une instance de Wine. Puis je personnalise le PushPin pour qu’il affiche le nombre de bouteilles, c’est à dire la propriété Count de la classe MyWine.

    public class BottlesToLocationConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            MyWine wine = value as MyWine;
            GeoCoordinate result = null;
    
            if (wine != null)
            {
                result = new GeoCoordinate(wine.WineInfos.Latitude.GetValueOrDefault(), 
                    wine.WineInfos.Longitude.GetValueOrDefault());
            }
    
            return result;
        }
    
        public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            return null;
        }
    }

    Le tour est joué !

    Accéder au service OData

    Le SDK Windows Phone 7.1 fournit un client WCF Data Services (vive Linq) ainsi que la possibilité de générer les classes proxy d’un service directement dans Visual Studio : bref, c’est tout pareil qu’en Silverlight classique.

    On commencer par ajouter la référence du service de cave à vins : http://stephecaveavins.cloudapp.net/CaveAVinsDataService.svc. Puis on instancie la classe de contexte qui vient d’être générée. Ensuite on construit sa requête de sélection ou on effectue les opérations CUD et on exécute tout cela de manière asynchrone.

    Reste la gestion du tombstoning du contexte WCF Data Services qui permettra de retrouver un état cohérent de nos entités : How to persist the state of an OData client for Windows Phone. En effet, depuis Windows Phone 7.1, la persistence des données est facilitée par la nouvelle méthode “Serialize” au niveau du contexte WCF Data Services.

    Tous les détails dans le tutoriel associé à paraitre.

    Modification de la structure de la base de données

    Pour permettre de réaliser ces fonctionnalités, nous avons besoin d’ajouter des informations dans la base de données et donc de modifier sa structure. Rappelons que celle-ci a été créée automatiquement à partir de nos classes POCOs, grâce à Entity Framework Code First.

    Il est également possible d’associer des classes POCOs à une base de données existante, et c’est ce qui a été fait dans notre cas, pour ajouter de nouvelles colonnes/propriétés. La structure de la base a été modifiée directement à partir du portail SQL Azure et les nouvelles propriétés de nos POCOS sont associées aux nouvelles colonnes de nos tables grâce à l’API Fluent pour Entity Framework Code First.

    Avant :

    image

    Maintenant:

    image

    L’entité MyWine est complétée par

    • la date d’achat du vin : pour le tri dans l’application et pouvoir visualiser facilement la dernière bouteille achetée

    L’entité Wine est complétée par:

    • Latitude: pour effectuer 1 seule fois la transformation Addresse/Coordonnées pour chaque vin affiché sur contrôle BingMap
    • Longitude : idem latitude
    • BarCode : pour identifier une bouteille à partir de la photo de son code barre – à venir

    Avec Fluent, cela se fait en quelques lignes dans le contructeur du contexte, après avoir complété les POCOs par les nouvelles propriétés:

    public class CaveAVinsContext : DbContext {
        public DbSet<MyWine> Bottles { get; set; }
        public DbSet<Wine> Wines { get; set; }
    
        public CaveAVinsContext()
            : base()
        {
            Database.SetInitializer<CaveAVinsContext>(null);
        }
    
        protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
            modelBuilder.Entity<MyWine>().Property(p => p.UserId);
            modelBuilder.Entity<MyWine>().Property(p => p.AddedDate);
    
            modelBuilder.Entity<Wine>().Property(p => p.BarCode);
    
            modelBuilder.Entity<Wine>().Property(p => p.Latitude);
            modelBuilder.Entity<Wine>().Property(p => p.Longitude);
            base.OnModelCreating(modelBuilder);
        }
    }

    Prendre la bouteille en photo

    C’est très facile grâce à l’API WP7 dédiée et cela se fait en quelques lignes, du genre :

    void TakeAPic()
    {
        CameraCaptureTask task = new CameraCaptureTask();
        task.Completed += (sender, photoResult) =>
        {
            if (photoResult.TaskResult == TaskResult.OK)
            {
                BitmapImage bmp = new BitmapImage();
                bmp.SetSource(photoResult.ChosenPhoto);
                PhotoSource = bmp;                                
            }
        };
        task.Show();
    }

    Attention de pas oublier de :

    • faire une rotation de l’image pour la stocker en mode portrait. On pourrait le faire à l’affichage par un RenderTransform mais du coup il faudrait l’effectuer dans chaque application cliente => factorisation métier côté serveur quand on peut !
    • réduire la taille de la photo avant de la stocker dans le blob storage, puisque nous n’utiliserons que des vignettes.

    Stocker les photos dans le blob Azure

    Une fois la photo prise et la fiche enregistrée, il faut :

    • soumettre la requête de modification au service WCF Data Services de notre Cave à Vins
    • uploader la photo (nommée avec un nouveau Guid pour pouvoir l’identifier de manière unique) dans les blobs Azure.

    Une fois de plus, le Toolkit Azure pour Windows Phone va nous aider en facilitant l’utilisation des blobs à partir de notre smartphone grâce à la librairie WindowsPhoneCloud.StorageClient.dll

    Pour commencer simplement, vous pouvez partir d’un sample de code issu du toolkit qui ne cible que la partie storage (merci Wade). Les credentials sont placés dans les ressources de l’application et sont donc visibles par tout un chacun, ce qui n’est pas recommandé. Mais dans un premier temps, on s’en contentera pour simplifier.

    Grâce à la classe CloudBlobClient fournie dans WindowsPhoneCloud.StorageClient.dll, l’upload de la photo (propriété PhotoStream de type Stream) s’effectue ainsi :

        public void UploadPhoto(Action callback = null)
        {
            this.IsUploading = true;
    
            this.blobClient.Upload(
                this.BlobName,
                this.PhotoStream,
                r => this.dispatcher.BeginInvoke(
                        () =>
                        {
                            this.IsUploading = false;
    
                            if (r.Exception == null)
                            {
                                MessageBox.Show(
                                    string.Format(CultureInfo.InvariantCulture, 
                                    "Image file {0} successfully uploaded!", this.BlobName),
                                    "Upload Photo Result",
                                    MessageBoxButton.OK);
    
                                if (callback != null)
                                {
                                    callback.Invoke();
                                }
                            }
                            else
                            {
                                MessageBox.Show(
                                    string.Format(
                                        CultureInfo.InvariantCulture,
                                        "Error: {0}",
                                        r.Exception.Message),
                                    "Upload Photo Result",
                                    MessageBoxButton.OK);
                            }
                        }));
        }
    }

    AmpouleLa version complète du toolkit vous permet de réaliser la même opération en version sécurisée, en ajoutant un service qui fait office de proxy d’authentification. C’est lui qui contiendra les credentials plutôt que votre application WP7 !

    Plus de contrôles Silverlight pour Windows Phone

    Le toolkit le plus utilisé est sans conteste le Silverlight Toolkit pour WP disponible sur codeplex.

    J’ai utilisé :

    • le LongListSelector permettant d’afficher une liste découpée selon un group by
    • une animation sur les listes :le TiltEffect, qui permet d’avoir un retour visuel sur sélection d’un élément
    • le menu contextuel : indispensable pour une bonne expérience utilisateur et éviter d’avoir trop de boutons partout

    J’avais également besoin d’un contrôle Rating et j’ai réutilisé celui-ci (sur codeplex) qui n’est pas prévu pour WP7, mais qui fonctionne bien du moment que l’on désactive le contrôle pendant une gesture.
    Un Rating control est également disponible dans le
    Silverlight Toolkit, mais je ne l’ai pas essayé dans le cadre d’une application WP.

    Le Coding4fun Tools est également très sympa (surtout qu’un de mes propres contrôles y a été intégré Clignement d'œil). Vous y trouverez un menu about, un colorpicker, etc, …

    Faites votre marché Rire

    Les tuiles dynamiques de l’écran d’accueil

    Avec WP7.1, il est ultra simple de rendre vos tuiles dynamiques.

    Un simple appel de méthode permet de mettre à jour une ou les deux faces de la tuile associée à votre application. Pour la Cave à Vins, la 1ère face affiche le nom de l’application, un petit dessin ainsi que le nombre total de bouteilles de votre cave. La 2ème face affiche le nom de la dernière bouteille achetée. Et c’est aussi simple que :

    public void CreateApplicationTile(IEnumerable<MyWine> bottles = null)
    {            
        var appTile = ShellTile.ActiveTiles.First();
    
        if (appTile != null)
        {
            var standardTile = new StandardTileData {
                Title = "Cave A Vins",
                BackgroundImage = new Uri("/icons/tileBackground2.png", UriKind.Relative),                    
                BackTitle = "Dernier achat",
            };
    
            if (bottles != null)
            {
                standardTile.Count = bottles.Sum(b => b.Count);
                if (bottles.Any())
                {
                    standardTile.BackContent = 
                        bottles.OrderByDescending(w => w.AddedDate)
                                .First()
                                .WineInfos.Name;
                }
            }
    
            appTile.Update(standardTile);
        }
    }  

    Côté pile, un MAGNIFIQUE petit dessin ainsi que le nombre total de bouteilles de votre cave :

    image

    Côté face : la dernière bouteille achetée

    image

     

     

    Voilà, tous les points sensibles de l’application sont maintenant exposés et détaillés. Je ne ferai pas de tutoriel pas à pas pour chacun des points, mais si vous rencontrez des difficultés avec l’un d’entre eux, je peux tout à fait développer le sujet dans un autre article.

    Reste à peaufiner l’application, à la localiser et à gérer le tombstoning correctement (notamment en ce qui concerne WCF Data Services).

    Dans le prochain article, nous verrons comment retrouver une bouteille à partir de la photo de son code barre et profiter ainsi des bouteilles déjà saisies par la communauté des utilisateur de l’application CaveAVins.

  • Stéphanie Hertrich

    Développer un projet aujourd’hui : La migration dans Azure

    • 0 Comments

    Update 18/10/2011: l’url du service OData devient http://stephecaveavins.cloudapp.net/CaveAVinsDataService.svc

    Un petit mot pour vous présenter les deux tutoriels qui vous permettront de faire migrer la base de données ainsi que le service de publication dans Azure.

    Résumé des épisodes précédents

    Tutoriels:

    Architecture On Premises :

    image

    Après la mise en pratique des deux tutoriels:

    - CaveAVins Tutoriel 3 : Migration d’une base SQL Server vers SQL Azure
    - CaveAVins Tutoriel 4 : Hébergement du service WCF Data Services dans Azure

    On obtient l’architecture suivante:

    image

    Le service OData publiant les données de la cave à vins est maintenant en ligne : http://stephecaveavins.cloudapp.net/CaveAVinsDataService.svc

    Vous pouvez l’utiliser très simplement dans un projet Visual Studio en faisant un “Add Service Reference”, ou sur d’autres plateformes clientes grâces aux différents helpers : http://www.odata.org/developers/odata-sdk.

    Le prochain article sera consacré à l’application CaveAVins pour Windows Phone 7.1. : avec Mango, c’est encore plus simple d’utiliser un service OData !

  • Stéphanie Hertrich

    Liste des nouvelles API pour WP7.1 Mango

    • 0 Comments

    Petit rappel vite fait pour vous attaquer aux nouveautés de Windows Phone 7.1 (Mango)…

    Et aussi pour les apps existantes :

  • Stéphanie Hertrich

    CaveAVins Tutoriel 4 : Hébergement du service WCF Data Services dans Azure

    • 0 Comments

    Update 18/10/2011: l’url du service OData devient http://stephecaveavins.cloudapp.net/CaveAVinsDataService.svc

    Après la migration des données dans SQL Azure effectuée dans le précédent tutoriel, c’est au tour du service WCF Data Services de publication des données d’être hébergé sur la plateforme Cloud. Il sera ainsi accessible facilement depuis l’extérieur, y compris par un smartphone.

    Les étapes décrites dans ce tutoriel sont valables pour n’importe quelle ASP.Net Web Application.

    Nous irons “de là”

    image

    à “de là”:

    image

    Résumé des épisodes précédents

    Tutoriels:

    - CaveAVins Tutoriel 1 : L’accès aux données avec Sql Server et EF Code First
    - CaveAVins Tutoriel 2 : La publication des données en OData avec WCF Data Services
    - CaveAVins Tutoriel 3 : Migration d’une base SQL Server vers SQL Azure
    - CaveAVins Tutoriel 4 : Hébergement du service WCF Data Services dans Azure (vous êtes ici Star)

    Pré-requis:

    1. Il vous faut un compte Azure que vous obtiendrez gratuitement pour une période de 30 jours: Azure Pass
    2. Vous pouvez utiliser n’importe quel service pour suivre ce tutoriel. Pour l’illustration nous partons de la solution construite depuis les 2 précédents tutoriels, que vous pouvez télécharger ici:

    3. Dans cette solution, il vous faudra modifier le fichier de configuration pour pointer sur votre base de données SQL Azure, comme expliqué dans le précédent tutoriel.
      Cela revient à ajouter la chaine de connexion appropriée dans le web.config du projet web comme par-exemple:

    <connectionStrings>
    <add name="CaveAVinsContext"     connectionString="Server=tcp:oy7122pvo6.database.windows.net,1433;Database=CaveAVins.Db.Azure; User ID=stephe@oy7122pvo6;Password=myPassword;Trusted_Connection=False;Encrypt=True;"
    providerName="System.Data.SqlClient"/>
    </connectionStrings>

    Les étapes

    1. Pour héberger un service sur Azure, il suffit d’ajouter un projet de type Azure dans la solution Visual Studio.
    2. Ce projet Azure permettra d’associer le projet web à un web rôle dans Azure et de le configurer.
    3. Il est ensuite possible d’exécuter le service dans l’émulateur Azure directement sur votre poste de travail, ce qui vous permet de rendre votre solution fonctionnelle et de la débugger sans utiliser de compte Azure.
    4. Quelques modifications de configuration seront nécessaires pour permettre l’hébergement dans Azure.
    5. Vous pourrez ensuite déployer le service dans Azure directement depuis Visual Studio, en pré-production
    6. Et la passer en production pour la rendre disponible publiquement avec une URL du type http://stephecaveavins.cloudapp.net/CaveAVinsDataService.svc

    C’est parti !

    Ouvrez la solution CaveAVins dans Visual Studio.

    Modifiez les propriétés de l’application Web de manière à ce qu’elle se positionne directement sur le service OData au démarrage:

    image

    Ajoutez un nouveau projet de type Windows Azure.

    image

    Appelez-le CaveAVins.Azure et cliquez sur OK.

    image

    Visual Studio nous propose d’ajouter de nouveaux projets pour les associer à des rôles, mais comme c’est un projet Web existant que nous souhaitons héberger dans Azure, nous avons déjà ce qu’il nous faut.

    image

    Le nouveau projet Azure est ajouté à la solution. Remarquez que le répertoire “Roles” est vide. Nous allons donc associer un web role au projet web existant : CaveAVins.WebApplication.

    image

    Faites un clic droit sur “Roles” et ajoutez un nouveau web role pour un projet de la solution

    image

    Notre projet CaveAVins.WebApplication apparait, et nous le sélectionnons.

    image

    Notre web role apparait dans le projet Azure : il sera hébergé sur la plateforme lors du déploiement.

    Exécution dans l’émulateur Azure

    En exécutant votre application (en veillant bien à ce que le projet de démarrage soit CaveAVins.Azure), l’émulateur Azure hébergera votre service. Vous avez accès à l’instance à travers la console de l’émulateur. Vous la trouverez dans les icones en bas à droite de votre écran:

    image

    image

    Le service apparait dans la page lors du lancement :

    image

    Maintenant que le service fonctionne dans l’émulateur, déployons le réellement dans Azure.

    Déploiement du service dans Azure

    Avant de déployer, modifions le nombre d’instances configurés pour le service et passons-le à 2.

    En effet, les caractéristiques de haute disponibilité d’Azure ne peuvent être garanties si vous ne déployez qu’une seule instance, et d’ailleurs la console d’administration vous préviendra de ce risque, comme ci-dessous :

    image

    Ampoule Pour vous familiariser avec le portail Azure, je vous conseille les fiches pratiques : Premiers Pas dans l’administration de Windows Azure.

    Nous modifions également la taille de la VM pour choisir le minimum correspondant à nos besoins et faire ainsi baisser le cout de mon hébergement.

    Puis nous désactivons les options de diagnostique.  Pour les utiliser sur Azure, il faudra modifier la valeur par défaut pour l’associer à votre compte de stockage azure.

    image

    Pour que les librairies spécifiques à notre projet soient incluses dans le package Azure, il faut activer la copie locale, dans les propriétés. Dans notre, cas il faudra l’appliquer à CaveAVins.Db et à EntityFramework.

    image

    Compilez (F6), faites un clic droit sur le projet Azure et choisissez “Publish”

    image

    Vous allez pouvoir travailler directement dans dans Visual Studio pour vos projets Azure, que ce soit pour le développement ou pour le déploiement. Mais pour cela il faut commencer par associer votre projet à votre compte Azure et environnement de travail (stockage, service host).

    Pour un premier déploiement, il vous faut donc accéder au portail Azure pour créer un Storage…

    image

    …ainsi qu’un nouveau Hosted Service.

    image

    Lorsque vous créerez le hosted service qui servira à héberger votre projet, il faudra décocher l’option de publication par défaut, puisque c’est à partir de Visual Studio que nous orchestrerons tout cela:

    image

    Si vous êtes perdus, suivez les étapes qui sont plus détaillées dans la fiche pratique de création d’un nouveau service

    Revenons à présent à notre déploiement depuis Visual Studio et créons les informations d’authentification nécessaires pour que l’utilisation du compte Azure puisse se faire.

    image

    image

    Ensuite suivez les étapes 2 et 3 indiquées sur la page, à savoir copier le chemin vers le certificat qui a été créé localement sur la machine.

    image

    L’ajouter dans le portail Azure

    image

    Copier le “subscription ID” comme demandé à l’étape 3, que vous trouverez ici:

    image

    On y arrive !

    image

    Par défaut, le déploiement est proposé dans l’environnement de staging (pré-production), ce qui nous convient bien pour le moment.

    Le déploiement sur Azure prendra un peu de temps, et vous pouvez évaluer l’avancement dans l’”Azure Activity Log” de Visual Studio.

    image 

    Ou dans l’explorateur de serveur toujours dans Visual Studio.

    image

    Ou encore directement dans le portail Azure.

    image

    Vos efforts sont payants : la prochaine fois que vous modifierez votre service et que vous voudrez le déployer, cela se fera en un clic…(bon disons deux : ”Publish” et “Ok”).

    Ampoule Vous pouvez aussi utiliser Web Deploy pour le déploiement dans Azure, grâce à Windows Azure Accelerator for Web Role.

    Votre service est maintenant prêt à être utilisé à l’adresse de staging : http://db4da25d018242349e92ad4b830b162b.cloudapp.net/CaveAVinsDataService.svc

    Vous pouvez passer votre service en production en publiant sur l’environnement de production dans Visual Studio ou en passant le service de pré-prod en production par le portail Azure :

    image

    Une fois l’opération réalisée, le service est disponible en production, et donc disponible à travers l’URL fixe http://stephecaveavins.cloudapp.net/CaveAVinsDataService.svc

    image 

    Cliquez sur http://stephecaveavins.cloudapp.net/CaveAVinsDataService.svc pour accéder au service.

    image

    Et voilà !

    Notre architecture devient:

    image

    Nous pouvons maintenant accéder aux données à partir d’une application Windows Phone : c’est le sujet de nos prochains tutoriels.

  • Stéphanie Hertrich

    CaveAVins Tutoriel 3 : Migration d’une base de données SQL Server vers SQL Azure

    • 0 Comments

    Ce tutoriel montre comment migrer une base de données SQL Server existante vers SQL Azure.
    Il a été écrit dans le cadre d’une suite d’articles mais la procédure est exactement la même pour n’importe quelle base SQL Server et vous pouvez donc la suivre indépendamment des exemples proposés.

    Dans notre projet démarré from scratch, nous sommes arrivés au stade suivant:

    image

    Pour pouvoir accéder à nos données depuis un téléphone, il nous faut les héberger sur un serveur accessible depuis l’extérieur.
    Dans notre cas, nous décidons d’utiliser la plateforme Azure, les motivations de ce choix sont détaillées dans l’article  Architecture et découpage du projet .
    Nous verrons qu’il est très simple de migrer un projet existant vers Azure. Dans notre cas, nous migrerons 2 éléments différents:

    • la base de données Sql Server
    • le service WCF Data Services qui publie les données en OData

    Dans ce tutoriel, nous commencerons par migrer la base de données Sql Server vers Sql Azure.
    Si ceci est votre première expérience de la plateforme, nous créerons également le serveur Sql Azure en pas à pas.
    Nous modifierons la chaine de connexion du service WCF Data Services : le service fonctionnera toujours, mais en adressant cette fois Sql Azure.
    Nous obtiendrons l’architecture suivante à la fin de ce tutoriel:

    image


    Puis nous migrerons le service WCF Data Services vers la plateforme Azure sous la forme d’un web role dans le tutoriel suivant.

    Rappel des épisodes précédents

    1. Développer un projet aujourd’hui : comment faire, par où commencer ?
    2. Architecture et découpage du projet
    3. Stockage des données avec Sql Server, EF Code First et Azure
    4. La publication des données
    5. La migration dans Azure 
    6. L’application Windows Phone basique
    7. Ajout de la fonction d’aide à l’achat
    8. Ajout des notifications sur les vins en promotions
    9. L’application Silverlight

    Tutoriels:

    - CaveAVins Tutoriel 1 : L’accès aux données avec Sql Server et EF Code First
    - CaveAVins Tutoriel 2 : La publication des données en OData avec WCF Data Services
    - CaveAVins Tutoriel 3 : Migration d’une base SQL Server vers SQL Azure (vous êtes ici Star)
    - CaveAVins Tutoriel 4 : Hébergement du service WCF Data Services dans Azure

     

    Pré-requis:

    1. Il vous faut un compte Azure que vous obtiendrez gratuitement pour une période de 30 jours: Azure Pass
    2. Nous partons de la solution construite depuis les 2 précédents tutoriels, que vous pouvons télécharger ici:

     

    Migration de la base de données Sql Server vers Sql Azure

    Un outil de migration téléchargeable sur codeplex va vous permettre d’effectuer cette opération en quelques clics :

    SQL Azure Migration Wizard

    Une fois le fichier décompressé, lancez l’application.

    image

    Sélectionnez “Analyser et migrer base de données SQL”

    image

    Entrez le serveur SQL utilisé pour le stockage des données et cliquez sur “Connecter”.

    image

    Choisissez CaveAVins.Db.CaveAVinsContext. C’est le nom de la base de données qui a été générée par Entity Framework Code First.

    Puis cliquez sur “Suivant”

    image

    Choisissez de scripter tous les objets : c’est le choix par défaut.

    image

    Voici un dernier rappel des éléments qui seront générés.

    image

    L’outil s’occupe de générer les scripts adéquats.

    image

    A présent, ces scripts vont être utilisés avec votre compte Azure pour générer la base de données Sql Azure correspondante.

    Pour renseigner ces informations, vous aurez besoin d’un serveur Sql Azure sur lequel créer votre base de données.
    Si vous n’avez pas encore créé de serveur, réalisez les étapes du chapitre suivant.

    Création du serveur Sql Azure

    Si c’est la première fois que vous utilisez Sql Azure, il vous faudra suivre les étapes suivantes.

    Accédez au portail Azure et connectez-vous avec le live Id que vous avez utilisé pour créer votre compte Azure.

    image

    Sélectionnez “Base de données” ainsi que votre abonnement, puis cliquez sur “Créer”.

    image

    Sélectionnez la zone géographique la plus proche : “West Europe”.

    image

    Choisissez votre identifiant et mot de passe.

    image

    Ajoutez une règle autorisant n’importe à quelle machine – y compris Azure – à accéder à la base.

    image

    Votre serveur Sql Azure est créé et apparait maintenant dans le portail.

    image

    Reprise de la migration

    Vous pouvez repasser sur l’assistant de migration et compléter les champs avec les informations correspondantes apparaissant sur le portail :

    image

    Cliquez sur “Connecter”.

    image

    Puis sur “Créer la base”.

    image

    Entrez le nom de la base de données que vous souhaitez créer.

    image

    Cliquez sur “Suivant”.

    image

    image

    La migration est terminée. Retournez sur le portail Azure, vous verrez apparaitre votre base de données.

    image

    Mise à jour de la chaine de connexion dans le service WCF Data Services

    Pour que notre service adresse la base de données SQL Azure, il suffit de modifier la chaine de connexion, que vous trouverez sur la droite du portail.

    image

    Cliquez sur “Afficher”.

    image

    Copiez la chaine de connexion ADO.Net et ajoutez-la dans une nouvelle section “connectionStrings” dans le web.config de notre service, comme ceci:

    image

      <connectionStrings>
        <add name="CaveAVinsContext" 
             connectionString="Server=tcp:oy7122pvo6.database.windows.net,1433;Database=CaveAVins.Db.Azure;User ID=stephe@oy7122pvo6;Password=myPassword;Trusted_Connection=False;Encrypt=True;"
             providerName="System.Data.SqlClient"/>
      </connectionStrings>

    Le nom de la chaine de connexion est important, puisqu’il doit correspondre au nom du contexte EF Code First associé à notre base de données, dans notre cas : CaveAVinsContext.

    Relancez le service : il accède maintenant à notre base de données Sql Azure !

    Test du service

    Pour le prouver, ajoutons une ligne dans la table Wines, par l’intermédiaire de l’outil d’administration en ligne de Windows Azure:

    image

    image

    Exécutons notre service et consultons la liste des vins à l’adresse: http://localhost:5972/CaveAVinsDataService.svc/Wines

    image

    Passons maintenant à la migration du service WCF Data Services. C’est ce que nous verrons dans le tutoriel suivant.

Page 1 of 1 (5 items)