Bienvenue sur notre blog !

MCNEXT devient Infeeny en 2017 !

Retrouvez ici tous les Posts (+ de 600) des consultants et experts du groupe Infeeny (330 collaborateurs, pure player Microsoft).

Vous voulez en savoir plus sur Infeeny ou vous souhaitez nous rejoindre ?
Consultez notre site infeeny.com

Vous pouvez aussi nous suivre sur :
Twitter : @Infeeny_fr – https://twitter.com/Infeeny_fr
LinkedIn : https://www.linkedin.com/company/infeeny
– et vous abonner à notre chaîne YouTube Infeeny !

Architecture d’une application Angular 2+

L’une des nouveautés d’Angular 2 est de pouvoir organiser son application en modules. Cette nouvelle façon d’architecturer l’application est vraiment au cœur d’Angular et il est important de bien comprendre comment ça marche afin de ne pas être perdu !

La déclaration d’un module

Alors comment se déclare un module ?  Il y a de fortes chances que vous sachiez déjà comment en faire un, car une application Angular 2 est un module en soi. Voici un exemple tiré de la documentation officielle pour vous rafraîchir la mémoire :

import { NgModule }      from '@angular/core';

import { BrowserModule } from '@angular/platform-browser';

@NgModule({

imports:      [ BrowserModule ],

providers:    [ Logger ],

declarations: [ AppComponent ],

exports:      [ AppComponent ],

bootstrap:    [ AppComponent ]

})

export class AppModule { }

Cependant si votre application est un peu complexe il est conseillé de séparer votre application en plusieurs modules (« feature-module ») et de faire un module partagé par tous (« Shared Module »).

Définitions

Bootstrap : Définit les composants qui vont être chargés au lancement de l’application. Chaque application doit bootstrapper au moins un « component », en général on le nomme AppComponent. Le tableau « bootsrap » doit être utilisé uniquement dans l’AppModule.

Declarations : Contient les « component », « directive » et « pipe » utilisé dans ce module. Ne doit pas contenir de services, d’autres modules, etc. Ne doit pas contenir de composants déclarés dans un autre module !

Exports : Permet de partager des éléments du module (« component, « directive », « pipe »). On peut aussi réexporter des éléments importés d’autres modules. Un élément déclaré ne peut être qu’utilisé qu’au sein du module où il a été déclaré, sauf si ce module l’exporte.

Imports : Permet d’importer des modules et d’utiliser les éléments exportés par ces modules. Eviter des imports inutiles, c’est relativement couteux ! Et oui, pour utiliser les composants d’une librairie il faudra importer ce module de librairie dans chacun de vos modules qui en ont besoin !

Providers : Permet d’enregistrer des services. A noté que contrairement aux éléments (« component », « directive » et « pipe »), chaque service mis en tant que providers dans NgModule est enregistré à la racine de l’application, il n’est pas encapsulé dans le module où il est déclaré.

Cas concret

En suivant les conseils précédents, on obtient cette architecture :

© Deborah Kurata

 

On peut aussi rajouter un « core module » afin d’enregistrer les différents providers de votre application, ce qui permet de s’assurer qu’on ne « provide » pas plusieurs fois le même service.

Remarques sur les modules « mixtes »

Certains modules comme le RouterModule déclarent à la fois des composants et des services. Ces modules doivent donc être importés différemment dans l’AppModule et les feature-module.

Exemple pour le RouterModule :

AppModule

@NgModule({

imports: [RouterModule.forRoot(ROUTES)]

})

class AppModule{}
FeatureModule

@NgModule({

imports: [RouterModule.forChild(ROUTES)]

})

class FeatureModule{}

 

Lorsque votre application grossit, il est intéressant de ne pas charger tous les composants d’un seul coup mais de les charger à la volée selon la navigation de l’utilisateur ! C’est ce que l’on appelle les modules « lazy-load » que nous verrons plus en détails dans un prochain post 😉

En attendant, j’espère que cet article vous aura permis de mieux comprendre le fonctionnement des modules Angular et comment architecturer son application.

Migration VSTS vers TFS 2015

Récemment j’ai dû effectuer une migration d’un code source situé sur un VSTS vers le TFS 2015 On-Premise du client. C’est un scénario qui n’est pas officiellement supporté par l’outil TFS Integration Platform, mais je n’ai pas rencontré de soucis majeur (j’ai migré uniquement le code source et non les work items).

