Le Post de MCNEXT

Les articles des consultants de MCNEXT

Les petites astuces du langage Javascript

Javascript est un langage qui avait été initialement conçu pour permettre de rendre les pages web un peu plus dynamiques, mais à l’époque de sa conception personne n’aurait imaginé qu’il pourrait prendre un jour une place aussi prépondérante dans la conception des applications web.

Alors que la nouvelle norme ECMAScript 5 commence à être doucement implémentée par les différents navigateurs du marché, certains développeurs ont su faire preuve de beaucoup d’astuce pour permettre à ce langage de donner le meilleur de lui-même.

Déterminer si une année donnée est bissextile

Aucune méthode n’est prévue nativement en Javascript pour permettre de déterminer si une année donnée est bissextile. Mais en s’appuyant sur le comportement par défaut des moteurs Javascript inclus dans les différents navigateurs, il est possible d’obtenir cette information.

function isLeapYear(year) {
    return new Date(year, 1, 29).getMonth() === 1;
}

L’astuce consiste tout simplement à créer une nouvelle date, correspondant au 29 février de l’année que l’on souhaite tester. Notez qu’en Javascript, le numéro de mois est en base 0; le mois de février correspond donc au chiffre 1.

Ce qu’il se passe, c’est que si l’année passée au constructeur de l’objet Date n’est pas bissextile, la date retournée ne sera pas le 29 février… mais le 1er mars. Il ne reste donc qu’à tester si le mois de cette date est bien toujours février, ou si celui-ci s’est miraculeusement transformé en mars.

Obtenir la plus petite ou la plus grande valeur contenue dans un tableau

Prenons le tableau suivant :

var numbers = [ 4, 8, 15, 16, 23, 42 ];

Par défaut, le langage Javascript ne contient aucune méthode particulière permettant de déterminer la plus petite valeur contenue par ce tableau. Par contre, il existe dans l’objet Math une méthode min() permettant de déterminer qu’elle est la plus petite valeur parmi toutes celles passées en paramètre. Il serait donc tentant d’essayer de brancher les deux ensembles, et c’est possible, grâce à la méthode spéciale apply().

Array.min = function(array) {
    return Math.min.apply(Math, array);
};

La méthode apply() permet d’exécuter une méthode en lui passant seulement deux paramètres. Le premier correspond au contexte d’exécution (le mot clef this dans le corps de la méthode), mais ici nous ne souhaitons pas le modifier et nous contentons donc de passer l’objet Math lui-même. Le second paramètre est celui qui nous intéresse. Il permet de passer les paramètres de la méthode non pas les uns après les autres mais regroupés dans un tableau. Or c’est justement d’un tableau de nombres dont nous disposons et que nous souhaitons tester.

Grâce à ce mécanisme, il est alors facile d’ajouter une nouvelle méthode min() à l’objet Array, et de brancher celle-ci à la méthode Math.min(). L’opération devient alors un jeu d’enfant :

var smallestNumber = Array.min(numbers); // 4

Vous pourriez arguer qu’il n’est pas beaucoup plus difficile d’écrire soi-même un algorithme pour boucler sur ces nombres et trouver lequel est le plus petit. Mais en utilisant une méthode incluse nativement dans le moteur Javascript, nous bénéficions d’une amélioration des performances, ce qui sur de très grands tableaux peut s’avérer décisif.

Je vous laisse deviner vous-même comment permettre le calcul de la plus grande valeur contenue dans un tableau.

Créer son propre opérateur de coalescence sur null

Javascript est un langage extrêmement souple, et un nouvel exemple de cette souplesse tient dans le fait que l’opérateur de comparaison OR (noté “||”) est capable d’avoir une influence sur l’assignation d’une variable. Voyons plutôt un exemple :

var nullVariable = null;
var anotherVariable = nullVariable || 12;

La variable nullVariable contient la valeur null. Nous tentons d’assigner cette valeur à une autre variable. Mais notez l’utilisation de l’opérateur OR. Grâce à lui, si la variable source a une valeur booléenne correspondant à false – ce qui est le cas pour le mot-clef null – c’est la valeur de l’opérateur de droite qui sera assignée. Dans notre exemple, la variable anotherVariable se verra donc assigner la valeur 12.

Ce mécanisme, très pratique au demeurant, correspond peu ou prou à l’opérateur ?? en C#. Attention néanmoins, car le test des valeurs booléennes en Javascript obéit parfois à des règles quelque peu abstraites. Par exemple le test du chiffre 0 renvoie false, alors que tout autre nombre – même négatif – renverra true.

Les barrières mentales du développeur junior

Quand on débute dans la programmation, on est souvent victime de son manque d’expérience. Par exemple, on est rarement conscient au départ de la pléthore d’outils qui s’offre à nous. J’ai ainsi souvenir d’avoir codé à mes débuts une fonction permettant de calculer la date de la veille, avant de découvrir quelques semaines plus tard que le Framework .NET propose une fonction toute faite pour cela (DateTime.AddDays(), à laquelle il suffit de passer un nombre négatif pour retrancher des jours).

Mais il y a aussi un certain nombre d’idées préconçues et de mythes auxquels il est bon de tordre le cou si l’on veut progresser rapidement. Nous allons ici en examiner quelques-uns.

Ce n’est pas parce qu’un code est long qu’il est lent

Le développeur junior a tendance à croire que plus les lignes de code s’empilent, et plus son application va prendre de temps pour s’exécuter. Cela paraît logique de prime d’abord, mais il faut toutefois nettement relativiser cette affirmation.

