[MOOC] Windows 8 - 1/ Les Contrats en C#

14. March 2013 00:03 by Renaud in MOOC, Windows 8  //  Tags: , , ,   //   Comments (0)

Dans cette vidéo d'une heure, on passe en revue les contrats dans les applications Windows Store. Les contrats permettent de développer des applications qui soient cohérentes et intégrées avec l'ensemble du système Windows 8, ce qui donne globalement une meilleure expérience utilisateur.

Les Contrats

On parle ici des trois principaux contrats que sont le Search, le Share et les Settings. De quoi s'agit-il et comment les implémenter dans une application écrite en C# ? Toutes les réponses sont dans la vidéos.

Au sommaire :

03'40" : Search : permettre de chercher dans votre application depuis n'importe où et n'importe quand.
24'33" : Share : tirer profit du potentiel des autres applications grâce au partage de données App-To-App.
41'32" : Settings : rassembler les paramètres de l'app dans un seul endroit pour offrir une expérience consistante.

Après avoir suivi cette vidéo :

Vous aurez appris à développer des applications super-intégrées à Windows 8, ce qui rendra vos utilisateurs contents :) et ça fait toujours plaisir de recevoir des reviews positives !

La suite

Dans les prochaines vidéos, on parlera du Cycle de vie de l'application et on verra quelques Tips & Tricks sur le XAML, Visual Studio et Blend.

 

[Windows 8] Un exemple court pour comprendre ce que sont Promise, then() et done() avec WinJS

27. January 2013 14:01 by Renaud in Windows 8  //  Tags: , , , , ,   //   Comments (0)

Le concept des Promise et la différence entre then() et done() sont assez difficiles à comprendre. Les explications dans la doc MSDN sont abstraites, et on pourrait croire que then() et done() font la même chose... mais ce n'est pas le cas. Voici un petit morceau de code qui, je pense, est plutôt explicite. Copiez/collez-le dans une nouvelle app Windows 8 JS/HTML et placez des breakpoints à chaque ligne, exécutez l'app, et lisez les commentaires. Le but de ce code est également de vous montrer qu'il n'est pas nécessaire avec les Promise d'écrire des fonctions, dans des fonctions, dans des fonctions... En effet, j'ai vu quelques personnes demander en quoi ça facilitait la vie d'utiliser les Promise avec WinJS. Ils demandent cela parce qu'ils pensent qu'ils doivent écrire du code comme cela :

