Welcome to MSDN Blogs Sign in | Join | Help

David Rousset

aka Luke CloudWalker

News

Quoi de neuf dans IE 9 ?

Je me suis occupé de regrouper l’ensemble des nouveautés d’Internet Explorer 9 pour le développeur sur un billet publié sur le blog français d’IE : http://blogs.msdn.com/iefrance/archive/2009/11/19/pdc09-aper-u-des-nouveaut-s-d-internet-explorer-9-pour-les-d-veloppeurs.aspx 

IE revient donc en force et ça fait plaisir !

Bien sûr, le keynote du 2ème jour m’a fait ultra plaisir avec la présentation des nouvelles fonctionnalités apportées par Silverlight 4 Beta. Les démos étaient tout simplement bluffantes. J’y reviendrais dans un prochain billet.

En attendant, n’hésitez pas à lire mon billet sur IE 9. Vous pourriez être (agréablement ?) surpris !

David

Web Application Toolkit : tirez parti des nouveautés d’Internet Explorer 8 sur vos sites en 1 clin d’œil

Internet Explorer 8 apporte de nombreuses améliorations et innovations : de nouvelles expériences utilisateur (telles que webslice, accélérateur, visual search, intégration dans Windows 7 et support du multi-touch), une excellente compatibilité avec la norme CSS 2.1, un moteur de rendu plus rapide, des tabs isolés (un par processus) pour améliorer la stabilité, un mode de navigation dit “In-Private” et de nombreuses caractéristiques tournées vers la sécurité faisant de lui certainement le navigateur le plus sûr du marché.

Pour ma part, je vous propose de nous concentrer ici sur les nouveautés autour de l’expérience utilisateur et du travail à effectuer par le développeur web. Nous avions déjà consacré à ce sujet un dossier IE8 pour les développeurs sur MSDN : http://msdn.microsoft.com/fr-fr/ie/msdn.dossier-ie8.aspx 

Depuis, nous avons publié un toolkit particulièrement intéressant. Il vous propose de vous simplifier encore plus la tâche en vous livrant des contrôles ASP.NET prêt à déposés sur votre page web. Ces derniers exposent alors facilement un webslice, un accélérateur ou un visual search. Ce même toolkit propose également une application relativement “élaborée” mettant en œuvre ces contrôles. Cela vous donne alors une idée du résultat que vous pouvez mettre en place sur vos propres sites web. Vous pouvez également en profiter pour vous inspirer du code source. L’ensemble est téléchargeable à l’adresse suivante : http://code.msdn.microsoft.com/WebAppToolkitIE8

Pour vous aider à mieux comprendre le potentiel caché derrière ces nouveautés, j’ai porté l’application de démo fournie avec ce toolkit sur Windows Azure ici : http://ie8demo.cloudapp.net . Si vous vous rendez sur ce site à l’aide du navigateur Internet Explorer 8, vous pourrez alors tester ces nouvelles fonctionnalités. Il y a même un joli WebSlice faisant appel à Silverlight 3 à découvrir !

Voici une idée du rendu visuel des 3 éléments fournis sur le site ie8demo :

ie8toolkitscreenshot

Découvrons comment obtenir la même chose en vidéo dans ce 1er webcast (double-cliquez pour le plein écran) :

Pour mettre en place le même genre de résultat sur votre site, rien de plus simple. Une fois le toolkit téléchargé, je vous propose de partir de cette solution Visual Studio 2008 simplifiée (extraite du projet IE8WebControls - All) :

Ensuite, il ne reste plus qu’à “drag’n’dropper” ces fameux contrôles, à remplir quelques propriétés et le tour est joué ! Voici ce qu’il faut faire en vidéo :

Simple n’est-ce pas ?

En complément au dossier MSDN IE8 dont je vous parlais plus haut et à ce Web Application Toolkit, je vous conseille vivement la session suivante des Microsoft Days 2009 : [MsDays09] - Internet Explorer 8 côté developpement réalisée par nos experts Français du support d’escalade. Ils ont pensé à des scénarios d’accélérateurs et webslices intéressants. Par ailleurs, vous découvrirez tout ce qu’un développeur doit savoir autour d’IE8. Elle complète ainsi une session que nos amis d’Ucaya avaient réalisé aux TechDays 2009.

4053721348_df4b3662e9[1]

Pour conclure, je vous invite à lire les articles écrit par mon collègue Stan sur IE 8 autour de la sécurité, du déploiement et de l’administration du navigateur dans l’entreprise :

- Vue d'ensemble d'Internet Explorer 8 pour l'entreprise en moins de 22 min
- Déploiement d'Internet Explorer 8.0 dans l'entreprise - partie 1 : introduction
- Déploiement d'Internet Explorer 8.0 dans l'entreprise - partie 2
- Déploiement d'Internet Explorer 8.0 dans l'entreprise - partie 3
- Vie privee et Internet Explorer 8 : nouvelles fonctions
- Filtre Smartscreen dans Internet Explorer 8.0 - partie 1

Il n’y a tout simplement aucun autre navigateur proposant une telle richesse pour l’administration dans l’entreprise.

David

Retrouvez l’ensemble des vidéos et présentations des Microsoft Days 2009
header_ms_days

Les voici enfin toutes réunies ici : http://www.lancements-microsoft.fr/webcasts

Pour ma part, outre la plénière, j’ai animé les sessions suivantes:

1 - [MsDays09] - Silverlight 3 : nouveautés et scénarios entreprise avec .NET RIA Services
2 - [MsDays09] - Développement ASP.NET et ASP.NET MVC lorsque mon collègue Pierre Couzy n’était pas disponible 
3 - [MsDays09] - Le Cloud Computing et le Système d'Information : Enjeux, opportunités et mise oeuvre avec mon collègue Damien Caro
4 - [MsDays09] – CloudyPizza ou comment utiliser Windows Azure et Microsoft Online Services pour gérer la croissance de mon entreprise toujours en compagnie de Damien.

Sachant que mon post précédent rendre dans le détails de ce qui est montré en démonstration dans les sessions Silverlight 3 et Windows Azure/Microsoft Online Services où Cloudy Pizza se retrouve être la base de nos explications.

David

Cloudy Pizza : une application Silverlight 3 .NET RIA Services indexable dans les nuages !

Pour ceux qui ont assisté aux Microsoft Days 2009 (que ce soit à Paris ou en région) aux sessions plénières ou aux sessions sur le cloud computing, vous avez pu découvrir ma magnifique application nommée “Cloudy Pizza”. Sous un air pas très sérieux, je me suis en fait amusé à inclure pas mal de notions intéressantes. Je vous propose ainsi de voir ensemble l’ensemble des fonctionnalités que j’ai mis en place et nous essaierons au travers de prochains billets de voir en détail comment les implémenter.

Voici en vrac ce que j’ai mis dedans: application Silverlight 3 SEO Friendly (indexable par les moteurs de recherches), .NET RIA Services connectée à une source SQL Azure, hébergement dans Windows Azure, utilisation de Membership Provider ASP.NET branchés sur le storage Azure, écriture du code en suivant le pattern MVVM (Model View View-Model) et framework de pages dynamiques en fonction du statut de l’authentification. Pour terminer, lorsque l’on commande une pizza (vous pouvez le faire en vous créant un compte sur mon application), une ressource est réservée sur Exchange Online (faisant parti de la suite BPOS pour Business Productivity Online Suite) et un email de confirmation vous est envoyé. L’idée est venue de Damien Caro qui souhaitait pouvoir utiliser Exchange Online pour réserver automatiquement un parc de motos/mobylettes pour les livraisons. Ensuite, les livreurs de pizzas reçoivent automatiquement les commandes à livrer sur leur mobile synchronisé à Exchange. Il m’a donc aidé à écrire le code sur cette partie.

Liens directs vers les sections :

1 - Une application Silverlight 3 indexable par les moteurs de recherches ?
2 - Un hébergement dans le cloud pour répondre à la charge de manière élastique
3 - Quels sont les impacts d’Azure sur le développement ?
4 - Des pages dynamiques en fonction du rôle et du niveau d’authentification
5 - L’utilisation d’Exchange Online via ses WebServices
6 - M-V-VM ?

Vous pouvez tester l’application ici : --> http://cloudypizza.cloudapp.net <--

Une application Silverlight 3 indexable par les moteurs de recherches ?

Bien sûr ! Je suis en fait parti du sample “Silverlight Store” qui jette les bases de la construction d’une application Silverlight 3 indexable par les moteurs de recherches. Cela consiste en fait à utiliser la productivité amenée par .NET RIA Services pour nous aider à :

- générer un contenu alternatif en HTML via ASP.NET
- générer facilement le robots.txt et sitemap.aspx utilisés par les moteurs de recherches
- coupler la même URL à 2 expériences différentes : ASP.NET ou Silverlight 3. Pour cela, on utilise intelligemment le moteur de routing d’ASP.NET avec celui de Silverlight 3.

Le sample Silverlight Store était basé sur un contenu XML. Je me suis donc simplement occupé de le transformer pour me connecter à une source SQL Server puis SQL Azure. Le passage de SQL Server à SQL Azure étant particulièrement simple puis qu’il a fallu uniquement changer ma chaîne de connexion pour que mon modèle Entity Framework se mette à discuter avec SQL Azure plutôt avec mon instance locale SQL Express 2008.

Alors comment ça marche? L’idée est de partir d’une master page ASP.NET dans laquelle on inclut la référence à notre application Silverlight. Ainsi, 2 routes s’offrent aux navigateurs lorsque l’on se connecte sur le site sur la même URL:

- Route 1 : le plug-in Silverlight n’est pas installé ou pas supporté par le navigateur (iPhone par exemple), on affiche alors un contenu HTML
- Route 2 : le plug-in Silverlight est disponible, on bascule sur l’expérience riche RIA

Par exemple, prenez le cas de cette URL complète : http://cloudypizza.cloudapp.net/Pizza.aspx?Name=Pizza+des+indecis

Avec le plug-in Silverlight 3 activé, vous noterez 2 choses:

cloudpizzapost001

- vous arrivez directement sur la bonne fiche produit. Le framework de routing d’ASP.NET a donc passé la main au moteur de navigation de Silverlight pour que ce dernier aille directement sur le produit “Pizza des indecis”
- l’URL n’a rien de spécifique à Silverlight

Du coup, si on désactive le plug-in Silverlight, on arrive sur ce type de contenu:

cloudpizzapost002

Contenu parfaitement compréhensible par un moteur de recherche! Par ailleurs, cela a également l’avantage de proposer un rendu alternatif de qualité aux navigateurs ne supportant pas encore Silverlight.

De plus, pour aider les moteurs de recherches, vous pouvez analyser le contenu produit par ces 2 URLs: http://cloudypizza.cloudapp.net/robots.txt & http://cloudypizza.cloudapp.net/Sitemap.aspx. Le sitemap étant généré dynamiquement en fonction du catalogue produit présent dans notre base de données bien sûr. Pour cela, on utilise un contrôle répéteur d’ASP.NET branché sur le contenu de la base via .NET RIA Services.

Ainsi, une fois ce travail proprement effectué, vous pouvez effectuer des recherches dans votre moteur de recherche préféré pour retrouver mes pizzas si appétissantes. Par exemple, sur Google : http://www.google.com/search?hl=fr&source=hp&q=pizza+des+jedis, 1er hit pour la pizza des jedis ! Je suis super fier ! :) (je sais, il peut apparaître bizarre d’être fier de ce genre de chose). Pareil sur Bing : http://www.bing.com/search?setflight=0&mkt=fr-fr&q=pizza+frdpe

Pour terminer sur ce chapitre, si l’indexation d’applications Silverlight 3 vous intéresse, nous avons travaillé sur la rédaction d’un livre blanc avec notre partenaire Referencement.com que vous pouvez récupérer ici.

Un hébergement dans le cloud pour répondre à la charge de manière élastique

Qu’est ce que le cloud computing en quelques mots? C’est la mise à disposition d’une plateforme de services (PaaS ou Platform as a Service) sous la forme de Data Centers répartis sur la planète vous offrant principalement 2 caractéristiques :

1 – Héberger ou exécuter votre application (.NET ou PHP) sur des serveurs maintenus, mis à jour, répliqués, géo-localisés (Amérique du nord, Europe, Asie) et sécurisés par un opérateur (Microsoft dans le cas de Windows Azure). Vous n’avez donc plus à vous soucier de la maintenance et de la disponibilité des serveurs hébergeant vos applications.
2 – Capable de supporter une forte montée en charge en vous mettant à disposition un nombre conséquent de machines sur lesquelles vous pouvez déployer rapidement et très facilement votre application. De manière analogue, cette plateforme vous permet également de facilement dé-provisionner les machines que vous vous êtes alloués. C’est ce que l’on appelle l’élasticité : pouvoir suivre de manière très fine la courbe de charge de votre application.

Voici ainsi 2 illustrations issues du futur coach MSDN sur Windows Azure qui sera bientôt publié ici : http://msdn.microsoft.com/fr-fr/msdn.coach.aspx

cloudpizzapost004 cloudpizzapost005

Sur la 1ère, on voit la vue de l’utilisation d’un data center en fonction de la charge. On s’aperçoit alors que nous ne sommes jamais pleinement efficace sur l’utilisation des ressources allouées. Soit on a trop de serveurs sur les bras et ils deviennent sous-utilisés avec l’impact financier que cela comporte : frais de maintenance, administration, amortissement, etc. Soit on a pas assez de serveurs et l’application n’est plus capable de répondre à la charge : timeout et perte d’exploitation/business.

L’idéal serait donc de pouvoir dynamiquement s’ajuster à la charge mesurée sur notre application et donc de suivre de manière très fine cette courbe. C’est ce qu’il se produit avec la 2ème vue grâce à l’utilisation du cloud computing.

Dans le cas de Windows Azure, jetons un œil sur le portail d’administration où se trouve hébergée Cloudy Pizza :

cloudpizzapost003

On observe 3 choses particulièrement intéressantes liées à notre plateforme de cloud computing:

- un environnement de pré-production (Staging) disponible nativement nous permettant, pour très peu de frais, de tester la nouvelle version de notre application avant de la basculer en production vers la gauche via le bouton circulaire du centre.
- le nombre d’instances dédiées à chacun de nos environnements. Ici 1 instance pour la production et 2 instances pour la pré-prod
- la localisation géographique de notre application

Tentons maintenant de raisonner à travers des scénarios d’usage mettant en valeur cette élasticité.

Une pré-production efficace, réelle et pas chère

Imaginons un instant que vous soyez propriétaire d’un data center dans lequel vous hébergez votre application. Que faire pour mettre un place un environnement de pré-production ? Si l’on souhaite en effet être dans un environnement identique à la production, il faudrait potentiellement investir dans un 2ème data center dans lequel on pourrait sereinement tester la prochaine version ou mise à jour de l’application avant de basculer vers la production. L’avantage de la plateforme Windows Azure est que cet environnement de pré-production vous est proposé par défaut. Testez votre nouvelle application sur le nombre souhaité d’instances, validez que tout se déroule comme prévu et basculer en production. Une fois l’ancienne production inversée avec la pré-production, vous pouvez dé-provisionner les machines virtuelles de la version N-1. L’avantage? Vous n’aurez payé uniquement ce que vous aurez consommé pendant les phases de recettes/tests de la pré-production. Vous n’avez ainsi pas à maintenir et payer une pré-production “en dure” de manière systématique. Voici un des premiers avantage de cette fameuse élasticité.

Par ailleurs, la bascule entre la pré-production et la production est immédiate. C’est certainement loin d’être le cas si vous avez 2 data centers sous la main.

Une montée en charge réactive et facile

Prenons un exemple désagréable. Imaginons que vous soyez responsable de la mise en production du site de déclaration de l’impôts sur le revenu. Votre pic de charge se fera sans doute aux alentours du mois d’avril/mai où l’ensemble des contribuables vont se rendre sur le site pour effectuer leur déclaration. Il faut donc prévoir le coup en terme de capacité en provisionnant un ensemble de serveurs capables de prendre en charge le pic et éviter d’avoir des utilisateurs citoyens mécontents de l’inaccessibilité du service. Cependant, une fois le pic de charge passé, l’activité du site gérant les déclaration va devenir très faible le reste de l’année. En effet, nous n’avons pas trop tendance à traîner sur le site des impôts une fois la déclaration faite.

Cet exemple se prête en fait très bien à la notion d’élasticité. Nous utilisons aussi fréquemment l’exemple d’un site d’e-commerce lançant une opération de promotion (à Noël par exemple). La charge devient plus élevée sur les fêtes de fin d’année et baisse drastiquement au mois de Janvier.

La plateforme Windows Azure répond très bien à ce besoin. Pour augmenter ou diminuer le nombre d'instances (de machines virtuelles) que vous souhaitez allouer à votre application, il suffit de cliquer sur le bouton “Configure” et de changer le paramètre :

<Instances count="1" /> vers <Instances count="10" /> par exemple.

Quelques minutes plus tard, 9 nouveaux serveurs auront été automatiquement provisionnées, votre application aura été publiée sur ces nouveaux serveurs et le load balancing sera mis en place pour répartir les requêtes sur l’ensemble de ces 10 serveurs. Tout cela en ne changeant finalement qu’un simple compteur. De manière analogue, le “deprovisionning” est aussi simple à gérer. C’est donc bien cela qu’apporte cette PaaS : un ensemble de services pour vous faciliter la vie et vous faire gagner en efficacité.

La géo-localisation facilitée

Continuons à rêver et imaginons cette fois-ci que notre application rencontre un succès planétaire. Si l’on héberge notre application sur un data center en France, les clients asiatiques ou américains auront une expérience dégradée par rapport à la clientèle française. Comment alors gérer cette situation ? Il faudrait fabriquer et déployer un data center dans ces nouvelles zones géographiques, déployer notre solution sur ces nouveaux sites, maintenir ces serveurs et gérer la redondances des données.

A nouveau, ce scénario est nativement couvert par Windows Azure. Actuellement, 6 data centers sont prévus répartis sur la planète. La mise à disposition de notre application sur d’autres data centers sera donc aussi simple que l’augmentation du nombre d’instances : entièrement automatisée.

Combien ça coute ?

Le “business model” a été présenté cet été et est disponible ici : http://blogs.msdn.com/windowsazure/archive/2009/07/14/confirming-commercial-availability-and-announcing-business-model.aspx

3 métriques sont donc importantes à retenir : l’utilisation CPU, le stockage et la bande passante.

Vous verrez ainsi qu’il ne faut pas obligatoirement aujourd’hui partir sur le cloud computing car le prix peut apparaître élevé par rapport à une solution de hosting classique si les services supplémentaires proposés par Windows Azure ne s’appliquent pas dans votre cas : élasticité simplifiée, pré-production facilitée et géo-localisation. A vous de sortir vos calculettes pour définir à partir de quel moment il est plus rentable d’héberger vous-mêmes votre solution ou de la pousser dans les nuages d’Azure.

Par contre, si vous avez besoin de manière ponctuelle d’un nombre important de ressources, Windows Azure apparaîtra comme une solution de 1er choix.

Plus d’infos sur Windows Azure :

- le centre de développement MSDN : http://msdn.microsoft.com/fr-fr/azure/
- Ze Cloud : http://www.zecloud.fr/