Tout d’abord, il faut parvenir à se mettre en tête que plusieurs milliers de lignes de code peuvent tout à fait s’exécuter en quelques millisecondes. Certains se sont amusés à mesurer que sur un ordinateur actuel, il est possible d’initialiser en l’espace d’une seule seconde plusieurs millions d’objets.

En réalité, les performances d’un programme sont liées d’une part à la manière dont celui-ci a été conçu, et d’autre part à quels types d’opérations celui-ci est dévolu. Il est évident qu’un programme qui en l’espace de quelques lignes de code effectue plusieurs opérations d’input/output (comme lire un fichier, ou requêter une base de données) sera plus lent qu’un autre qui se contente de manipuler des types primitifs.

Croire que la quantité de lignes de code tapée est directement corrélée à la vitesse d’exécution d’un programme est donc faux, et le programmeur débutant doit apprendre à se concentrer sur la qualité du code, et non sur la quantité, car c’est cette qualité et la manière dont le programme est conçu qui vont réellement influencer ses performances.

Rajouter des niveaux d’indirection se fait généralement au bénéfice du code

Dans le même esprit, le fait qu’un programme soit conçu avec de nombreux niveaux d’indirection (des méthodes, qui appellent d’autres méthodes, qui appellent d’autres méthodes, etc), et fasse appel à de nombreuses abstractions, ne contribue pas forcément à rendre celui-ci plus compliqué ou plus inintelligible. Bien sûr, certains paradigmes de programmation, comme les design patterns, nécessitent une solide expérience pour être compris et manipulés. Mais ces outils architecturaux sont avant tout là pour rendre le code mieux articulé, plus efficace et assurer sa pérennité; en un mot : à le rendre plus propre.

Que ce soit ces design patterns, les principes de programmation SOLID, ou tout simplement le vieux principe voulant qu’on ne doit pas copier/coller du code mais le factoriser pour mieux le réutiliser, tout tend à encourager le développeur à multiplier les niveaux d’indirection.

Constatant que j’avais tendance à écrire des fonctions faisant plusieurs centaines de lignes, un collègue de MCNext m’a un jour obligé à me limiter à un maximum de 50 lignes par fonction. En me pliant à cet exercice, j’ai appris à mieux découper mon code, à abstraire ce qui pouvait l’être, et plus généralement à voir les niveaux d’indirection comme autant de points d’articulation dans mes programmes.

Le code est à tout le monde…

Un autre point important qu’il est bon de garder en tête, est que le code d’une application appartient à tous ceux qui travaillent dessus.

Concevoir une application professionnelle est rarement le travail d’un seul homme, et chaque membre de l’équipe devrait donc pouvoir s’approprier la base de code en entier.

Cette affirmation a plusieurs conséquences. Tout d’abord, il convient qu’une équipe de programmeurs se mette d’accord sur un vocabulaire commun, qui sera réutilisé tout au long du développement. Par exemple, il y a une différence sémantique entre parler d’image et d’illustration. J’ai eu l’occasion d’utiliser cette différence dans un projet afin d’enrichir les interactions avec les autres membres de l’équipe. Cette notion de vocabulaire peut même être élargie au commanditaire de l’application, afin d’améliorer là encore la qualité des échanges.

Toujours autour de la notion de compréhension, se pose généralement la question de : on code en français ou en anglais ? En effet, la plupart des langages de programmation utilisent des mots-clefs en anglais, et le .NET ne fait pas exception. Toutefois, il est tout à fait concevable d’utiliser des noms d’entités en français. Beaucoup de développeurs préfèrent coder entièrement en anglais, toutefois cette question devrait être systématiquement débattue en équipe. Personnellement, j’ai tendance à préférer coder en anglais, mais avec les commentaires rédigés en français, afin de s’assurer qu’aucun détail technique (que l’on transmet généralement dans ces commentaires) ne soit perdu. Par contre il est préférable d’éviter d’imposer l’anglais à une équipe où le niveau dans cette langue serait plutôt faible; les fautes d’orthographe et de grammaire ne sont généralement pas d’une grande aide lorsqu’il s’agit d’améliorer la compréhension d’un programme.

Mais le point le plus important de cette notion de le code est à tout le monde, c’est que chaque membre de l’équipe devrait pouvoir intervenir comme bon lui semble sur n’importe quelle partie du programme. Bien sûr telle ou telle fonctionnalité qui aura été codée par tel ou tel développeur sera mieux comprise de celui-ci. Toutefois, aucun développeur ne devrait considérer un code qu’il a écrit comme son code, et chacun devrait pouvoir contribuer à améliorer continuellement la base de code. Il ne faut donc pas hésiter à réécrire le code d’un autre si l’on pense que celui-ci peut être amélioré, que ce soit en terme de compréhension ou de performances.

Toutefois, il s’agit de savoir se montrer diplomate. Il est facile de vexer les autres lorsqu’on remet en cause la qualité de leur travail. Par ailleurs, j’ai souvent vu des développeurs modifier le code d’un autre non pas pour l’améliorer, mais par pure maniaquerie (en l’indentant d’une manière particulière par exemple). Même si nous sommes tous un peu maniaques, ce genre de pratiques est à proscrire.

En outre, renommer des entités pour garder une base de code homogène est un bien, mais ne doit pas aboutir à des aller/retour continuel pour décider qui de Michel ou Jean-Pierre a choisi le meilleur terme. Les règles de nommage, qu’on établi au début d’un projet, sont aussi là pour éviter ce type de situation.

Un développeur junior ne doit en tout cas pas avoir le moindre scrupule à “bousculer” le code des autres s’il juge que ses changements sont opportuns.

…et tout le monde est susceptible de travailler dessus