asyncCall().then(function() {
    anotherAsyncCall().then(function(){
        aThirdAsyncCall();
    }
}

Et c'est vrai que dans ce cas, on pourrait se poser des questions sur l'utilité des Promise. On ne fait que réécrire du code avec des callbacks imbriqués pour finir avec un bordel absolu. Evidemment ce n'est pas le cas ! Regardez le code qui suit et lisez les commentaires :)

 WinJS.xhr({ url: "http://www.microsoft.com" })
        .then(function (microsoftResult) {
            // Ici, on reçoit une réponse, comme on s'y attendait.
            // Que faisons-nous ensuite? 
            // On pourrait faire un autre appel async,
            // ou juste retourner une valeur simple pour voir...
            // Retournons une url, que l'on utilisera 
            // par la suite pour faire une nouvelle requête :
            return "http://dev.windows.com";
        }).then(function (devWindowsUrl) {
            // devWindowsUrl contient simplement la valeur retournée dans la partie précédente.
            // Maintenant, essayons un autre appel async
            // et plutôt que d'utiliser des callbacks (then)
            // retournons simplement l'objet Promise !!
            return WinJS.xhr({ url: devWindowsUrl });
        }).then(function (devWindowsResult) {
            // Quand on arrive ici, on peut voir que dewWindowsResult ne contient pas de Promise.
            // Ca contient en fait le résultat de la Promise, c'est à dire la réponse à la requête.
            // C'est donc là que se situe la magie =)

            // Maintenant déclenchons une exception en appelant une fonction inexistante...
            return devWindowsResult.callNonExistingFunction();
        }).then(function (nonExistingResult) {
            // Nous n'atteignons pas ce point-ci...
            return "ha bon, ça existait finalement?";
        }, function (nonExistingError) {
            // Au lieu de ça, on arrive ici, parce que la Promise s'est terminée avec une erreur.
            // Mais c'est pas grave. Vu qu'on est là, on peut gérer cette erreur.
            // On va retourner un message gentil pour rassurer tout le monde.
            return "cette fonction n'existe pas mais c'est ok, on a géré l'exception !";
        }).then(function (errorHasBeenHandledResult) {
            // du coup, tout rentre dans l'ordre et on continue
            return "content =)";
        }).done(function (result) {
            // et pour finir, il faudrait cloturer par un appel à done()
            // La différence est que si une exception est déclenchée
            // à l'intérieur de cette fonction, l'exception sera vraiment lancée
            // et pas simplement passée comme paramètre à un prochain callback

            // L'exception sera lancée de manière asynchrone, donc si elle vous intéresse
            // il faut catcher les exceptions de la dernière chance au niveau de l'app

            // Essayez de dé-commenter cette ligne pour voir.
            //return result.callANonExistingMethod();
        }, function (error) {
            // Ici on peut éventuellement gérer une erreur renvoyée par l'appel asynchrone précédent.
            var resultError = error;
        });

Pour être sûr de catcher les exceptions asynchrone, un petit coup de WinJS pour ajouter un eventhandler au niveau de l'app :

    var app = WinJS.Application;
    app.onerror = function (error) {
        //Log the last-chance exception 
    };

Enfin, sachez que dans le cas où vous terminez par done(), si vous ne fournissez pas de callback pour le onError, et que la Promise se termine avec une erreur, cette erreur sera automatiquement forwardée, et donc une exception de la dernière chance sera déclenchée !

 

[Windows 8] Short code sample to understand Promise, then() and done() with WinJS

27. January 2013 14:01 by Renaud in Windows 8  //  Tags: , , , ,   //   Comments (0)

I just wrote a small piece of code which is, in my opinion, self-explanatory. Copy/past those lines in a blank Windows 8 JS/HTML app and put some break points at each line. Then, follow the story :)

The aim of this example is to show that you don't have to write functions, within functions, within functions.

Indeed, I know some people think they have to write code like this :

asyncCall().then(function() {
    anotherAsyncCall().then(function(){
        aThirdAsyncCall();
    }
}

But then, why would we use Promises ? Is it just another way to write messy code? Of course not ! Look at this code and read the comments :)

 WinJS.xhr({ url: "http://www.microsoft.com" })
        .then(function (microsoftResult) {
            // Here we receive the response, as excepted.
            // So what do we do here? We could try another asynchronous call,
            // or just return a simple value.
            // Let's return the url that we want to fetch in the next call :
            return "http://dev.windows.com";
        }).then(function (devWindowsUrl) {
            // The devWindowsUrl simply contains the value that we returned in the previous call.
            // Now let's try another Async call, and instead of using callbacks here, let's just return the promise !!
            return WinJS.xhr({ url: devWindowsUrl });
        }).then(function (devWindowsResult) {
            // When we are here, you can see that devWindowsResult doesn't contain a promise.
            // It contains the actual value that we wanted to retrieve from the previous async call.
            // That's the magic =)

            // Now let's throw an exception by calling a non-existing function
            return devWindowsResult.callNonExistingFunction();
        }).then(function (nonExistingResult) {
            // We don not hit this breakpoint
            return "wow, does it really exist?";
        }, function (nonExistingError) {
            // Instead, we are here, because the promised is fulfilled with an error
            // Now let's return something nice, because we managed to handle the error.
            return "that function didn't exist but it's okay, we handled the exception!";
        }).then(function (errorHasBeenHandledResult) {
            // then, everything continues normally
            return "happy =)";
        }).done(function (result) {
            // and at the end you should end up with a done function.
            // The difference is that if there is an exception thrown, 
            // within this function, the error will be actually thrown
            // and not just passed as an argument in a next callback.

            // The error is thrown asynchronously, so you should ensure
            // you catch the last-chance exception at the app-level.
            return result.callANonExistingMethod();
        }, function (error) {
            // Here we can eventually handle an error in the previous 'then' error handling callback.
            var resultError = error;
        });

Then, to make sure you handle the exceptions that are thrown asynchronously, you can just add this eventhandler with WinJS :

    var app = WinJS.Application;
    app.onerror = function (error) {
        //Log the last-chance exception 
    };

Finally, if you use a done() function at the end of your async calls, remember that the previous promise could throw an exception. If it is the case, and that you didn't provide a onError callback, the exception will be automatically forwarded and you will end up with a first chance exception !

[Windows 8] HTML/JS : VariableSize List View and Template Selection

24. January 2013 00:01 by Renaud in Windows 8  //  Tags: , ,   //   Comments (0)

Here is my first attempt to achive a VariableSize List View in HTML /JS. I tried to apply the same concept as what I knew about XAML and the TemplateSelector, so I started with a function returning the right template, and finally I come to this satisfaying solution :) I just made a first try to achieve this : http://sdrv.ms/Yosvcr Instead of giving a Template to the ListView, I gave it a function that selects the right template according to the index of the item. Then you have different template, with different style, but all the items style have the same size. Then, if you read the end of this page, the paragraph about cell-spanning, you'll see that you need to change two more things to achieve what you want : change the groupInfo or itemInfo properties of the GridLayout used in your ListView. Here are the key parts of the sample I provided : 1/ First, you declare two or more templates + your listview:

    <div id="mediumListIconTextTemplate" data-win-control="WinJS.Binding.Template">
        <div class="mediumItem">
            <h4 data-win-bind="innerText: title"></h4>
            <h6 data-win-bind="innerText: text"></h6>
        </div>
    </div>

    <div id="largeListIconTextTemplate" data-win-control="WinJS.Binding.Template">
        <div class="largeItem">
            <h2 data-win-bind="innerText: title"></h2>
            <h3 data-win-bind="innerText: text"></h3>
        </div>
    </div>

    <div id="listView"
        data-win-control="WinJS.UI.ListView"
        data-win-options="{ 
                itemDataSource: myData.items.dataSource, 
                itemTemplate:myData.template, 
                selectionMode: 'none', 
                tapBehavior: 'none', 
                swipeBehavior: 'none'
            }">
    </div>