Quels sont les impacts d’Azure sur le développement ?

Revenons à Cloudy Pizza et tentons d’analyser les impacts qu’Azure a eu sur le développement.

Finalement, très peu ! Pour quelles raisons ? Tout simplement car le .NET Framework 3.5 SP1 est nativement hébergé dans Windows Azure et que je peux donc souvent déployer telle quelle une application ASP.NET. Par ailleurs, SQL Azure est une version de SQL 2008 hébergée par Microsoft. Il y a cependant quelques petites subtilités à connaître en fonction des scénarios. Si le sujet vous intéresse, mon collègue Pierre Couzy a fait une série de posts sur le sujet sur son blog : http://blog.couzy.com/ D’ailleurs, il indique également comment héberger votre application PHP dans Windows Azure. J’en avais déjà parlé pour ma part dans un post précédent. De plus, je ne serais aussi que trop vous conseiller de parcourir l’ensembles des posts et vidéos de Patrick Guimonet ici : http://blogs.technet.com/patricg/archive/2009/10/09/premiers-pas-avec-sql-azure-les-vid-os-sont-en-ligne.aspx qui vous guidera de la création de la base à la migration des données d’une instance locale vers SQL Azure.

Dans mon cas, je n’ai eu qu’à recréer une base de données à travers le portail d’administration de SQL Azure, de créer un schéma similaire à celui de ma base de données SQL Express 2008 et d’injecter les mêmes données. Une fois l’opération faîte, restait plus qu’à changer la chaîne de connexion. Dans mon cas, rien d’autre à faire !

Voici la tête du portail d’administration :

cloudpizzapost006

Et voici à quoi ressemblent les chaînes de connexion :

cloudpizzapost007

Alors c’est tout, il faut juste changer la chaîne de connexion dans tous les cas ?

Non, cela serait malhonnête de ma part de tenter de vous faire croire cela. Si votre application ASP.NET ne fait jamais appel au système de fichiers local à la machine qui l’héberge, vous pourrez alors porter votre application logiquement telle quelle. Cependant, que se passe-t-il lorsque vous avez besoin de discuter avec le système de fichiers ?

Dans le cas d’une application hébergée dans Windows Azure, il faut pouvoir gérer le cas où notre code va être distribué sur plusieurs serveurs. Si notre application tourne sur 100 serveurs, hors de question de discuter directement avec une instance particulière. En effet, si l’utilisateur arrive d’abord sur l’instance 2, que l’on stocke des données sur cette instance et que le moment d’après l’utilisateur arrive sur l’instance 58, comment allez-vous synchroniser l’état entre les instances ?

cloudpizzapost015

Pour éviter cela, nous allons utiliser un système de fichiers distribués basé sur une architecture à base de Blob pour le stockage binaire des fichiers et Table pour stocker des informations diverses et variées. La notion de Table ne doit pas être comparée aux tables d’une base de données relationnelles. C’est une structure en tableau à plat que l’on peut par contre requêter via un provider LINQ. Toutes ces notions vous seront détaillées dans le coach MSDN. J’en avais également déjà fait mention dans un post précédent lorsque je présentais l’architecture de l’application que nous avions montrée en plénière des TechDays 2009.

L’avantage du stockage de Windows Azure est que l’on y accède via HTTP REST depuis n’importe laquelle de nos instances. Comme on peut le voir sur le schéma précédent, nos 10 instances discutent avec le même stockage centralisé/distribué. Voici par exemple les URLs correspondantes pour Cloudy Pizza sur le portail d’administration:

cloudpizzapost008

Mais vu que les données de mes fiches produits de Pizza, les commandes et les informations sur les utilisateurs sont stockées dans SQL Azure, à quoi m’a servi ce fameux “Azure Storage” ?

cloudpizzapost009

Comme je suis parti du template de projet Silverlight 3 “Business Application”, j’ai la possibilité de pouvoir créer des utilisateurs et de me loguer sur l’application. En effet, le template propose cela nativement comme j’ai déjà pu en parler dans ce post précédent sur l’introduction à .NET RIA Services. Cela mets alors en place une authentification ASP.NET par formulaire relayée ensuite vers le client Silverlight grâce à .NET RIA Services. Or, cette authentification ASP.NET est basée sur les Membership Provider connectés par défaut vers l’instance locale de SQL Express sur une base nommée aspnetdb.

Dans Windows Azure, nous n’avons pas d’instance locale de SQL Server pour gérer nos utilisateurs. Par contre, le système de Membership Provider d’ASP.NET est extensible et rien ne nous empêche de le brancher sur quelque chose d’autre. Dans mon cas, je l’ai donc simplement branché sur le stockage d’Azure en utilisant un sample du Windows Azure SDK nommé ASPProvider. Ensuite, il ne reste plus qu’à modifier le web.config pour qu’il utilise ces nouveaux providers:

<authentication mode="Forms" />

<anonymousIdentification enabled="true" />

<membership defaultProvider="TableStorageMembershipProvider" 
            userIsOnlineTimeWindow="20">
  <providers>
    <clear />
    <add name="TableStorageMembershipProvider" 
         type="Microsoft.Samples.ServiceHosting.AspProviders.TableStorageMembershipProvider" 
         description="Membership provider using table storage" 
         applicationName="CloudyPizza.Web" 
         enablePasswordRetrieval="false" 
         enablePasswordReset="true" 
         requiresQuestionAndAnswer="false" 
         minRequiredPasswordLength="1" 
         minRequiredNonalphanumericCharacters="0" 
         requiresUniqueEmail="true" 
         passwordFormat="Hashed" />
  </providers>
</membership>

<roleManager enabled="true" 
             defaultProvider="TableStorageRoleProvider" 
             cacheRolesInCookie="true" 
             cookieName=".ASPXROLES" 
             cookieTimeout="30" 
             cookiePath="/" 
             cookieRequireSSL="false" 
             cookieSlidingExpiration="true" 
             cookieProtection="All">
  <providers>
    <clear />
    <add name="TableStorageRoleProvider" 
         type="Microsoft.Samples.ServiceHosting.AspProviders.TableStorageRoleProvider" 
         description="Role provider using table storage" 
         applicationName="CloudyPizza.Web" />
  </providers>
</roleManager>

L’ensemble est alors transparent pour le client Silverlight 3 qui discute avec une couche d’abstraction gérée par .NET RIA Services. Vous pouvez donc très bien imaginer écrire vos propres providers connectés à n’importe laquelle de vos sources de données.

En complément, je vous invite à lire ces 2 excellents articles traitant de la migration d’une application hébergée de manière “classique” vers Azure écrits par Sébastien Pertus :

- Plateforme Azure : Migrer ! : http://www.techheadbrothers.com/Articles.aspx/plateforme-azure-migrer
- Plateforme Azure : Migrez ! Part II : http://www.techheadbrothers.com/Articles.aspx/plateforme-azure-migrez-part-ii

Pour reprendre un schéma de Sébastien, à ce stade, le diagramme de Cloudy Pizza ressemble à cela :

image1[1]
© Tech Head Brothers

Des pages dynamiques en fonction du rôle et du niveau d’authentification

Analysons un peu ce qu’il se passe lorsque l’on se connecte au site via le bouton “login”. Vous êtes prompté pour vous loguer :

cloudpizzapost010

Loguez-vous avec un compte déjà créé ou créez vous un compte en cliquant sur “Register Now”. Une fois authentifié, vous noterez l’apparition de nouveaux onglets/options dans la barre de menu de l’application Silverlight de manière dynamique :

cloudpizzapost011
Avant authentification…

cloudpizzapost012
…après authentification : de nouveaux choix disponibles

Une fois authentifié, vous pouvez donc passer une commande un cliquant sur “basket” : un email de confirmation vous sera envoyé vers l’adresse email que vous aurez entré pendant le “Register Now”. Si vous cliquez sur “orders”, vous verrez la liste des commandes déjà effectuées. Pour commander, cliquez sur les images de pizza. Cela ajoutera une ligne de commande. Choisissez alors la quantité et le type :

cloudpizzapost013

Pour mettre en place les pages dynamiques, j’ai réutilisé la logique exposée par Brad dans ce post là. Dans son cas, il utilisait MEF et une réflexion coté serveur de packages XAP pour dynamiquement ajouter de nouvelles pages. Dans mon cas, j’ai coupé la partie MEF pour simplifier et mis en place une logique purement cliente. J’y reviendrais dans mon prochain post. Ensuite, les pages sont affichées en fonction de l’état de l’authentification ou du niveau de rôle (Administrateur, etc.). Tout cela en tagguant simplement les pages des bons attributs.

L’utilisation d’Exchange Online via ses WebServices

Quand Damien est arrivé avec ses aspirations d’IT Pro et convaincu qu’un développeur est une espèce de magicien capable de coder n’importe quoi grâce à du VBScript, j’ai eu un peu peur. :) Heureusement, autant IT Pro qu’il soit, il est moins bête qu’il en a l’air. Pour preuve, je l’ai déjà vu jouer avec Visual Studio (Respect !). Enfin, bon, on s’écarte du sujet.

Dans une vie passée, je savais très bien coder des applications discutant avec Exchange 2007 via les WebServices qu’il expose. Mais quiz de cet Exchange Online ? Vais-je devoir tout réapprendre et coder de manière différente ? Fort heureusement non ! C’est l’avantage de la symétrie que Microsoft propose entre le monde de l’entreprise et notre offre de cloud computing. Un développeur sachant manipuler les WebServices d’Exchange 2007 ne sera pas perdu avec ceux exposés par Exchange Online pour la simple et bonne raison que… ce sont les mêmes ! Exchange Online est donc bien un Exchange hébergé et maintenu par Microsoft avec lequel je peux travailler en tant que développeur de manière transparente.

On retrouve donc cette symétrie des produits et des compétences dans les 2 mondes tel qu’illustré par le diagramme suivant :

cloudpizzapost016

Dans Cloudy Pizza, j’ai donc tout simplement fait mon ajout de référence Web depuis l’URL qui va bien depuis les nuages : https://red002.mail.emea.microsoftonline.com/EWS/Exchange.asmx et la génération du proxy client s’est faite de manière habituelle. Ensuite, j’ai pu réutiliser tels quels les exemples fournis dans MSDN comme ceux-là par exemple:

- Creating E-mail Messages (Exchange Web Services) : http://msdn.microsoft.com/en-us/library/aa563009.aspx
- Getting User Availability (Exchange Web Services) : http://msdn.microsoft.com/en-us/library/aa494212.aspx
- Creating Appointments (Exchange Web Services) : http://msdn.microsoft.com/en-us/library/aa563060.aspx 

Ni plus, ni moins.

M-V-VM ?

Le pattern MVVM (pour Model View View-Model) apporte une approche “à la MVC” particulièrement intéressante pour le monde de WPF ou Silverlight lorsqu’il s’agit d’industrialisation des développements. Mais, comme MVC, il ne sera pas à utiliser de manière systématique. Avec Mitsu, nous l’avons largement couvert lors de la journée des “Mercredis du développement”  à l’aide de nos acolytes Simon d’Access-IT et Nicolas de Tekigo. Cette journée sera bientôt disponible en webcasts : http://blogs.msdn.com/mitsufu/archive/2009/09/04/mdd-industrialisation-des-d-veloppements-n-tiers-avec-wpf-et-silverlight.aspx.

Un développement MVVM vous apportera de nombreux bénéfices comme des tests unitaires performants et adaptés, des vues XAML uniquement dédiées à l’affichage et faisant appel de manière très agréable au binding, etc.

cloudpizzapost014

En Français, je vous conseille la lecture de ce post de Simon : http://www.simonferquel.net/blog/archive/2009/03/25/silverlight-silverlight-3--ria-services--mvvm-et-testabiliteacute.aspx , notre star du testing Silverlight et de MVVM. ;-)

En Anglais, notre architecte Nikhil a fait une série de posts très intéressante sur ce sujet :

- http://www.nikhilk.net/NET-RIA-Services-ViewModel-Pattern.aspx
- http://www.nikhilk.net/NET-RIA-Services-ViewModel-Pattern-2.aspx
- http://www.nikhilk.net/Silverlight-ViewModel-Pattern.aspx
- http://www.nikhilk.net/Silverlight-ViewModel-MVC.aspx

Pour l’instant, Microsoft ne propose pas vraiment de template de projet pour faire du MVVM sous Silverlight comme on peut le trouver pour WPF à travers le toolkit ou comme avec ASP.NET MVC. Cependant, il commence à éclore quelques initiatives intéressantes comme celle-ci que je vous conseille : http://www.galasoft.ch/mvvm/getstarted/ 

What’s coming next ?

Voilà pour ce tour d’horizon de Cloudy Pizza finalement assez long. J’ai prévu de publier le code mais il faut d’abord que je travaille à la résolution de quelques bugs et à l’amélioration de certaines parties dont je ne suis pas encore très fier. ;-)

Stay tuned pour des posts plus techniques et plus détaillés. Le prochain sera dédié à la sécurité autour de .NET RIA Services et à la mise en place de pages dynamiques avec une astuce intéressante.

David

Silverlight 3 : ajoutez un behavior d’effets physiques à vos éléments

Si vous cliquez sur mon image en costard ci-dessous qu’adore Mitsu, vous verrez qu’une sorte d’effet physique se met en route là où vous aurez cliqué. J’ai honteusement récupéré le behavior de Nikhil dont il parle ici : http://www.nikhilk.net/BouncingPlane-Behavior.aspx

L’idée des behaviors est très séduisante. Elle propose une collaboration entre les développeurs et les designers encore plus riche. Le développeur conçoit un comportement à appliquer sur un élément (mise en place d’un effet physique, gestion automatique du multi-touch, etc.) et le designer peut alors appliquer ce comportement sur ses éléments dans Expression Blend 3 sans avoir à comprendre la moindre ligne de code.

Pour mieux comprendre, je vous propose donc de créer le même genre de résultat que mon badge ci-dessus (ou à gauche dans le menu) en utilisant Expression Blend 3 et le tout sans coder! Pour cela, récupérez le package ZIP ci-dessous contenant le code source du behavior. Il est également déjà compilé dans le fichier BoucingPlaneBehavior.dll présent dans \Bin\Release. Cela vous évite éventuellement d’avoir besoin de Visual Studio.

Copiez la DLL dans le répertoire de votre choix puis ajoutez les entrées suivantes dans la base de registre:

Windows Registry Editor Version 5.00

[HKEY_CURRENT_USER\Software\Microsoft\Expression\Blend\3.0\Toolbox][HKEY_CURRENT_USER\Software\Microsoft\Expression\Blend\3.0\Toolbox\Silverlight][HKEY_CURRENT_USER\Software\Microsoft\Expression\Blend\3.0\Toolbox\Silverlight\v3.0] [HKEY_CURRENT_USER\Software\Microsoft\Expression\Blend\3.0\Toolbox\Silverlight\v3.0\BoucingPlaneBehavior]
@="CheminVersLaDll"

Vous trouverez également un exemple nommé BoucingBehaviors.reg dans le ZIP que vous pouvez modifier et appliquer sur votre machine.

L’idée maintenant est d’ajouter un nouveau behavior dans la liste proposée par défaut sous Blend 3. J’ai donc bêtement suivi les indications de notre chère MSDN : http://msdn.microsoft.com/en-us/library/ee341397(Expression.30).aspx . On peut également simplement ajouter une référence à la DLL dans n’importe quel projet si vous voulez éviter d’ajouter ces entrées dans la base de registre. Une fois la référence ajoutée, le behavior sera visible par Blend 3.0. Allez, jouons avec tout cela maintenant.

Lancez Blend 3.0 et créez un nouveau projet Silverlight 3:

behavioretape001

Drag’n’droppez un contrôle image :

behavioretape002

Spécifiez la source de votre image et ajoutez un petit effet de Pixel Shader de type DropShadow. Si vous ne savez pas comment faire, rendez-vous dans ce billet.

Rendez-vous dans les Behaviors et vous devriez voir le BouncingPlane si vous n’avez pas loupé l’étape de la base de registre :

behavioretape003

Prenez le BouncingPlane et drag’n’droppez le sur l’image dans l’arborescence de contrôles:

behavioretape004

Voilà! C’est fini! Lancez l’ensemble en pressant la touche magique F5 et vous pourrez vous aussi cliquer sur vos images (de vos chefs? ;-)) avec un effet de physique:

behavioretape005

Allez, pour le vous le prouver, voici la réalisation en vidéo en moins d’1 min 30 chrono ! (Double-cliquez pour le plein écran)

Sur ce, comportez-vous bien.

David

Libération complète du coach Silverlight 3 sur MSDN

Face aux nombreux emails que j’ai reçu me demandant l’accès au reste du coach MSDN sur Silverlight 3, nous avons décidé avec Marine de publier l’ensemble des webcasts que j’avais réalisé.

Il manque donc encore quelques labs sous forme “écrite” que je me chargerais d’écrire courant du mois d’Octobre. Mais vous pouvez déjà tout suivre sous forme vidéo et vous aurez l’ensemble du code source pour toutes les étapes.

En effet, je suis bien occupé ces derniers temps à préparer l’évènement des Microsoft Days sur lequel je présenterais Silverlight 3 (ses nouveautés et .NET RIA Services) et des sessions autour du Cloud Computing. Cet évènement aura lieu sur Paris puis sur plusieurs villes en province. Pour tout savoir, voici les pointeurs clés:

- Rencontres Techniques (RT) pour les développeurs : http://msdn.microsoft.com/fr-fr/microsoft-days.aspx
- Rencontres Techniques (RT) pour les ITPros : http://technet.microsoft.com/fr-fr/microsoft-days.aspx
- Rendez-vous Décideurs Informatiques (RDI) : http://www.microsoft.com/france/entreprises/evenements/rendez-vous-decideurs/

Je suis également occupé de travailler avec Mitsu sur la journée industrialisation du développement WPF & Silverlight la semaine prochaine. Nous y parlerons de pattern MVVM, de tests unitaires et de l’incontournable .NET RIA Services. Vous pouvez en savoir davantage sur cette journée ici et vous inscrire ici.

A bientôt !

David

Le nouveau Coach Silverlight 3 est disponible!

bb899456.polaroid%20coach%20silverlight(fr-fr,MSDN.10)[1] Avant de partir en vacances, je me suis occupé de réaliser une petite série de WebCasts (26 en tout pour près de 4h30 de visionnage) pour vous permettre d’apprendre à prendre en main Silverlight 3. J’ai essayé de vous laisser jouer avec la plupart des grands concepts de Silverlight et des grandes nouveautés de la version 3 : pixel shaders, accélération GPU, binding entre éléments, projection 3D et out of browser. Sans oublier la composante business représentée par les 2 derniers labs sur .NET RIA Services.

Nous ferons évoluer la même application au fur et à mesure de l’introduction des concepts afin d’avoir un fil conducteur sympathique.

Le coach est dors et déjà en ligne ici : http://msdn.microsoft.com/fr-fr/silverlight/msdn.coachsilverlight.aspx 