Un développeur ne devrait jamais oublier que d’autres personnes sont susceptibles d’intervenir sur le code qu’il écrit, et donc de s’assurer que celui-ci respecte les canons de lisibilité et de maintenabilité du métier. Un code se doit d’être conçu de manière à expliciter de la manière la plus claire possible son fonctionnement et sa finalité.

Pourtant, parvenir à atteindre un tel niveau de qualité n’est pas chose aisée, surtout pour un débutant, et même en y mettant la meilleure volonté du monde, il n’est pas rare lorsqu’on a plusieurs mois de recul d’éprouver soi-même des difficultés à se replonger dans un code qu’on avait pourtant programmé soi-même.

Comparez les deux bases de code suivantes. Laquelle vous paraît la plus compréhensible ?

public int GetResult(string number)
{
    var order = (from o in Session.Orders
                 where o.Id == number
                 select o).First();

    /*********************************************
     * Ici beaucoup trop de code permettant de calculer
     * le statut d'une commande.
     ********************************************/

     int result = resultatDesCalculsPrecedents;
     return result;
}

public enum OrderStatus
{
    Canceled,
    Pending,
    Paid,
    Delivered
}

public OrderStatus GetOrderStatus(string orderId)
{
    Order order = OrderRepository.GetOrderFromId(orderId);
    OrderStatus orderStatus = new OrderStatusSpecification(order).Execute();
    return orderStatus;
}

La différence de clarté entre ces deux codes est flagrante. Le code de qualité utilise des termes très précis pour expliciter son fonctionnement et sa finalité, là où l’autre reste très vague.

Même le type de retour est différent. Le mauvais code renvoie un simple nombre entier qui n’a de sens que celui que l’équipe aura bien voulu lui donner par convention, ce sens risquant d’évoluer pendant le cycle de développement de l’application, avec les conséquences qu’on imagine. Utiliser une énumération permet à peu de frais d’expliciter le sens du résultat de l’opération.

Par ailleurs, dans le code de qualité, les calculs potentiellement complexes sont isolés par un niveau d’indirection, alors que dans l’autre, tout est compressé dans un seul bloc.

S’attacher à rendre un programme plus clair ne permet pas seulement à l’équipe de travailler dans de meilleures conditions, cela permet aussi de rendre le code plus pérenne.

Parvenir à remplir au mieux cet objectif s’apprend beaucoup avec l’expérience. Toutefois je ne saurai trop vous conseiller cet excellent livre (en anglais) qui donne de nombreuses clefs pour apprendre à manipuler du code et à le rendre plus souple.

En tout état de cause, on devrait toujours penser aux autres développeurs lorsque l’on conçoit un programme; ceux qui sont susceptibles de travailler dessus aussi bien demain que dans un an.

Comment ne pas simplifier la vie aux pirates sur votre site ASP.NET MVC

Voici une capture d’écran de l’en-tête de la réponse HTTP envoyée par une application ASP.NET MVC hébergée par un serveur web IIS :

Capture de réponse HTTP-

Comme on le voit, avec chaque requête à laquelle l’application répond sont envoyées un certain nombre d’informations concernant :

  • Server : le type de serveur hébergeant l’application, ainsi que sa version.
  • X-AspNet-Version : la version du moteur ASP.NET utilisé par l’application.
  • X-AspNetMvc-Version : la version spécifique d’ASP.NET MVC utilisée par l’application.
  • X-Powered-By : Le langage de programmation utilisé côté serveur.

Tout cela peut s’avérer extrêmement néfaste pour votre application! En effet, ces informations ne regardent personne, et surtout pas les pirates qui ne demandent rien de mieux que d’essayer de s’infiltrer par toutes les failles de sécurité concernées par ces technologies, et auxquelles votre serveur est susceptible d’être sensible s’il n’a pas été correctement mis à jour.

Pour vous donner une idée, cela revient à donner à un cambrioleur votre adresse ainsi que la marque et le modèle de votre serrure. Tout ce qui lui manque, c’est la forme de la clef.

Malheureusement, communiquer ces informations est le comportement par défaut de toute application ASP.NET MVC. Nous allons voir néanmoins comment modifier ce comportement pour faire disparaître ces données de nos en-têtes de réponse HTTP.

Commençons par le plus simple : pour retirer l’en-tête X-AspNetMvc-Version, il suffit de rajouter la ligne suivante dans la méthode Application_Start qui se trouve dans la classe MvcApplication de votre fichier Global.asax.cs.

protected void Application_Start()
{
    AreaRegistration.RegisterAllAreas();
    // Ajoutez cette ligne :
    MvcHandler.DisableMvcResponseHeader = true;

    RegisterGlobalFilters(GlobalFilters.Filters);
    RegisterRoutes(RouteTable.Routes);
}

Pour ce qui est des en-têtes X-AspNet-Version et X-Powered-By, il va vous falloir effectuer quelques modifications dans le fichier web.config à la racine de votre application web.

D’abord, s’il n’est pas encore présent, ajoutez un nœud “configuration/system.web/httpRuntime”. Pour désactiver l’en-tête X-AspNet-Version, ajoutez-y un attribut “enableVersionHeader” et donnez-lui la valeur “false”.

<system.web>
    <httpRuntime enableVersionHeader="false" />
    <!-- Ici le reste de la section system.web -->
</system.web>

Ensuite, pour supprimer l’en-tête X-Powered-By, rendez-vous dans la section “configuration/system.webServer”. S’ils ne sont pas encore présents, ajoutez-y la série de nœuds “httpProtocol/customHeaders”, et adjoignez-y un nœud “remove” dont l’attribut “name” devra avoir la valeur “X-Powered-By”. Notez que comme pour tout ce qui a trait à la section “configuration/system.webServer”, vous pouvez directement effectuer cette manipulation dans la console d’IIS 7.x.