Notice the itemTemplate property. It refers to myData.template, which is a function I defined in my JS file. Then you can add some CSS :

.mediumItem {
    width:100px;
    height:100px;
    background-color:cornflowerblue;
}

.largeItem {
    width:100px;
    height:150px;
    background-color:green;
}

Then, some javascript in a separated file :

(function () {
    "use strict";

    // Create a new bindable list
    var list = new WinJS.Binding.List([]);
    // some fake data
    list.push({ title: "Titre 1", text: "Texte 1" });
    list.push({ title: "Titre 2", text: "Texte 2" });
    list.push({ title: "Titre 3", text: "Texte 3" });
    list.push({ title: "Titre 4", text: "Texte 4" });

    // my function that selects the template
    function selectTemplate(itemPromise) {
        // it receives a promise of an item
        return itemPromise.then(function (item) {

            // Then I can get the item
            // and based on its index property I can choose a templatE.
            var container = window.document.createElement("div");
            var itemTemplate;
            switch (item.index) {
                case 0:
                    itemTemplate = WinJS.Utilities.query("#mediumListIconTextTemplate")[0];
                    break;
                case 1:
                    itemTemplate = WinJS.Utilities.query("#largeListIconTextTemplate")[0];
                    break;
                default:
                    itemTemplate = WinJS.Utilities.query("#largeListIconTextTemplate")[0];
                    break;
            }

            // I put my item in a container and style it with the choosen template.
            itemTemplate.winControl.render(item.data, container);
            return container;
        });
    }

    // The selection function has to be marked as supported for processing or you get an error.
    WinJS.Utilities.markSupportedForProcessing(selectTemplate);

    // declare the model and expose the selectTemplate function.
    WinJS.Namespace.define("myData",
    {
        items: list,
        template: selectTemplate
    });

})();

At this point, it uses the right template. But I still have to change the Layout, as explained in the msdn doc. So when the page gets processed by WinJS to display the controls :

           args.setPromise(WinJS.UI.processAll().then(function () {
                var listView = WinJS.Utilities.query('#listView')[0].winControl;
                listView.layout = new WinJS.UI.GridLayout;

                // Enable CellSpanning and give base size.
                listView.layout.groupInfo = function () {
                    return {
                        enableCellSpanning: true,
                        cellWidth: 50,
                        cellHeight: 50
                    };
                }
            }));

With those settings, the cell containing your item will be sized to fit best your template!

 

Developers Voice

22. January 2013 09:01 by Renaud in   //  Tags:   //   Comments (0)

Ces dernières années, nous avons été heureux de vous voir, si nombreux, participer aux évènements organisés dans nos locaux. Nous avons fait beaucoup de nouvelles rencontres, de nouveaux partenariats, et avons collaboré avec vous à divers projets.