Comme d’habitude, vous trouverez une formule qui marche bien : une vidéo présentant les concepts sur des slides PowerPoint puis une vidéo démontrant le concept à travers un lab réalisé sous Visual Studio 2008. Vous aurez également en complément le code source de départ de chaque lab et le code source d’arrivée si vous suivez bien les étapes. Pour terminer, le lab est livré sous forme écrite en plus de la version vidéo. Vous pouvez donc suivre le lab en fonction de vos préférences vidéo ou écrit (sachant que parfois les 2 sont bien complémentaires).

Notre marketeuse préférée (Miss Marine Tranquard) n’a publié pour l’instant qu’une partie de la série. Elle s’occupera ensuite de publier 2 nouveaux labs par semaine. Nous n’avons pas encore tout publié car je n’ai pas fini d’écrire les labs “écrits”.

Voici le programme complet pour vous donner une idée de ce qui vous attend (en vert les concepts, en rouge les Labs):

001 - Présentation générale de Silverlight 3 : Ce webcast est accessible à tout le monde (même aux ITs ! :)) pour découvrir Silverlight pour la 1ère fois ainsi que pour découvrir quelques nouveautés de Silverlight 3 en action. Nous positionnons l’agenda des 26 WebCasts, la technologie et certains contrôles communautaires supplémentaires.

002 - Les bases d'une application Silverlight : Nous verrons ici la structure d’une application Silverlight, où elle s’héberge et son format.

003 - Lab Etape 0 : création d’une application Silverlight 3 vide de type Navigation Application et analyse de son fonctionnement.

004 - Concepts XAML, Formes de bases et Events : Nous verrons ici sommairement ce qu’est que le XAML. Puis nous verrons les basiques, quelques contrôles de bases et la gestion évènementielle.

005 - Lab Etape 1 : mise en place de l’application qui va nous servir tout le long des 12 labs. Nous allons ici faire nos premiers pas en XAML et réagir à quelques évènements. Dans un 1er temps, notre application aura pour but l’affichage de vidéos stockées sur un serveur distant.

006 - Silverlight et la vidéo – WebClient : Nous découvrirons ici les possibilités média de Silverlight 3 avec la présentation du MediaElement, des formats supportés et une introduction au Smooth Streaming. Nous verrons aussi le principe du WebClient pour les téléchargement asynchrones.

007 - Lab Etape 2 : utilisation du MediaElement et du Webclient.

008 - Styles - Templating – DataBinding : Silverlight permet de modifier facilement le look & feel d’une application à travers des notions comme le style tout d’abord puis de manière plus étendue comme le templating. Nous verrons également un concept majeure de Silverlight : le databinding.

009 - Lab - Etape3 : modification complète de l’application en changeant un dictionnaire de ressource contenant tous les styles, mise en place du templating et du databinding.

010 - Binding entre elements - Transformation - Projection3D : Découverte de deux nouveautés de Silverlight 3 : le binding entre éléments et la projection 3D.               

011 - Lab - Etape4 : utilisation du binding entre éléments : textblock branché à une combobox puis slider branché à une projection 3D sur une vidéo.

012 - Animations classiques et easing - Moteur physique : Découverte des possibilités du moteur d’animation de Silverlight 3 dont les nouveautés : les EasingFunctions. Présentation rapide d’un moteur physique open source.

013 - Lab Etape5 : Utilisation d’Expression Blend 3 pour créer une animation « classique » puis ensuite élastique (Easing). Nous utiliserons également Blend 3 pour revoir quelques détails cosmétiques de l’application et découvrir l’intérêt de cet outil dans la manipulation du XAML par un designer.

014 - WCF et Silverlight 3 : Nous allons découvrir ici comment Silverlight peut communiquer avec un service distant de type WebService ou WCF. Nous verrons aussi quelques subtilités à connaître avec Silverlight dans ce contexte.

015 - Lab Etape 6 : création d’un service WCF « compatible Silverlight » et consommation de ce service depuis notre client Silverlight. Analyse du flux avec un outil de traces réseaux simple (Web Development Helper). Utilisation de la sérialisation texte XML puis binaire et comparaison entre les 2.

016 - SandBox - OpenSaveFileDialog – Quota : Silverlight tourne au sein du navigateur et dans un contexte dit de « client Web ». Cela implique donc des mécanismes de sécurité particuliers. Revue du SandBoxing et de l’accès aux fichiers de la machine exécutant l’application Silverlight.

017 - Lab Etape 7 : utilisation des APIs OpenFileDialog et SaveFileDialog pour lire une vidéo stockée localement et sauvegarder une vidéo distante localement.

018 - Pixel Shaders : Silverlight 3 apporte la possibilité de mettre en place des effets appelés Pixel Shaders. Découvrons comment s’en servir et leur principe.

019 - Lab Etape 8 : mise en place de pixel shaders de manière très simple via le XAML avec Visual Studio et Blend 3. Mise en place d’un pixel shader par code pour mise en emphase d’une fenêtre modale.

020 - Accélération Matérielle GPU : Silverlight 3 est désormais capable de tirer partie du GPU de la carte graphique. Cela n’est pas automatique cependant ! (comme les anti-biotiques). Découvrons les mécanismes d’utilisation.

021 - Lab Etape 9 : utilisons la carte graphique pour soulager le processeur et analysons dans quels cas elle est véritablement utilisée ou non.

022 - Out of browser et autres nouveautés : Silverlight 3 est capable de rendre une application fonctionnelle en dehors du navigateur en ne faisant quasiment rien. S’ajoute cependant des particularités intéressantes à ce mode dit « Offline ».

023 - Lab Etape 10 : rendons notre application disponible en dehors du navigateur. Nous allons voir ici également comment gérer la mise à jour automatique de notre application.

024 - Introduction à .NET Ria Services : .NET RIA Services est un nouveau framework ayant pour objectif d’apporter une expérience RAD (Rapid Application Development) au monde de la RIA. Il va donc grandement simplifier les problématiques de développement n-tiers.

025 - Lab Etape 11 : Reprise de notre application et enrichissement en suivant les étapes décrites ici : http://blogs.msdn.com/davrous/archive/2009/05/28/comment-d-velopper-des-applications-d-entreprises-orient-es-donn-es-avec-silverlight-3-introduction-net-ria-services-2-4.aspx pour faire appel à .NET RIA Services et afficher des données d’une base de données dans une grille.

026 - Lab Etape 12 : Suivi des étapes décrites ici : http://blogs.msdn.com/davrous/archive/2009/05/28/comment-d-velopper-des-applications-d-entreprises-orient-es-donn-es-avec-silverlight-3-introduction-net-ria-services-3-4.aspx pour gérer le paging, grouping, sorting, la sauvegarde, les child windows et la validation automatique de règles métiers.

En espérant que tout cela vous serve au mieux!

David, coach à ses heures perdues

Tutorial – apprenez à vaporiser votre blog dans les nuages grâce à BlogEngine.Net et Windows Azure

En partant de zéro, je vous propose de voir les étapes à suivre pour mettre en place une plateforme de blog basée sur l’excellent BlogEngine.Net au sein de notre plateforme de Cloud Computing Windows Azure. Le but du jeu étant de vous permettre d’arriver au résultat disponible ici : http://tektekpocket.cloudapp.net/ hébergé dans les nuages.

Pré-requis à installer sur votre machine avant toutes choses:

- Visual Studio 2008 SP1, Visual Studio 2010 Beta 1 ou Visual Web Developer 2008 SP1 (gratuit)
- Le SDK d’Azure
- Les Tools Azure pour Visual Studio 2008 SP1

Phase 1 : préparation du coté de la plateforme Windows Azure 

1 – Créez-vous un LiveID (sur www.hotmail.fr par exemple) si vous n’en n’avez pas déjà un puis associez le au portail Azure en vous rendant sur : http://www.azure.com et cliquez sur « Sign In »

3907369608

Ensuite choisissez « Windows Azure » :

3907369972

Une fois le bon LiveID (ici tektekpocket) choisit, vous pouvez l’associer au portail :

3907370084

3907370220

Ici, on vous demande un token (une sorte de clé) pour pouvoir continuer. Dans notre cas, nous ne l’avons pas encore demandé alors cliquez sur « Cancel » :

3906591695

2 – Il faut donc générer une clé pour créer une application Windows Azure. Pour cela, rendez-vous ici : http://www.microsoft.com/azure/register.mspx et cliquez sur « Register for Azure Services ». Vous serez conduit sur la plateforme Microsoft Connect :

3907370608

Remplissez les différentes informations demandées puis vous arrivez là. Cliquez sur « Clés de produits » puis « Demandez une nouvelle clé de produit » puis « Obtenir la clé » :

3906592233

3907371076

3907371280

Votre clé sera alors générée immédiatement :

3906592609

Copiez-la dans un endroit sûr, à l’abri du soleil et de l’humidité.

3 – On peut désormais retourner sur le portail pour utiliser cette clé. Pour cela, rendez-vous dans la partie « Account » puis cliquez sur « Manage My Tokens » puis entrez la clé obtenue ci-dessus dans la zone de texte. Cliquez sur « Claim Token ». Cela vous permettra d’activer l’utilisation du service de calcul (Compute) et de stockage de Windows Azure. Retournez sur « Summary » et cliquez sur le nom du projet (ici PDC08 CTP) :

3906592743

Cliquez ensuite sur « + New Service » :

3907371676

Vous arrivez sur cette page. On va commencer par créer un espace de stockage en cliquant sur « Storage Account » :

3906593017

Remplissez les champs en fonction de vos préférences puis cliquez sur « Next » :

3907371900

Donnez ensuite un nom unique (sous forme d’URL) à votre espace de stockage puis cliquez sur « Create » :

3907372044

Vous arrivez alors sur cette page récapitulative :

3906593481

Pensez à bien noter le nom de votre compte (ici tektek par exemple) et au moins la clé primaire. Nous allons nous en servir plus tard pour BlogEngine.Net. Au pire, vous pourrez toujours revenir vers cette page pour noter à nouveau l’ensemble.

4 – Une fois l’espace de stockage alloué, il faut indiquer que l’on souhaite également pouvoir utiliser la plateforme d’hébergement d’applications (Hosted Services). Pour cela, revenez à cette page et cliquez sur « Hosted Services » :

3907372284

Remplissez à nouveau les informations demandées :

3906593707

3906593859

Une fois ces étapes suivies, vous arrivez sur le portail d’administration de la plateforme d’exécution dans le nuage proposant un environnement de pré-production (Staging) et de production.

3906593923

Les nuages sont prêts à nous accueillir. Revenons quelques temps sur terre avant de s’envoler à nouveau.

Phase 2 : téléchargement de BlogEngine version Azure et exécution de la solution dans l’environnement de simulation

1 – Téléchargez une version de BlogEngine. NET modifié pour fonctionner sur le storage d’Azure (Table & Blob) ici : http://kleartouch.codeplex.com/ . A noter, pour les spécialistes, que le Membership Provider d’ASP.NET (pour l’authentification des utilisateurs) a également été porté pour fonctionner sur Azure dans le code fourni.

3906593979

2 – Une fois le fichier ZIP récupéré, il faut le « débloquer » en allant dans les propriétés :

3906594145

Sinon Visual Studio râlera un peu en disant qu’il a tendance à ne pas faire confiance au contenu. Cela n’empêche pas le bon fonctionnement, mais c’est quand même mieux de faire les choses proprement. ;-)

3 – Lancez Visual Studio 2008 en mode administrateur et ouvrir le .SLN qui va bien : BlogEngine.Azure.sln

3907372908

Note : il est important de lancer Visual Studio 2008 en mode administrateur pour pouvoir lancer la « fabrique » (l’environnement de simulation) d’Azure. Sinon, Visual Studio râlera à nouveau mais cette fois-ci vous empêchera d’aller plus loin lorsque vous tenterez d’exécuter l’application. Sacré VS !

4 – Dans la version que nous avons récupérée avec Stan, il y avait un léger souci empêchant la compilation. Pour corriger le problème, il faut enlever un thème qui semble corrompu pour l’instant. Supprimez le répertoire « n3oEco » de l’arborescence du projet BlogEngine dans la fenêtre « Solution Explorer » de Visual Studio 2008 :

3906594655

Compilez l’ensemble, vous ne devriez pas avoir d’erreurs de compilations. Vous n’aurez peut-être pas à faire de même si l’auteur du code corrige l’ensemble d’ici là (je m’en vais lui indiquer).

5 – Il faut préparer l’environnement de simulation local à pouvoir recevoir le schéma de tables retenues par BlogEngine. Tout d’abord, faites bouton-droit sur BlogEngine.Azure et cliquez sur « Create Test Storage Tables ».

3906594387

Si tout se passe bien, vous aurez ce gentil message en retour :

3907373396

Ensuite, positionnez le projet BlogEngine.Setup comme projet de démarrage :

3906594799

Lancez ensuite (si ce n’est déjà fait), l’environnement de simulation du stockage d’Azure : « Development Storage » :

3907373598

Puis vérifiez bien que la base de données « BlogEngineAzure » est celle active par défaut:

3907373670

3906595139

Pour finir, exécutez ce programme Console en appuyant sur F5 :

3907373886

6 – Repositionnez le projet BlogEngine.Azure comme projet de démarrage :

3907373954

Puis lancez le projet Web Azure avec le bon vieux F5 afin de vérifier que tout fonctionne correctement.

3906595667

Nous avons pour l’instant confirmé que la plateforme de blog BlogEngine.NET fonctionne correctement dans l’environnement de simulation d’exécution de Windows Azure appelée la « Development Fabric » disponible sur http://127.0.0.1:81. Nous utilisons également pour l’instant des données disponibles dans l’environnement de simulation de stockage d’Azure appelée donc « Development Storage » disponible sur http://127.0.01:1000 (blob) et http://127.0.0.1:1002 (table). Les données sont accessibles via REST. Nous n’utilisons pas ici les notions de queues.

Vous pouvez tenter de créer quelques posts, de modifier quelques paramétrages, etc. Login par défaut : admin/admin.

Phase 3 : exécution locale dans l’environnement de simulation mais utilisation des données « Live » depuis Windows Azure

Avant de tout basculer en production, une bonne pratique consiste à d’abord préparer la structure et les données de nos tables dans Windows Azure (et donc plus localement en simulation) mais de laisser la partie exécution (ASP.NET) en local. Cela permet ainsi de tester, débugger et ajustez quelques réglages en utilisant un jeu de tests réel en production tout en ayant une expérience de débogage immédiate et simple. Ce n’est effectivement plus le cas lorsque vous poussez votre code dans Windows Azure : pas question d’attacher notre débuggeur préféré au processus qui tournent dans les nuages !

1 – Pour cela, il faut modifier le ServiceConfiguration.cscfg du projet BlogEngine.Azure pour se connecter désormais vers Windows Azure Storage.

Voici un exemple de nouveau fichier .cscfg (pensez à bien utiliser votre clé et le nom du compte généré sur le portail Azure pour pointer vers votre propre stockage) :

<?xml version="1.0"?>

<ServiceConfiguration serviceName="BlogEngine" xmlns="http://schemas.microsoft.com/ServiceHosting/2008/10/ServiceConfiguration">

  <Role name="BlogEngine">

    <Instances count="1" />

    <ConfigurationSettings>

      <Setting name="LogAllRequests" value="false" />

      <Setting name="LogFailedRequests" value="true" />

      <!--<SETTING NAME="BLOBSTORAGEENDPOINT" VALUE="HTTP://127.0.0.1:10000" />

      <SETTING NAME="QUEUESTORAGEENDPOINT" VALUE="HTTP://127.0.0.1:10001" />

      <SETTING NAME="TABLESTORAGEENDPOINT" VALUE="HTTP://127.0.0.1:10002" />

      <SETTING NAME="ACCOUNTNAME" VALUE="DEVSTOREACCOUNT1" />

      <SETTING NAME="ACCOUNTSHAREDKEY" VALUE="EBY8VDM02XNOCQFLQUWJPLLMETLCDXJ1OUZFT50USRZ6IFSUFQ2UVERCZ4I6TQ/K1SZFPTOTR/KBHBEKSOGMGW==" />-->

      <Setting name="BlobStorageEndpoint" value="https://blob.core.windows.net"/>

      <Setting name="QueueStorageEndpoint" value="https://queue.core.windows.net"/>

      <Setting name="TableStorageEndpoint" value="https://table.core.windows.net"/>

      <Setting name="AccountName" value="tektek"/>

      <Setting name="AccountSharedKey" value="votreprimaryaccesskeyici"/>

    </ConfigurationSettings>

  </Role>

</ServiceConfiguration>

En jaune se trouve les parties que vous devez modifier : le nombre d’instances de serveurs Web que vous souhaitez allouer au blog, le nom du compte de votre stockage Windows Azure et la clé primaire générée précédemment. Le nombre d’instance peut être augmenté plus tard une fois le projet déployé pour pouvoir répondre dynamiquement à un pic de charge suite à une opération marketing par exemple puis ensuite être redescendu à sa valeur initiale. C’est tout l’intérêt du coté élastique proposé par une plateforme de Cloud Computing.

2 – Il faut ensuite modifier le fichier web.config du projet BlogEngine. Après cette ligne de XML :

<add key = "DefaultSessionContainerName"/>

Utilisez ces lignes à la place de celles d’origine (n’oubliez toujours pas d’y insérer vos propres informations de connexion !) :

<!--<add key = "BlobStorageEndpoint" value="http://127.0.0.1:10000"/>

<add key = "QueueStorageEndpoint" value="http://127.0.0.1:10001"/>

<add key = "TableStorageEndpoint" value="http://127.0.0.1:10002"/>

<add key = "AccountName" value="devstoreaccount1"/>

<add key = "AccountSharedKey" value="Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw=="/>-->

 

<add key = "BlobStorageEndpoint" value="https://blob.core.windows.net"/>

<add key = "QueueStorageEndpoint" value="https://queue.core.windows.net"/>

<add key = "TableStorageEndpoint" value="https://table.core.windows.net"/>

<add key = "AccountName" value="tektek"/>

<add key = "AccountSharedKey" value="votreprimaryaccesskeyici"/>

3 – Il faut falloir maintenant provisionner vos tables dans le nuage pour faire pointer la plateforme de blog vers des données en production.

Pour cela, allez dans les propriétés du projet BlogEngine.Setup puis dans l’onglet Debug et entrez d’abord le nom de votre compte de stockage suivi de votre clé dans la zone de texte « Command Line arguments »

3907374284

Remettez ensuite BlogEnginer.Setup comme projet de démarrage et lancez le programme en mode console pour créer les tables dans le storage Cloud :

3906595991

Petit tip : pour analyser/débugger/comprendre le contenu et le fonctionnement du stockage Windows Azure (Table, Blob, Queue), je ne serais que trop vous recommander de télécharger 2 petits outils disponibles gratuitement sur codeplex :

- Azure Storage Explorer : http://azurestorageexplorer.codeplex.com/
- Azure Blob Explorer uniquement dédié à la manipulation des blobs (nos fichiers dans le cloud en quelques sortes) et plus à l’aise dans cette tâche que le précédemment: http://blobexplorer.codeplex.com/

Avec Azure Storage Explorer, on peut alors voir la structure des tables créées, retrouver les posts effectués, analyser les logs de BlogEngine pour trouver d’éventuels problèmes, etc… Le tout en WPF s’il vous plait !

3906596167