<system.webServer>
    <httpProtocol>
      <customHeaders>
        <remove name="X-Powered-By" />
      </customHeaders>
    </httpProtocol>
    <!-- Ici le reste de la section system.webServer -->
</system.webServer>

L’en-tête Server est le cas le plus délicat. En effet, il est impossible de supprimer cet en-tête, que ce soit dans la configuration de notre application web, ou dans celle d’IIS. Pour arriver à nos fins, nous allons donc devoir intercepter la réponse HTTP avant que celle-ci soit envoyée au client, et la modifier.

Pour effectuer cette opération, nous allons altérer le pipeline de traitement de notre application web, en utilisant un HttpModule. Pour cela, il suffit de créer une classe héritant de IHttpModule. J’ai choisi d’appeler ma classe “CustomHeadersModule”. Nous devons d’ores et déjà implémenter les membres de l’interface “IHttpModule”; il s’agit des méthodes “Init” et “Dispose”. Vous pouvez laisser “Dispose” vide. Par contre dans “Init”, nous allons nous abonner à l’évènement “PreSendRequestHeaders”.

public class CustomHeadersModule : IHttpModule
{
    public void Init(HttpApplication context)
    {
        context.PreSendRequestHeaders += OnPreSendRequestHeaders;
    }

    public void Dispose()
    {
    }

    private void OnPreSendRequestHeaders(object sender, EventArgs e)
    {
        HttpContext.Current.Response.Headers.Remove("Server");
        // Ou bien
        HttpContext.Current.Response.Headers.Set("Server", "Apache");
    }
}

Dans l’EventHandler qui va nous servir à nous abonner, nous allons pouvoir librement et au choix, soit supprimer complètement l’en-tête Server, soit plus sournoisement la modifier pour donner l’impression que nous utilisons en réalité une autre technologie de serveur web (ici en l’occurrence Apache, très populaire et principal concurrent d’IIS).

Il reste toutefois une action à effectuer : enregistrer ce HttpModule dans le pipeline de traitement de notre application ASP.NET MVC, ce qui se fait soit directement dans le console d’IIS, soit en modifiant à nouveau la section “configuration/system.webServer” de notre fichier web.config, cette fois-ci dans la sous-section “modules”.

<system.webServer>
    <modules>
        <add name="CustomHeadersModule" type="VotreNamespace.CustomHeadersModule" />
    </modules>
    <!-- Ici le reste de la section system.webServer -->
</system.webServer>

Toutes ces customisations vont contribuer à rendre votre application web plus sûre. Mais bien sûr, avoir un serveur web correctement mis à jour est encore le meilleur moyen de se prémunir des attaques de pirates.

Recherche Microsoft : 3 démonstrations nouvelle interface NUI

Microsoft présente dans ces 3 video des exemples intéressants d’interfaces homme-machine évolués .

La première video concerne l’amélioration de l’interactivité grâce à l’usage d’un écran “transparent” et d’une interface 3D .

La 2ème video concerne un projet “Holoflector” qui, grâce à un miroir, sur-imprime l’image d’une personne à son équivalent virtuel “kinect” .

La 3 ème video présente “Illumishare”. Grace à un couple “projecteur/caméra”, ce projet offre une nouvelle façon de collaborer en partagant un espace bureau “projeté” .

Bonnes pratiques pour stocker des informations dans les fichiers de configuration

Lors du développement d’une application, il est courant de stocker des informations dans les fichiers de configuration, que ce soit “app.config” pour les clients lourds, ou “web.config” pour les applications web.

La méthode la plus simple pour stocker ces informations est d’utiliser la section “AppSettings”.

<AppSettings>
  <add key="ContactMail" value="contact@mcnext.com" />
</AppSettings>

 

string mail = ConfigurationManager.AppSettings["ContactMail"];

C’est une manière pratique de conserver des données qui pourront être facilement modifiées en production, car ces fichiers ne sont pas compilés.

Malheureusement, on constate souvent que ces données ont tendance à s’empiler au fur et à mesure que le développement avance, au point de se retrouver parfois avec d’interminables sections “AppSettings”.

Première alternative : créer ses propres SectionHandler

Une alternative à ce problème est de créer ses propres sections de configuration. Il faut pour cela créer une classe qui hérite de ConfigurationSection.

namespace ApplicationNamespace
{
    public class ContactSectionHandler : ConfigurationSection
    {
        [ConfigurationProperty("Mail", IsRequired = true)]
        public string Mail
        {
            get
            {
                return (string)this["Mail"];
            }
        }
    }
}

 

<configuration>
  <configSections>
    <section name="contact" type="ApplicationNamespace.ContactSectionHandler, NomDeLAssembly" />
  </configSections>
  <contact Mail="contact@mcnext.com" />
</configuration>

L’accès aux données se faisant ensuite tout aussi simplement qu’avec “AppSettings” :

string mail = ((ContactSectionHandler)ConfigurationManager.GetSection("contact")).Mail;

Ces sections de configuration personnalisées peuvent aussi contenir des collections de pairs clef/valeur. Cela se fait en créant une classe qui hérite de ConfigurationElementCollection pour représenter la collection, et une autre classe qui hérite de ConfigurationElement pour représenter un élément de cette collection. On peut alors obtenir ce type de représentations :

<contacts>
  <contact nom="Hémery" prenom="Pierre-Yves" fonction="Directeur du Pôle .NET" mail="pole-dotnet@mcnext.com" />
  <contact nom="Baduel" prenom="Roch" fonction="Directeur du Pôle Biztalk" mail="pole-biztalk@mcnext.com" />