Nous souhaitons évidemment poursuivre ces activités cette année encore ! Mais nous aimerions aller plus loin.

En plus de proposer nous-même des événements en espérant que les sujets vous plaisent, pourquoi ne vous laisserions-nous pas faire vos propres propositions ? Pour cela nous avons ouvert un espace sur lequel vous avez la parole. C'est donc à vous de nous dire ce qui vous intéresserait, et a vous de faire votre calendrier du MIC !

Visitez le UserVoice du MIC !

Vous êtes développeur et vous aimeriez parler d'un sujet qui vous passionne ? Dites-le ! Et si ce sujet intéresse d'autres personnes, nous pourrions envisager d'organiser un afterwork, un apéro, ou même une journée de formation complète sur le sujet ! Vous aimeriez savoir comment partager un maximum de code entre vos applications mobiles cross-plateformes ? Vous voudriez apprendre à utiliser du NFC dans une application Windows Phone 8 ? Découvrir une partie spécifique de Windows Azure ?Ou avoir des retours d'expériences sur l'Agilité dans des projets à grande échelle ? Quel que soit le sujet, nous essayerons de trouver des personnes ayant de l'expérience dans ce domaine pour répondre à vos questions ! ( Ça peut d'ailleurs être vous si vous avez envie de parler ;))

#AKWP8 / Hackathon Windows Phone 8 au Moulin de la Forge

16. December 2012 00:12 by Renaud in   //  Tags:   //   Comments (0)

Après 3h de route, on arrive enfin au Moulin de la Forge, un endroit un peu coupé du monde (et du réseau Internet :)) et qui, pour la deuxième fois, est squatté par la communauté des développeurs Windows Phone. Le #AKWP8, ce n'est pas un "concours" pour les développeurs. Il n'y a pas de pression, pas d'engagement. C'est simplement un weekend, organisé par Microsoft France, pour réunir tous les passionnés. Alors forcément ça attire du monde. Pas moins de 100 développeurs dans la salle. On a attendu que tout le monde arrive et s'approprie un bonnet pour faire le lancement.

Le programme est complètement libre : chacun bosse sur ce qu'il veut, seul ou en équipe. Mais le weekend est rythmé par quelques milestones:

Vendredi soir de 23h à ... Bootcamps :

Les évangélistes Microsoft et quelques volontaires organisent des petits ateliers pour parler de technologies à la demande des participants. On a eu droit à  DirectX, le NFC sur Windows Phone, Windows Azure Mobile Services, Windows 8 et le Modern UI, etc...

Samedi, 12h-18h, Fast Code !

Pierre Cauchois lance le sujet à midi : développer une app sur le thème du #AKWP8 ou du Moulin de la Forge ! Ceux qui le veulent ont 6h pour développer un proto pour en faire une démo. Juste pour le fun :)

Samedi de 20h à 2h matin, Bootcamps II

Pour ceux que ça intéresse, petits cours sur le portage d'application Windows Phone vers Windows 8, et WP7 vers WP8.

Dimanche de 11h jusqu'au départ... Submission party

Parce qu'au final on espère voir quelques apps soumises sur le store :)

Les achievements

Mais le top du top, c'est cette idée d'achievements pour faire gagner des stickers aux devs qui réussiront quelques défis! Rien de très sérieux, mais ça fait toujours plaisir :) Mon laptop devient mon tableau de chasse ! Quelques-uns des achievementsque j'ai débloqué :

  • FastCoder : pour avoir participé au FastCode ^^
  • Samaritan : pour avoir aidé quelques personnes qui peuvent en témoigner.
  • Azure : une app avec un backend dans le cloud !
  • ....

C'est la deuxième fois que j'ai la chance de participer à cet événement qui est juste épique et j'ai déjà hâte de voir ce que Microsoft nous proposera pour la prochaine édition :) Si vous voulez suivre un peu l'event en live, c'est ici : #AKWP8 !

[Windows 8] C# / XAML : FlipView, Context Indicator et Prévisualisation

4. December 2012 16:12 by Renaud in Windows 8  //  Tags: , ,   //   Comments (2)

Dans cet article on va voir comment reproduire le Context Indicator que l'on peut voir dans le Store. Cet indicateur, c'est ce que vous pouvez voir en dessous du flipview montrant les différents screenshots de l'application, et qui vous donne une idée de l'endroit où vous vous trouvez dans la liste.

Indicateur dans le store

Reproduire l'indicateur du store