4 – Remettez le projet BlogEngine.Azure comme projet de démarrage et relancez le localement afin de vérifier que tout fonctionne : exécution locale, stockage Cloud. Si vous avez créé des posts dans le stockage local (Development Storage), vous ne devriez logiquement ne plus les voir car nous sommes désormais connecté au storage de Windows Azure (le vrai !).

Dernière étape : il nous faut maintenant pousser la solution (WebRole) également dans les nuages.

Phase 4 : publication du WebRole dans Azure pour une exécution complètement gérée par le cloud (Vers l’infini et au-delà !)

1 – Pour cela, rien de plus simple ! Publiez le package en faisant bouton-droit sur BlogEngine.Azure :

3907374768

2 – Ensuite, une fenêtre d’exploration de fichiers est ouverte à l’endroit où se trouve les 2 paquets à télécharger vers Windows Azure. Le portail Windows Azure est également affiché dans une nouvelle fenêtre du navigateur.

Cliquez sur le nom du projet, puis ensuite sur la partie WebRole pour revenir à cette fenêtre :

3906593923

Cliquez sur « Deploy » et remplissez cette fenêtre en copiant/collant le chemin vers chacun des 2 fichiers proposés dans l’explorateur de fichiers puis cliquez à nouveau sur « Deploy » :

3906596337

3906596427

Quelques secondes plus tard, vous revenez sur cet écran. Cliquez alors sur « Run » pour lancer les machines virtuelles que vous vous êtes octroyé dans le fichier de configuration (1 par défaut) :

3907375070

Une fois les machines démarrées et prêtes à être utilisées, vous obtiendrez cet écran :

3906596575

L’environnement de pré-production est disponible. Cliquez sur l’URL un peu étrange pour tester que la plateforme de blog fonctionne désormais correctement en mode 100% Cloud (sans IT ajouté).

3 – Pour basculer en production, il suffit de cliquer sur cet icône :

3906596671

Et dire que vous êtes d’accord :

3907375344

Voici alors l’état final de la page d’administration :

3907375452

Ensuite, imaginons qu’une nouvelle version de la plateforme de blog soit disponible, il suffit de la déployer en pré-production branchée sur les mêmes données que la production. Cela vous permet facilement de tester son comportement sur l’URL un peu spéciale avant de cliquer sur le bouton de bascule pour déployer la nouvelle version en production après avoir réalisé une série de tests pour vous assurer de ne rien casser.

De même, si votre blog rencontre (comme le mien je l’espère !) un succès inattendu induisant un ralentissement suite à un nombre important d’utilisateurs, il vous suffit simplement de cliquer sur « configure… » puis de passer le nombre d’instances Web de 1 à N afin de répondre à la charge. Le tout sera alors déployé, configuré, « load-balancé » et mis en ligne en quelques minutes. Faisons le test en passant le nombre d’instances de 1 à 2 puis en cliquant sur « Save » :

3906597093

La page d’administration nous notifie qu’une mise à jour est en cours :

3907375708

Quelques minutes plus tard…

3907375772

Nous avons bien désormais 2 serveurs Web capables de prendre les requêtes en frontal. Tout cela, sans avoir du apprendre à maîtriser un Load-Balancer, à modifier notre code, à configurer de nouvelles machines ni à republier notre application. La plateforme Azure s’est occupé de tout automatiser pour assurer le succès de votre plateforme de blogging.

Disclaimer : malgré toute la puissance et l’efficacité proposée par la plateforme de services Azure, il n’existe pas encore de moyens techniques efficaces pour blogguer à votre place et assurer le succès de votre blog de manière totalement automatique. Vos petits doigts et votre talent seront donc toujours de rigueur !

Petite note : pendant la mise à jour, votre blog peut ne plus être disponible. Ce n’est donc pas une bonne idée de le faire en production. Mieux vaut donc le faire en pré-production et ensuite basculer l’ensemble. Cela permet d’éviter d’avoir un éventuel arrêt de services.

Aller, profitez en bien : pour l’instant tout est gratuit ! :)

David, back from the Sky.

Tutorial pour utiliser simplement les Pixel Shaders avec Silverlight 3

Silverlight 3 nous propose une nouveauté particulièrement intéressante pour effectuer des traitements graphiques sympathiques : les pixel shaders. En gros, cela consiste à appliquer une équation mathématique sur chacun des pixels constituant l’élément à modifier. Le langage retenu par Silverlight 3 pour ces shaders est le HLSL dont vous trouverez de la littérature en Anglais sur Wikipedia ou sur MSDN. Il ressemble à une espèce de C.

Alors tout cela est bien joli, mais faut-il pour autant être une Medal Fields de mathématique pour pouvoir jouir de cette nouvelle puissance graphique à la portée de nos petits doigts de développeurs ?

Heureusement que non ! Sinon, j’ai bien peur que je n’aurais pas pu m’en servir (je suis devenu nul en math après le BAC semblerait-il :)).

A travers ce tutorial, nous allons mettre au point la petite application Silverlight 3 ci-dessous (cliquez sur les pinguins!)


Par défaut, 2 effets sont facilement disponibles sur n’importe lequel de vos éléments. Ils se trouvent sous la propriété
Effect et se nomment BlurEffect et DropShadowEffect.

Note 1: vous trouverez à la fin de ce billet une vidéo de démonstration suivant les étapes décrites dans ce tutoriel.

Note 2: contrairement à WPF 3.5 SP1, les effets de type Pixel Shaders sont rendus de manière « logicielle » (c'est-à-dire par notre CPU préféré) et non pas par le GPU de la carte graphique. Dès que vous appliquerez un effet de shader, vous perdrez de facto l’accélération matérielle sur l’élément cible. Plus d’infos sur la
gestion du GPU par SL3 ici.

Allez, je vous propose de suivre quelques étapes pour découvrir tout cela sans mal de tête.

1 – Créez un projet Silverlight 3 de type « Silverlight Application » que vous hébergerez dans une simple page HTML.
2 – Créez un répertoire « images » à la racine de votre projet et insérez-y 2 images de votre choix. Dans mon cas, j’ai pris les images « Penguins.jpg » et « Tulips.jpg » présentes dans les samples de Windows 7.
3 – Au sein de la grille, insérez un contrôle Image et pointez vers l’une de vos 2 images.
4 – Observez la propriété Effect du contrôle Image. Nous allons d’abord utiliser un effet d’ombre portée à l’aide de ce bout de XAML :

<Image Source="images/Penguins.jpg" Margin="20">

    <Image.Effect>

        <DropShadowEffect ShadowDepth="10" Direction="45" />               

    </Image.Effect>

</Image>

Les propriétés ShadowDepth  et Direction indiquent respectivement le niveau de profondeur de l’ombre portée et la direction de celle-ci. Voici le résultat en image :

SL3PS001 par vous

5 – Utilisons maintenant à la place un effet de flou (Blur). Pour cela, utilisez le morceau de XAML suivant :

<Image.Effect>

    <BlurEffect Radius="5" />

</Image.Effect>

Voici le résultat avec cet effet :

SL3PS002 par vous
Ne réglez pas votre téléviseur, nous contrôlons les horizontales et les verticales avec l’effet myope de Silverlight 3.

Si l’on souhaite mettre en place davantage d’effets, il faut alors créer ce que l’on appelle un « custom effect » à l’aide du langage HLSL dont je vous parlais plus haut.

Il faut écrire un .FX et cela ressemble alors à cela :

float4 main(float2 uv : TEXCOORD) : COLOR

{

   float2 dir = uv - center;

  

   float2 toPixel = uv - center; // vector from center to pixel

       float distance = length(toPixel);

       float2 direction = toPixel/distance;

       float angle = atan2(direction.y, direction.x);

       float2 wave;

       sincos(frequency * distance + phase, wave.x, wave.y);

            

       float falloff = saturate(1-distance);

       falloff *= falloff;

            

       distance += amplitude * wave.x * falloff;

   sincos(angle, direction.y, direction.x);

   float2 uv2 = center + distance * direction;

  

   float lighting = saturate(wave.y * falloff) * 0.2 + 0.8;

  

   float4 color = tex2D( implicitInputSampler, uv2 );

   color.rgb *= lighting;

  

   return color;

}

Une fois ce shader écrit, il faut le compiler en .PS à l’aide du SDK de DirectX. C’est ce fameux .PS (le shader compilé) que l’on pourra ensuite appliquer au sein d’une application Silverlight 3 comme effet personnalisé. Et c’est là que vous vous dites « mince, j’aurais du définitivement mieux suivre mes cours de Math au lieu d’aller jouer au baby foot moi ! ». En tout cas, c’est ce que je me dis de mon coté.

Heureusement, rien n’est perdu ! Pendant que nous allions jouer au baby foot, d’autres suivaient ardemment les cours de traitement du signal et autres joyeusetés. Ils ont ensuite eu la bonne idée de créer une librairie d’effets shaders compatibles avec WPF et Silverlight 3. Ils ont déposés le fruit de leur labeur sur codeplex :  http://wpffx.codeplex.com/

Reprenons alors la suite de notre tutorial.

6 – Récupérez le code des librairies présentes sur CodePlex
7 – Ouvrez le projet contenu dans le répertoire « WPFSLFx\WPFSLFx\SL\SLShaderEffectLibrary » et compilez le.
8 – Ajoutez une référence à la DLL « SLShaderEffectLibrary.dll » ainsi générée dans le répertoire « Bin ».
9 – Déclarez ce nouveau namespace dans votre XAML :

xmlns:ShaderEffectLibrary="clr-namespace:ShaderEffectLibrary;assembly=SLShaderEffectLibrary"

10 – Vous avez désormais une nouvelle panoplie d’effets à votre disposition !

SL3PS003 par vous

11 – Utilisons maintenant celui faisant des vagues :

<Image.Effect>

    <ShaderEffectLibrary:RippleEffect />

</Image.Effect>

Et voici le résultat :

SL3PS004 par vous  

C’est quand même pas mal non ?

Bon maintenant, j’aimerais aller un peu plus loin en mettant en place des animations utilisant ces effets pour effectuer une jolie transition entre 2 images.

Comme nous utilisons un contrôle container de type « Grid », les éléments que l’on met dedans sont automatiquement superposés les uns sur les autres. Cela nous arrange donc pour mettre au point une animation de transition. On va en effet jouer sur la propriété d’opacité pour passer d’une image à l’autre.

12 – Revenons donc à ce XAML simplifié :

<Image x:Name="image2" Source="images/Tulips.jpg" Margin="20" />

<Image x:Name="image1" Source="images/Penguins.jpg" Margin="20" />

13 – Nous allons d’abord jouer sur les valeurs d’opacité pour mettre en place l’animation la plus simple qui soit. Pour cela, déclarez ce storyboard comme ressource au contrôle :

<UserControl.Resources>

    <Storyboard x:Name="maJolieAnimation">

        <DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="image1" Storyboard.TargetProperty="(UIElement.Opacity)">

            <EasingDoubleKeyFrame KeyTime="00:00:00" Value="1"/>

            <EasingDoubleKeyFrame KeyTime="00:00:05" Value="0"/>

        </DoubleAnimationUsingKeyFrames>

    </Storyboard>

</UserControl.Resources>

On indique ici de faire passer la propriété opacité de notre image 1 (le pingouin) de 1 (visible) à 0 (invisible) à travers une animation durant 5 secondes. Lorsque l’image 1 ne sera plus visible, nous verrons donc l’image 2 qui se trouve en dessous. Pour lancer l’animation, abonnez-vous à l’évènement MouseLeftButtonDown de l’image 1 et lancez le code suivant :

private void image1_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)

{

    maJolieAnimation.Begin();

    maJolieAnimation.AutoReverse = true;

}

Testez l’ensemble. En cliquant sur l’image 1, vous enclenchez l’animation de fondu. Grâce à l’AutoReverse, vous reviendrez alors automatiquement au statut de départ.

14 – Couplons maintenant à cet effet de fondu, un effet de shader animé basé sur le RippleEffect. Commencez par utiliser ce XAML pour l’image 1 :

<Image x:Name="image1" Source="images/Penguins.jpg" Margin="20" MouseLeftButtonDown="image1_MouseLeftButtonDown">

    <Image.Effect>

        <ShaderEffectLibrary:RippleEffect Amplitude="0" Frequency="0" />

    </Image.Effect>

</Image>

 

On déclare ici que l’on souhaite appliquer l’effet RippleEffect qui n’a pour l’instant aucun résultat visible puisque nous avons positionné l’amplitude et la fréquence de la vague à 0.

 

15 – Modifions notre storyboard pour travailler sur cet effet en ajoutant ce XAML en dessous du travail effectué sur l’opacité :

 

<DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="image1" Storyboard.TargetProperty="(UIElement.Effect).(RippleEffect.Frequency)">

    <EasingDoubleKeyFrame KeyTime="00:00:00" Value="0"/>

    <EasingDoubleKeyFrame KeyTime="00:00:05" Value="75"/>

</DoubleAnimationUsingKeyFrames>

<DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="image1" Storyboard.TargetProperty="(UIElement.Effect).(RippleEffect.Amplitude)">

    <EasingDoubleKeyFrame KeyTime="00:00:00" Value="0"/>

    <EasingDoubleKeyFrame KeyTime="00:00:05" Value="1.1"/>

</DoubleAnimationUsingKeyFrames>

 

Nous travaillons ici sur 2 propriétés supplémentaires : la valeur de fréquence et d’amplitude allant respectivement de 0 à 75 et de 0 à 1.1 pendant 5 secondes. Pour rappel, nous faisons également varier l’opacité dans la même tranche de temps.

 

Compilez et testez l’application pour vérifier que la jolie animation fonctionne bien.

 

SL3PS004b par vous  

 

Alors logiquement, tel que je vous connais, vous devriez me dire 2 choses :

 

1 – Comment apprendre à connaître le fonctionnement de ces nouveaux effets (les propriétés à manipuler, le résultat à l’écran, etc.) ?

2 – Suis-je obligé d’écrire le XAML des animations à la main ?

 

Pour la 1ère question, la réponse peut passer par l’utilisation d’un outil appelé Shazzam se trouvant ici : http://shazzam-tool.com/ . Ce dernier permet de tester différents pixels shaders avec un éditeur de .FX intégré. Vous trouverez des informations écrites par l’auteur de l’outil ici.

 

Pour la 2ème question, je vous propose d’utiliser un outil plutôt doué pour la génération de XAML… j’ai nommé Express Blend 3 !

 

16 – Ouvrez la page MainPage.xaml avec Blend 3

 

SL3PS005 par vous

 

On voit alors plusieurs choses. Tout d’abord, on retrouve bien l’effet actuellement appliqué à notre première image :

 

SL3PS006 par vous  

 

En cliquant sur « New », vous pouvez également retrouver l’ensemble des effets de notre librairie :

 

SL3PS007 par vous  

 

Cela indique que nous allons pouvoir plutôt utiliser Blend 3 pour appliquer des effets à nos éléments plutôt que de taper le XAML à la main dans Visual Studio. Par ailleurs, on peut également voir et éditer l’animation que nous avons mise en place :

 

 SL3PS008 par vous

 

17 – Nous allons alors en profiter pour légèrement améliorer l’animation actuellement en place sur la variation de l’opacité. Après avoir sélectionné « maJolieAnimation », cliquez sur l’élément « Opacity » de l’objet « image1 » :

 

SL3PS009 par vous  

 

Au lieu d’avoir une animation linéaire, j’aimerais plutôt avoir une animation relativement lente au début et s’accélérant vite à la fin pour que nous ayons plus le temps de voir l’effet shader animé sur l’image 1. Pour cela, cliquez sur la combo « EasyFunction » et choisissez la 1ère de type « Quintic In » :

 

SL3PS010 par vous  

 

Cela devrait alors vous produire le XAML suivant :

 

<UserControl x:Class="TestPSLibrary.MainPage"

    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

    xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"

    xmlns:ShaderEffectLibrary="clr-namespace:ShaderEffectLibrary;assembly=SLShaderEffectLibrary"

    mc:Ignorable="d" d:DesignWidth="640" d:DesignHeight="480">

    <UserControl.Resources>

        <Storyboard x:Name="maJolieAnimation">

            <DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="image1" Storyboard.TargetProperty="(UIElement.Opacity)">

                <EasingDoubleKeyFrame KeyTime="00:00:00" Value="1">

                    <EasingDoubleKeyFrame.EasingFunction>

                        <QuinticEase EasingMode="EaseIn"/>

                    </EasingDoubleKeyFrame.EasingFunction>

                </EasingDoubleKeyFrame>

                <EasingDoubleKeyFrame KeyTime="00:00:05" Value="0">

                    <EasingDoubleKeyFrame.EasingFunction>

                        <QuinticEase EasingMode="EaseIn"/>

                    </EasingDoubleKeyFrame.EasingFunction>

                </EasingDoubleKeyFrame>

            </DoubleAnimationUsingKeyFrames>

            <DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="image1" Storyboard.TargetProperty="(UIElement.Effect).(RippleEffect.Frequency)">

                <EasingDoubleKeyFrame KeyTime="00:00:00" Value="0"/>

                <EasingDoubleKeyFrame KeyTime="00:00:05" Value="75"/>

            </DoubleAnimationUsingKeyFrames>

            <DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="image1" Storyboard.TargetProperty="(UIElement.Effect).(RippleEffect.Amplitude)">

                <EasingDoubleKeyFrame KeyTime="00:00:00" Value="0"/>

                <EasingDoubleKeyFrame KeyTime="00:00:05" Value="1.1"/>

            </DoubleAnimationUsingKeyFrames>

        </Storyboard>

    </UserControl.Resources>

    <Grid x:Name="LayoutRoot">

        <Image x:Name="image2" Source="images/Tulips.jpg" Margin="20" />

        <Image x:Name="image1" Source="images/Penguins.jpg" Margin="20" MouseLeftButtonDown="image1_MouseLeftButtonDown">

            <Image.Effect>

                <ShaderEffectLibrary:RippleEffect Amplitude="0" Frequency="0" />

            </Image.Effect>

        </Image>

    </Grid>

</UserControl>

 

Sauvegardez et recompilez. Si tout s’est bien passé, vous devriez alors obtenir l’application Silverlight 3 présentée au début de ce billet.

 

Voici le projet Visual Studio 2008 correspondant à cet article :

 

Pour terminer, voici une vidéo de 15 min où je me propose de suivre ces mêmes étapes pour vous (double-cliquez dessus pour le plein écran) :

 

Pour discuter davantage sur ce sujet, n'hésitez pas à nous rejoindre sur ce fil de discussion

 

Bon Pixel Shaders et à bientôt !

 

David

Utilisez LINQ pour faciliter l’accès aux listes Sharepoint via ses WebServices

Interroger une liste SharePoint depuis le webservice exposé qui va bien n’est pas très difficile mais c’est un peu casse pied de manipuler le flux XML retourné et de jouer avec le langage de requêtes de SharePoint appelé CAML. Voyons donc comment utiliser les dernières technologies disponibles avec le .NET Framework 3.5 telle que LINQ pour rendre meilleure notre vie de développeur.

Partons de la liste d’exemple suivante :

3685013544

Notre but ici sera de se créer une petite librairie permettant d’interroger le WebService de Sharepoint pour manipuler cette liste et ses éléments via un mapping objet et grâce l’utilisation de LINQ.