Pour rappel TFS Integration Platform est un outil développé par l’équipe ALM Rangers qui permet d’effectuer des migrations entre différentes versions de TFS. Les migrations peuvent être interrompues puis reprises. Cependant cet outil n’est plus mis à jour depuis 2012. A noter pour une migration dans le sens inverse, Microsoft a lancé un outil en preview : TFS Database Import Service for Visual Studio Team Services

Prérequis

  • un serveur SQL (SQL Express peut suffire) plus ancien que SQL Server 2014
  • le compte local qui fait tourner l’application doit pouvoir
    • Être administrateur du poste
    • Créer une base de donnée sur le serveur SQL
    • TFS Source : Être membre du groupe « Project Collection Proxy Service Accounts » et avoir des droits de lecture sur le projet
  • Disposer d’un compte pour le VSTS étant membre du groupe « Project Collection Proxy Service Accounts » et avoir des droits de lecture/écriture sur le projet (il peut être différent du compte local)
  • Visual Studio 2012 Pro ou supérieur (Team Explorer 2012 n’est plus disponible en standalone)

Installation

Après avoir double-cliqué sur le .msi, l’écran ci-dessous apparaît. Ici rien de particulier, installer juste le « TFS Integration Tools ».

Vous arrivez ensuite à cet écran où on vous demande la chaîne de connexion SQL, n’oubliez pas qu’à l’installation l’outil va créer une BDD, votre compte doit donc avoir les droits suffisants sur le serveur.

Bravo l’outil est maintenant installé, passons à la création de la migration !

Migration pas à pas

Voici l’écran d’accueil de l’application. La première chose à faire est de cliquer sur « Create New » (colonne de droite).

Avec l’explorateur Windows allez dans le dossier « Team Foundation Server » si ce n’est pas le cas et choisissez « VersionControl.xml ».

Il faut maintenant configurer la migration, veuillez cliquer sur « Configure » et choisir « VC11 Adapter » :

Sélectionner ensuite votre Team Project de source/cible :

Il ne reste plus qu’à lancer la migration et à résoudre les conflits s’il y en a. A noter que vous pouvez très bien mettre en pause la migration ou la finir une première fois, effectuer quelques commits sur la branche source et la relancer. Cela permet une interruption de service plus courte si une équipe est en train de travailler sur le projet durant la migration.

Une dernière petite astuce pour la route, je conseille de faire la migration sur une nouvelle VM que vous « jetterez » après la migration. Cela évite ainsi de polluer son poste de travail avec une vieille version de VS et de se prémunir d’un éventuel redémarrage de son poste de travail alors que la migration est en cours.

La migration est assez longue car vous aurez surement des conflits à résoudre donc je vous conseille de ne pas l’effectuer si vous avez une quantité importante de données.

 

Retour d’expérience SignalR avec load-balancing

Dans cet article je vais parler d’un cas d’utilisation assez avancé de SignalR : faire communiquer plusieurs applications Angular en temps réel via SignalR, chaque application étant load-balancée sur 2 serveurs. Etant donné que c’est un cas avancé, je considère que vous savez déjà comment fonctionne SignalR (si ce n’est pas le cas, il est très facile de trouver des bons tutoriels sur Google).

Architecture

En effet plusieurs applications peuvent communiquer entre elle via SignalR si celles-ci utilisent la même base de données et le même nom pour le hub. Pour un tutoriel sur comment configurer le Scale-Out SQL Server pour SignalR, je vous conseille celui de Microsoft.

Flux du message au sein de l’application

 

 

signalR