Pour y arriver, on va modifier légèrement le template du FlipView. Pour ça, il suffit d'utiliser Blend et de modifier une copie du template existant.

On va ensuite  y ajouter une ListView :

Une fois qu'on a cette ListView, on va faire plusieurs choses :

  • Binder la propriété ItemsSource avec le FlipView pour avoir le même nombre d'éléments dans chaque liste
ItemsSource="{TemplateBinding ItemsSource}"
  • Binder la propriété SelectedItem avec le FlipView  pour les synchroniser
SelectedItem="{Binding SelectedItem, Mode=TwoWay, RelativeSource={RelativeSource Mode=TemplatedParent}}"
  • Modifier l'orientation de la liste en activant le scroll horizontal et en changeant l'orientation du StackPanel qui va contenir les items.
ScrollViewer.HorizontalScrollBarVisibility="Auto"
ScrollViewer.VerticalScrollBarVisibility="Disabled"
ScrollViewer.HorizontalScrollMode="Enabled"
ScrollViewer.VerticalScrollMode="Disabled"

Le panel :

    <ListView.ItemsPanel>
        <ItemsPanelTemplate>
            <StackPanel  Orientation="Horizontal" />
        </ItemsPanelTemplate>
    </ListView.ItemsPanel>
  • Et pour finir, on va sauvagement modifier le style des items et des items containers. On va vraiment faire un gros nettoyage pour éviter d'avoir l'habituelle bordure mauve lorsqu'un élément est sélectionné. On va garder le strict minium et faire en sorte d'avoir un rectangle gris par défaut, et blanc lorsque l'élément est sélectionné. Je vous épargne le code, mais vous pouvez le trouver dans le projet téléchargeable à la fin de l'article :)

Et voilà le résultat :

Aller plus loin et créer une barre de preview !

L'idée est d'utiliser cet indicateur pour donner plus d'infos à l'utilisateur, et lui permettre de l'utiliser même pour naviguer dans le flipview ! Pour vous donner une idée du résultat :)

Pour faire ça, on va principalement modifier le ItemTemplate de la ListView :

<ListView.ItemTemplate>
    <DataTemplate>
        <Grid HorizontalAlignment="Center" VerticalAlignment="Center">
            <Image Source="{Binding ImageUri}" Stretch="UniformToFill"/>
        </Grid>
    </DataTemplate>
</ListView.ItemTemplate>

Si l'on s'arrête là, lorsque l'on se déplace à partir du FlipView, on modifie bien l'item sélectionné dans la ListView. Mais si l'on se déplace trop loin, il se peut que cet item se retrouve en dehors du champs de vision ! Pour éviter ça, on va écouter l'événement SelectionChanged de la ListView, et faire en sorte que l'item sélectionné soit toujours visible.

private void ListViewSelectionChanged1(object sender, Windows.UI.Xaml.Controls.SelectionChangedEventArgs e)
{
    // Si un nouvel item est bien sélectionné
    if (e.AddedItems.Count > 0){
        // On scroll vers cet item !
        ((ListView)sender).ScrollIntoView(e.AddedItems.First());    }
}

Et voilà :) Les sources des deux projets sont téléchargeables sur mon Skydrive : http://sdrv.ms/SJv8PX

 

[Windows 8] C# / XAML : FlipView, Context Indicator & Items Preview

4. December 2012 15:01 by Renaud in Windows 8  //  Tags: , , ,   //   Comments (3)

Let's see how we can reproduce the Context Indicator that you can see in the Store application. This indicator is what you see behind the flipview that shows you the screenshots of an app, and that tells what is your position in that list.

 Indicator for the Wikipedia app in the Store.

Reproduce the Store's Indicator

To achieve this, we will have to slighty modify the FlipView template. Open Blend and use the command "Edit Template > Edit a copy...

 

Add a ListView to it in the visual tree of the FlipView. 

 

Now that we have that list, we can do a few things :

  • Bind the ItemsSource with the parent FlipView so that we have the same quantity of elements in each list
ItemsSource="{TemplateBinding ItemsSource}"
  • Bind the SelectedItem property with the FlipView to make sure both are syncrhonized together
SelectedItem="{Binding SelectedItem, Mode=TwoWay, RelativeSource={RelativeSource Mode=TemplatedParent}}"
  • Set the orientiation and the scrolling horizontal