</contacts>

Expliquer dans le détail comment créer ces sections de configuration personnalisées serait un peu long. Je vous invite à vous reporter à la documentation sur MSDN pour obtenir des informations supplémentaires. Car ce qui nous intéresse ici, c’est la seconde alternative : celle qui permet de ne pas avoir à créer de section personnalisées, tout en évitant de se retrouver avec des fichiers de configuration où tout est mélangé.

Seconde alternative : utiliser les SectionHandler “clefs en main”

Une alternative peu connue et beaucoup plus simple que la création de sections personnalisées est l’utilisation des SectionHandler “clefs en main” fournis en standard dans le Framework .NET. Ceux-ci sont au nombre de trois :

  • SingleTagSectionHandler, qui permet de créer une section simple contenant des attributs.
  • NameValueSectionHandler, qui permet de créer une collection de paires clef/valeur, où chaque clef peut être répétée plusieurs fois.
  • DictionarySectionhandler, qui permet de créer une collection de paires clef/valeur, où chaque clef doit être unique.

Il faut tout d’abord déclarer ces sections dans le nœud “configuration/configSections” :

<configuration>
  <configSections>
    <!-- Les noms donnés à chaque section sont purement arbitraires -->
    <section name="singleSection" type="System.Configuration.SingleTagSectionHandler" />
    <section name="nameValueSection" type="System.Configuration.NameValueSectionHandler" />
    <section name="dictionarySection" type="System.Configuration.DictionarySectionHandler" />
  </configSections>
  <!-- ... -->
</configuration>

Il ne reste ensuite plus qu’à utiliser ces sections :

<singleSection nom="Hémery" prenom"Pierre-Yves" fonction="Directeur du Pôle .NET" mail="pole-dotnet@mcnext.com" />
<nameValueSection>
  <add key="ValeurEnDouble" value="toto" />
  <add key="ValeurEnDouble" value="titi" />
  <add key="AutreValeur" value="foobar" />
</nameValueSection>
<dictionarySection>
  <add key="DRH" value="drh@mcnext.com" />
  <add key="CONTACT" value="contact@mcnext.com" />
</dictionarySection>

La récupération des données dans le code C# se fait là encore très facilement. SingleTagSectionHandler et DictionarySectionHandler vous renverront une Hashtable, tandis que NameValueSectionHandler vous renverra une NameValueCollection.

string mail = ((Hashtable)ConfigurationManager.GetSection("singleSection"))["mail"];
// valeurEnDouble aura la valeur "toto,titi" (nos deux valeurs séparées par une virgule)
string valeurEnDouble = ((NameValueCollection)ConfigurationManager.GetSection("nameValueSection"))["ValeurEnDouble"];
string drh = ((Hashtable)ConfigurationManager.GetSection("dictionarySection"))["DRH"];

Comme on le voit, ces SectionHandler “clefs en main” permettent d’organiser très simplement les données stockées dans les fichiers de configuration, sans avoir à en passer par l’exercice souvent fastidieux de la création de sections personnalisées.

Une autre bonne pratique qu’il est bon de noter est d’encapsuler l’accès à ces données dans des classes statiques, et d’y gérer l’éventuelle levée d’exceptions. Par exemple en contrôlant qu’une certaine clef existe bel et bien.

public static class ConfigurationData
{
    private static readonly Hashtable _sectionDatabaseAccess = (Hashtable)ConfigurationManager.GetSection("databaseAccess");

    public static int Timeout
    {
        get
        {
            if (_sectionDatabaseAccess.ContainsKey("timeout"))
            {
                int val;
                if (!int.TryParse(_sectionDatabaseAccess["timeout"].ToString(), out val))
                    throw new Exception(@"La clef ""timeout"" de la section ""databaseAccess"" doit stocker un nombre entier.");

                return val;
            }

            throw new Exception(@"La section de configuration ""databaseAccess"" devrait contenir une valeur pour la clef ""timeout"".");
        }
    }
}

L’accès aux données s’en trouve nettement facilité :

int timeout = ConfigurationData.Timeout;

Localiser la saisie utilisateur côté client dans ASP.NET MVC 3

Depuis la première version d’ASP.NET MVC, un des composants qui a subi le plus de modifications est sans doute la validation côté client. Au départ Microsoft avait développé sa propre librairie Javascript, avant de se tourner peu à peu vers jQuery, une librairie très populaire qu’ils ont choisi d’intégrer directement à leur solution.

Le contrecoup de ce revirement est que selon qu’une application est basée sur ASP.NET MVC 1, 2 ou 3, la validation côté client peut fonctionner selon des mécanismes assez différents. La localisation de cette validation en particulier peut s’avérer assez délicate à mettre en place.

La localisation de la validation dans ASP.NET MVC 3

Quand on parle de localisation de la validation, on ne fait pas seulement allusion au fait que les messages qui s’affichent soient dans la langue attendue, il s’agit aussi que les informations saisies par l’utilisateur soient validées selon les règles adéquates. Par exemple, que penser d’une application entièrement en français qui refuserait le nombre décimal “5,5″ parce que celui-ci contient une virgule comme séparateur décimal? Ce n’est probablement pas ce à quoi s’attendraient la plupart des utilisateurs.

Avec ASP.NET MVC 3, parvenir à mettre en place cette localisation est un vrai parcours du combatant. En effet, tout repose maintenant sur le plugin jQuery Validation, qui utilise un système de “règles” pour valider la saisie utilisateur. Les règles fournies par défaut sont adaptées à la culture anglaise, et il faut les surcharger, c’est à dire les remplacer et les adapter, si l’on souhaite que notre application accepte de valider une culture différente.