Comme vous pouvez le voir avec le schéma ci-dessus, on a décidé de propager le message SignalR au sein de l’application Angular en « broadcastant » un nouveau message. Ceci permet d’avoir une méthode unique pour effectuer la communication entre le serveur (C#) et le client qui ne fait pas intervenir de code métier.

Voici la classe utilisée pour le message :

public class ChannelEvent<T>
{

public string Id { get; private set; }

public string EventName { get; set; }

public string Timestamp { get; private set; } = DateTime.Now.ToString("dd/MM/yyyy HH:mm:ss.fff");

public T Data { get; set; }

public ChannelEvent(string eventName, T data)
{
EventName = eventName;
Data = data;
Id = $"{EventName}:{Guid.NewGuid()}-{Timestamp}";
}

}

Côté client, vu que l’application utilisait Angular, nous avons créé un service pour encapsuler le hub.

Le service : 

import { Injectable, Inject } from "@angular/core";
import { Injectable, Inject } from "@angular/core";
import { Subject } from "rxjs/Subject";
import { Observable } from "rxjs/Observable";
import { Broadcaster } from './BroadCasterService';

@Injectable()export class EventHubService {
   public hubConnection: any;
   private hubProxy: any;
   private lastEventsIds = new Array<string>();

   constructor(    
     @Inject(Broadcaster) private broadcaster: Broadcaster)
  {
    this.hubConnection = window.$.hubConnection(window.location.href);
    this.hubProxy = this.hubConnection.createHubProxy("myHub");
    this.hubConnection.error((error: any) => {
    this.errorSubject.next(error);        });
    this.hubProxy.on("send", (ev: Models.ChannelEvent<any>) =>
    {
       if (this.IsNew(ev)) {
         this.broadcaster.broadcast(ev.EventName, ev.Data);
       }
    });
  }
  /** On évite de publier plusieurs fois le même message côté client. Cela peut arriver si par exemple, une personne est dans plusieurs groupes */
  IsNew(ev: Models.ChannelEvent<any>): boolean {
    if (Enumerable.from(this.lastEventsIds).any(x => x === ev.Id)) {
      return false;
    }
    else {
      this.lastEventsIds.push(ev.Id);
      return true;
    }
  }
}

Le broadcaster : service utilisé dans tout l’application pour faire communiquer les composants entre eux, et utilisé aussi par le service ci-dessus.

@Injectable()
export class Broadcaster {

private _eventBus: Subject<BroadcastEvent>;

constructor() {
 this._eventBus = new Subject<BroadcastEvent>();
 }

broadcast(key: any, data?: any) {
 this._eventBus.next({ key, data });
 }

/**
 * NE PAS OUBLIER DE SE DESINSCRIRE SINON L'INSTANCE RESTE EN MEMOIRE !!
 * @param key
 */
 on<T>(key: any): Observable<T> {

return this._eventBus.asObservable()
 .filter(event => event.key === key)
 .map(event => <T>event.data);
 }
}

interface BroadcastEvent {
 key: any;
 data?: any;
}

A savoir

  • Ne pas hésiter à faire une interface pour tester l’envoi de message et vérifier l’état de la connexion SignalR
  • SQL Server n’est pas viable comme Scale-Out pour SignalR si la contrainte temps réel est forte (le Service Broker peut mettre jusqu’à 3 minutes pour notifier si la charge est très importante)
  • Ne pas créer trop de groupes SignalR (> 1 000 ça ralentit)
  • Faire attention à ce que le load balancer laisse passer les web sockets
  • Prérequis : SQL Server 2005+, Windows Server 2012 / Win8 (iis 8.0)

 

Je pense que ce cas d’utilisation de SignalR, même s’il est complexe peut régulièrement être utilisé en entreprise où un utilisateur doit jongler entre plusieurs applications. Cela lui évite de devoir attendre et de rafraîchir la page manuellement, ou d’être automatiquement prévenu qu’un collègue est déjà en train d’éditer cet objet (contrat, client..).

SCCM – Un didacticiel vidéo sur les mises à jour

Windows 10 a apporté un changement dans la façon dont les mises à jour sont publiées par Microsoft, les mises à jour sont maintenant cumulatives. Depuis la sortie de Windows 10, cette approche de mise à jour cumulative a été proposée pour les autres systèmes d’exploitation. Mais pour beaucoup, il reste encore une certaine confusion autour de ce nouveau mode de patch.

Lire la suite

Windows 10 1709 – problème avec le paramètre BitLocker/DMA

Si vous avez déployé la security baseline de Microsoft pour Windows 10 v1709, vous pouvez avoir subi des défaillances de périphériques et de composants. En effet, les paramètres d’objet de stratégie de groupe BitLocker recommandés dans la security baseline pour Windows 10 incluent l’activation de «Disable new DMA devices when this computer is locked» pour se défendre contre les attaques Direct Memory Access (DMA).

Lire la suite