ScrollViewer.HorizontalScrollBarVisibility="Auto"
ScrollViewer.VerticalScrollBarVisibility="Disabled"
ScrollViewer.HorizontalScrollMode="Enabled"
ScrollViewer.VerticalScrollMode="Disabled"

The stackpanel :

    <ListView.ItemsPanel>
        <ItemsPanelTemplate>
            <StackPanel  Orientation="Horizontal" />
        </ItemsPanelTemplate>
    </ListView.ItemsPanel>
  • And finally, we will dramaticaly change the items style and the items containers style. We clean them up to remove the purple border on the selected item. We just keep what we need : a gray-filled border which becomes white when the item is selected. I wont copy/paste the code here but you can grab it at the end of this post.

And here is the result : 

Go further with a preview bar !

Now the idea is to use that indicator to give more information to the user. Let's say you have a big list and you want to show a preview with a thumbnail, so that it's easier to navigate throught the flipview. Here is what it would look like :) 

To achieve that, we just have to modify the ItemTemplate of the ListView :

<ListView.ItemTemplate>
    <DataTemplate>
        <Grid HorizontalAlignment="Center" VerticalAlignment="Center">
            <Image Source="{Binding ImageUri}" Stretch="UniformToFill"/>
        </Grid>
    </DataTemplate>
</ListView.ItemTemplate>

If we stop here, we will just miss a thing : when you navigate in the list using the FlipView itself, you can see that the selected item in the ListView is well syncrhonized. But if you go to far in the list, the selected item may be out of the field of view. It's easy to avoid that, by listening to the SelectionChanged event on the ListView, and each time an item is selected you ask the ListView to scroll and make sure the item is visible !

private void ListViewSelectionChanged1(object sender, Windows.UI.Xaml.Controls.SelectionChangedEventArgs e)
{
    // Si un nouvel item est bien sélectionné
    if (e.AddedItems.Count > 0){
        // On scroll vers cet item !
        ((ListView)sender).ScrollIntoView(e.AddedItems.First());    }
}

And there you are :) You can grab the bits of those two projects on my Skydrive : http://sdrv.ms/SJv8PX

Windows Azure Mobile Services : Intro

3. December 2012 15:12 by Renaud in Windows Azure  //  Tags: , ,   //   Comments (0)
Suite au Windows App Day et à l'excellente session de Kristof Rennen sur les Mobile Services, je me suis dit que je pourrais également faire un article sur le sujet. J'en avais parlé à l'occasion du premier Café Numérique de Tournai. Voici en quelques mots de quoi il s'agit :)

Les technologies évoluent, et les utilisateurs sont de mieux en mieux équipés et deviennent plus exigeants. Comment faire en sorte de créer une application qui soit à la hauteur de la demande des utilisateurs ? Il y a en quelque sorte un minimum requis d'office. Des features indispensables. Et cela peut parfois décourager le développeur qui souhaiterait se lancer. Par exemple, une application uniquement offline aura peu de chance de survivre après une réinstallation ou un changement de device, parce que l'utilisateur sera frustré d'avoir perdu ses données... Plusieurs difficultés s'opposent aux développeurs qui veulent se démarquer. Ils doivent par exemple :

  • Mettre au point un service web, sans spécialement savoir comment s'y prendre
  • Rendre ce service disponible via internet
  • S'habituer à la programmation asynchrone
  • Mettre en place et maintenir un moyen d'identification de l'utilisateur pour des scénarios un peu plus avancés