Ce que fournit jQuery Validation

En standard, jQuery Validation fourni trois autres groupes de règles, pour les cultures allemande, néerlandaise et brésilienne. Mais non seulement celles-ci sont très incomplètes (la néerlandaise et la brésilienne ne surchargent que la règle de validation des dates) mais aucune ne colle à la culture française. Et voici ce que propose le fichier de règle pour la culture allemande :

/*
 * Localized default methods for the jQuery validation plugin.
 * Locale: DE
 */
jQuery.extend(jQuery.validator.methods, {
	date: function(value, element) {
		return this.optional(element) || /^\d\d?\.\d\d?\.\d\d\d?\d?$/.test(value);
	},
	number: function(value, element) {
		return this.optional(element) || /^-?(?:\d+|\d{1,3}(?:\.\d{3})+)(?:,\d+)?$/.test(value);
	}
});

Les allemands utilisent bien la virgule comme séparateur décimal; en revanche ils utilisent le point comme séparateur de milliers (alors que nous utilisons un espace blanc). Bien sûr il serait facile de recopier le contenu de ce fichier avant de l’adapter, mais ce scénario n’est réaliste que si notre application n’est conçue que pour la langue française. Que faire si cette dernière est multilingue?

La librairie jQuery Globalization

L’intérêt récent de Microsoft pour jQuery les a amené à proposer leurs propres plugins : jQuery DataLink pour la liaison de données, jQuery Templates pour le templating et jQuery Globalization pour la localisation. Jusqu’à il y a peu, ces trois plugins, encore à l’état de béta version, étaient considérés par l’équipe jQuery comme des plugins “officiels”. Ce n’est plus le cas, toutefois les deux premiers plugins ont vu leur existence prolongée par leur créateur, sous la forme de JsRender et JsViews. Ils devraient être à terme inclus dans la librairie jQuery UI. Quand à jQuery Globalization, il était déjà très complet et parfaitement utilisable en production, et c’est heureux puisque nous allons nous en servir pour rendre notre application multilingue.

jQuery Globalization est composé de très nombreux fichiers correspondant à autant de cultures. Ces fichiers exposent les caractéristiques de chacune de ces cultures, ainsi que des fonctions permettant de traduire aussi bien les dates que les nombres décimaux, et bien plus encore.

Pour implémenter ce plugin dans une application web ASP.NET MVC 3, rien de plus simple. Après l’avoir téléchargé et placé dans notre solution, nous devons tout d’abord le référencer :

<script type="text/javascript" src="@Url.Content("~/Scripts/jquery/plugins/glob/jquery.global.js")"></script>

Ensuite nous devons charger dynamiquement le fichier de localisation correspondant à la culture de l’utilisateur, et configurer le plugin pour utiliser celui-ci :

<script type="text/javascript" src="@Url.Content("~/Scripts/jquery/plugins/glob/globinfo/jquery.glob." + Request.UserLanguages[0] + ".js")"></script>
<script type="text/javascript">
    jQuery.global.preferCulture("@Request.UserLanguages.ToCorrectCase()");
</script>

Request.UserLanguages est un tableau permettant d’obtenir côté serveur la liste des cultures configurées (par ordre de préférence) dans le navigateur de l’utilisateur. Vous vous demandez sans doute à quoi sert la fonction ToCorrectCase(). Malheureusement certain navigateurs comme Firefox renvoient “fr-fr” pour la langue française quand ils devraient renvoyer “fr-FR” (notez la différence de casse), et jQuery Globalization est sensible à ce détail; il faut donc s’y adapter et c’est à ça que sert cette fonction.

N’oubliez pas que les fichiers source de jQuery sont disponibles sur le CDN de Microsoft, tout comme de nombreux plugins.

Tout le nécessaire est maintenant en place pour permettre la localisation multilingue de notre application.

Comment relier jQuery Validation et jQuery Globalization

La dernière étape va consister à relier jQueryValidation, qui s’occupe de la mécanique de validation côté client de l’application, à jQuery Globalization, qui s’occupe exclusivement de la localisation.

Pour cela, nous devons faire référencer un nouveau fichier Javascript par notre application, et y ajouter le code suivant :

jQuery.extend(jQuery.validator.methods, {
    date: function (value, element) {
        return this.optional(element) || jQuery.global.parseDate(value) != null;
    },
    number: function (value, element) {
        return this.optional(element) || !isNaN(jQuery.global.parseFloat(value));
    },
    range: function (value, element, param) {
        value = jQuery.global.parseFloat(value);
        return this.optional(element) || (value &gt;= param[0] &amp;&amp; value &lt;= param[1]);
    }
});

Par le biais de ce code nous surchargeons trois règles de validation de jQuery Validation : la validation de la date, des nombres décimaux, et des intervalles. D’autres règles pourraient potentiellement être également surchargées.

Grâce à ce “pont” établi entre les deux plugins, jQuery Validation va maintenant se servir des fonctions de jQuery Globalization pour valider la saisie de l’utilisateur. Supposons que celui-ci doive indiquer quel sera le pourcentage de TVA sur un produit quelconque. La propriété correspondante dans le modèle de la vue ressemblerait à ceci :

/// <summary>
/// TVA applicable sur le produit
/// </summary>
[Range(0.0, 100.0)]
public double TVA { get; set; }

Notez que la règle de validation de nombre décimal est implicite dès lors qu’il s’agit d’un type “double” (nombre décimal à double précision).