La méthode classique

Ajoutons une référence au service Web qui va bien en faisant « Add Service Reference » sur le projet, puis « Advanced » puis « Add Web Reference.. ». Dans l’URL, entrez n’importe quelle adresse pointant vers un serveur SharePoint suivit ensuite de « /_vti_bin/Lists.asmx ». Dans mon cas, je nommerais la référence « MOSSListWS ».

3684201643

Cela va nous construire le proxy client que l’on pourra bien évidement utiliser vers d’autres serveurs SharePoint.

Si l’on appelle la méthode GetListItems() sur la liste précédente via le code suivant :

// On instancie le proxy du webservice SPS

MOSSListWS.Lists list_svc = new MOSSListWS.Lists();

// On utilise l'identité actuelle comme Credentials pour

// appeler le Webservice

list_svc.Credentials = CredentialCache.DefaultCredentials;

 

// On indique au proxy l'URL cible

list_svc.Url = _sharePointURL;

 

// On récupère tous les enregistrements

XmlNode itemCollection = list_svc.GetListItems(_nomListe, string.Empty, null, null, "0", null, "");

Voici le type de XML qui est retourné par la méthode dans itemCollection :

<rs:data ItemCount="7" xmlns:rs="urn:schemas-microsoft-com:rowset">

  <z:row ows_Attachments="0" ows_LinkTitle="Halo 3"

         ows_Plateforme="Xbox 360"

         ows_Description="Le meilleur jeu de FPS sur console"

         ows_Prix="60.0000000000000" ows_MetaInfo="1;#"

         ows__ModerationStatus="0"

         ows__Level="1"

         ows_Title="Halo 3"

         ows_ID="1"

         ows_owshiddenversion="1"

         ows_UniqueId="1;#{03EF1580-F6DE-4BAA-9D80-7665207789CB}"

         ows_FSObjType="1;#0"

         ows_Created_x0020_Date="1;#2009-06-23 16:02:06"

         ows_Created="2009-06-23 16:02:06"

         ows_FileLeafRef="1;#1_.000"

         ows_FileRef="1;#sites/davrous/Lists/Liste Produits/1_.000"

         xmlns:z="#RowsetSchema" />

  <z:row ows_Attachments="0" ows_LinkTitle="Visual C# Express" ows_Plateforme="Windows" ows_Description="Le meilleur éditeur de code gratuit du marché :)" ows_Prix="0" ows_MetaInfo="2;#" ows__ModerationStatus="0" ows__Level="1" ows_Title="Visual C# Express" ows_ID="2" ows_owshiddenversion="1" ows_UniqueId="2;#{2031D3B5-F3B8-4597-9567-137ACCD2C1DB}" ows_FSObjType="2;#0" ows_Created_x0020_Date="2;#2009-06-23 16:02:49" ows_Created="2009-06-23 16:02:49" ows_FileLeafRef="2;#2_.000" ows_FileRef="2;#sites/davrous/Lists/Liste Produits/2_.000" xmlns:z="#RowsetSchema" />

</rs:data>

Il faudrait donc parser ce morceau de XML soit à la main soit via du XPath pour retrouver les informations qui nous intéressent. Je ne sais pas vous, mais moi, le XPath je ne suis pas super fan.

Création d’un mapping objet

Sur la copie d’écran de notre liste « Liste Produits », 4 colonnes sont utilisées: Nom du produit, Plateforme, Description et Prix.

On va donc partir sur cette définition objet pour faire le mapping avec la liste :

public class Produit

{

    public string Nom { get; set; }

    public string Description { get; set; }

    public string Plateforme { get; set; }

    public double Prix { get; set; }

}

On va ensuite créer une classe de base nommée BaseSPSList qui fonctionnera avec n’importe quelle type de liste SharePoint, quelques soient les colonnes qui ont été définies mais qui du coup offrira très peu de services : simplement récupérer les valeurs de la 1er colonne. Puis ensuite une classe héritant de BaseSPSList nommée ProductsSPSList qui sera spécialisée et dédiée à la liste « Liste Produits » telle que définie par la 1ère copie d’écran.

Dans cette classe spécialisée, nous ferons donc appel au type Produit et nous aurons accès à des méthodes pour créer un nouvel enregistrement dans la liste, mettre à jour un enregistrement et supprimer un enregistrement.

Pour éviter un aller/retour systématique vers le serveur SharePoint, un petit mécanisme de cache sera mis en place. Par ailleurs, dans cet exemple de code, j’ai fait le choix de retourner l’ensemble des enregistrements de la liste. Cela n’est pas forcément optimal. On peut éventuellement demander à SharePoint, via l’appel à la méthode GetListItems(), de ne retourner qu’un sous-ensemble grâce à l’utilisation de requêtes appelées CAML. Autre approximation dans cet exemple, on va considérer que le nom du produit nous servira comme clé pour les mises à jour et suppression depuis notre couche objet.

Bref, certaines choses sont mal et devront être revues si vous avez l’idée saugrenue de reprendre ce code en production.

Voici le code que je vous propose, rendez-vous après celui-ci pour quelques commentaires additionnels. A tout de suite donc !

// Classe de base pour les opérations communes à toutes les listes

public class BaseSPSList

{

    // URL du serveur SharePoint cible

    protected string _sharePointURL;

    // nom de la liste

    protected string _nomListe;

    // on se sert d'un cache mémoire pour éviter

    // trop d'aller/retour serveur

    protected IEnumerable<XElement> cachedSPSXElements = null;

    // Du coup, il faut pouvoir regénérer le cache si besoin

    public bool IsCacheDirty { get; set; }

 

    // Le constructeur a besoin de l'URL du site SharePoint ainsi

    // que la liste visée contenu dans ce même site

    public BaseSPSList(string SharePointURL, string nomListe)

    {

        this._sharePointURL = SharePointURL + "/_vti_bin/Lists.asmx";

        this._nomListe = nomListe;

        this.IsCacheDirty = true;

    }

 

    // Exemple de méthode qui fonctionne quelque soit la liste

    // fournie vu que ows_LinkTitle est systématiquement utilisé

    // par SharePoint 2007 comme nom de 1ère colonne

    public IEnumerable GetDistinctFirstColumnValues()

    {

        if (IsCacheDirty || cachedSPSXElements == null) BuildFirstQuery();

 

        var query = from x in cachedSPSXElements

                    where x.Attribute("ows_LinkTitle") != null

                    select new

                    {

                        Title = x.Attribute("ows_LinkTitle").Value

                    };

 

        var resultat = (from f in query

                        select f.Title).Distinct();

 

        return resultat;

    }

 

    // On appel cette méthode que lors de la 1ere action effectuée

    protected void BuildFirstQuery()

    {

        // On instancie le proxy du webservice SPS

        MOSSListWS.Lists list_svc = new MOSSListWS.Lists();

        // On utilise l'identité actuelle comme Credentials pour

        // appeler le Webservice

        list_svc.Credentials = CredentialCache.DefaultCredentials;

 

        // On indique au proxy l'URL cible

        list_svc.Url = _sharePointURL;

 

        // On récupère tous les enregistrements

 // TO DO: ajouter la possibilité de spécifier un filtre

        XmlNode itemCollection = list_svc.GetListItems(_nomListe, string.Empty, null, null, "0", null, "");

 

        // On parse le flux XML retourné par le webservice

        // pour faire appel ensuite à LINQ2XML

        XDocument cachedXMLDocument;

        cachedXMLDocument = XDocument.Parse(itemCollection.OuterXml.ToString());

        // Namespace spécifique au XML retourné par SharePoint

        XNamespace ns = "#RowsetSchema";

        cachedSPSXElements = cachedXMLDocument.Descendants(ns + "row");

        IsCacheDirty = false;

    }

}

 

// Classe spécialisée sur notre définition de liste

// comme "Liste Produits"

public class ProductsSPSList : BaseSPSList

{

    // Constante spécifique à SharePoint pour

    // son nommage interne via son schéma de liste

    const string SPS_INT_NOMPRODUIT = "ows_LinkTitle";

    const string SPS_INT_PLATEFORMES = "ows_Plateforme";

    const string SPS_INT_DESCRIPTION = "ows_Description";

    const string SPS_INT_PRIX = "ows_Prix";

    const string SPS_INT_SharePointID = "ows_ID";

 

    const string SPS_NOMPRODUIT = "Title";

    const string SPS_PLATEFORMES = "Plateforme";

    const string SPS_DESCRIPTION = "Description";

    const string SPS_PRIX = "Prix";

 

    public ProductsSPSList(string SharePointURL, string ListName)

        : base(SharePointURL, ListName)

    {

    }

 

    // Méthode retournant l'ensemble des produits de la liste

    public IEnumerable<Produit> GetProducts()

    {

        System.Globalization.CultureInfo ci;

        ci = System.Globalization.CultureInfo.CreateSpecificCulture("en-us");

 

        // Si c'est le 1er appel ou si le cache n'est plus considéré

        // comme à jour, on rappatrie les enregsitrements depuis SharePoint

        // sinon on utilise le cache mémoire pour éviter un aller/retour

        if (IsCacheDirty || cachedSPSXElements == null) BuildFirstQuery();

 

        // Requete LINQ permettant de faire le mapping

        // entre le flux XML brut retourné par SharePoint

        // et notre modèle de données Produit

        var produits = from x in cachedSPSXElements

                       where x.Attribute("ows_LinkTitle") != null

                       select new Produit

                       {

                           Nom = x.Attribute(SPS_INT_NOMPRODUIT).Value,

                           // permet de gérer les cas où la colonne n'a pas de valeur

                           // renseignée pour ce produit

                           Plateforme = x.Attribute(SPS_INT_PLATEFORMES) != null ? x.Attribute(SPS_INT_PLATEFORMES).Value : string.Empty,

                           Description = x.Attribute(SPS_INT_DESCRIPTION) != null ? x.Attribute(SPS_INT_DESCRIPTION).Value : string.Empty,

                           Prix = x.Attribute(SPS_INT_PRIX) != null ? double.Parse(x.Attribute(SPS_INT_PRIX).Value, ci) : -1,

                           SharePointID = x.Attribute(SPS_INT_SharePointID) != null ? x.Attribute(SPS_INT_SharePointID).Value : string.Empty,

                       };

 

        return produits;

    }

 

    // Retourne le produit correspondant au nom passé en argument

    public IEnumerable<Produit> GetProductByName(string nomProduit)

    {

        IEnumerable<Produit> produits = GetProducts();

 

        var filtreProduits = from produit in produits

                             where produit.Nom == nomProduit

                             select produit;

 

        return filtreProduits;

    }

 

    // Méthode pour mettre à jour un produit coté liste SharePoint

    // Si le produit existe déjà, il est mise à jour

    // Sinon, il est tout simplement créé

    public bool UpdateProduct(Produit majProduit)

    {

        // On regarde si le produit existe déjà ou pas dans le cache

        IEnumerable<Produit> produitExistant = GetProductByName(majProduit.Nom);

        try

        {

            // Il n'a pas été trouvé en mémoire

            // Il faut donc le créer coté SharePoint

            if (produitExistant.Count().Equals(0))

            {

                // Il faut indiquer d'après cette opération

                // le cache ne refletera plus la liste SharePoint

                IsCacheDirty = true;

                return AddNewProduct(majProduit);

 

            }

            else

            {

                majProduit.SharePointID = produitExistant.First().SharePointID;

                return UpdateExistingProduct(majProduit);

            }

        }

        catch (Exception)

        {

            return false;

        }

    }

 

    public bool DeleteProduct(Produit supProduit)

    {

        IEnumerable<Produit> produitExistant = GetProductByName(supProduit.Nom);

        try

        {

            // Il n'a pas été trouvé en mémoire

            // Nous avons donc rien à faire

            if (produitExistant.Count().Equals(0))

            {

                return true;

 

            }

            else

            {

                // Le cache ne sera plus à jour après cette opération

                IsCacheDirty = true;

                string SharePointID = produitExistant.First().SharePointID;

                return DeleteExistingProduct(SharePointID);

            }

        }

        catch (Exception)

        {

            return false;

        }

    }

 

    // Méthode pour ajouter un nouveau produit

    private bool AddNewProduct(Produit nouveauProduit)

    {

        try

        {

            MOSSListWS.Lists list_svc = new MOSSListWS.Lists();

            list_svc.Credentials = CredentialCache.DefaultCredentials;

 

            list_svc.Url = _sharePointURL;

 

            XmlDocument doc = new XmlDocument();

            XmlElement batch_element = doc.CreateElement("Batch");

 

            batch_element.SetAttribute("ListVersion", "1");

 

            string item = "<Method ID=\"1\" Cmd=\"New\">" +

                "<Field Name=\"ID\">New</Field>"

                + "<Field Name=\"" + SPS_NOMPRODUIT + "\">" + nouveauProduit.Nom + "</Field>"

                + "<Field Name=\"" + SPS_PLATEFORMES + "\">" + nouveauProduit.Plateforme + "</Field>"

                + "<Field Name=\"" + SPS_DESCRIPTION + "\">" + nouveauProduit.Description + "</Field>"

                + "<Field Name=\"" + SPS_PRIX + "\">" + nouveauProduit.Prix + "</Field>"

                + "</Method>";

 

            batch_element.InnerXml = item;

 

            // Aucune exception n'est levée en cas de non ajout

            // Il faut donc vérifier l'errorcode dans retour XML

            XmlNode resultat = list_svc.UpdateListItems(_nomListe, batch_element);

 

            return resultat.InnerText.Equals("0x00000000");

        }

        catch (Exception ex)

        {

            string err = ex.Message;

            return false;

        }

    }

 

    // Methode pour mettre à jour un enregistrement coté SharePoint

    private bool UpdateExistingProduct(Produit majProduit)

    {

        try

        {

            MOSSListWS.Lists list_svc = new MOSSListWS.Lists();

            list_svc.Credentials = CredentialCache.DefaultCredentials;

 

            list_svc.Url = _sharePointURL;

 

            XmlDocument doc = new XmlDocument();

            XmlElement batch_element = doc.CreateElement("Batch");

 

            batch_element.SetAttribute("ListVersion", "1");

 

            string item = "<Method ID=\"1\" Cmd=\"Update\">" +

                "<Field Name=\"ID\">" + majProduit.SharePointID + "</Field>"

                 + "<Field Name=\"" + SPS_NOMPRODUIT + "\">" + majProduit.Nom + "</Field>"

                + "<Field Name=\"" + SPS_PLATEFORMES + "\">" + majProduit.Plateforme + "</Field>"

                + "<Field Name=\"" + SPS_DESCRIPTION + "\">" + majProduit.Description + "</Field>"

                + "<Field Name=\"" + SPS_PRIX + "\">" + majProduit.Prix + "</Field>"

                + "</Method>";

 

            batch_element.InnerXml = item;

            XmlNode resultat = list_svc.UpdateListItems(_nomListe, batch_element);

 

            return resultat.InnerText.Equals("0x00000000");

        }

        catch (Exception ex)

        {

            string err = ex.Message;

            return false;

        }

    }

 

    // Méthode pour supprimer un enregistrement coté SharePoint

    private bool DeleteExistingProduct(string SharePointID)

    {

        try

        {

            MOSSListWS.Lists list_svc = new MOSSListWS.Lists();

            list_svc.Credentials = CredentialCache.DefaultCredentials;

 

            // The URL property for WebService retrieve

            list_svc.Url = _sharePointURL;

 

            XmlDocument doc = new XmlDocument();

            XmlElement batch_element = doc.CreateElement("Batch");

 

            batch_element.SetAttribute("ListVersion", "1");

 

            string item = "<Method ID=\"1\" Cmd=\"Delete\">" +

                "<Field Name=\"ID\">" + SharePointID + "</Field></Method>";

 

            batch_element.InnerXml = item;

            XmlNode resultat = list_svc.UpdateListItems(_nomListe, batch_element);

 

            return resultat.InnerText.Equals("0x00000000");

        }

        catch (Exception ex)

        {

            string err = ex.Message;

            return false;

        }

    }

 

    // Si vous avez besoin d'ajouter des dates de .NET vers une liste SharePoint

    // il faut la convertir au format ISO 8601

    private static String ConvertDateTimeToISO8601(DateTime dt)

    {

 

        return dt.ToString("yyyy'-'MM'-'dd'T'HH':'mm':'ss'Z'");

    }

 

    private static DateTime ConvertISO8601ToDateTime(String iso)

    {

        return DateTime.ParseExact(iso, "yyyy'-'MM'-'dd'T'HH':'mm':'ss'Z'", System.Globalization.CultureInfo.InvariantCulture);

    }

}

J’espère avoir suffisamment commenté le code pour qu’il soit compréhensible en 1ère lecture. La dernière partie est un cadeau bonus si comme moi vous galérez à un moment pour convertir un type DateTime de .NET défini dans votre mapping objet vers le format date de SharePoint. On ne l’utilise pas dans cet exemple mais cela peut toujours vous servir.

Si vous avez été attentif, vous avez probablement remarqué les constantes que j’ai surlignées en jaune. Comment ai-je deviné leurs valeurs ? En analysant tout bêtement le morceau de XML mentionné en début d’article. Une meilleure approche sera d’interroger le service Web de liste via la méthode GetList() pour récupérer le schéma XML défini par SharePoint pour ma liste d’exemple et générer le mapping objet de manière automatique en analysant le schéma plutôt que de le coder en dur comme je l’ai fait.

Toujours est-il, une fois que vous avez compris le concept, voici ensuite le type de client pouvant faire appel au code précédent s’il est mis dans une librairie DLL :

#region Section Lecture de la liste

// on instancie notre super Helper

ProductsSPSList monHelper = new ProductsSPSList("http://myemea/sites/davrous", "Liste Produits");

 

// on souhaite récupérer l'ensemble des produits

// inscrits dans la liste SharePoint "Liste Produits"

var tousLesProduits = monHelper.GetProducts();

 

// On peut alors simplement parcourir les produits

// un à un

foreach (Produit p in tousLesProduits)

{

    Console.WriteLine(p.Nom + " - Plateforme : " + p.Plateforme);

}

 

Console.WriteLine("-------------------");

 

// Encore mieux, comme nous retournous un

// IEnumerable depuis notre librairie, on peut

// filtrer le retour avec une requête LINQ!

var produitsXbox360 = from produits in tousLesProduits

                      where produits.Plateforme.Equals("Xbox 360")

                      select produits;

 

// On peut à nouveau parcourir la projection

foreach (Produit p in produitsXbox360)

{

    Console.WriteLine(p.Nom);

}

#endregion

 

#region Section Mise à jour de la liste

// Mettons à jour d'un produit existant en le recherchant

// d'abord par son nom

Produit Natal = monHelper.GetProductByName("Natal").First();

// On change le prix

// Note : ce prix est le fruit de mon imagination, n'allez

// surtout pas en déduire quoique ce soit

Natal.Prix = 50;

 

// On lance l'opération de mise à jour coté serveur SharePoint

if (monHelper.UpdateProduct(Natal))

    Console.WriteLine("Mise à jour de {0} effectuée avec succès.", Natal.Nom);

else

    Console.WriteLine("Erreur lors de la mise à jour de {0}.", Natal.Nom);

 