Tout cela demande de l'investissement et du temps. Et c'est là qu'il est bon de parler de Windows Azure Mobile Services. A eux seuls, les Mobile Services d'Azure résolvent les 4 points cités ci-dessus, et permettent encore davantage !

  • Ils permettent de créer une API de type REST en quelques clics, sans avoir à écrire une seule ligne de code.
  • Ils sont directement hébergés sur le cloud de Windows Azure, et sont pour le moment gratuits (jusqu'à 10 services).
  • Ils sont accompagnés d'un SDK disponible sur Windows 8, Windows Phone 8 et iOS et qui permet de communiquer hyper simplement avec le service, facilitant ainsi le développement.
  • Ils proposent de prendre en charge pour vous la gestion de l'identification avec différents providers tels que Microsoft (live), Facebook, Twitter et Google. Cela signifie que vous n'avez plus besoin de vous occuper vous mêmes des évolutions des APIs de chacun des provides. Microsoft le fait pour vous !

Création d'un service

La création en elle-même prend quelques secondes. Cela se passe en deux étapes. Choix du nom du service et association d'une base de données. On propose un nom de service. Azure vérifie que ce nom soit disponible. Si oui, on choisit entre la création et la réutilisation d'une base de données, et on passe à l'étape suivante qui est la configuration de cette dernière. Une fois qu'on a rempli ce rapide formulaire, Azure fait son boulot pour nous fournir un service mobile tout neuf.

Une fois le service créé, on a accès à l'habituel tableau de bord (dashboard) qui permet de contrôler rapidement l'utilisation du service en temps réel. Dès lors, le service est bel et bien disponible ! 30 secondes pour créer un service, c'est l'une des forces du cloud.

Pour pouvoir commencer à utiliser ce service et stocker des données, on va commencer par créer une nouvelle table via le portail.

Et c'est comme ça qu'en quelques clics, on résout les deux premiers problèmes du développeur ! Nous avons une API qui permet de stocker des données dans une table TodoItem, et qui est accessible via internet.

Utilisation du Mobile Services SDK

Si vous n'êtes pas familier avec les HttpClient et n'avez aucune idée de comment interroger un service REST en C#, ce n'est pas grave. Lorsque vous créez votre premier service, Azure vous propose de télécharger une application d'exemple utilisant le Mobile Service SDK. Ce SDK va vous faciliter la vie pour communiquer avec le service mobile et notamment pour effectuer les opérations de base que sont la lecture, l'insertion, la mise à jour et la suppression de données. Cette application contient une interface minimale pour gérer nos Todo. Si on regarde un peu les sources, on peut trouver dans la classe App un bout de code qui instancie un MobileServiceClient grâce à l'url du service et à la clé secrète de l'API (que l'on peut trouver sur le portail Azure) :

        public static MobileServiceClient MobileService = new MobileServiceClient(
            "https://cafentournai.azure-mobile.net/",
            "ryPMCIcJjtbkqmWrkGphhiHJXdIyoI27"
            );

Et là, vous vous dites sans doute qu'on n'a même pas encore défini ce qu'était un TodoItem... En fait, par défaut, le Mobile Service travaille avec des tables à schéma dynamique. Cela signifie que des colonnes sont automatiquement ajoutées pour pouvoir stocker toutes les propriétés des objets envoyés lors des requêtes ! Il n'y a donc pas besoin de décrire les tables côté service. On va simplement définir la classe côté client, avec quelques attributs :

    public class TodoItem
    {
        public int Id { get; set; }

        [DataMember(Name = "text")]
        public string Text { get; set; }

        [DataMember(Name = "complete")]
        public bool Complete { get; set; }
    }

A partir de là, on peut faire appel au service avec un peu de Linq. Par exemple, récupérer la liste des TodoItems qui n'ont pas encore été complété.

        List<TodoItem> items;

        private async void RetrieveUncompleteTodoItems()
        {
            IMobileServiceTable<TodoItem> todoTable = App.MobileService.GetTable<TodoItem>();

            // The query excludes completed TodoItems
            items = await todoTable
                .Where(todoItem => !todoItem.Complete)
                .ToListAsync();
        }

Laisser Azure gérer l'identification

Pour finir, ajouter une identification dans vos applications peut être un gros plus ! Pour garder un backup des données de l'utilisateur, ou permettre la synchronisation de données entre différents devices. Cela permet également de donner des droits d'accès plus spécifiques à chaque tables : si vous vous rappelez de l'étape de création de la table TodoItem, vous vous souvenez sans doute qu'il était possible de préciser des différents niveaux de permissions pour chaque fonction CRUD :

  • Everyone : cette option rend toutes vos données accessibles par défaut
  • Anyone with the Application Key : cette option restreint l'utilisation aux applications/utilisateurs possédant la clé secrète
  • Only Authenticated Users : les utilisateurs doivent être identifiés pour pouvoir communiquer avec l'API
  • Only Scripts and Admins : limite l'utilisation à la clé maître, ou aux scripts côté serveur.

Pour configurer tout ça, il suffit d'aller dans la partie Identity du portail, et de fournir des "clés" qui vous nous identifier auprès de différents providers tels que Microsoft, Facebook, Twitter, ... On peut donc aller sur https://developers.facebook.com/ ou https://dev.twitter.com/, créer une "application" pour obtenir des clés, et laisser nos utilisateurs s'identifier grâce à leurs propres comptes. Pour les comptes Microsoft, il faut aller sur le portail http://manage.dev.live.com/.

De retour dans mon application, il suffit d'une ligne de code pour demander à l'utilisateur de se connecter :

var user = await MobileService.LoginAsync(MobileServiceAuthenticationProvider.Twitter);

La méthode LoginAsync prend en paramètre le provider que l'on veut utiliser. Dans ce cas-ci, c'est Twitter. Une interface familière va s'afficher pour demander à l'utilisateur d'entrer ses identifiants.

La méthode LoginAsync est effectivement asynchrone. C'est pour cela que l'on utilise le mot clé await. Lorsque l'utilisateur a entré ses informations et autorisé l'application, la tâche est effectivement terminée et retourne un objet décrivant l'utilisateur. A partir de ce moment, l'utilisateur peut communiquer avec l'API. Il n'y a rien d'autre à faire... Ce n'est donc pas à vous de devoir maintenir du code, et si demain Twitter ou Facebook décidaient de changer radicalement la manière dont fonctionnent leurs APIs, Microsoft mettrait à jour son SDK et votre application serait toujours fonctionnelle. Toutefois, cette façon de faire est assez limitée. Les utilisateurs ne restent pas connectés d'une session à l'autre, et doivent entrer leurs identifiants à chaque fois, ce qui semble un peu curieux. Mais d'après un post d'un employé de Microsoft sur MSDN, une mise à jour du SDK devrait sortir prochainement pour apporter une solution ! :)