Maintenant si par exemple l’utilisateur a son navigateur configuré dans la culture française, et qu’il saisit “5,5″, nous serons en mesure de valider que ce nombre est dans un format décimal correct, et qu’il est compris dans une intervalle allant de 0 à 100. Notre application web est donc bien multilingue.

Exemple de développement ASP MVC

Alexandru Radu est expert .NET  dans le pôle du même nom . Il a développé chez lui un site web en ASP MVC pour pouvoir  piloter et visualiser à distance les caméras de surveillance de sa maison ( à la campagne)  . Nous lui avons demandé de faire un petit film pour présenter ce qu’il a réalisé . Merci à lui !

Le code sources est disponible ici

SharePoint Conference 2011 : C’est fini !

Voilà qui conclut cette semaine à la SharePoint Conference 2011 à Anaheim. Celle-ci aura été intéressante dans l’ensemble même si comme de plus en plus souvent sur ces évènements à forte population (7500 personnes rappelons-le), le niveau des sessions est assez déséquilibré avec des choses formidables et d’autres plus que moyennes voir médiocres.

Vivement l’année prochaine à Las Vegas avec l’annonce du probable SharePoint 2013   ;–)

Le programme de l’après-midi va être un peu de tourisme à Los Angeles (Venice Beach, Santa Monica, Beverly Hills…) avant de reprendre l’avion demain dans la journée pour enchainer sur 11h de vol (mais ça le vaut bien).

Quelques photos souvenirs …

How Microsoft Built Academy, it’s social Video Platform

Session animée par Austin Winters

La session va aborder un sujet qui intéresse de plus en plus de monde aujourd’hui: comment intégrer un « Youtube » dans mon entreprise ?

On va pour ça prendre l’exemple d’Academy, la plateforme de partage de vidéos mise en place par Microsoft.

On commence par visionner une vidéo amusante sur notre sujet, histoire de détendre un peu l’atmosphère pour cette dernière session de la SharePoint Conference :) .

Nous allons parler patterns, architecture et intégration de fonctionnalités sociales puis montrer que SharePoint 2010 peut parfaitement répondre à ce besoin.

Quelques composants clés d’une plateforme de partage vidéo dans SharePoint :

  • Les fonctionnalités communautaires et sociales
  • Le stockage de documents, l’affichage (ici les documents sets), la gestion
  • La taxonomie
  • Le moteur de recherche FAST
  • Le design de portail
  • Windows Media Services

On décrit maintenant le pattern d’un portail.

D’abord le publishing site. Sa gestion est faite côté client.

Puis le document center et l’intégration des documents sets offerte par SharePoint 2010.

Puis le stockage des données,  elles peuvent être stockées dans SharePoint ou utiliser le RBS.

Puis les services partagés, avec la taxonomie, la recherche, …

On reparle des documents sets et des fonctionnalités sociales offertes par SharePoint : tagging, rating, commentaires, my sites, …

Ensuite on aborde le sujet FAST qui permet de faire des recherches poussées sur les vidéos.

La WebPart de recherche FAST permet d’afficher des résultats de type vidéos liés au contexte de la page.

Un lab est disponible, pour ceux qui veulent se lancer dans l’aventure: http://aka.ms/podcasting .

On passe maintenant à une démo.

La collection de sites présentée reprend le pattern évoqué plus haut.

On voit un publishing site, un document center avec des documents sets, …

La Home Page des documents sets est customisée pour permettre l’affichage de la vidéo.

Ils ont fait le choix de supprimer le ribbon afin de simplifier la contribution pour les utilisateurs et de ne pas les  perdre dans une multitude de fonctionnalités dont ils n’ont pas besoin. L’un des seuls boutons présents est le bouton d’upload.

L’upload de vidéo déclenche la création d’un document set.

La home page du document set est complètement customisée. Elle ressemble à s’y méprendre à la page de visualisation d’une vidéo sur Youtube :)

On a un lecteur de vidéo, l’affichage d’informations comme son hauteur, sa durée, … les actions classiques comme l’envoi à un ami, une zone de commentaires, …

Un bouton visible uniquement par le contributeur permet de créer un aperçu de la vidéo à un moment précis. L’aperçu de la vidéo est stocké dans une bibliothèque est utilisé notamment dans les résultats de recherche. La vidéo est également stockée dans SharePoint mais le speaker insiste sur le fait qu’il s’agit d’une démo et que le chargement de vidéos depuis une base de données est  lourd.

Sur un environnement de production il faut absolument la stocker sur un serveur dédié. Ca permet par exemple le streaming.

On voit ensuite les différentes modifications apportées à l’affichage des résultats de recherche.

On définit les éléments utiles pour la gestion de vidéos : les metadonnées, l’encoding live, le transfert, la contribution des utilisateurs…

Un graphe présente le process depuis l’arrivée des vidéos vers SharePoint jusqu’à la sortie vers les supports tels que tv, xbox, dvd, ipad, …

Le graphe en 3 mots :

Create -> Manage(SharePoint) -> Experience (medias)

On voie ensuite le process d’upload,  avec les bases de données etc…

Les medias sont stockés sur des serveurs, les metadonnées dans des bases de contenu. SharePoint fait le lien entre tout ça.

Le moteur d’encodage met à jour les métadonnées automatiquement à partir d’un fichier vidéo.

SharePoint ne gère pas directement l’affichage de la vidéo, il charge juste, par exemple, un contrôle SilverLight qui lui va rechercher la vidéo sur un serveur distant.

On peut même faire appel à une plateforme de streaming externe pour le stockage des vidéos.

Retour à une démo sur Academy…

On voit comment les pages sont construites.