// Testons maintenant la création d'un nouveau produit

Produit nouveauProduit = new Produit();

nouveauProduit.Nom = "Zune HD";

nouveauProduit.Plateforme = "Xbox 360";

nouveauProduit.Description = "un super baladeur qui envoit";

nouveauProduit.Prix = 35;

 

// Même méthode que précédemment sauf que cette fois-ci

// nous allons detécter l'absence du produit dans le cache

// donc on va lancer l'opération de création coté SharePoint

if (monHelper.UpdateProduct(nouveauProduit))

    Console.WriteLine("Création de {0} effectuée avec succès.", nouveauProduit.Nom);

else

    Console.WriteLine("Erreur lors de la création de {0}", nouveauProduit.Nom);

#endregion

 

#region Section Suppression de la liste

// Sitôt créé, sitôt détruit

// La vie d'un produit n'est pas toujours rose vous savez...

Produit Zune = monHelper.GetProductByName("Zune HD").First();

if (monHelper.DeleteProduct(Zune))

    Console.WriteLine("Suppression de {0} effectuée avec succès.", Zune.Nom);

else

    Console.WriteLine("Erreur lors de la suppression de {0}", Zune.Nom);

#endregion

 

Console.ReadLine();

Avouez que c’est nettement plus agréable à manipuler de cette façon ? En partant de la liste présentée en début d’article, voici le résultat de l’exécution de ce code client :

3685013748

Vous trouverez ci-dessous un fichier ZIP contenant ces exemples de code sous forme de 2 projets : 1 projet de type librairie donc contenant la logique du helper et 1 projet de type application console référençant la DLL puis faisant appel au helper comme ci-dessus.

Pour aller plus loin, on pourrait alors imaginer un générateur de code / création de mapping relationnel similaire à ce que nous avons aujourd’hui avec LINQ to SQL ou Entity Framework mais connecté à un type SharePoint. Il existe justement un projet de ce genre sur notre plateforme de partage de codes source ici : http://www.codeplex.com/LINQtoSharePoint . Malheureusement inachevé (le support des mises à jour n’existe pas par exemple), le code source du projet n’attend que vous pour continuer son bonhomme de chemin !

David

Comment développer des applications d’entreprises orientées données avec Silverlight 3 : introduction à .NET RIA Services (4/4)

Article mis à jour : 13 juillet 2009 pour la sortie de Silverlight 3 RTW et .NET RIA Services Juillet 2009

Ce billet est donc le dernier d’une série de quatre consacrés à l’introduction à .NET RIA Services. Voici le lien vers les autres billets:

- Introduction aux concepts derrière .NET RIA Services et vidéo Hello Word .NET RIA
- Création du squelette d’une application de gestion de clients en Silverlight 3 / .NET RIA Services
- Utilisation de nouveaux contrôles données de Silverlight 3 / Implémentation d’une règle de validation

Le résultat final en vidéo

Double-cliquez sur la vidéo pour la mettre en plein écran.

Vous pouvez télécharger le code source complet correspondant au suivi de l’ensemble de ces étapes ici:

Conclusion

Nous n’avons vu ici qu’une infime partie des possibilités que nous apporte .NET RIA Services. Il y a d’autres choses intéressantes comme la restriction d’appels à certaines méthodes en fonction de l’appelant, la gestion des rôles et de l’authentification, la gestion des transactions. J’espère malgré tout vous avoir donné un bon aperçu des capacités de cette technologie et surtout de son intérêt principal : apporter une productivité accrue sur le développement d’application Web RIA. J’espère vous en avoir convaincu !

Les ressources complémentaires

Tout d’abord, commençons par ce qui a été présenté au MIX09 à Las Vegas en mars dernier :

- La session Building Amazing Business Centric Applications with Microsoft Silverlight 3 animée par Brad Abrams. Si vous n’avez pas beaucoup de temps, il faut absolument au moins voir cette session! De plus, Brad a eu l’excellente idée d’accompagner sa session d’un billet très détaillé sur son blog permettant de refaire la même application ici. Un must !

Vous pouvez notamment voir sa démo finale ici : http://www.hanselman.com/abrams/#/Views/HomePage.xaml offrant quelques fonctionnalités supplémentaires par rapport à ce que nous avons vu dans ces 4 billets comme une vue maitre/détail, un filtrage des éléments avec une AutocompleteTextbox et l’ajout d’un nouvel enregistrement à travers l’utilisation du contrôle DataForm nouveau également.

- La session .NET RIA Services - Building Data-Driven Applications with Microsoft Silverlight and Microsoft ASP.NET animée par Nikhil Kothari bien complémentaire de la session de Brad. Vous verrez par exemple comment utiliser une source storage de Windows Azure.

- Le document de référence actuel: Microsoft .NET RIA Services July 2009 Preview où l’on aborde en détail toutes les possibilités offertes par .NET RIA Services non couvertes par ces 4 articles (et elles sont nombreuses!)

Ensuite, voici une autre ressource que j’ai pris plaisir à lire :

- Développer des applications orientées “métier” avec Silverlight 3 et les .NET RIA Services ! sur le blog de Thomas Lebrun

L’un de mes prochains posts tentera de vous expliquer en quoi .NET RIA Services et certaines nouveautés supplémentaires de Silverlight 3 comme le deep linking et le framework de navigation vont vous permettre de grandement faciliter le travail de référencement de votre application RIA par un moteur de recherche : ce que l’on appelle donc SEO ou Search Engine Optimization.

A bientôt donc !

David

Comment développer des applications d’entreprises orientées données avec Silverlight 3 : introduction à .NET RIA Services (3/4)

Article mis à jour : juillet 2009 pour la sortie de Silverlight 3 RTW et .NET RIA Services Juillet 2009 

Nous avons construit le squelette de notre application dans le 2ème billet. Nous allons ici faire usage de nouveaux contrôles de Silverlight 3 et ajouter une règle de validation coté serveur pour observer comment elle se réplique coté client par la suite.

Utilisation de nouveaux contrôles Silverlight 3

Reprenons notre application. Pour l’instant, vous allez me dire : « c’est bien gentil tout ça mais afficher tous les enregistrements sans pagination, c’est nul ! ». Bon, alors tentons de régler ce différent.

Le contrôle DataSource

Commencez par retirer les quelques lignes de code que nous avions ajoutées dans le code behind : Home.xaml.cs. On va tenter de faire la même chose en pur XAML.

Ajoutez l’utilisation de ces namespaces à votre contrôle :

xmlns:riaControls="clr-namespace:System.Windows.Controls;assembly=System.Windows.Ria.Controls"

xmlns:riaData="clr-namespace:System.Windows.Data;assembly=System.Windows.Ria.Controls"

xmlns:domain="clr-namespace:GestionClientsRIA.Web"

Le dernier est l’équivalent du « using » fait en C#. Insérez ce bloc de XAML au début du StackPanel :

<riaControls:DomainDataSource x:Name="source"

              QueryName="GetCustomers"

              AutoLoad="True">

    <riaControls:DomainDataSource.DomainContext>

        <domain:CustomersContext />

    </riaControls:DomainDataSource.DomainContext>

</riaControls:DomainDataSource>

On indique ainsi que l’on souhaite appeler la méthode GetCustomers depuis le domaine CustomersContext. Il nous reste maintenant à indiquer au contrôle grille où se trouve sa source de données :

<data:DataGrid x:Name="GrilleClients" ItemsSource="{Binding Data, ElementName=source}" />

On utilise donc ici le binding entre éléments, autre nouveauté déjà abordée dans ce précédent billet. Si on exécute l’ensemble, on a bien un résultat identique au code C# avec la méthodeLoad(contexte.GetCustomersQuery()).

Trions maintenant les données par ordre croissant selon le nom de l’entreprise à laquelle le client appartient. Pour cela, ajoutez ce morceau de XAML juste avant la balise fermante </riaControls :DomainDataSource> :

<riaControls:DomainDataSource.SortDescriptors
    <riaData:SortDescriptor PropertyPath="CompanyName" Direction="Ascending" />
</
riaControls:DomainDataSource.SortDescriptors>


Désormais les enregistrements sont bien triés par ordre alphabétique croissant selon le nom de l’entreprise. Mais je n’ai toujours pas répondu au besoin de pagination. J’y arrive, j’y arrive…

Le contrôle DataPager

Dans le StackPanel où se trouve le contrôle DataGrid, ajoutez ce XAML en dessous de la grille de données :

<data:DataPager PageSize="10" Source="{Binding Data, ElementName=source}" />

On indique ici d’afficher les enregistrements 10 par 10. Relancez l’ensemble :

RIAImage14

Nous avons donc bien la pagination en marche. Par contre, nous chargeons toujours l’ensemble des enregistrements malgré le fait de les visualiser par lot de 10. Il serait donc peut-être plus intéressant de charger les données au fur et à mesure que l’on avance dans la pagination. Pour cela, rien de plus simple ajoutez l’attribut suivant :

LoadSize="20"

à la source après l’attribut  AutoLoad="True" par exemple. Bah c’est tout ! Désormais, toutes les 2 pages, un lot de 20 enregistrements supplémentaires seront chargés en mémoire en asynchrone et en tâche de fond sans que vous n’ayez rien eu à faire.

Le contrôle ActivityControl

L’inconvénient de ces chargements asynchrones est que l’utilisateur ne comprends par forcément ce qu’il se passe lorsqu’il lance une action en cliquant et que cela met quelques millisecondes à s’afficher. Il faut donc le faire patienter et lui indiquer qu’une opération est en cours.

Pour cela, récupérez le fichier attaché à ce billet « ActivityControl.zip » contenant l’assembly « ActivityControl.dll ». Ajoutez ensuite une référence à cette assembly dans votre projet Silverlight. Ce contrôle sera probablement directement intégré dans la version finale de .NET RIA Services.

Ce contrôle est maintenant directement présents dans les références d’un projet de type Business Application. Il ne reste donc plus qu’à ajouter cet espace de nom à votre contrôle :

xmlns:activity="clr-namespace:System.Windows.Controls;assembly=ActivityControl"

Puis englobez le StackPanel contenant la grille et le DataPager entre ces 2 balises XAML :

<activity:Activity IsActive="{Binding IsBusy, ElementName=source}" VerticalAlignment="Top" HorizontalAlignment="Left"></activity:Activity>

Désormais, grâce à cela, lorsque l’on arrive sur la 3ème page le chargement des 20 prochains enregistrements est fait pendant qu’une animation « Loading » se lance :

RIAImage15

Groupons les données

Si l’on souhaite grouper les enregistrements par pays par exemple, c’est à nouveau d’une simplicité déconcertante. En dessous du tri par « CompanyName » de notre DomainDataSource, ajoutez ce XAML :

<riaControls:DomainDataSource.GroupDescriptors
    <riaData:GroupDescriptor PropertyPath="Country" />
</
riaControls:DomainDataSource.GroupDescriptors>


Et voici le résultat :

RIAImage16

On peut même fermer les nœuds pour une meilleure visibilité (comme ici Austria).

Gestion de la sauvegarde

Ajoutons d’abord un bouton pour laisser l’utilisateur sauvegarder ses changements. Pour cela, insérer le bout de XAML dans le StackPanel au dessus de la grille :

<Button x:Name="BoutonSauvegarde" Content="Sauvegarder les changements" Click="BoutonSauvegarde_Click" />

Maintenant, il nous faut lancer l’opération de sauvegarde avec ce code C# :

private void BoutonSauvegarde_Click(object sender, System.Windows.RoutedEventArgs e)
{
    if (source.HasChanges) 
    {
        source.SubmitChanges(); 
   
    else 
   
        MessageBox.Show("Aucun changement detecté."); 
    }
}


Notre objet contenant les enregistrements en mémoire maintient en effet une liste des modifications effectuées (ajout, suppression ou modification). On teste donc le booléen HasChanges pour savoir si quelque chose a été changé par l’utilisateur et si c’est le cas on voit les changements au serveur Web via la commande SubmitChanges() pour que ce dernier s’occupe à son tour de mettre à jour la base de données.

Utilisation d’une Child Window

Si aucun changement n’a été détecté et que l’utilisateur clique sur le bouton de sauvegarde, une fenêtre externe à Silverlight de style popup JavaScript est levée :

RIAImage17

Ce n’est pas optimal en termes d’expérience utilisateur. On va utiliser une autre nouveauté de Silverlight 3 pour améliorer tout cela. Ajoutez un nouvel élément à votre projet Silverlight de type « Silverlight Child Window » et nommez le « InfoWindow.xaml » :

RIAImage18

Remplacez le XAML proposé par celui-ci :

<controls:ChildWindow x:Class="GestionClientsRIA.InfoWindow" 
           xmlns=http://schemas.microsoft.com/winfx/2006/xaml/presentation 
           xmlns:x=http://schemas.microsoft.com/winfx/2006/xaml 
           xmlns:controls="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls" 
           Width="200" Height="100" 
           Title="Information utilisateur"> 
    <Grid x:Name="LayoutRoot" Margin="2"> 
        <Grid.RowDefinitions
            <RowDefinition /> 
            <RowDefinition Height="Auto" /> 
        </Grid.RowDefinitions
        <TextBlock x:Name="InfoToDisplay" Grid.Row="0" /> 
        <Button x:Name="OKButton" Content="OK" Click="OKButton_Click" Width="75" Height="23" HorizontalAlignment="Right" Margin="0,12,79,0" Grid.Row="1" />
    </Grid>
</controls:ChildWindow>


Revenons maintenant dans notre vue HomePage.xaml.cs et utilisez ce code en remplacement du précédent :

private int nombreEntiteesModifiees = 0;


private
void BoutonSauvegarde_Click(object sender, System.Windows.RoutedEventArgs e)

    if (source.HasChanges) 
   
        nombreEntiteesModifiees = source.DomainContext.Entities.GetChanges().ModifiedEntities.Count(); 
        source.SubmitChanges(); 
   
    else 
   
        InfoWindow infoWindow = new InfoWindow(); 
        infoWindow.InfoToDisplay.Text = "Aucun changement détecté."
        infoWindow.Show(); 
    }


private void source_SubmittedChanges(object sender, SubmittedChangesEventArgs e)

    InfoWindow infoWindow = new InfoWindow(); 
    infoWindow.InfoToDisplay.Text = nombreEntiteesModifiees + " modifications effectuées"
    infoWindow.Show(); 
    nombreEntiteesModifiees = 0;
}


Et ajoutez ce « using » :

using System.Windows.Ria.Data;

Enfin ajoutez l’abonnement à l’évènement SubmittedChanges au niveau de la source dans le XAML :

SubmittedChanges="source_SubmittedChanges"

On a désormais une expérience utilisateur plus « intégrée » :

RIAImage19

Et on a surtout la main sur le design de la fenêtre affichée. J’aurais pu y mettre de la vidéo, une belle image, etc.

Mise en place d’une règle de validation

Maintenant que nous laissons l’utilisateur sauvegarder les données, il serait peut-être bon d’ajouter un peu de validation de ses saisies. Retournons dans l’application ASP.NET et plus précisément dans le fichier « CustomersService.metadata.cs » qui fut généré automatiquement grâce à la case « Generate associated classes for metadata ».

Rendez-vous sur le champ Country (Pays). Nous allons spécifier une expression régulière sur ce champ indiquant que les valeurs autorisées ne peuvent qu’être des caractères alphabétiques commençant par une majuscule. Cela nous donne le résultat suivant :

[RegularExpression("[A-Z][A-Za-z]*", ErrorMessage="Les caractères non alphabétiques ne sont pas autorisés")]
public string Country;


On indique également le message d’erreur a affiché si l’utilisateur s’égard à vouloir insérer des caractères étranges pour saisir le nom du pays. Compilez l’ensemble et testez la solution.

RIAImage20

Si vous tentez alors de modifier un nom de pays en ajoutant un chiffre, le message d’erreur de validation est automatiquement levé. Aucun aller/retour serveur n’a été nécessaire pour cela, la logique est bien embarquée coté client Silverlight. Il suffit d’aller le voir dans le proxy client généré :

[DataMember()]

[RegularExpression("[A-Z][A-Za-z]*", ErrorMessage="Les caractères non alphabétiques ne sont pas autorisés")]

[StringLength(15)]

public string Country

{

    get

    {

        return this._country;

    }

    set

    {

        if ((this._country != value))

        {

            this.ValidateProperty("Country", value);

            this.OnCountryChanging(value);

            this.RaiseDataMemberChanging("Country");

            this._country = value;

            this.RaiseDataMemberChanged("Country");

            this.OnCountryChanged();

        }

    }

}

Un ensemble d’attributs peuvent ainsi être spécifiés sur les champs de vos objets métiers couvrant les scénarios les plus communs. Vous pouvez également implémenter votre propre logique de validation avec une classe de type « Shared » qui sera automatiquement répliquée coté client.

Concluons et observons le résultat final en action en vidéo dans le 4ème et dernier billet.

Comment développer des applications d’entreprises orientées données avec Silverlight 3 : introduction à .NET RIA Services (2/4)

Article mis à jour : juillet 2009 pour la sortie de Silverlight 3 RTW et .NET RIA Services Juillet 2009 

J’espère vous avoir donné l’eau à la bouche avec la précédente vidéo du 1er billet. Nous allons maintenant créer une petite application de bout en bout et introduire quelques concepts principaux au fur et à mesure. Pour cela, nous allons utiliser la célèbre base de données d’exemple NorthWind. Vous pouvez la télécharger ici. Vous pouvez également voir le résultat final en action dans la vidéo contenue dans le dernier billet.

Note : les captures d'écrans ont été réalisés avec le thème par défaut d'une application "Business Application" avec Silverlight 3 Beta et .NET RIA Services Mai 2009. Vous n'aurez pas le même template d'affichage avec Silverlight 3 RTW et .NET RIA Services Juillet 2009 mais j'ai bien mis à jour l'ensemble des 4 articles pour la RTW.

Création d’une petite application étape par étape

Création du projet Silverlight 3

Lancez Visual Studio 2008 et créer un nouveau projet Silverlight 3 de type « Silverlight Business Application » cette fois-ci et nommez le « GestionClientsRIA ».

RIAImage1

Une fois le projet créé, si vous vous rendez dans les propriétés du projet Silverlight, vous noterez l’apparition d’une nouvelle option :

3573455193

Cela vous permettra de lier le projet ASP.NET au projet Silverlight 3. C’est la fameuse glue dont je vous parlais plus haut. Vous allez mieux comprendre au fur et à mesure. On peut éventuellement établir cette liaison plus tard sur un projet existant par exemple.

Découverte de l’application par défaut

Vous pouvez dors et déjà lancer l’application Silverlight 3 pour tester ce que l’on vous propose « Out of the box » comme disent les Américains :

RIAImage3

Note : dans la version Silverlight 3 RTW, vous aurez plutôt un écran ressemblant à cela:

Template Business Application SL3 RTW

Essayez par exemple de cliquer sur « about » et de revenir ensuite sur « home ». Vous verrez alors 2 choses intéressantes :

1 – les URLs changent derrière le symbole # pour viser la bonne vue : http://localhost:port/BusinessApplicationTestPage.aspx#/Home pour la page d’accueil par exemple et http://localhost:port/BusinessApplicationTestPage.aspx#/About pour la page « A propos ».
2 – Cela permet alors de naviguer dans votre application Silverlight 3 avec la gestion de l’historique du navigateur :