As Xinyang notes, we'll soon be making improvements to our Login API to provide support for WebAuthenticationBroker's SSO feature. Also, in just a few weeks we'll be releasing an update that enables you to get and, most importantly, set the authenticationToken and userId meaning that you can cache the full Mobile Services credentials however you see fit. We'll provide plenty of samples that show how this works.

Dans un prochain article, on parlera plus en détails de l'identification, et de comment on peut dès maintenant permettre à l'utilisateur de ne pas devoir s'identifier à chaque session.

Développez votre app Windows début 2013 !

1. December 2012 15:12 by Renaud in Events, Windows 8, Windows Azure, Windows Phone  //  Tags: , ,   //   Comments (0)
Article original sur le blog du MIC.

Vous avez une idée d'application en tête depuis quelques temps et vous aimeriez la réaliser ? Ou bien vous êtes simplement curieux et avez envie d'apprendre les dernières technologies Microsoft ? A partir de janvier 2013, le MIC Belgique organise des labs (gratuits !) tournant autour du développement d'applications mobiles connectées au cloud. Le but est d'arriver à réaliser un projet de bout en bout qui soit disponible sur Windows 8 (tablette/pc) et/ou Windows Phone 8 (smartphone), tout en étant relié au cloud de Windows Azure.

Deux niveaux de sessions sont proposés pour répondre à vos besoins de manière adaptée, et vous permettre d'évoluer. Il y aura d'abord des sessions Discovery pour apprendre les bases. Et pour ceux qui veulent aller plus loin, nous continuerons avec des sessions Advanced présentant les aspects plus complexes ! Toutes ces formations sont gratuites, et destinées à une audience de développeurs .NET. Vous pouvez librement vous inscrire à une ou plusieurs sessions. Pas la peine toutefois de vous inscrire à deux sessions Discovery pour une même techno : il s'agira de la même formation ! Voici l'agenda complet : Discovery #1 :

15/01/13 Windows 8
22/01/13 Windows Phone 8
29/01/13 Azure Mobile

Discovery #2 :

30/01/13 Windows 8
05/02/13 Windows Phone 8
12/02/13 Azure Mobile

 Advanced :  /! Ces sessions sont destinées à des développeurs déjà expérimentés!

13/02/13 Windows 8
19 & 20/02/13 Windows Azure
22/02/13 Windows Phone 8        

Rendez-vous très prochainement au MIC ! ;)

TextBox

About the author

I'm a developer, blog writer, and author, mainly focused on Microsoft technologies (but not only Smile). I'm Microsoft MVP Client Development since July 2013.

Microsoft Certified Professional

I'm currently working as an IT Evangelist with an awesome team at the Microsoft Innovation Center Belgique, where I spend time and energy helping people to develop their projects. I also give training to enthusiastic developers and organize afterworks with the help of the Belgian community.

MIC Belgique

Take a look at my first book (french only): Développez en HTML 5 pour Windows 8

Développez en HTML5 pour Windows 8

Membre de l'association Fier d'être développeur

TextBox

Month List