Ils utilisent beaucoup la fenêtre modale fournie avec SharePoint 2010 pour la navigation et l’affichage des vidéos.

On voit les différentes fonctionnalités présentes sur la page du document set : I like it, génération du code html pour l’intégration dans un autre site, … pour faire simple, tout ce qu’il y a sur Youtube.

Il montre en détail les métadonnées du document set : la taxonomie est très utilisée !

Puis le process d’upload de la vidéo vers un dossier. C’est le champ DocumentID qui est utilisé pour nommer le fichier sur le file system.

L’aperçu de la vidéo est envoyé vers un serveur de fichiers et la vidéo vers un serveur de streaming.

Beaucoup de choses sont fournies OOTB comme le rating par exemple, les statistiques de consultations …

On peut pluger des outils du marché pour avoir des statistiques supplémentaires.

Les mysites sont également très customisés. Ils ressemblent à une page de profil Youtube.

On peut vraiment faire des choses très poussées avec la vidéo sous SharePoint si on met en place l’infrastructure qui va avec.

Je vous recommande d’aller voir le podcast car la session était très intéressante :) .

Best practices for creating Publishing Page Layouts

Session animée par Geoffrey Edge

Nous allons aborder dans cette session les bonnes pratiques pour la création de page layouts dans SharePoint.

  • On commence par le sommaire :
  • Le moteur de rendu des pages publishing
  • Les différences entre masterpage et page layouts
  • Les composants d’un page layout
  • L’impact du contenu et du design du site sur les page layouts
  • Les exemples avec le site brembo ou sharepoint.microsoft.com
  • La création des page layouts
  • Le déploiement

Le moteur de rendu fonctionne de la manière suivante : le navigateur requête la page, le page layout est recupéré, la masterpage est récupérée, les contrôles présents dans le page layout génèrent le rendu des champs de la page.

On nous rappelle la différence entre la masterpage, qui constitue la structure commune à toutes les pages, du page layout, qui charge des contrôles dans les zones prévues (PlaceHolders).

Le contenu d’un page layout :

  • Les zones de webparts
  • Les contrôles des champs
  • Les div, …
  • Le css
  • Le code behind (parfois)
  • La navigation de contenu (différent de la navigation du site)
  • Les textes et images non éditables.

On commence la première démo.

On nous présente un exemple de page avec un branding très poussé. Ca ne ressemble pas vraiment à un site SharePoint.

Les éléments qui  n’appartiennent pas à un page layout :

  • La navigation de site
  • Le branding commun
  • Les éléments du head

Nous abordons ensuite l’impact du site.

Les besoins du site définissent les best practices.

Le type de site impacte les page layouts, le nombre de pages, l’audience cible du site, la templatisation.

On évoque différents types de sites : micro sites, les brochures, les knowledge bases, les sites de eCommerce, les sites corporate et bien d’autres…

L’emplacement des pages définit ce qui est dans le layout. Les pages « top level » on peut de champs en général.

Plus on descend dans la hiérarchie, plus les pages sont structurées.

Page d’accueil -> page de catégorie -> page de contenu

Une nouvelle démo nous permet de mettre en évidence tout ça.

On voit la structure de la home page d’un site, puis des pages de contenus (produits), …

Concernant la création des page layouts, on peut utiliser Visual Studio ou Sharepoint Designer.

On voit un autre exemple de site qui n’a aucun champ sur sa home, que des zones de webparts.

Sur la page de catégories, idem, il n’y pas de champs par contre sur les pages de produits, plein de champs.

Il est important de limiter ce que peuvent faire les contributeurs et de ne leur laisser l’accès qu’aux éléments qu’ils sont sensés modifier.

Un petit tour sur Brembo a présent.

On fait une démo avec quelques best practices.

Sur une page, on a beaucoup de jQuery et notamment un slide show. Les images sont stockées dans une librairie avec des métadonnées sur les images (temps d’affichage, ordre, ..)

Il conseil l’utilisation de la dataform webpart et de jQuery. La dataform webpart est capable d’agréger des données.

On aborde rapidement le framework de la modal dialog. Elle est uttilisée pour certains contenus. (natif ave SharePoint en appelant SP.UI.ShowModal().

On explique ensuite l’EditModePanel qui permet de gérer les metadonnées de la page non visibles (tags, titre, …). Par exemple, un DelegateControl peut être utilisé pour afficher les valeurs de la balise meta à partir de ces tags.

On voit également l’utilisation de la ContentQuery webpart qui requête certaines pages en fonction d’une metadonnée de l’EditModePanel.  Elle est recommandée pour l’affichage de news par exemple.

Puis on passe la home page du site sharepoint.microsoft.com en mode édition pour voir comment elle est construite.

Concernant les templates, il faut faire attention à en limiter le nombre disponible pour ne pas « perdre » le contributeur.

Pour terminer la session nous parlons de la création des types de contenu et des page layouts.

Il existe plusieurs techniques pour la création de types de contenu: SharePoint Designer, Visual Studio, code, Powershell…

Quelques plugins pour Visual Sudio : Comunity kit for SharePoint, caml.net.intellisense (pratique :) )

Une dernière démo nous montre les différentes techniques.

Il existe aussi plusieurs techniques pour créer des page layouts : SharePoint Designer, Visual Studio , les 2 !

SharePoint Designer : facile, pour les non développeurs, peux flexible, pages déghostées

Visual Studio : plus flexible, réservé aux développeurs.

L’idéal est de designer la page dans Designer puis copier dans Visual Studio pour packager.

Cette session ne nous dévoile finalement pas grand-chose alors qu’il s’agissait d’une session niveau 300.

Suivre

Get every new post delivered to your Inbox.