3573455503

Le tout sans avoir encore rien codé. Sympa non ? :) Silverlight 3 embarque en effet un framework de navigation. Vous pouvez alors modifier les URLs pour masquer le nom des vues et avoir des choses plus explicites comme http://localhost:port/votrepage.aspx#Accueil par exemple. Mais ne nous attarderons pas sur cette notion ici, j’y reviendrais probablement dans un futur billet.

Continuons de jouer avec l’application fournie par défaut et cliquez sur « login » :

RIAImage5

Depuis la mise à jour de Mai 2009 de .NET RIA Services, on vous propose une gestion intégrée de l’authentification des utilisateurs. Cliquez sur « Register now » et créez-vous un utilisateur.

Vous notez alors déjà certaines fonctionnalités sympathiques :

RIAImage6

En effet, une validation coté client Silverlight est proposée grâce à .NET RIA Services après avoir défini la règle coté serveur. L’expérience utilisateur est également relativement agréable. Nous allons voir comment mettre en place cette validation un peu plus loin.

Gestion de la couche d’accès aux données

Récupérez la base de données NorthWind et glissez/déplacez le fichier NORTHWND.MDF dans le dossier « App_Data » de votre projet ASP.NET.

RIAImage7

Ajoutez un nouvel élément à votre projet ASP.NET de type ADO.NET Entity Data Model et nommez le CustomersModel

RIAImage8

Choisissez « Generate from database » et faites « Next » jusqu’à cet écran :

RIAImage9

Cliquez sur la table « Customers » et nommez le modèle « CustomersModel » puis « Finish ».

Un modèle Entity Framework sera donc généré automatiquement pour vous. Considérons qu’il représente votre couche d’accès aux données. Le code généré automatiquement se trouve dans « CustomersModel.Designer.cs ». Avant tout chose, compilez votre solution. Cela est nécessaire pour que le modèle Entity soit visible dans l’étape suivante.

Il faut désormais rendre accessible cette couche d’accès aux données au client Silverlight qui se trouve de l’autre coté du tuyau ou de l’autre coté du nuage.

Pour cela, ajoutez un élément de type « Domain Service Class » à votre projet ASP.NET et nommez le CustomersService.cs

RIAImage10

Cliquez sur « Add », vous arrivez sur cette fenêtre :

RIAImage11

Cochez toutes les cases. Pour faire simple, avant de rentrer un peu plus dans le détail :

- « Enable Client access » permet d’exposer votre logique métier vers le client Silverlight
- « Enable editing » va permettre de générer automatiquement les méthodes pour mettre à jour, ajouter, supprimer des enregistrements.
- « Generate associated classes for metadata » va nous permettre de spécifier des règles de validation coté serveur sur des champs via des attributs. Ces règles seront alors automatiquement répliquées et appliquées coté client comme on a pu le voir avec le contrôle de création d’un utilisateur plus haut. Le fait de cocher cette case va nous prémâcher le travail en générant à nouveau du code pour nous mais on aurait tout à fait pu le faire à la main plus tard.

Le service qui sera exposé au client se trouve alors dans le fichier « CustomersService.cs ». 4 méthodes ont été générées pour nous :

public IQueryable<Customers> GetCustomers()
public void InsertCustomers(Customers customers)
public void UpdateCustomers(Customers currentCustomers, Customers originalCustomers)
public void DeleteCustomers(Customers customers)

Permettant respectivement de récupérer la liste des clients, insérer un nouveau client, mettre à jour et supprimer un client dans la base. Si nous n’avions pas coché la case « Enable editing », nous n’aurions eu que la 1ère méthode. D’ailleurs notez que cette dernière retourne un IQueryable. Nous allons donc pouvoir lancer une requête LINQ coté client pour ne récupérer que les enregistrements qui nous intéressent.

Compilez la solution à nouveau. C’est obligatoire pour que le client Silverlight puisse voir ce service.

Utilisation du service .NET RIA coté client

Rendez-vous dans le projet Silverlight et dans la vue Home.xaml.

Identifiez le contenu du StackPanel et retirer le. Glissez/déposez le contrôle DataGrid dedans et nommez la grille « GrilleClients ». Voici le XAML correspondant au container Grid :

<Grid x:Name="LayoutRoot">

<ScrollViewer x:Name="PageScrollViewer" Style="{StaticResource PageScrollViewerStyle}" >

  <StackPanel x:Name="ContentStackPanel" Style="{StaticResource ContentStackPanelStyle}">

    <TextBlock x:Name="HeaderText" Style="{StaticResource HeaderTextStyle}"

                       Text="Grille Clients"/>

     <data:DataGrid x:Name="GrilleClients"></data:DataGrid>

  </StackPanel>

</ScrollViewer>

</Grid>

Rendez-vous dans le code behind dans Home.xaml.cs et ajoutez ce « using » :

using GestionClientsRIA.Web;

Surprenant n’est ce pas ? On demande à utiliser du code défini sur le serveur d’une certaine manière. Déclarez cette variable membre :

CustomersContext contexte = new CustomersContext();

Cela correspond à la projection coté client de notre service CustomersService présent sur le serveur Web. Ajoutez alors ce code dans le constructeur en dessous de InitializeComponent() :

// On définit la source de données pour le binding

GrilleClients.ItemsSource = contexte.Customers;

// On charge les données depuis le serveur en asynchrone

contexte.Load(contexte.GetCustomersQuery());

On précise l’entité à associer à la grille (on aurait pu en effet choisir plusieurs tables lors de la conception de notre modèle avec Entity Framework) et on lance le téléchargement des données. Le téléchargement se fait ensuite automatiquement de manière asynchrone et de manière transparente. En effet, vous ne voyez ici aucun abonnement au moindre évènement et la moindre utilisation de délégué. Cette complexité est par défaut masquée. Par contre, ne vous étonnez pas si vous ne voyez pas les données apparaître de suite lorsque vous application Silverlight commence à s’afficher. Il faut en effet attendre que la 2ème phase du chargement asynchrone soit déclenchée pour que les données soit injectées dans la grille.

Allez, lançons l’ensemble pour voir à quoi cela ressemble !

RIAImage12

Et voilà, j’ai déjà l’ensemble des clients de la base dans mon contrôle DataGrid en ayant écrit que 3 lignes de code. Pas mal non ? A noter que vous pouvez déjà cliquer sur les colonnes pour effectuer un tri sur celles-ci et même changer une valeur en cliquant dans l’une des cases. Cependant, la modification ne sera effectuée qu’en mémoire coté client vu que nous n’avons pas encore implémenté la sauvegarde vers la base.

Utilisons un peu de LINQ

Vous noterez que la méthode Load() prend en paramètre une requête.  Pour l’instant, nous avons utilisé une requête retournant l’ensemble des clients. Filtrons un peu plus les données. Pour cela, commencez par ajouter ce using :

using System.Windows.Ria.Data;

 Et chargez désormais les données à l’aide de ces lignes de code :

//Création du filtre à envoyer au serveur

var query = from clients in contexte.GetCustomersQuery()

            where clients.Country.Equals("France")

            select clients;

 

// On charge les données depuis le serveur en asynchrone

contexte.Load(query);

On indique donc que l’on souhaite récupérer uniquement les clients habitant en France. Il est très important de comprendre que cette requête LINQ n’est pas exécutée coté client après avoir récupéré l’ensemble des enregistrements depuis le serveur. Cela n’aurait aucun intérêt et engorgerait le réseau inutilement. Non, cette requête LINQ est sérialisée et envoyée au serveur Web qui effectue lui-même la requête au près du serveur de base de données et le résultat est alors renvoyé du serveur Web vers le client Silverlight ! La plomberie a bien été entièrement masquée et on a traversé les différents tiers sans aucune difficulté.

On peut également filtrer en amont sur le service exposé au client Silverlight. Pour cela, rendez-vous dans « CustomersService.cs » du projet ASP.NET et ajoutez cette méthode :

public IQueryable<Customers> GetCustomersByCountry(string country)

    var customersInThisCountry = 
        from c in this.Context.Customers 
        where c.Country == country 
        select c; 

    return customersInThisCountry;
}

Compilez votre solution. Retournez dans le code du client Silverlight et vous verrez qu’une nouvelle méthode nommée GetCustomersByCountryQuery() est apparue. Remplacez l’appel à GetCustomersQuery() par cette ligne de code :

contexte.Load(contexte.GetCustomersByCountryQuery("France"));

Relancez l’ensemble : on obtient bien le même résultat sauf que cette fois-ci, on expose directement une collection limitée d’enregistrements depuis notre serveur Web. Nous avons donc la liberté de filtrer les informations remontées à chaque tiers.

Explication d’une partie de la magie cachée derrière

J’imagine votre curiosité sur l’implémentation sous-jacente de cette magie. Faisons un parallèle avec des notions déjà connues, prenons l’exemple d’un service Web. Ce dernier expose ses méthodes disponibles à travers un contrat en WSDL et la sérialisation des informations envoyées entre le service et le client consommant les méthodes se fait en SOAP/XML. On peut donc ensuite imaginer écrire un client consommant ce service en écrivant du code soi-même envoyant des requêtes HTTP vers le service Web, gérant soi-même l’encapsulation en XML/SOAP des données, etc. C’est ce que l’on appelle écrire un proxy client. Mais que c’est fastidieux de faire tout cela à la main ! Heureusement, Visual Studio nous propose depuis longtemps de faire simplement un « Add Web Reference » et on lui donne l’URL où se trouve exposé le WSDL. Il se débrouille alors comme un grand pour fabriquer le proxy client. Il ne nous reste plus alors qu’à ajouter le bon « using » coté client et on a l’impression de pouvoir appeler des méthodes en local alors que ces dernières sont bien exécutées de l’autre coté. Productivité et complexité masquée.

On peut tout à fait appliquer cette même idée de génération de proxy client avec .NET RIA Services. Vous définissez un service coté ASP.NET vous permettant de charger des enregistrements, des les mettre à jour. Vous définissez également les règles de validation à appliquer sur les champs des objets associés aux enregistrements. Vous pourriez alors écrire vous-même un client consommant ce service en réécrivant du code pour faire l’appel au service (via WCF) et s’occupant de valider les champs de saisie (duplication du code). Heureusement, .NET RIA Services s’occupe de cela pour vous.

Le début de la magie commence par cet attribut :

[EnableClientAccess()]

Cela va indiquer à Visual Studio d’analyser les méthodes présentes dans votre classe service dérivant dans notre cas de LinqToEntitiesDomainService. Alors où est caché le proxy client résultant coté Silverlight ? Pour le voir, cliquez sur le bouton « Show All Files » sur votre projet Silverlight.

RIAImage13

Un dossier apparaît nommé « Generated_Code » et vous découvrez à l’intérieur un fichier « GestionClientsRIA.Web.g.cs » (.g pour generated). C’est le proxy client ! On y découvre nos différentes méthodes Load notamment et on peut voir dans le constructeur par défaut vers quel type d’URL va se faire la requête HTTP sous-jacente :

public CustomersContext() : 
                base(new HttpDomainClient(new Uri("DataService.axd/GestionClientsRIA-Web-CustomersService/", System.UriKind.Relative))) 
       
        }

Si l’on y ajoute un petit coup de Fiddler pour analyser le trafic réseau et si l’on charge les enregistrements avec cette ligne de code :

contexte.Load(contexte.GetCustomersByCountryQuery("Italy"));

On voit partir cette requête :

#                 Result       Protocol   Host           URL            Body          Caching    Content-Type            Process    Comments                    Custom
17               200             HTTP          127.0.0.1:52878         /ClientBin/DataService.axd/GestionClientsRIA-Web-CustomersService/GetCustomersByCountry?country=Italy 1 194          no-cache  Expires: -1                  text/json; charset=utf-8                    iexplore:6648

Cela ressemble donc méchamment à l’utilisation de REST et JSON derrière. :) Voici d’ailleurs le retour :

{"__type":"DataServiceResult:DomainServices","IsDomainServiceException":false,"Results":[{"__type":"Customers:http://schemas.datacontract.org/2004/07/GestionClientsRIA.Web","Address":"Via Monte Bianco 34","City":"Torino","CompanyName":"Franchi S.p.A.","ContactName":"Paolo Accorti","ContactTitle":"Sales Representative","Country":"Italy","CustomerID":"FRANS","Fax":"011-4988261","Phone":"011-4988260","PostalCode":"10100","Region":null},{"__type":"Customers:http://schemas.datacontract.org/2004/07/GestionClientsRIA.Web","Address":"Via Ludovico il Moro 22","City":"Bergamo","CompanyName":"Magazzini Alimentari Riuniti","ContactName":"Giovanni Rovelli","ContactTitle":"Marketing Manager","Country":"Italy","CustomerID":"MAGAA","Fax":"035-640231","Phone":"035-640230","PostalCode":"24100","Region":null},{"__type":"Customers:http://schemas.datacontract.org/2004/07/GestionClientsRIA.Web","Address":"Strada Provinciale 124","City":"Reggio Emilia","CompanyName":"Reggiani Caseifici","ContactName":"Maurizio Moroni","ContactTitle":"Sales Associate","Country":"Italy","CustomerID":"REGGC","Fax":"0522-556722","Phone":"0522-556721","PostalCode":"42100","Region":null}],"TotalCount":-2,"ResultCount":3}

Grâce à l’utilisation de ces standards, vous pourriez donc tout à fait faire appel au service .NET RIA exposé coté ASP.NET depuis AJAX ou PHP.

Astuce : par défaut Fiddler ne voit pas le trafic sur localhost. Changez alors l’URL pour accéder à votre application Web de http://localhost:port/BusinessApplicationTestPage.aspx#/Home vers http://ipv4.fiddler:port/BusinessApplicationTestPage.aspx#/Home

Nous allons maintenant voir comment utiliser de nouveaux contrôles orientés données de Silverlight 3 et comment spécifier des règles de validation pour améliorer notre application dans ce 3ème billet.

Comment développer des applications d’entreprises orientées données avec Silverlight 3 : introduction à .NET RIA Services (1/4)

Article mis à jour : juillet 2009 pour la sortie de Silverlight 3 RTW et .NET RIA Services Juillet 2009

Selon une étude Gartner de Mai 2005, environ 60% des nouvelles applications utiliseront une technologie RIA d’ici 2010. Aujourd’hui, nous pouvons utiliser différentes technologies pour construire une application RIA comme par exemple AJAX, Flash et Silverlight. Coté AJAX, on atteints déjà en grande partie le maximum de ce que l’on peut faire en terme d’expérience utilisateur à cause des limitations du HTML et des langages de scripts client. En attendant de voir ce que nous fournira HTML5 et CSS3 d’ici quelques années, cela positionne Silverlight comme particulièrement intéressants avec le bon goût d’être disponible de suite. Ainsi, nous allons nous pencher ici sur les nouveautés de Silverlight 3 et plus spécifiquement autour de la simplification de l’écriture d’applications n-tiers orientées données.

Silverlight est une technologie particulièrement intéressante pour rendre la couche cliente d’une application Web efficace et attrayante mais je rencontre malgré tout souvent des développeurs sceptiques sur sa capacité à représenter la couche de présentation d’une application d’entreprise. Pourtant, elle permet de se soustraire de problématiques agaçantes et récurrentes comme la gestion des CSS, du rendu multi-navigateurs, de l’adaptation à la résolution de l’écran, d’animations… sans compter la présence d’un environnement .NET dans le navigateur !

Bref, je ne reviendrais pas sur les avantages d’une technologie comme Silverlight dans un scénario RIA. Cependant, bien que Silverlight 2 constitue un sous-ensemble de WPF (Windows Presentation Foundation) et du .NET Framework 3.5, une grande partie des fonctionnalités de WPF permettant de créer des applications orientées données n’ont pas été portées. En conséquence, certains développeurs ont fait l’impasse sur Silverlight 2 car l’implémentation de l’infrastructure centrée sur les données dans une solution Web leur semblait trop compliquée à mettre en œuvre.

Revenons d’ailleurs rapidement sur la problématique du flux de données dans une application n-tiers sur le Web. Analysons le diagramme suivant récupéré du document Microsoft .NET RIA Services May 2009 Preview :

3573504021

C’est un schéma relativement classique. Nos données sont stockées dans une base de données (Database) comme SQL Server, Oracle, MySQL. Ce serveur pouvant être stocké ou non sur la même machine où se trouve hébergée notre application Web. Pour accéder à nos données depuis notre application, on met en place une couche d’accès aux données (Data Access Layer). Ce travail peut aujourd’hui être simplifié par l’utilisation de technologies comme LINQ to SQL ou Entity Framework. Il faut ensuite implémenter les règles métiers et la logique globale de notre application.

Une fois l’ensemble des ces tâches effectuées, on peut considérer avoir terminé la partie serveur de notre application Web. Si l’on décide de partir sur un frontal client en technologie Silverlight, comment allons-nous exposer cette partie serveur au client ? Jusqu’à présent, cela consistait à l’exposer sous la forme d’un WebService ou d’un service WCF avec l’aide ou non de technologies type REST/ADO.NET Data Services. Ensuite, si l’on souhaitait éviter un aller/retour serveur sur la validation de certaines contraintes (valeurs autorisées dans un formulaire de saisie par exemple), il fallait répliquer une partie du code de validation serveur dans le code du client.

Vous aurez donc compris que ce que l’on gagne à mieux tirer partie de la puissance du poste client avec des technologies RIA comme Silverlight ou même AJAX, on le perds d’un autre coté en complexité avec la plomberie à mettre en place pour faire communiquer le client et le serveur Web.

L’idéal serait donc de faire appel à une technologie ou un framework nous permettant de simplifier ces concepts. En tant que développeur, on ne veut ainsi pas perdre de temps à implémenter la plomberie de communication entre le client et le serveur, de validation coté client (voir réplication) des règles métiers définies coté serveur mais comme d’habitude se concentrer sur l’essentiel.

.NET RIA Services : développez des applications n-tiers sans vous en rendre compte !

.NET RIA Services a exactement pour but de simplifier et de masquer toute cette plomberie nécessaire à la création d’une application Web dite RIA (Rich Internet Application) orientée données. Pour cela, cette technologie fournit un jeu de composants et d’extensions d’ASP.NET facilitant le processus de développement d’une application n-tiers, rendant votre application presque aussi simple à développer que si vous étiez sur un seul tiers (ou 2 tiers si la base de données n’est pas sur le serveur Web). De plus, certains services tels que l’authentification ou la gestion des rôles sont également fournis.

De son coté, Silverlight 3 apporte de nouveaux contrôles et de nouvelles fonctionnalités voués également à simplifier le développement d’applications orientées données comme les nouveaux contrôles de données type DataGrid, de navigation, de validation et de gestion de fenêtres.

La combinaison de ces apports coté serveur à ASP.NET et coté client à Silverlight 3 va donc nous permettre de développer des applications d’entreprise de manière extrêmement simplifiée. Ses concepteurs considèrent ainsi que .NET RIA Services apporte une expérience RAD (Rapid Application Development) au monde RIA. Une productivité bienvenue en ces périodes sombres de fortes contraintes économiques…

