Industrialiser le développement avec Silverlight 4 et RIA Services http://blog.jeanlucboucho.com/ Mercredi 9 Février Jean-Luc Boucho Architecte Solutions Winwise Arnaud Auroux Consultant Access it IDF
L’expert de référence ! Société d’expertise sur les technologies Microsoft Partenaire historique et stratégique de Microsoft Plus de 90 collaborateurs certifiés interviennent sur des missions à forte valeur ajoutée : Missions d’expertise Conseil & Audit Réalisation de projets à engagement de résultats Une offre couvrant l’ensemble du cycle de vie des applications : Travail collaboratif, portail d’entreprise et Workflow Business Intelligence & Data Management Interfaces utilisateurs, Rich Internet Application & desktop application Architecture d’entreprise et Architecture Life cycle Management Infrastructure, Sécurité et Réseaux Centre de formation et de Certification Microsoft WINWISE est le pôle d’expertise MICROSOFT du Groupe ALTEN et bénéficie de la puissance financière d’un leader incontesté WINWISE 130/136 Rue de Silly 92100 Boulogne-Billancourt www.winwise.com
Access It IdF en quelques mots… Société de services, conseil / expertise, et formation, exclusivement sur les technologies Microsoft 20+ collaborateurs spécialisés sur les techno MS, dont 11 MVP Interventions en mode : Conseil, expertise, coaching et formation Réalisation, au forfait ou en Assistance Technique .NET Plateforme Applicative Framework et langages .Net, AZURE, Silverlight, WPF/Surface, VS/TFS, Windows Phone 7,… SQL Server (SSIS, SQL, SSAS, SSRS), PowerPivot, SharePoint & on-line, Office 365,… Collab. BI
Agenda Présentation Industrialisation WCF RIA Services Développement rapide d’applications Industrialisation Patterns Persistance, Domaine, Opérations Approche MVVM Authentification et autorisation Testabilité Rappeler les fonctionnalités de RIA Services Découvrir le potentiel d’extensibilité Industrialiser une solution RIA Services
Couche de présentation Couche d’accès aux données Problématiques RIA Application cliente Service Couche de présentation Couche métier Couche métier Couche d’accès aux données Base de données Coût de mise en place important Autorisations Accès concurrentiels Duplication de la logique métier
Couche de présentation Couche d’accès aux données WCF RIA Services Simplifier la communication afin que le métier devienne le centre d’intérêt. RIA Couche de présentation Couche métier Couche d’accès aux données Base de données Notion de domaine : opérations + entités + validations Côté client Contrôles spécifiques Contexte de donnée « Tracking » d’objets Côté serveur WCF Validations Accès aux données Sécurité
Démo WCF RIA Services Démo lecture / édition, 0 code.
Développement rapide d’applications Serveur Création du modèle d’entité Création du Domain Service Création des requêtes Ajout des métadonnées Client Utilisation du DomainContext Utilisation des requêtes générées DataBinding SubmitChanges Dépendance à la technologie de persistance des données Rigidité de la structure
Industrialisation « Déployer des pratiques pour améliorer la productivité et la robustesse des applications tout en restant dans des délais et des coûts maîtrisés » Séparer les responsabilités
Patterns d’industrialisation Repository Unit Of Work Dependency Injection MVVM (Model View View-Model) Unit Testing …et aussi : AOP (Aspect-Oriented Programming) Pattern Repository But : agir comme intermédiaire entre le domaine et la couche de persistance Mise en œuvre : un repository par domaine, générique et extensible Pattern Unit Of Work But : gérer une liste d’objets affectés par une transaction métier, leur persistance et les problèmes de concurrence Mise en œuvre : exploiter l’extensibilité du DomainService protected virtual bool PersistChangeSet(); Pattern Dependency Injection But : Mécanisme d’injection d’objet permettant de séparer la création de l’objet du lieu de son utilisation. Il existe trois types d’injection : via le constructeur, via un champ/propriété, via une interface Mise en œuvre : Framework Unity Injecter le service de domaine dans RIA Services Côté client Injecté le contexte RIA dans les services applicatifs Pattern : Unit Testing But : améliorer la qualité du code en écrivant un test par fonctionnalité Mise en œuvre : Microsoft Visual Studio Unit Testing Unit Test for Silverlight (Silverlight toolkit) Pattern MVVM But : Séparer l’interface, la logique métier et les données La view définit le layout, elle consomme les données et opérations exposées par le ViewModel. Le ViewModel référence les données (Model). Unit Test for Silverlight (Silverlight toolkit…?) AOP (Aspect-Oriented Programming) Déjà utilisé par RIA Services pour : La sécurité, la validation, … Les opérations du service de domaine, …
Industrialiser la persistance Principes Isoler la persistance dans un repository pour la découpler du service de domaine Accès au repository via une interface IRepository Générique, supportant les opérations CRUD standards pour accélérer le développement Extensible, pour définir des opérations spécifiques supplémentaires Un repository : LinqToEntitiesRepository<TContext> pour supporter EntityFramework (TContext correspond au modèle) Domaine IRepository Implémentation de la persistance (LinqToEntities…) Data Source Entité Métier
Industrialiser la persistance IRepository, LinqToEntitiesRepository<TContext> new LinqToEntitiesRepository<NorthwindEntities>();
Industrialiser la persistance Démo Industrialiser la persistance Comparatif avec RAD et Repository Evoquer POCO
Industrialiser le domaine Principes Définir une classe de base : RepositoryDomainService pour Accéder au IRepository depuis le domaine Bénéficier des opérations standard (CRUD) Valider les lots de modifications (Transaction) Redéfinir si nécessaire les opérations dans le domaine Présentation Domaine Repository Entité Métier Entité Métier
Industrialiser le domaine RepositoryDomainService
Industrialiser le domaine NorthwindService EntityDomainServiceDescriptionProvider : description du modèle EntityDomain : opérations CRUD autorisées pour chaque entité IRepository : persistance du modèle [EnableClientAccess()] [EntityDomainServiceDescriptionProvider(typeof(NorthwindEntities))] [EntityDomain(typeof(Customers), EntityDomainOperations.All)] [EntityDomain(typeof(Regions), EntityDomainOperations.Query)] ... public class NorthwindService : RepositoryDomainService { public void DeleteCustomers(Customers customer) base.Repository.Delete<Customers>(customer); }
Industrialiser le domaine Instanciation du service de domaine Par défaut, le service est instanciée par RIA Services C’est insuffisant : il faut configurer le repository à utiliser Solution : Extensibilité du DomainServiceFactory Unity pour injecter le service de domaine dans RIA Services
Industrialiser le domaine Application Web Northwind (Global.asax.cs) protected void Application_Start(object sender, EventArgs e) { UnityHelper.UnityContainer.RegisterType<NorthwindService>( new InjectionProperty("Repository", typeof(LinqToEntitiesRepository<NorthwindEntities>))); DomainService.Factory = new DomainServiceFactory(); } DomainServiceFactory public class DomainServiceFactory : IDomainServiceFactory { public DomainService CreateDomainService( Type domainServiceType, DomainServiceContext context) DomainService domainService = UnityHelper.UnityContainer .Resolve(domainServiceType) as DomainService; domainService.Initialize(context); return domainService; }
Industrialiser le domaine Démo Industrialiser le domaine
Gestion des opérations A l’initialisation, RIA Services : Identifie les services de domaine en inspectant les types possédant l’attribut DomainServiceDescriptionProviderAttribute Appelle la méthode CreateProvider() sur l’attribut pour obtenir un fournisseur de description du service, de type : DomainServiceDescriptionProvider Appelle la méthode CreateDescription() sur le fournisseur pour obtenir la description du service, de type DomainServiceDescription Récupère les informations de la description : Les entités du modèle, de type Type Les opérations, de type DomainOperationEntry Rend accessible en WCF les opérations et entités
Gestion des opérations RIA Services possède un très bon niveau d’extensibilité, les classes : DomainServiceDescriptionProviderAttribute DomainServiceDescriptionProvider DomainOperationEntry … sont destinées à être héritées ! RIA Services possède sa propre représentation du modèle et des opérations du domaine, cette indépendance permet tout type d’implémentation Nous avons exploité cette extensibilité pour adapter l’implémentation EntityFramework de Microsoft en ajoutant le support du repository Implémentation EntityFramework
Gestion des opérations Démo Gestion des opérations
Du service vers le client DomainService DescriptionProvider GetDescription … Invocation des opérations DomaineContext.Load(EntityQuery) DomaineContext.SubmitChanges DomainService Description GetInvokeOperation … Génération du contexte client … public sealed partial class NorthwindContext : DomainContext { }
Approche MVVM VIEW VIEWMODEL MODEL Controls Layout Actions Triggers DataBindings VIEWMODEL Commandes Opérations Propriétés MODEL Données Règles métier
Approche MVVM RIA Services 1.0 VIEW Controls Layout Actions Triggers DataBindings VIEWMODEL Commandes Opérations DOMAINSERVICE DomainOperations DomainContext EntitySets MODEL Entités Validateurs Proxy généré
Approche MVVM SP1 beta VIEW VIEWMODEL DataService DOMAIN SERVICE MODEL Controls Layout Actions Triggers DataBindings VIEWMODEL Commandes Opérations Propriétés DataService GetData PersitData EntityList DOMAIN SERVICE DomainContext EntitySets MODEL Entités Validateurs Proxy généré
Démo Approche MVVM
Sécurité - Serveur Classe AuthenticationBase et attribut RequireAuthentication Attribut RequireRole Infrastructure ASP.NET Intégration au processus « Query / Submit »
Sécurité - Serveur RIA Services fournit un service remplissant toutes les fonctionnalités d’authentification Le paramétrage de la sécurité s’effectue de manière classique dans le fichier Web.config [EnableClientAccess] public class AuthenticationService : AuthenticationBase<User> { } <roleManager enabled="true" /> <authentication mode="Forms" > <forms name=".SimpleRIA_ASPXAUTH" /> </authentication> ...
Sécurité - Serveur Pour les opérations implémentées dans le domaine par codage, utiliser les attributs RIA Services : Pour les opérations CRUD standards, utiliser l’attribut EntityDomainAttribute : [RequiresAuthentication] [RequiresRole("Admin")] [EntityDomain(typeof(Customers), Operations = EntityDomainOperations.All, RequiresAuthentication = EntityDomainOperations.All, QueryRequiresRole = new []{"StdUser"}, InsertRequiresRole = new []{"Admin"}, UpdateRequiresRole = new []{"Admin"}, DeleteRequiresRole = new []{"Admin"}) ]
Sécurité - Client Classe WebAuthenticationService Point d’entrée du processus d’authentification. Classe FormsAuthentication et WindowsAuthentication Processus d’authentification spécialisés. Classe AuthenticationDomainContextBase Accès client au service d’authentification. Interfaces IIdentity et IPrincipal Visibility, pattern ICommand WebContextBase : contexte de l’application WebAuthenticationService : contient une référence vers le DomainContext d’authentification AuthenticationDomainContextBase : classe de base des fournisseurs d’authenfication
Sécurité - Client Utilisation dans un ViewModel Propriété public bool CanDeleteCustomer { get { return this.DomainAuthService .CanDeleteCustomer; } } Command (CanExecute) ICommand deleteCustomerCommand = new RelayCommand<Customer>( this.DeleteCustomer, c => this.CanDeleteCustomer )); Service dédié public class DomainAuthService { public bool CanDeleteCustomer { get { return WebContext.Current.User.IsInRole("Admin"); } } } Forte dépendance aux règles définies côté serveur
Sécurité - Client Inclure au contexte les règles définies côté service CodeGeneratorTextTemplate (toolkit sp1) [DomainServiceClientCodeGenerator(typeof(CodeGenerator), "C#")] public class CodeGenerator : CSharpClientCodeGenerator { protected override DomainContextGenerator DomainContextGenerator { get { return new AuthorizationCodeGenerator(); } } } Génération personnalisée du DomainContext client Les restrictions clientes sont souvent dirigées par les règles définies sur les opérations côté service. Gestion déclarative (pour les cas particuliers) AuthorizationSamples (http://code.msdn.microsoft.com/RiaServices) <Button s:Authorization.RequiresRole="Admin,CustomerManager"/>
Démo Sécurité
Testabilité DomainService Implémentation d’un repository de base pour les tests Définition d’un repository spécifique à chaque contexte. Configuration du conteneur IOC pour l’utilisation du repository spécifique de test.
Testabilité – DomainService Démo Testabilité – DomainService
Testabilité DomainContext Implémentation d’un DomainClient de base pour les tests. Définition d’un DomainClient spécifique à chaque contexte. Configuration du conteneur IOC pour l’utilisation du DomainClient spécifique de test. Ou service wcf de mock local
Testabilité – DomainContext Démo Testabilité – DomainContext
Conclusion RIA Services Adaptée au model RAD. Souple Extensible Donc adaptée aux applications d’entreprise Téléchargez et utilisez notre framework http://rialternative.codeplex.com/ http://rialternative.codeplex.com/
Références Téléchargements http://www.silverlight.net/getstarted/riaservices/ WCF Ria Services Code Gallery http://code.msdn.microsoft.com/RiaServices Kyle McClellan http://blogs.msdn.com/b/kylemc/ Colin Blair http://www.riaservicesblog.net/Blog/ Jeff Handley http://jeffhandley.com/ Brad Abrams http://blogs.msdn.com/b/brada/
MSDN et TechNet : l’essentiel des ressources techniques à portée de clic Portail administration et infrastructure pour informaticiens Portail de ressources technique pour développeurs http://technet.com http://msdn.com