Si l’on reprend le diagramme précédent, .NET RIA Services va donc jouer le rôle de glue entre notre serveur (sa couche d’accès aux données et ses règles métiers) et le client Silverlight. Elle va nous permettre de développer dans notre projet Silverlight en nous donnant l’impression d’être physiquement sur le serveur Web. Une expérience de développement particulièrement agréable vous allez voir !

Note : .NET RIA Services va être démontré dans cet article sous l’aspect Silverlight avec l’utilisation d’Entity Framework en tant qu’ORM. Cependant, il est important de noter que .NET RIA Services n’est pas exclusivement lié à Silverlight 3 ou à Entity Framework comme le montre le schéma suivant :

3573504107

Il a donc pour but final de simplifier les problématiques n-tiers dans de multiples scenarios. Aujourd’hui sont supportés de manière native Linq to SQL et Linq to Entity. Vous pouvez déjà vous connecter à des tables de Windows Azure par exemple mais cela nécessitera un peu plus de travail de votre part.

Préparation du poste de développement

Voici les pré-requis pour pouvoir développer une application Silverlight 3 / .NET RIA Services :

1 – Visual Studio 2008 SP1 ou sa déclinaison gratuite Visual Web Developer Express 2008 SP1
2 – Silverlight 3 RTW : le
SDK et les outils pour Visual Studio 2008.
3 -
.NET RIA Services : c’est la version de Juillet 2009 allant bien avec Silverlight 3 RTW

Un clavier, une souris et vos doigts. :)

Note : Visual Studio 2010 Beta 1 supporte bien les projets de type Silverlight 3 Beta mais pas encore .NET RIA Services. Il faudra attendre Visual Studio 2010 Beta 2 pour avoir un support parfait de Silverlight 3 RTW et .NET RIA Services avec un nouveau designer de surface bien plus évolué que celui de VS 2008 pour Silverlight 2. Dans cet article, nous resterons donc sur Visual Studio 2008 SP1.

Un aperçu rapide de .NET RIA Services en vidéo

Avant toute chose, voici un bref aperçu des nouvelles possibilités offertes par .NET RIA Services et Silverlight 3. Un teasing en mode Hello World de .NET RIA en quelques sortes. :) – Double-cliquez sur la vidéo pour la mettre en plein écran –

Rendez-vous maintenant dans le 2ème billet pour découvrir étape par étape comment écrire une petite application RIA de gestion de clients et comprendre un peu mieux comment .NET RIA Services fonctionne.

Réflexions sur l’utilisation de PHP dans le monde Microsoft et sur ses intérêts

Ces derniers temps, il m’arrive souvent d’avoir la chance de pouvoir discuter avec des développeurs de la communauté PHP. En comparant nos 2 univers, on peut voir clairement qu’il y a de bonnes synergies à mettre en place et que les 2 mondes ont beaucoup à apprendre l’un de l’autre en les faisant communiquer.

Il y a plusieurs scénarios intéressants à mon sens. Je vous propose de les revoir ensemble. N’ayant pas encore énormément de recul sur le monde merveilleux du développement PHP, je suis ouvert à toutes les formes de commentaires et de critiques. Dès l’instant qu’elles sont constructives bien sûr!

1 – Vous êtes développeur sur la plateforme LAMP et vous êtes très heureux ainsi. Utilisez nos services grâce aux standards!

3500455163Vous ne souhaitez pas toucher à la moindre lettre de votre éclairage. Genre, la touche W de votre clavier ne vous inspire pas du tout. :) Malgré tout, certains services peuvent être susceptibles de vous intéresser. Prenons par exemple les services Live proposant la possibilité d’authentifier des utilisateurs sur vos sites Web avec leur Live ID. Cela peut clairement avoir un intérêt vu les plus de 600 millions de Live ID présents sur Internet à l’heure actuelle!

Pour cela, le Live Framework pourra vous aider à mettre en place cette intégration. Basé sur les standards du Web, cela ne devrait pas vous poser la moindre difficulté. Vous pourrez alors ensuite accéder aux contacts, accéder à un espace Live Mesh, utiliser Virtual Earth, etc.

Si le sujet vous intéresse, je vous conseille de regarder ces 2 WebCasts (en Anglais):

- PDC09 : “Live Services: Programming Live Services Using Non-Microsoft Technologies” : http://channel9.msdn.com/pdc2008/BB51/ . Vous trouverez également un helper PHP pour le Live Framework ici

- MIX09 : “Running PHP on Microsoft Servers and Services” : http://videos.visitmix.com/MIX09/T21F vers la 43ème minute. Vous verrez comment interagir avec les services Live depuis une application PHP (avec WordPress en l’occurrence).

Les standards sont également intensivement utilisés dans notre plateforme Azure. Vous pourrez ainsi facilement faire appel à des services exposés sous forme de WebServices depuis vos applications PHP. Si ce sujet spécifique vous intéresse, je vous conseille alors cette session d’1h en Français : “Scénarios d'interopérabilité de la plateforme Azure en Java, Ruby et Cobol” . Les principes exposés étant les mêmes pour un accès depuis PHP.

2 – Vous souhaitez développer sur Windows mais déployer sous Linux

Pour quelles raisons? Parce vous trouvez plus agréable une machine sous Windows pour travailler et développer. Pourquoi pas, ce n’est pas moi qui vous dirais le contraire ! :)3501270832

Dans ces cas là, je vous invite alors à regarder la solution WAMP suivante : http://www.wampserver.com/ et à lire le blog suivant très intéressant : http://blog.wampserver.com/ animé par Romain BOURDON.

Voici un bref descriptif issu du site: “WampServer est une plate-forme de développement Web sous Windows. Il vous permet de développer des applications Web dynamiques à l'aide du serveur Apache2, du langage de scripts PHP et d'une base de données MySQL. Il possède également PHPMyAdmin et SQLite Manager pour gérer plus facilement vos bases de données.

3 – Vous souhaitez porter ou écrire votre application PHP de Linux/Apache vers Windows/IIS (avec FastCGI).

J’ai en effet constaté que les développeurs LAMP développent souvent sous Windows (avec WAMP donc) et publient ensuite sous Linux. Il serait donc peut-être plus intéressant d’avoir un ensemble cohérent avec une station de développement sous Windows et le serveur Web également sous Windows. De plus, il arrive également que certaines demandes clientes imposent l’utilisation de serveur Windows pour le déploiement des solutions PHP.

Par ailleurs, cela vous permet alors d’héberger des applications ASP.NET et PHP sur le même serveur grâce à l’utilisation du couple Windows/IIS. Simplification des problématiques d’administration donc.

A noter: qui à passer sous Windows, il me semble qu’il faut mieux passer sous IIS/FastCGI. Les raisons sont assez simples: Apache vient du monde Unix et lève par défaut un processus par demande (même si cela peut-être changé depuis la version 2 avec le module mpm_winnt_module). Pour des choix d’architecture, Windows est nettement moins à l’aise avec la création de nombreux processus par rapport à une base Unix. Mieux vaut donc partir sur le serveur Web IIS (Internet Information Server) prévu pour tirer le maximum de l’architecture de Windows et présent par défaut. D’autre part, sauf erreur de ma part, WAMP n’est pas actuellement supporté en production.

Pour vous aider à développer du PHP sur Windows, il est important de noter que nous avons sorti une série de kit de formation autour de ce sujet téléchargeable ici : “PHP on Windows Training Kit (April 2009)” : http://go.microsoft.com/?linkid=9656081

A l’intérieur de ce kit PHP, voici les ateliers susceptibles de vous intéresser:

Utilisation des fonctionnalités de contrôle d’accès d’IIS 7.0 pour PHP

3501271108

Cet exercice vous introduit l’utilisation des fonctionnalités de contrôle d’accès d’IIS 7.0. Cela vous permet alors de créer une gestion des accès flexible et facile à administrer.

Ainsi, contrairement au passé avec CGI, IIS 7.0 et FastCGI permettent à PHP d’avoir un modèle d’exécution simplifiant l’administration de la sécurité. Dans ce nouveau modèle, les scripts PHP peuvent être exécutés en utilisant l’identité de “l’application pool” à laquelle l’application est rattachée.

Utilisation des fonctionnalités média d’IIS 7.0 au sein d’une application PHP

3500455587

Vous verrez ici l’utilisation des fonctionnalités Media d’IIS 7.0. Cela vous permettra de construire rapidement une application PHP pour proposer une solution Web de diffusion vidéo en utilisant les fonctionnalités proposées par défaut d’IIS 7.0 et de réduire les coûts de diffusion média en contrôlant la bande passante.

Vous verrez également comment embarquer un player de vidéos en Silverlight 2 dans votre page PHP

Comment débugger du PHP sur IIS

3500455659

Cette partie explique brièvement les problèmes classiques que l’on rencontre lorsque l’on installe PHP sur IIS 7.0. Vous y trouverez ainsi une illustration des techniques de “troubleshooting” (débogage) pouvant être mise en œuvre pour diagnostiquer et résoudre des problèmes PHP sous IIS 7.0.

Une fois maitrisées, ces techniques peuvent réduire de manière significative le temps passé à débugger son application pendant le cycle de développement ainsi que lors de la mise en production.

Comment migrer une application PHP vers IIS 7.0

3500455737

Vous verrez ici la stratégie typique de migration d’une application PHP vers IIS 7.0 Vous verrez ainsi que le support de PHP d’IIS 7.0 est très compatible avec l’existant et dans la plupart des cas ne requiert pas de modifications spécifiques pour passer d’Apache vers IIS 7.0/FastCGI.

Par ailleurs, un des points bloquants historique et connu a toujours été le module Apache de réécriture d’URLs mod_rewrite. IIS 7.0 propose désormais le module “URL Rewrite” permettant de formater les URLs pour une meilleure indexation par les moteurs de recherches par exemple.

Pour terminer sur cette partie, un des bénéfices induit par le travail de migration d’une application PHP de Linux/Apache vers Windows/IIS/FastCGI est l’ouverture vers le Cloud. En effet, vous vous ouvrez alors facilement le portage vers notre plateforme d’hébergement et d’exécution dans le Cloud : Windows Azure. Si ce sujet vous intéresse, mon collègue Pierre Lagarde vous indique la marche à suivre pour publier une application PHP dans Windows Azure à travers ces 2 billets:

- “Support de Fast-CGI dans l’hébergement Windows Azure” : http://blogs.msdn.com/pierlag/archive/2009/03/20/support-de-fast-cgi-dans-l-h-bergement-windows-azure.aspx

- “Solution Azure Php (Exemple)” : http://blogs.msdn.com/pierlag/archive/2009/03/30/solution-azure-kphp-exemple.aspx

La session indiquée plus haut du MIX09 : “Running PHP on Microsoft Servers and Services” vous intéressera alors également.

4 – Vous souhaitez bénéficier de services dans vos applications PHP non disponibles dans MySQL

Rien ne vous empêche dès lors de faire appel à SQL Server 2008 depuis PHP.

A noter: notre équivalent gratuit à MySQL se nomme SQL Server 2008 Express. Vous pouvez donc le télécharger gratuitement ici : Sql Express 2008 . Ce dernier bénéfice bien par exemple des nouveaux types spatiaux même dans sa version gratuite.

Dans le kit présenté plus haut, voici la série qui pourra vous intéresser :

Démos

Démo avec les nouveaux types pour la géo-localisation

3500455823

Cette démo a pour but de vous présenter les capacités spatiales de SQL Server 2008 intégrée dans PHP.

Cette application se repose ainsi sur SQL Server pour le stockage et les calculs sur les types de données géo-spatiaux pour ensuite passer la main à Virtual Earth afin de rendre les figures sur une carte.

3501270968

Démo de rapports avec SQL Server Reporting Services

3501271554

Cette démo a pour but de vous montrer les fonctionnalités de “reporting” de SQL Server 2008 au sein d’une application PHP. Cette application s’appuie ainsi sur SQL Server Reporting Services (le service de génération de rapports intégré à SQL Server) pour générer et exposer des rapports personnalisés. 

Ateliers

Introduction à l’utilisation de SQL Server depuis PHP 

3500455999 A travers cet atelier, vous apprendrez à effectuer les opérations classiques d’accès aux données (Création, Lecture, Mise à jour, Suppression) vers SQL Server depuis des scripts PHP tournant sous IIS 7. Vous verrez ainsi les étapes à suivre pour vous connecter à la base de données et comment effectuer ces opérations au sein d’une transaction. 

Utilisation des fonctionnalités de recherche de texte libre et des BLOBs depuis PHP grâce à SQL Server  

3501271702

A travers cet atelier, vous apprendrez à tirer partie des fonctionnalités de recherches de texte libre (Full-Text Search) et gestion de “Filestream” (flux de données) depuis votre application Web PHP.

Vous utiliserez ainsi des scripts PHP pour effectuer des recherches plein texte sur des documents stockés sous la forme de BLOBs (binary large objects data).

Les requêtes de type texte libre effectuent des recherches linguistiques sur des données de type texte en travaillant sur des mots et des phrases à travers des règles spécifiques à chaque langage comme le Français ou le Japonais par exemple. Pour chacun des langages supportés, SQL Server fournit des composants linguistiques spécifiques. Vous pouvez même éventuellement rechercher des synonymes.

Ressources complémentaires 

Comment accéder aux bases de données SQL Server depuis PHP

3500456221

Le driver Microsoft SQL Server pour PHP permet aux développeurs PHP d’accéder aux données d’une base SQL Server 2005 ou SQL Server 2008. Ce driver inclut le support des méthodes d’authentification Windows et SQL, les transactions, l’accès aux métadonnées, la gestion d’erreur, le pooling de connections, etc. Cet article explique comment charger et configurer le driver et présente comment tirer partie de plusieurs des fonctionnalités mentionnées avant. Cet article peut être consulté en ligne directement ici : http://msdn.microsoft.com/en-us/library/cc793139(SQL.90).aspx

5 – Notre outil de développement Visual Studio 2008 grâce à VS.PHP

dd647545.php-atelier-01(fr-fr,MSDN.10)[1] S’il y a bien une chose qui m’ait marqué ces derniers temps en côtoyant les développeurs PHP, c’est la multitude d’outils utilisés rarement bien intégrés les uns aux autres. Par ailleurs, certaines fonctions qui me paraissent aujourd’hui vitales ne sont pas toujours de la partie. C’est le cas de la complétion automatique nommée IntelliSense chez Microsoft ou alors également du debugging facile de son application.

De même, l’intégration continue, la gestion de tests unitaires ou de tests de montée en charge d’application Web sont des fonctionnalités intégrées de facto dans les versions Team de Visual Studio par exemple. Ce n’est pas toujours évident de mettre tout cela en place avec les outils gratuits pour gérer du PHP. Le couplage de Visual Studio avec TFS (Team Foundation Server) permet une gestion avancée du code source. On retrouve aussi des choses comme la génération de build basée sur des critères de qualité (build si uniquement couverture >80% des tests par exemple).

Pour être honnête, s’il y a bien quelque chose sur lequel on me titille jamais à la concurrence, c’est bien notre outil de développement Visual Studio.

Note: A ma grande surprise, j’ai actuellement rencontré peu de personnes développant avec Eclipse pour faire du PHP. Si j’ai rencontré le mauvais échantillon, n’hésitez pas à venir vers moi me vanter les mérites d’Eclipse pour faire du PHP! A mon sens, c’est en effet l’outil de développement qui fait clairement face à Visual Studio dans ma tête.

Alors je sais: chez Microsoft nos outils de développement ne sont pas gratuits (encore que… voir la gamme gratuite Express). Mais cela peut valoir le coup je pense de se poser la question: ne vaut-il mieux parfois investir dans ces outils plutôt que de galérer à mettre en place une 12aine d’outils gratuits finalement plus complexes à maitriser ? C’est un vaste débat que l’on ne pourra pas couvrir en quelques lignes ici…

dd647546.clip_image002(fr-fr,MSDN.10)[1]Malgré tout, vous devriez jeter un coup d’œil au plug-in VS.PHP de la société JCX Software permettant le support de PHP directement au sein de Visual Studio. A vous le support abouti de l’IntelliSense, des points d’arrêt pour le debugging facile et de la gestion du source code par TFS !

Pour en savoir davantage, je vous conseille 2 pointeurs:

1 – la vidéo de notre plénière des TechDays 2009 (Plénière Jour 1) où mon collègue Pierre Lagarde vous faisait une démonstration du produit en action. C’est l’une des 1ères démonstrations.

2 – le coach MSDN VS.PHP : http://msdn.microsoft.com/fr-fr/vstudio/msdn.coach.vsphp.aspx où retrouverez un atelier accompagné d’une vidéo pour apprendre à maitriser l’ensemble.

Une offre commerciale sur VS.PHP en cours

Si cet outil vous intéresse, sachez qu’il existe actuellement une offre commerciale en cours. Voici comment cela se présente. La société STR propose la vente de ce plug-in en France: http://www.str.fr/

Le produit VS.PHP coute environ 100€ mais son achat ouvre le droit à la “competitive upgrade” vous permettant d’acheter la référence suivante:

Visual Studio Professional / Visual Studio Pro 2008 Win32 French UPG DVD / Developer Tools / C5E-00253
Prix constaté : ~630€

Au lieu de cette référence classique:

Visual Studio Professional /  Visual Studio Pro 2008 Win32 French DVD / Developer Tools / C5E-00251
Prix constaté : ~920€

Soit VS+PHP à environ 730€ au lieu de VS nu à environ 920€ (attention, ce sont des prix en boite. Les prix en volume sont clairement inférieurs). Par ailleurs, ce sont des prix constatés sans aucun engagement de ma part. Contactez directement le revendeur pour avoir plus de détails si besoin.

Conclusion

Je pense que vous aurez compris que Microsoft ne prends pas à la légère la communauté PHP et l’immense expertise des développeurs PHP sur le marché. D’après ma brève expérience, ils existent de nombreux profiles différents de développeurs PHP, utilisant des framework différents, des outils différents, des méthodologies différentes avec des niveaux techniques différents. On retrouve en effet des développeurs “formés sur le tas” ou des passionnés faisant intensivement usage du copier/coller de code aux développeurs chevronnés adeptes du pattern MVC, de l’intégration continue, mettant en place de vrais projets industriels. On partage donc à ce niveau là une histoire commune! Dans la communauté du développement Microsoft, on passe également facilement du développeur de macros VBA formé sur le tas aux développeurs Web ASP.NET MVC adeptes du TDD (Test Driven Development), j’en passe et des meilleurs. Bref, il existe une mixité de profiles et de talents dans les 2 communautés. Pourquoi ne pas mixer l’ensemble un peu plus? :-)

Cependant, il serait mal venu de tenter de résumer l’intérêt que pourrait avoir le monde PHP à travailler avec des technologies Microsoft à travers ce simple billet. Il y a par exemple d’autres scénarios non encore traités qui sont également très intéressants comme l’utilisation de Silverlight 3 comme couche de présentation frontale à votre site Web PHP. J’espère que nous aurons l’occasion d’en rediscuter prochainement.

J’espère cependant avoir abordé certains sujets ayant attisé votre curiosité. J’attends maintenant vos retours!

A bientôt.

David

More Posts Next page »
Page view tracker