Bienvenue à Blogs CodeS-SourceS Identification | Inscription | Aide

Atteint de JavaScriptite Aiguë [Cyril Durand]

Expert ASP.net Ajax et WCF, Cyril Durand parle dans son blog de point techniques sur ASP.net, ASP.net Ajax, JavaScript, WCF et .net en général. Cyril est également consultant indépendant, n'hésitez pas à le contacter pour de l'assistance sur vos projets

Actualités

  • Blog de Cyril DURAND, passionné de JavaScript, Ajax, ASP.net et tout ce qui touche au developpement Web Client-Side.

    N'hésitez pas à me contacter pour vos projets .net : architecture, accompagnement, formation, ...

    View Cyril Durand's profile on LinkedIn
    hit counters


    Expertise Commerce server et BizTalk

AppFabric – Faut il l’utiliser pour écrire une couche de service ?

Avec l’arrivé de AppFabric, il est désormais simple d’héberger des workflow Worflow Foundation dans IIS.

Afin de communiquer avec l’extérieur, un Workflow peut utiliser les composants ReceiveRequest et SendRequest, ces composants utilisent WCF pour dialoguer. Il est donc tentant d’écrire sa couche de service en utilisant AppFabric.

Je me suis intéressé à cette question.

D’un point de vue performance, j’ai réalisé un service WCF classique et un service WCF utilisant WF. Ces 2 services réalisent la même chose. Ils ne font rien d’intéressant, je souhaitais juste connaitre le surcout lié à WF.
Vous trouverez ci-dessous le code utilisé.

Service WCF classique :

image

Service WF :

image

Et voici le code utilisé pour mesurer les performances :

image

Les tests sont multithreadés pour simuler une forte charge.

J’ai exécuté le code sur ma machine (8Go de ram, 8 cœurs) en utilisant IIS7.5 (Windows 7). Les 2 tests se sont effectués à la suite, dans les mêmes conditions.

Avec la configuration par défaut, j’obtiens les résultats suivant :

  • Service WCF classique : 3.5 secondes
  • Service WF classique : 6.3 secondes

Sans surprise, la solution utilisant WF est plus lente. Par contre, le delta est conséquent : +80%. J’ai alors vérifié la configuration du service au niveau IIS, et désactivé le Monitoring.

image

Après avoir refait un test, les résultats sont les suivant :

  • Service WCF classique : 3.5 secondes
  • Service WF classique : 4.5 secondes

La différence de performance est alors réduite, la surcouche WF ne coute plus que 30%.

    Nous avons vu que d’un point de vue technique, l’écart de performance est faible. Si le service n’est pas critique en terme de performance, ce choix est tout à fait envisageable.

    D’un point de vue fonctionnelle, il faut se demander si l’on a vraiment besoin de Workflow Foundation ou si les services WCF classique suffisent. Voici les questions que l’on peut se poser ?

    • Allez-vous utiliser les composants de Workflow Foundation ? ou créer une activité personnalisée qui contiendra tout votre code ?
    • Vos workflow ont-ils une vie ? Accèderez-vous plusieurs fois à vos Workflow ?
    • Allez-vous persister vos Workflows ?
    • Allez-vous surveiller vos Workflows ? (monitoring)

    Si vous répondez non à toutes ces questions, le choix de Workflow Foundation avec AppFabric n’est peut-être pas nécessaire pour vos besoins, sinon, ce choix est envisageable.

    Et vous ? Qu’en pensez-vous ? Dans quelle contexte avez-vous utilisé AppFabric ?

    IIS et l’héritage de la configuration des répertoires virtuels ; le module URL Rewrite à la rescousse

    IIS permet d’héberger des sites web et des répertoires virtuels. Un répertoire virtuel est une sorte de sous dossier : un mini site web à l’intérieur d’un site web. Les répertoires virtuels peuvent être pratiques pour héberger des sous application, par exemple des blogs ou un site d’administration.

    On pourrait imaginer avoir un site web contenant 2 répertoires virtuels : admin et blogs. La capture d’écran ci-dessous illustre cette configuration.

    image

    Cependant attention ! Les répertoires virtuels héritent de la configuration du site web parent. Ainsi, dans notre exemple l’application “blogs” héritera de la configuration du site IISTest. Cela peut être problématique, très souvent on ajoute des httpmodules ou autres fonctionnalités propres à un site web ; l’ajout de ces fonctionnalité peut être non désirées et entrainer des problèmes sur ces sous-sites. 

    Il est possible de contourner le problème en utilisant le module “Url Rewriter v2.0” de IIS. Comme son nom l’indique, ce module permet de faire de la réécriture d’url, il est téléchargeable via WebPI ou à cette adresse : http://www.iis.net/download/urlrewrite.

    L’idée est d’héberger le site web racine dans une application virtuelle puis de rediriger toutes les requêtes vers ce répertoire virtuelle sauf les requêtes allant vers /admin ou /blogs.

    Dans un premier temps, il faut alors déplacer tous les fichiers du site web vers un répertoire vitrtuel que l’on pourrait nommer www

    image

    Ensuite, au niveau du site web, il faut ajouter la règle de rewriting suivante :

    image

    Vous pouvez aussi éditer directement votre fichier de configuration et ajouter les lignes suivantes :

    <system.webServer>
      <rewrite>
        <rules>
          <rule name="www redirect">
            <match url=".*" />
            <action type="Rewrite" url="/www/{R:0}" />
            <conditions>
              <add input="{SCRIPT_NAME}" pattern="/admin/.*" negate="true" />
              <add input="{SCRIPT_NAME}" pattern="/blogs/.*" negate="true" />
              <add input="{SCRIPT_NAME}" pattern="/www/.*" negate="true" />
            </conditions>
          </rule>
        </rules>
      </rewrite>
    </system.webServer>

    Ainsi, toutes les requêtes allant vers votre site web seront réécrites vers le répertoire /www/. Puisqu’il s’agit de réécriture (rewriting), l’utilisateur ne verra aucune différence au niveau de l’url.

    Et vous, avez-vous déjà eu des problèmes liés à l’héritage de configuration des répertoires virtuels ? Quelle solution avez-vous utilisée ?

    ASP.net - Accès concurrent à une même session interdite – SessionState en mode ReadOnly

    De plus en plus d’applications web utilisent des services “Ajax” pour communiquer avec les serveurs. Ces services retournent généralement du JSON qui sera ensuite interprété côté client.

    Pour diverses raisons, il est possible de vouloir exécuter 2 requêtes simultanément. Par exemple, un traitement longue durée s’effectue en arrière-plan tandis que le reste de l’application continue de fonctionner et d’effectuer des requêtes simples.
    Dans certains cas, ASP.net peut bloquer la deuxième requête en attendant la fin de la première, cela peut s’avérer très problématique.

    Il m’est récemment arrivé ce cas, j’ai trouvé l’explication du côté des sessions ASP.net :

    Concurrent Requests and Session State

    Access to ASP.NET session state is exclusive per session, which means that if two different users make concurrent requests, access to each separate session is granted concurrently. However, if two concurrent requests are made for the same session (by using the same SessionID value), the first request gets exclusive access to the session information. The second request executes only after the first request is finished. (The second session can also get access if the exclusive lock on the information is freed because the first request exceeds the lock time-out.) If the EnableSessionState value in the @ Page directive is set to ReadOnly, a request for the read-only session information does not result in an exclusive lock on the session data. However, read-only requests for session data might still have to wait for a lock set by a read-write request for session data to clear.
    >> http://msdn.microsoft.com/en-us/library/ms178581.aspx 

    Comme le note l’article MSDN, l’accès aux sessions est exclusif. Si une requête a besoin d’un accès à une session, toutes les autres requêtes ayant besoin d’accéder à cette même session sera mis en attente.

    Avant de rentrer en détail dans les explications, il est important de savoir que les navigateurs limitent leur nombre de connexion simultanées. Internet Explorer 8- effectue maximum 2 requête simultanées pour un même nom d’hôte (cela correspond à la RFC et ne sera plus le cas avec IE9) alors que Firefox en fait 5.

    Pour mettre en avant ce comportement, j’ai utilisé le bout de code suivant :

    for (var i = 0; i < 20; i++) {
        $.ajax({
            cache: false,
            dataType: 'json',
            async: true,
            url: 'PouetService.svc/DoWork',
            success: function (result) {
                $('#pouet').append('<li>' + result.d + '</li>');
            }
        });
    }

    Lorsque j’exécute ce code, j’obtiens les résultats suivant avec Firebug :

    image

    On voit que 5 requêtes sont lancés de façon simultanées par le navigateur cependant les réponses arrivent de façon séquentiel.

    Ce comportement peut être bloquant. Pour contourner cela, il est possible d’indiquer à ASP.net comment la requête accède à la session de l’utilisateur. Il y a 3 choix possible : aucun accès à la session, accès en lecture seul ou accès complet à la session. Seul l’accès complet ne peut pas être concurrent.

    Si votre requête n’a pas besoin des sessions ou a besoin d’un accès en lecture seul aux sessions, il faut alors l’indiquer à ASP.net, ainsi la requête ne sera pas bloquée.

    Comment spécifier le mode d’accès aux sessions ?

    La modification du mode d’accès à la session dépend de façon dont est effectuée la requête.

    Si la requête est une page ASP.net (WebForm ou MVC), alors on peut indiquer le mode d’accès dans la directive de page à l’aide de l’attribut EnableSessionState. Les valeurs possibles sont True, False, ReadOnly.

    <%@ Page Language="C#" AutoEventWireup="true" EnableSessionState="False" CodeBehind="…" Inherits="…" %>

    La valeur true est la valeur par défaut et donne un accès total à la session, seule cette valeur bloque les autres requêtes.

    La valeur false permet de ne pas avoir de session pour la requête en cours. Dans ce cas, si vous tentez d’accéder à la session alors que la session est désactivé, vous aurez l’exception suivante : “Session state can only be used when enableSessionState is set to true”.

    Comme son nom l’indique, la valeur ReadOnly permet d’accéder à la session mais la modification de valeur est interdite. Une nouveauté a été introduite dans .net 4.0, il est possible d’ajouter une valeur dans la session même en mode ReadOnly seul la modification de valeur est interdite avec .net 4.0. Avec .net 3.5, la création ou modification de valeur est interdite. Attention, si vous tentez de modifier une valeur, aucune erreur ne sera levée. Pour savoir si la session est en ReadOnly ou non, on peut utiliser la propriété IsReadOnly de l’objet Session.

    Il est possible de changer la valeur par défaut pour toutes les pages depuis le fichier de config :

    <system.web>
      <pages enableSessionState="ReadOnly" />
    </system.web>

    Autre nouveauté de ASP.net 4.0, on peut définir de façon impérative cette valeur, il faut pour cela utiliser la méthode SetSessionStateBehavior du HttpContext. Cette méthode doit par contre être appelée avant l’évènement AcquireRequestState.

    Si la requête est un handler (ashx), alors par défaut, vous n’avez pas accès à la session. Pour avoir un accès total à la session, il faut implémenter l’interface IRequiresSessionState pour avoir un accès en lecture seul, il faut implémenter l’interface IReadOnlySessionState.

    public class PouetHandler : IHttpHandler, IReadOnlySessionState

    Le mécanisme décrit pour les pages reste identiques.

    Si la requête est un service WCF, on ne peut pas contrôler le mode de session utilisé. La seule solution que j’ai trouvé consiste à désactiver le mode de compatibilité ASP.net, ainsi on aura plus accès à la session.

    Pour désactiver le mode de compatibilité ASP.net, il faut enlever l’attribut AspNetCompatibilityRequirement du service et l’attribut aspNetCompatibilityEnabled de la section serviceHostingEnvironment du fichier de config

    [AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]

    Je n’ai pas creusé avec Reflector. Si quelqu’un à une autre solution, je suis preneur.


    Après avoir configuré correctement le mode d’accès à la session ASP.net, le comportement de mon application est désormais correcte : on peut voir que 5 requêtes s’exécutent en parallèle, ces 5 requêtes correspondent aux pool de requêtes de Firefox

    image

    Pour conclure, si votre page n’a pas besoin d’accéder à la session, désactiver la session. Si votre page ne fait que lire des objets en session, alors utilisez le mode ReadOnly. De plus, au-delà de l’accès concurrent, ASP.net effectuera moins de traitement, les performances de votre application sera alors meilleures.

    Et vous, avez-vous déjà eu des problèmes similaires ?

    Problèmes de performances ? Quelles sont les causes possibles ? Voici une liste

    Travaillant très fréquemment sur des problèmes de performances, je me suis demandé quelles sont les causes courantes de ces problèmes. J’ai alors rédigé une liste listant les problèmes de performances déjà rencontrés.

    L’idée est d’avoir une checklist indiquant l’ensemble des causes possibles pour un problème de performance. Cette liste ne contient volontairement pas d’éléments de méthodologie pour diagnostiquer les problèmes de performances, seules les causes sont listées.

    Vous trouverez ci dessous cette liste, cette liste et non exhaustive et est amenée à évoluer. N’hésitez pas à me donner vos idées pour la compléter.

    Problèmes liées au code

    • Problème algorithmique
      • Parcours de collection trop importante par rapport au besoin
        • Ex : Calcul des promotions sur l'ensemble des produits alors que seul 10 produits sont affichés
      • Réalisation de calcul non nécessaire
        • Ex : réalisation d'un calcul lourd sur l'ensemble des nœuds d'un arbre alors que seul les nœuds de niveau 1 sont affichés au client
      • Non utilisation de contexte : les même informations sont recalculés plutôt que sauvegardés au sein d'un contexte
        • Appels à des calculs algorithmiques complexes trop fréquents
        • Appels à la base de données trop fréquents
        • Appels à des WebService trop fréquents
      • Mauvaise estimation de la volumétrie
        • ex : chargement d'un fichier XML en mémoire. Développé avec un fichier de quelques ko, en production avec un fichier de plusieurs centaines de Mo.
      • Gestion de la parallèlisation
        • Problème de synchro de thread (dead lock)
        • Appel aux services tiers de façon synchrone
          • info : Les services tiers peuvent être défaillants ou surchargés
        • Non asynchronisation de méthode / mauvaise utilisation de la parallèlisation
          • Ex : Une requête attend que son entrée dans les logs soit écrite pour pouvoir continuer. Cette action n'influe pas sur le résultat, elle peut être déléguée
        • info : Ce problème arrive et arrivera de plus en plus fréquemment suite au nombre de cœur en constante augmentation
      • Mauvaise découpe de l’application
        • manque d’architecture
          • ex : mauvaise séparation des couches
        • Code trop complexe
          • ex : un écran qui fait trop de choses au lieu de plusieurs écrans simples
          • tips : non utilisation du SRP (Single Responsibility Principle)
          • tips : non KISS compliant
        • Page trop complexe
          • Poids de la page trop important ; la réponse envoyé au client fait plusieurs centaine de ko voir mo
            • ex : le viewstate est beaucoup trop lourd
          • Trop de dépendance vers l’extérieur
            • ex : JavaScript de tracking, régie pub
            • ex : trop d’images sont chargés sur la page
          • Complexité du code client
            • ex : CSS trop lourde ou complexe
            • ex : incohérence des JavaScript envoyés au client
            • ex : HTML complexe et mal construit
    • Mauvaise utilisation du framework
      • Non libération des ressources non managées
      • Mauvaise utilisation du framework .net
        • Ex : concaténation de String sans utilisation de StringBuilder
        • Ex : Utilisation de tableau au lieu d'utilisation de Stream
        • Ex : Génération d’un fichier XML en concaténant des bouts de String
      • Réécriture de code présent dans le framework .net
    • Mauvaise gestion du cache
      • Absence de cache sur la couche présentation
        • tips : L'ajout d'outputCache est la solution idéale quant à ces problèmes
      • Durée de vie du cache trop court
      • Couche de cache trop nombreuses
        • Cache au niveau de l'accès à la base, cache métier, cache présentation 1, cache présentation2, etc.
    • Autres
      • Dépendances non mis à jour ou non testé
        • Ex : utilisation d’un code trouvé sur le net sans l’avoir relu

    Problèmes liées à la configuration

    • Configuration de IIS
      • Compression GZip non activée
        • tips : sur IIS 7+, un mécanisme désactive la compression des fichiers dynamiques si la charge CPU est trop importante
      • Pas de cache client sur les fichiers statiques
        • ex : images, CSS, JavaScript
      • Activation de modules IIS inutiles
        • ex : module d'authentification
      • Règle de rewriting trop complexe
      • Redirections trop nombreuses
        • ex : http ==> https ==> sous domaine ==> login ==> etc.
      • Configuration d'une stratégie des AppPool trop agressifs
        • ex : configuration du recyclage des applications toutes les 20 minutes
      • Utilisation du mode 32 bits non nécessaire sur un système d’exploitation 64 bits
      • Problème sur la configuration avancée de IIS
        • ex : taille de la file d'attente, délai d'attente du ping, chargement du user profile, etc.
    • Base de données
      • Opération de maintenance en période de charge
      • Table d'historisation non nettoyée ou non partitionnée
        • ex : Insertion d'une entrée dans une table des logs contenant plusieurs millions de lignes
      • Index
        • Fragmentation des indexes importants
        • absence ou surplus d'index
        • Absence de plan de maintenance
          • pour reconstruire les index
          • pour sauvegarder les fichiers de logs 
      • Fichier de log et fichier de données sur la même partition physique (disque dur)
        • tips : Ce problème apparait dans un contexte de forte charge SQL
    • Configuration de l'application
      • Valeurs des timeout trop élevées
      • Utilisation des url de preproduction plutôt que des urls de production
      • Configuration de debug laissé en production
      • Log applicatifs trop fréquents
        • ex : mauvaise configuration de log4net ; écriture de l’ensemble des infos
      • Dépendances utilisées non à jour ; la dernière version ayant corrigé des problèmes de performances
    • Configuration des autres applications
      • Antivirus qui scrute tous les fichiers
      • Outil de monitoring
        • Outil de backup qui monopolise toute la bande passante
        • Outils de monitoring qui surveille trop
          • ex : un outil de monitoring qui effectue plusieurs vérifications par second
          • ex : L’outil de monitoring relance trop fréquemment les applications
      • Problème DNS : le DNS ne répond pas ou prends du temps
        • info : Un site web peut avoir besoin de faire des requêtes DNS pour connaitre l'ip d'un service web.
      • Système d'exploitation membre d'un Active Directory
        • AD non accessible, trop lent, mal répliqué
      • Batches
        • Batch utilisant 100% de CPU/RAM pendant quelques secondes
        • Traitement des opérations sur l’ensemble plutôt que par lot
          • ex : application qui met à jour des milliers d’éléments en une fois plutot que plein de mis à jour par petit paquet.
        • Mauvaise plannification des batches
          • ex : Plannification des batches en période de forte activité
      • Autres :
        • Système d'exploitation pas à jour
        • Quota définit par l'hébergeur
        • Attaque DoS en cours

    Problèmes liées à l'infrastructure

    • Disque dur
      • Erreur dans la grappe RAID 
        • ex : reconstruction du RAID en cours
        • ex : Utilisation du bit de parité pour accéder aux données (RAID5)
      • Fragmentation des disques élevée
      • Partitionnement physique incohérent
      • RAID logiciel plutôt que matériel
      • Manque d'espace disque
    • CPU
      • CPU pas assez puissant
      • CPU trop puissant : plus le nombre de cœur est élevé, plus les problèmes de synchro de thread sont fréquent
    • Mémoire
      • Manque de RAM
        • info : Le système swap en permanence pour trouver de la ram
        • ex : l’application fonctionne en mode dégradée (le cache n’est pas utilisé
      • Système d'exploitation installé en 32 bits alors que l'on dispose de plus de 4Go de RAM
    • Réseau
      • Carte réseau défaillante
        • Driver de carte réseau non à jour
      • Surcharge réseau
        • réseau mal dimensionné (utilisation de switch 10Mbits/s)
          • Restriction de bande passante liée à l'hébergement
          • Carte non configurée en Full-Duplex
      • Switch / réseau défaillant
        • perte de paquet
        • Mauvaise configuration des protocoles de routages
      • Topologie réseau incohérente
        • ex : Plusieurs switch/routeur sont à traverser pour attaquer la base de données
        • ex : Utilisation de plusieurs vlan entre les différents serveurs applicatifs
      • Firewall
        • Mauvaise configuration du firewall
        • Sous dimensionnement du firewall
      • Activation de IpV6 (ou ipv4) inutile
    • Load Balancing
      • Load balancer inactif
      • Mauvaise répartition de la charge
      • Load balancer sous dimensionnée par rapport au reste de l'infra.
    • Autres :
      • Mauvaise utilisation d'un proxy applicatif
      • Virtualisation
        • outils client non installés sur la VM
        • mauvaise configuration des disques virtuels sur les disques physiques
        • mauvaise configuration de l’hyperviseur

    Et vous quelles autres causes avez-vous déjà rencontrés ? N’hésitez pas à me fournir vos éléments, je compléterais la liste en conséquence.

    Dell E6510 et 8Go de ram : problème de souris et autres

    J’ai récemment commandé un nouveau laptop, un dell E6510 avec une configuration assez sympathique :

      • Latitude E6510 : Base standard
      • Processor : One Intel Core i7-640M (2.8Ghz,4M,Dual Core)
      • Écran : 15,6 pouces Full HD (1920X1080) Antireflet Panneau LCD WLED
      • Mémoire : 8Go (2x4Go) 1333MHz DDR3 Bicanale

    Le tout pour un peu plus de 2000€ TTC.

    24 novembre :

    Je reçois ma machine, je rencontre alors un problème avec mon touchpad, Windows réagissait bizarrement avec la souris : tout se passait comme si les boutons étaient coincés après un click, etc. Je réinstalle alors le système et me dit qu’après avoir réinstallé les drivers, le problème disparaitrait. Après réinstallation : même problème, cela se produit également avec une souris externe et dans le bios.

    J’effectue alors un diagnostic avec l’utilitaire DELL présent dès le démarrage, j’obtiens le code d’erreur 3500:021E

    25 novembre :

    Premier appel chez DELL, ils m’envoient un technicien pour changement de la carte mère et du clavier.

    Entre temps, j’ai réussi à utiliser la machine, il est en effet possible de désactiver le touchpad dans le bios. Ainsi, on peut utiliser une souris externe. Ce n’est pas très pratique dans le train mais cela à l’avantage de fonctionner

    DSC_5224

    29 novembre :

    Rappel chez DELL, suite à un quiproquo, l’intervention n’avait pas été déclenchée …

    1er décembre :

    Premier technicien DELL : après environ 2h, la carte mère et le touchpad sont changés : l’écran ne fonctionne plus, le touchpad pas plus …

    3 décembre :

    Second technicien DELL : après une lutte acharnée de plus de 4h, la carte mère, le touchpad et l’écran sont changés. L’écran refonctionne mais toujours pas le touchpad ….

    5 décembre :

    Appel chez DELL, on me propose un retour atelier, cela devrait prendre 4 à 5 jours.

    du 10 au 23 décembre :

    Plus de 10 appels chez DELL pour savoir où est la machine, on doit me rappeler, on ne me rappelle jamais, on me donne des infos contradictoires : que la machine est déjà livrée, qu’ils attendent des infos, etc.

    image

    23 décembre :

    Je reçois la machine, DELL doit toujours me rappeler pour m’informer sur l’état de l’intervention. Même problème, même message d’erreur dans l’outil de diagnostic.

    Je rappel DELL, on doit me rappeler … après 4 ou 5 appels, j’arrive enfin à avoir quelqu’un qui s’occupe de mon cas, on me propose un échange standard. Ils doivent me rappeler pour me le confirmer aujourd’hui … Si l’échange est confirmé, cela devrait se faire sous 2 semaines.

    Entre temps, j’ai vu qu’un nouveau BIOS (version A06) était disponible depuis le 12 décembre, j’essaye de l’installer : sans succès, impossible de lancer l’appli : elle se lance et se ferme. Le problème se produit avec un OS 32 et 64 bits avec 7 ou Vista ... Après de nombreux essais, j’ai trouvé une solution, il faut installer le bios A01, puis le patch P02 puis le bios A06. Malheureusement, le problème persiste, de plus j’ai eu quelques écrans bleus depuis la MAJ du bios.

    J’ai alors décidé de regarder physiquement le problème. J’ai alors débranché le clavier comme expliqué sur cette vidéo :

    Puis, après plusieurs tests, j’ai observé que la connectique du clavier était décomposé en deux, je me suis dit qu’il devait y avoir une partie pour le trackpad (les 4 pins), et une partie pour le touchpad.

    J’ai alors mis un bout de chatterton sur les 4 pins de la partie droite de la connectique (cf photos ci dessous) et rebranché le clavier : le problème à disparu, je peux enfin utiliser le touchpad, le trackpad est cependant inactif.

    DSC_5220DSC_5221

    Je devrais avoir une nouvelle machine d’ici quelques jours, je ne suis pas sur que cela corrige le problème et pense plutot à une incompatibilité matérielle, affaire à suivre …

    Et vous, avez vous déjà eu des problèmes similaires ?

    Extraction des binaires d’une application à partir d’un dump – debug avancé avec WinDBG

    En cas de crash ou de mauvais fonctionnement d’une application en production, il est courant d’utiliser un dump afin de comprendre la cause du problème.

    Un dump est une image mémoire du processus à un instant t. Celui-ci va contenir l’ensemble des informations du processus : le stack trace des différents threads, l’ensemble des variables du tas, etc … Pour en savoir plus sur les dump et windbg, je vous conseils les articles de Tess Fernandez -if broken it is, fix you should : .NET Debugging Demos - Information and setup instructions

    Dans certains cas, il est intéressant de récupérer l’ensemble des assemblies chargées par l’application. A partir de ces binaires on peut effectuer une analyse plus précise du code grâce à Reflector par exemple. Ces fichiers sont présents dans les dumps.

    Comment extraire ces fichiers ?

    Pour lister ces fichiers, il faut d’abord charger le dump dans WinDBG (disponible ici : Debugging Tools for Windows). Puis, il faut utiliser la commande lm, cette commande permet de lister l’ensemble des modules chargés par l’application. La documentation sur la commande lm est disponible ici : [MSDN] lm (List Loaded Modules)

    Exemple :

    0:000> .loadby sos mscorkws
    0:000> lm
    start    end        module name
    01110000 01134000   WebDev_WebServer20        (deferred)             
    04740000 05238000   mscorlib_ni               (deferred)             
    05c90000 05c98000   WebApplication23          (deferred)             
    060e0000 06122000   SMDiagnostics_ni          (deferred)             
    07440000 07448000   App_Web_8l9otbrp          (deferred)             
    077b0000 079fe000   System_Web_Extensions_ni  (deferred)             
    07a00000 07bc5000   System_Web_Services_ni    (deferred)
    ...

    La première colonne correspond à l’adresse mémoire où est stocké le module, la troisième colonne correspond au nom du module.

    L’une des options intéressante est l’option f. Cette option permet de connaitre le chemin complet d’où le module a été chargé.

    Exemple :

    0:000> lm f
    start    end        module name
    01110000 01134000   WebDev_WebServer20       C:\Program Files (x86)\Common Files\Microsoft Shared\DevServer\10.0\WebDev.WebServer20.exe
    04740000 05238000   mscorlib_ni              C:\Windows\assembly\NativeImages_v2.0.50727_32\mscorlib\f58ab951b57c8526430486dcf7ee38fd\mscorlib.ni.dll
    05c90000 05c98000   WebApplication23         C:\Windows\Microsoft.NET\Framework\v2.0.50727\Temporary ASP.NET Files\root\eaa0bd70\633d2a55\assembly\dl3\4d666377\583d14c9_f85ecb01\WebApplication23.DLL
    060e0000 06122000   SMDiagnostics_ni         C:\Windows\assembly\NativeImages_v2.0.50727_32\SMDiagnostics\9de488bf62eebca425759ea94d9a70e8\SMDiagnostics.ni.dll
    07440000 07448000   App_Web_8l9otbrp         C:\Windows\Microsoft.NET\Framework\v2.0.50727\Temporary ASP.NET Files\root\eaa0bd70\633d2a55\App_Web_8l9otbrp.dll
    077b0000 079fe000   System_Web_Extensions_ni C:\Windows\assembly\NativeImages_v2.0.50727_32\System.Web.Extensio#\0119cf02155b33d89fca6687c3e03705\System.Web.Extensions.ni.dll
    07a00000 07bc5000   System_Web_Services_ni   C:\Windows\assembly\NativeImages_v2.0.50727_32\System.Web.Services\ee24fe21a061801bb923bdc23c96388d\System.Web.Services.ni.dll
    07fa0000 08274000   System_Data              C:\Windows\assembly\GAC_32\System.Data\2.0.0.0__b77a5c561934e089\System.Data.dll

    Attention, si vous debuggez une application 32 bits sur un système 64 bits, WOW (Window On Window - la technologie Windows permettant d’exécuter des applications 32 bits sur un environnement 64 bits) sera utilisé par le système d’exploitation. Dans ce cas, les adresses mémoires ne seront pas les bonness, celles-ci seront préfixées par 0000000`. Il faut alors charger les extensions wow64 grâce à la command e.load wow64exts suivi de la commande !sw.

    Exemple :

    0:000> .load wow64exts
    0:000> !sw
    Switched to 32bit mode
    0:000:x86> lm
    ...

    La commande SaveModule permet d’extraire un module vers un fichier sur le disque dur. Le premier argument est l’adresse mémoire où est située le module, le second, le chemin où stocker le fichier.

    Exemple :

    0:000> !savemodule 05c90000 c:\tmp\WebApplication23.dll
    3 sections in file
    section 0 - VA=2000, VASize=774, FileAddr=200, FileSize=800
    section 1 - VA=4000, VASize=390, FileAddr=a00, FileSize=400
    section 2 - VA=6000, VASize=c, FileAddr=e00, FileSize=200

    Le fichier peut alors être analysé avec Reflector.

    Si vous souhaitez extraire tous les modules chargés par le processus, il faudra scripter windbg. Vous trouverez ci-dessous un exemple de script permettant d’extraire tous les modules dans le dossier c:\tmp\extract. Attention, ce dossier doit exister pour que windbg écrive les modules.

    .foreach(moduleName {lm1m}) {   .foreach /pS 4 /ps 100 (address {lm m ${moduleName}}){     !SaveModule ${address} c:\tmp\extract\${moduleName}.dll   }
    }

    Ce script doit être enregistré dans le fichier c:\tmp\extract\script.txt. Pour l’exécuter, il faut alors utiliser la commande suivante dans WinDBG.

    $><c:\tmp\extract\script.txt 
    Test de montée en charge avec Visual Studio – cookies et viewstate …

    La version Ultimate de Visual Studio permet d’effectuer des tests de montée en charge. J’ai récemment eu quelques soucis lié aux cookies.

    Pour effectuer un test de montée en charge sur une application web, il faut enregistrer un scénario web : un fichier .webtest, puis créer un fichier de montée en charge : un fichier .loadtest, ce dernier utilisera un ou plusieurs scénarios web.

    Afin de créer mes scénario web, j’utilise Fiddler. Pour cela, je lance un navigateur vide de tous cookies, cache, etc. Puis je lance Fiddler, je joue mon scénario, je sélectionne seulement les requêtes qui m’interessent et j’exporte les requêtes en tant que WebTest Visual Studio.

    image

    Après avoir importé mon test dans Visual Studio, l’exécution se déroule sans problème :

    image

    Je créé alors un test de montée en charge avec un utilisateur qui répète le même test web pendant quelque minutes.

    Comme on peut le voir sur les-captures ci dessous, la première exécution du scénario fonctionne mais plus les suivantes. Tous les scénarios se terminent avec des erreurs liées au viewstate : “validation of viewstate mac failed

    image

    image 

    Il faut savoir que lorsqu’on exécute un test de montée en charge, Visual Studio créé des utilisateurs virtuels. Ces utilisateurs virtuels possèdent des cookies qui leur sont propres. Entre 2 exécution de scénario, Visual Studio va utiliser le même utilisateur virtuel, les cookies seront alors réutilisés.

    Afin de ne plus être perturbé par les utilisateurs réentrant, il est possible d’indiquer à Visual Studio de ne pas réutiliser les utilisateurs virtuels. Ce paramètre se configure au niveau des propriétés du scénario du test de montée en charge, il s’agit de la propriété Percentage of New Users. En le définissant à 100%, Visual Studio ne réutilisera pas les utilisateurs virtuels.

    image

    Cette astuce a permis de corriger mon souci. Il s’agissait d’un cas particulier où la valeur des cookies impacte l’ordre des pages du scénario. Il aurait été possible de régler le problème en créant 2 scénarios : l’un pour les nouveaux utilisateurs et un autre pour les utilisateurs réentrant puis d’utiliser des conditions pour jouer le bon scénario. Je n’ai pas choisi cette solution par facilité et pour limiter les problèmes liés à la maintenance.

    Et vous, avez vous eu des problèmes similaires avec les tests de montée en charge Visual Studio ?

    [TFS] Comment forcer la saisie d’un Area ou Iteration

    Lorsque l’on créé un Work Item dans TFS, il est possible de le classer dans un “area” et dans une “iteration”.

    Dans la plupart des types de projet, un "area” correspond à une catégorie, une “iteration” à un numéro de version.

    Il est possible de créer des sous catégories et des sous itérations depuis Team Explorer. La capture d’écran ci-dessous montre la fenêtre de gestion des area / iteration

    image

    Cependant, par défaut, tous les contributeurs peuvent saisir des Work Items dans toutes les catégories y compris la catégorie principale.

    Généralement, nous avons besoin d’être le plus précis possible au niveau du Work Items. Nous ne souhaitons alors pas qu’un utilisateur puisse utiliser l’area ou iteration par défaut.

    Comment forcer la saisie d’une catégorie autre que celle par défaut ?

    Afin de répondre à ce problème, nous pouvons utiliser les options de sécurité des area ou iteration. Lorsque vous créez un area ou itération, un bouton “Security…” se trouve en bas à gauche de l’écran.

    Il faut alors désactiver la permission “Edit Work items in this node” sur le noeud que vous souhaitez. Ainsi l’utilisateur du groupe en question n’aura plus la possibilité de créer ou modifier un Work Item dans cette catégorie.

    Il faudra ensuite redonner cette permission sur les areas / iterations filles. Si vous ne le faites pas, plus personnes ne pourra modifier ou ajouter des work items.

    La capture d’écran ci-dessous montre la fenêtre de configuration des permissions.

    image 

    Ainsi, lorsqu’un utilisateur tentera de créer ou modifier un bug dans une area où il n’a pas les droits, il verra le message suivant en cas d’erreur de validation :

    image

    ou, l’erreur TF237111 : The current user does not have permissions to save work items under the specified area path.

    image

    Cette astuce peut aussi être utilisée pour clore une itération et ainsi interdire toute création de bug autre que dans la version en prod / dev.

    Et vous, avez-vous déjà utilisé ces options de sécurités ? Si oui, pour quelle problématique ?

    hMailServer – connecter TFS, Sharepoint, SSRS, … avec gmail ou autre serveur SMTP

    J’ai récemment mis en place une infrastructure complète utilisant TFS 2010, Sharepoint 2010, etc. Cette infrastructure ne contient pas de serveur de messagerie et utilise gmail avec un domaine personalisé.

    Il est possible d’envoyer des mails via gmail en utilisant le protocole SMTP. Pour cela, il est nécessaire de s’authentifier et d’utiliser du SSL.

    Malheureusement, TFS 2010, Sharepoint 2010, SQL Server Reporting Services (SSRS) ne permettent pas de s’authentifier à un serveur SMTP. Il me fallait un moyen simple de rediriger des mails envoyés via TFS, Sharepoint, SSRS vers gmail.

    J’ai d’abord essayé de configurer le serveur SMTP fourni avec IIS en SMTP Relayer. Après plusieurs essais infructueux, j’ai abandonné cette idée …

    J’ai ensuite utilisé un mini serveur SMTP codé en C#, une implémentation est disponible ici : Get SharePoint to Mail with an SMTP Server Requiring Authentication. Après quelques modifications, cela fonctionnait avec un compte gmail. Cependant, j’avais toujours une erreur de communication avec SSRS.

    Je me suis alors mis en quête d’une nouvelle solution et j’ai trouvé hMailServer. hMailServer est un serveur mail complet et gratuit permettant entre autres de faire du relais SMTP. Après l’avoir installé et configuré, je pouvais envoyer des mails depuis TFS, Sharepoint, SSRS, SQL Server, ...

    Au niveau de la configuration, j’ai rajouté un domaine au niveau de la console d’administration. Puis pour relayer tous les mails vers un compte gmail, au niveau du noeud Settings > Protocols > SMTP, il faut utiliser la configuration suivante :

    • Remote host name : smtp.gmail.com
    • Remote TCP/IP port : 465
    • Server Require authentication : true
    • userName / password : le compte gmail associé
    • Use SSL : true

    image

    Je ne suis pas allé très loin dans la configuration de cet outil. Je m’en sers seulement en relais SMTP mais j’ai vu qu’on pouvait faire beaucoup plus.

    J’aurais également pu utiliser Exchange Server. hMailServer se configure en 20min, ne prend que 10Mo de mémoire et tous les utilisateurs de cette infrastructure utilisent un compte gmail. C’est loin d’être le cas de Exchange :)

    Et vous avez vous d’autres solutions permettant de faire du relaie SMTP ?

    [TFS2010] Droits sur les Workspace – Workspace public et serveur de build

    L’une des nouveautés de TFS 2010 est la possibilité d’avoir des droits sur les workspaces TFS. 3 droits sont disponibles :

    • private workspace : seul le propriétaire du workspace peut lire et écrire dans ce workspace. Il s’agit de la valeur par défaut et du fonctionnement de TFS 2008
    • public workspace (limited) : Tout le monde peut lire dans ce workspace. Seul le propriétaire peut faire des modifications.
    • public workspace : Tout le monde peut lire et écrire dans ce workspace.

    image

    A quoi cela peut-il servir ?

    Cette fonctionnalité permet d’avoir une machine partagée pour les intervenants ponctuels (intégrateurs, pompiers, …). Ainsi, vous configurez une fois la machine : IIS, fichiers hors TFS, etc. Les utilisateurs ponctuels pourront alors travailler sans devoir reconfigurer l’environnement. C’est très pratique lorsque vous travaillez avec IIS, BizTalk, etc.

    Serveur de build

    Cette fonctionnalité peut aussi servir sur les serveurs de build. Un serveur de build est composé de un ou plusieurs agents, chaque agent dispose de son propre workspace. Par défaut, ce workspace est privé est associé au compte du service de build. Pour des raisons de sécurité et aussi par simplicité, il est plus simple d’ouvrir une session TSE sur le serveur de build avec un compte autre que le compte de service. 

    Grâce à la visibilité des workspace, vous pouvez debugger un problème de build sans avoir à lancer une session avec le compte de service.

    Bien sûr, cela perd un peu d’utilité si vous utilisez des agents avec un compte interactif.

    Comment changer la visibilité d’un workspace ?

    Comme on le voit sur la capture du dessus, on peut modifier cette visibilité dans les propriétés du workspace. Si vous ne pouvez pas lancer un Visual Studio avec le compte de service, il est possible de modifier cette visibilité depuis la ligne de commande.

    Il faut d’abord executer la commande suivante qui va lister les workspace pour un utilisateur :

    tf workspaces /owner:XXX\buildsvc /collection:http://tfs.XXX.local:8080/tfs/XXX

    image

    Cette commande va nous donner le nom du workspace (ici, 1_2_tfs). Il faudra alors utiliser la commande suivante pour changer la visibilité :

    tf workspace /collection:http://tfs.XXX.local:8080/tfs/XXX 1_2_tfs;XXX\buildsvc /permission:Public

    Comment utiliser un workspace public ?

    Lorsque vous lancerez Visual Studio sur la machine où le workspace est public, vous le verrez directement dans le source control explorer. Il n’y a aucune action particulière à effectuer.

    En savoir plus sur les permissions des workspace : Improvements to workspaces in TFS 2010 

    Et vous, avez-vous déjà utilisé un workspace public ? Si oui, pour quelle utilité ?

    ASP.net – inscrire les UserControl (ascx) dans le fichier web.config

    Je vous avais parlé il y a quelques temps de la possibilité d’enregistrer les contrôles personnalisés dans le fichier web.config : Enregistrer ses WebControls dans le Web.Config 

    Il est également possible d’enregistrer ses contrôles utilisateurs (usercontrol) dans ce fichier de configuration. Pour cela, il suffit de rajouter les lignes suivantes :

    image

    Ainsi, vous pouvez utiliser vos contrôles utilisateurs dans votre page en utilisant simplement <mag:List runat="server" />. Vous n’avez plus besoin de rajouter la directive @Register en haut de votre page.

    Team Build – erreur “Task could not find "sgen.exe"”

    J’ai récemment activé les builds sur un serveur TFS 2010, hébérgé sur Windows Server 2008 R2 x64. Le projet que je souhaitais compiler est un projet .net 3.5, ce projet a été converti de VS2008 vers VS2010.

    Malheureusement, lorsque j’ai lancé ma première build j’ai eu l’erreur suivante :

    C:\Windows\Microsoft.NET\Framework64\v4.0.30319\Microsoft.Common.targets (2249): Task could not find "sgen.exe" using the SdkToolsPath "" or the registry key "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Microsoft SDKs\Windows\v7.0A". Make sure the SdkToolsPath is set and the tool exists in the correct processor specific location under the SdkToolsPath and that the Microsoft Windows SDK is installed

    Apres quelques recherches, je me suis rendu compte que le problème était assez courant sur le net. J’ai essayé plusieurs solutions sans réel succès.

    L’une des solutions couramment proposée est d’installer Visual Studio sur le serveur de build : chose que je ne voulais pas faire.

    Afin de corriger le problème, j’ai installé le SDK de Windows 7 et .net 4.0 : Download : Microsoft Windows SDK for Windows 7 and .NET Framework 4.

    J’ai installé seulement les outils du SDK (cf capture):

    image

    J’ai également installé le SDK de Windows 7 et .net 3.5 SP1, mais je ne pense pas que cela soit utile.

    Malheureusement, cela ne suffisait toujours pas.

    J’ai alors utilisé l’outil WinSdkVer disponible dans le dossier %ProgramFiles%/Microsoft SDKs/Windows/v7.1/Setup/ .

    Attention, si vous lancez cet outil en mode GUI directement depuis l’explorateur, vous aurez l’erreur suivante :

    ---------------------------
    Windows SDK Configuration Tool Error
    ---------------------------
    Your system does not have Visual Studio 2005 or Visual Studio 2008 installed.
    ---------------------------
    OK  
    ---------------------------

    Il faut le lancer en ligne de commande :

    C:\Program Files\Microsoft SDKs\Windows\v7.1\Setup>WindowsSdkVer.exe -version:v7.1

    Désormais, je n’ai plus cette erreur lors d’un build automatique. Merci à Florent pour l’astuce de l’outil en ligne de commande.

    Et vous, avez vous rencontré d’autres soucis pour compiler des projets .net 3.5 depuis Team Build 2010 ?

    IIS7 - Administrer un serveur web IIS à distance depuis windows 7

    La console d’administration IIS7 sous Windows Server 2008 ou 2008 R2 laisse la possibilité de se connecter à un serveur distant.

    image

    Cependant, si vous essayez de vous connecter à votre serveur, vous risquez d’avoir le message d’erreur suivant :

    ---------------------------
    Connect to Server
    ---------------------------
    Could not connect to the specified computer.

    Details: Unable to connect to the remote server
    ---------------------------
    OK  
    ---------------------------

    C’est normal : pour des raisons de sécurité et de performance, l’administration à distance n’est pas activée.

    Configuration du serveur

    Afin d’activer l’administration à distance, il est nécessaire d’installer un composant à IIS.

    Pour cela, il faut activer le “role service” nommé “Management Service”, cet ajout se fait via le “server manager” de Windows. 

    image

    Après avoir installé ce composant, trois nouvelles icônes apparaissent au niveau du noeud serveur dans la console d’administration IIS :

    image

    La fonctionnalité “Management Service” permet d’activer l’administration à distance. La capture ci dessous montre les paramètres disponibles :

    image

    Par défaut, un certificat SSL auto-signé est utilisé pour chiffrer la communication. On peut bien sur utiliser un autre certificat que celui par défaut.

    L’authentification Windows est aussi activée par défaut. Mais on peut aussi utiliser les comptes IIS configurés au niveau de la fonctionnalité “IIS Manager Users

    Enfin, la fonctionnalité “IIS Manager Permissions” permet d’autoriser ou non des utilisateurs au niveau des sites web ou application virtuelles. Si l’on veut définir des droits plus précis, il faudra utiliser la feature “Server Delegation”. Pour ce dernier point davantage d’explications sont disponibles ici : Feature Delegation Page [Technet]

    Lorsque vous assignez des droits pour un utilisateur précis au niveau d’un site précis à l’aide de la feature “IIS Manager Permissions”, vous aurez une erreur d’authentification en vous connectant à l’aide du lien “connect to a server …”

    ---------------------------
    Connect to Server
    ---------------------------
    Could not connect to the specified computer.

    Details: The remote server returned an error: (401) Unauthorized.
    ---------------------------
    OK  
    ---------------------------

    Il faut alors utiliser le lien “connect to a site …” afin de gérer ce site web.

    Vous pouvez désormais vous connecter à distance sur ce serveur via un compte administrateur.

    image

    Configuration pour l’accès depuis Windows 7 ou Vista

    Par défaut, la console d’administration IIS de Windows 7 ou Windows Vista ne peut pas se connecter à des serveurs distants.

    Si l’on souhaite administrer un serveur distant depuis une console d’administration IIS Windows 7 ou Windows Vista, il faut installer un module additionnel. Ce module est gratuit et est distribué par Microsoft, il se trouve ici : http://www.iis.net/download/IISManager

    Comme la plupart des modules IIS, ce plugin s’installe via Windows Platform Installer (WPI)

    image

    Une fois installé, vous disposez de la même console d’administration que sur un serveur. Vous pouvez alors vous connecter à distance et gérer votre serveur depuis 7.

    Et vous ? Comment administrez-vous vos serveurs IIS ? Utilisez-vous cette fonctionnalité ?

    Reverse Proxy et IIS7 - mise en place du module Application Request Routing (ARR)

    J’ai récemment eu besoin de rendre visible des sites hébergés sur deux serveurs différents de mon réseau local vers l’extérieur.

    Ayant qu’une seule IP publique et plusieurs serveurs Web locaux, je ne peux pas rediriger toutes les requêtes du port 80 vers une IP locale précise.

    J’ai donc ajouté un serveur faisant office de reverse proxy. Toutes les requêtes sur le port 80 sont redirigées vers ce serveur, ce serveur redirige ensuite les requêtes vers les serveurs locaux.

    Prenons par exemple, le cas où tous les sites web de web de preproduction sont hébergés sur un serveur nommé pprod.xxx.local et les sites web d’intégration sur int.xxx.local. Lorsque j’accède à SiteName.pprod.xxx.com ou SiteName.int.xxx.com j’aimerais accéder au site web correspondant.

    Le schéma ci-dessous illustre le principe :

     

    image

    Afin de réaliser ce comportement, j’ai installé le module Application Request Routing (ARR) sur le serveur app.xxx.local. ARR est un module gratuit édité par Microsoft permettant de réécrire les urls en utilisant le module Url Rewrite, il permet aussi de gérer du cache. Vous pouvez le télécharger à partir de cette adresse : http://www.iis.net/download/applicationrequestrouting 

    J’ai utilisé Web Platform Installer pour installer le module, cela m’a automatiquement installé IIS7 et les composants additionnels requis.

    Une fois installé, vous retrouvez le module ARR et le module URL Rewrite dans la console d’administration IIS, au niveau du noeud serveur.

    image

    Double cliquer dans le module et activer le reverse proxy au niveau des paramètres du reverse proxy et cocher la case “enable proxy”.

    image image

    Une fois cette manipulation effectuée, il faut rajouter une règle au niveau du module Url Rewrite.

    Pour cela nous allons partir d’une règle vide, et créer la règle suivante :

    Pattern : *
    Conditions : {HTTP_HOST} match *.pprod.XXX.com,
    Conditions : “track capture groups accross conditions” coché. Cela permettra de récupérer la valeur de *
    Rewrite Url : http://{C:1}.pprod.XXX.local/{R:1}

    La capture ci-dessous illustre la règle créée dans IIS.

    image

    Faites de même pour la règle *.int.local.

    Au final, vous aurez alors vos différentes règles de redirection directement dans le module URL Rewrite.

    image

    Sur les serveurs web, au niveau des sites web, il faut avoir configuré les bindings pour écouter sur SiteName.pprod.XXX.local

    image

    Il ne reste plus qu’à configurer le DNS pour que *.pprod.XXX.com et *.int.XXX.com pointe vers votre IP public.

    Le module “Application Request Routing” permet également de gérer du cache, pour en savoir plus rendez-vous ici : Application Request Routing

    Pour que le plugin fonctionne, il faut laisser au moins un site web sur le serveur, ne faites pas comme moi et ne supprimez pas le site web par défaut.

    Et vous, qu’utilisez-vous pour faire un serveur reverse proxy ? Avez-vous déjà utilisé le module ARR ?

    Analyser du HTTPS avec Fiddler

    Fiddler est un outil permettant d’analyser toutes les requêtes HTTP effectuées par votre machine, pour cela il agit comme un proxy.

    Azra a déjà parlé de Fiddler il y a quelques temps ici : Fiddler, analyser les communications client/serveur pour AJAX

    Lorsque l’on doit débugger un site utilisant HTTPS, ce qui transite entre le client et le serveur est chiffré, c’est le principe de HTTPS.

    image

    La version 2 de Fiddler permet de déchiffrer les requêtes HTTPS. Pour cela, il faut aller dans le menu Tools > Fiddler Options > HTTPS et décocher la case "Decrypt HTTPS Traffic" .

    L’ensemble de la manipulation est décrite ici : http://www.fiddler2.com/fiddler/help/httpsdecryption.asp

    image

    Le principe du Man In the Middle est mis en jeu pour que cela fonctionne.

    [C#] Cast ou as – opérateur de conversion classique ou utilisation du mot clé as

    Récemment, on m’a demandé s’il valait mieux utiliser l’operateur de conversion classique ou l’operateur as pour effectuer une conversion. J’ai donc cherché à savoir quelle était la meilleure méthode au niveau du temps d’exécution.

    Les méthodes de conversion classique et l’opérateur as ne sont pas exactement équivalents. Bien sur, tous deux permettent de changer le type de l’objet, mais certaines différences existent.

    Si l’on essaye de convertir un objet en un mauvais type, avec as, il n’y aura pas d’erreur, l’opération retournera null alors qu’avec un cast classique une exception de type InvalidCastException sera levée. De plus, l’opérateur as  n’exécutera pas les operateurs de conversions explicites.

    Afin de comparer les performances, voici le code que j’ai utilisé, j’ai tout d’abord créé 2 classes avec une relation d’héritage entre elles, puis j’effectue une boucle de 100 millions de cast. J’ai choisi d’écrire le code du test directement dans la méthode plutôt qu’une méthode externe afin d’éviter les optimisations d’inlining du compilateur et du JIT.

    public class Person { public void PersonPouet() { } } public class Developper : Person { public void DevelopperPouet() { } }
    static void CaseX() { Console.Write("Case#X\t"); Stopwatch watcher = new Stopwatch(); Person p = new Developper(); watcher.Reset(); watcher.Start(); for (int i = 0; i < 100000000; i++) { // code test case } watcher.Stop(); Console.Write("\t{0:N0}", watcher.ElapsedMilliseconds); watcher.Reset(); watcher.Start(); for (int i = 0; i < 100000000; i++) { // code test as } watcher.Stop(); Console.Write("\t{0:N0}", watcher.ElapsedMilliseconds); Console.Write("\r\n"); }

    J’ai ensuite testé différents cas d’utilisation des opérateurs de conversion :

    Cas 1 : Conversion seule sans utiliser l’objet retourné

    // cast Developper d = (Developper)p; // as Developper d = p as Developper;

    Cas 2 : Conversion et vérification la non nullité de d

    // cast Developper d = (Developper)p; // as Developper d = p as Developper; if (d != null) { }

    Cas 3 : Utilisation classique sans la vérification que p est bien un Developper

    // cast Developper d = (Developper)p; d.DevelopperPouet(); // as /// attention : on ne teste pas que d est différent de null /// si p n'est pas un Developper alors on obtiendra une NullReferenceException Developper d = p as Developper; d.DevelopperPouet();

    Cas 4 : Utilisation classique avec la vérification sur p

    // cast Developper d = (Developper)p; d.DevelopperPouet(); // as Developper d = p as Developper; if (d != null) { d.DevelopperPouet(); }

    Cas 5 : Conversion classique et utilisation d’une méthode de la classe de base, le cast est ici inutile.

    // cast Developper d = (Developper)p; d.PersonPouet(); // as Developper d = p as Developper; d.PersonPouet();

    Cas 6 : Vérification du type avant l’opération de conversion

    // cast if (p is Developper) { Developper d = (Developper)p; d.DevelopperPouet(); } // as Developper d = p as Developper; if (d != null) { d.DevelopperPouet(); }

    Cas 7 : Vérification du type avant l’opération de conversion avec une conversion impossible

    // cast if (p is String) { String s = (String)p; s.Trim(); } // as String s = p as String; if (s != null) { s.Trim(); }

    Cas 8 : Utilisation de GetType() pour vérifier le type de l’objet.

    Note : Attention les 2 cas ne sont pas exactement équivalents, si p est une classe enfant de Developper alors le premier cas ne se réalisera, alors que le deuxième si.

    // cast if (p.GetType() == typeof(Developper)) { Developper d = (Developper)p; d.DevelopperPouet(); } // as Developper d = p as Developper; if (d != null) { d.DevelopperPouet(); }

    Résultats

    Voici les résultats pour 100 millions d’exécutions exprimées en millisecondes. J’ai d’abord effectué mes tests en compilant pour la plate-forme x86 avec la CLR2 (.net 3.5 SP1) et la CLR 4 (.net 4.0).

     image 

    Puis en compilant pour la plate-forme x64.

    image

    Explications

    Pour le cas 1, grâce aux optimisations du compilateur, le mot clé as est plus rapide. Dans ce cas, le compilo constate que le résultat de la conversion n’est jamais utilisé, il ne compile alors pas le corps de la méthode.

    Pour les cas 2 à 5, on observe que l’opération de cast est légèrement plus rapide. On voit également que sous .net 4, le cast a été fortement amélioré : +65% de gain de temps.

    Pour les cas 6 et 7, on voit que le mot clé is ralentit les différentes méthodes.

    Enfin, pour le cas 8, l’appel de la méthode GetType() est plus rapide que l’utilisation de l’opérateur as. Je ne sais pas exactement d’ou cela vient, il faudrait étudier de plus près la compilation JIT.

    Conclusion

    Si vous êtes sûr du type de l’objet à convertir, il est alors préférable d’utiliser un cast. Si par contre vous n’êtes pas sur du type de l’objet et que vous avez besoin de vérifier le type, il est alors préférable d’utiliser l’operateur as.

    Ces tests ont également montré les différences entre la CLR x64 et x86, on a pu voir que sous la CLR2 la version x86 était plus optimisée que la version x64, cela n’est plus le cas sous la CLR4. On voit également que la CLR4 est globalement plus optimisé que la CLR2, notamment en x64.

    Malgré les différences en termes de performances, il ne faut pas oublier que les différences s’expriment en nanosecondes …

    ASP.net nested master page – un concept simple mais puissant

    Récemment, j’ai fait découvrir à un collègue le concept de nested MasterPage, je me suis alors rendu compte que cette subtilité était malheureusement très peu connu des développeurs.

    Avant de parler des nested MasterPage, parlons des MasterPage. Une master Page est une fonctionnalité introduite avec .net 2.0 permettant de créer un page maitre dont vont “hériter” des pages filles. Cela permet de partager du contenu identique entre plusieurs pages : une sorte de “template” où l’on peut renseigner les parties communes d’un site web : header, footer, etc.

    Pour cela, les master page utilisent un contrôle contentPlaceHolder permettant de définir la ou les zones que les pages filles peuvent modifier. Au niveau des pages filles, cette “surcharge” s’effectue via un contrôle asp:content.

    Exemple :

    -- Pouet.master <%@ Master %> <html> <head>...</head> <body> HEADER <asp:ContentPlaceHolder ID="MainContent" runat="server"/> FOOTER <body> </html> -- Page.aspx <%@ Page MasterPageFile="~/Pouet.master" %> <asp:content contentPlaceHolderId="MainContent" runat="server"> BODY de la page </asp:content>

    Les nested master page étendent ce concept : cela permet d’avoir une hiérarchie de page maitre. Cela peut être utile lorsque par exemple nous avons une section du site qui a toujours la même tête (checkout, FAQ, …). Dans ce cas,  vous pouvez faire une master Page qui utilise une autre master Page.

    --Pouet.master <%@ Master %> <html> <head>...</head> <body> HEADER <asp:ContentPlaceHolder ID="MainContent" runat="server"/> FOOTER <body> </html> --Pouet2.master <%@ Master MasterPageFile="~/Pouet.master" %> <asp:content contentPlaceHolderId="MainContent"> Pouet2 CommonBody <asp:ContentPlaceHolder ID="SubContent" runat="server"/> </asp:content> -- Page.aspx <%@ Page MasterPageFile="~/Pouet2.master" %> <asp:content contentPlaceHolderId="SubContent" runat="server"> BODY de la sous page </asp:content>

    Techniquement, il est possible de faire cela depuis l’apparition des master page c’est à dire depuis .net 2.0. Cependant, le designer de Visual Studio 2005 ne le supportait pas, il a fallut attendre l’arrivé de VS2008.

    Et vous, est-ce une fonctionnalité que vous allez utiliser ou que vous utilisez déjà couramment ?

    [MIX10] Keynote deuxième journée – Internet Explorer 9, Html5, Visual Studio 2010, OData

    Le deuxième keynote du mix fut très riche en contenu.

    Internet Explorer 9

    Juste un après le lancement de Internet Explorer 8, Microsoft a dévoilé les nouveautés de Internet Explorer 9.

    SDC10235SDC10244

    Désormais, IE supportera HTML5, SVG et CSS3. L’élément video sera supporté, il ne sera plus nécessaire d’avoir recours à Flash ou Silverlight pour insérer de la vidéo dans un site wbe. Cela permet de nombreuses choses, il sera possible de skinner une vidéo (bordure, opacité, …) simplement via des règles CSS.

    SDC10236 

    Au niveau des performances, le moteur de rendu utilisera le GPU, c’est à dire l’accélération matérielle de la carte graphique, cela permettra de considérablement augmenter les performances lors d’animation complexes, notamment au niveau des vidéos. Le moteur JavaScript a également été modifié, comme sur la plupart des navigateurs concurrents, JavaScript est désormais compilé. Cela va grandement améliorée la rapidité d’execution sous Internet Explorer.

    J’ai pris en vidéo les comparaisons de performance entre IE9 et FF, tout simplement bluffant.

    On peut voir sur l’image ci dessous, la différence de performance mesuré via SunSpider (outil webkit) entre IE8 (à droite) et IE9 (en rouge).

    SDC10239

    Les résultats détaillé du benchmarking sont disponible ici : Webkit SunSpider JavaScript Benchmark Results 

    La Technologie preview de IE9 est désormais disponible en téléchargement : http://ie.microsoft.com/testdrive/. Ce site regroupe également les différentes démos de HTML5, les tests de performances, etc. Les previews de IE9 seront mis à jour toutes les 8 semaines environ.

    Microsoft continue de travailler sur le support des standards, la preview actuelle atteint 55% au test Acid3.

    image

    Ils vont également contribuer à l’écriture de tests permettant de vérifier la compatibilité multi navigateur.

    Visual Studio 2010 & .net 4.0

    Scott Guthrie a ensuite repris la main et a parlé des nouveautés de Visual Studio 2010, rien de bien nouveau par rapport à la PDC09. Les nouveautés ayant déjà été largement traité sur le net, je vais laisser de coté cette partie.

    John Resig, concepteur de jQuery, a annoncé que Microsoft travaillé avec son équipe à la création d’un plugin jQuery pour gérer les templates. Je n’ai pas encore regardé en détail ces nouveautés mais cela semble fortement inspiré du moteur de template annoncé pour Microsoft ASP.net 4.0 Ajax. Ce plugin est en tout cas une très bonne nouvelle, c’est un réel manque par rapport à d’autres framework comme extjs.

    John Resig annoncant le plugin de template pour jQuery

    Open Data Protocol

    Douglas Perry nous a ensuite expliqué que l’on ne consultait plus les sites web de la même façon qu’il y a quelques années. Un navigateur n’est pas la seule solution pour “consulter” internet. On peut désormais utiliser de nombreux outils comme son téléphone, une application client lourd, un navigateur, etc … Les sites web basculent petit à petit en mode API.

    SDC10249

    C’est dans cet esprit que Microsoft à créer un standard nommé Open Data Protocol reposant sur HTTP et XML. Ce format va beaucoup plus loin que RSS, il spécifie la façon dont les données sont stockées mais aussi la façon pour y accéder, c’est à dire le format de l’url.

    Après quelques démos sur OData, Douglas a parlé de SQL Azure, il est désormais possible de créer une base de données directement depuis une interface web; une sorte de Sql Management Studio en mode web. Les bases de données SQL Azure pourront désormais exposer leurs données à travers OData en cochant simplement une case.

    SDC10247 SDC10248

    Le keynote s’est terminé par un discours de Bill Buxton sur le design et la conception des outils. Ce keynote était très riche et intéressant, le webcast est déjà disponible ici : http://live.visitmix.com/MIX10/Sessions/KEY02

    [MIX10] Keynote première journée – Windows Phone 7 et Silverlight 4

    Comme l’année dernière, me revoici à Las Vegas pour Mix10. Ce matin a eu lieu le premier keynote animé par Scott Guthrie.

    Le keynote s’est déroulé en 2 parties : Silverlight 4.0 et Windows Phone 7

    Silverlight 4.0

    Le taux de pénétration de Silverlight a considérablement augmenté, il était de 45% l’année dernière, il est désormais de 60%. Nous avons ensuite eu quelques retours sur les projets utilisant Silverlight, notamment les jeux Olympique de Vancouver. Les sources de l’application des JO sont d’ailleurs distribués en open source sur codeplex : http://smf.codeplex.com

    Puis, nous avons vu rapidement les nouveautés de Silverlight 4 : dual screen support, webcam, Microphone, etc.

    SDC10173

    Nous avons ensuite eu une démo d’une application Silverlight 4 réalisé pour eBay, cette application s’utilise en mode offline (out of browser) et permet de vendre un objet. Parmi les fonctionnalités présentées : l’utilisation de la webcam afin de récuperer la description d’un produit à partir de son code barre, le drag & drop d’une image depuis l’explorateur windows vers l’application Silverlight.

    image

    Scott a continué les annonces en expliquant que Visual Studio 2010 supportera nativement Silverlight 4, il a également annoncé la mise à disposition dès maintenant de la release candidate de Silverlight 4

    Il a rapidement parlé de blend 4, notamment au niveau du licensing ; la mise à jour Blend 3 vers Blend 4 sera gratuite.

    Windows Phone 7

    Joe Belfiore, corporate vice president de Windows Phone nous a montré les principales fonctionnalités de Windows Phone : social network, calendar, pictures, .... On voit que Microsoft a vraiment travaillé sur l’ergonomie du téléphone : finit le menu démarrer, les scrollbar minuscule, … Quand on a connu les anciennes versions de Windows Mobile, on se demande si le produit présenté est bien le “même” produit.

    imageSDC10181 

    SDC10184 SDC10185

    Ces démos nous montrent que Microsoft a clairement envie de revenir dans la bataille des “téléphones” multi usage.

    Scott nous a ensuite expliqué que l’on pouvait faire des applications Windows Phone en utilisant silverlight ou en utilisant XNA. Après quelques minutes de théorie, la pratique est arrivée. Scott à tout d’abord fait une application “Hello World” depuis Visual Studio, puis à transformé cette application en un client twitter. En quelques minutes ettrès peu de temps et lignes de code, nous avons eu une application fonctionnelle. Nous avons également vu que le développement pouvait se faire soit en utilisant un simulateur soit directement sur le téléphone.

    SDC10186

    Scott nous a ensuite annoncé que les outils pour développer des applications Windows Phone seront gratuits, une pré version des outils de développement est disponible dès maintenant : http://www.microsoft.com/express/Downloads/#2010-Visual-Phone

    SDC10191

    Enfin, nous avons eu quelques démos de projet concret tournant sur windows Phone 7. Ce qui m’a surtout séduit dans les démos, c’est l’homogénéité des outils. Tout tourne autour de Visual Studio, .net et XAML, un développeur WPF voir même Web aura très peu de mal à commencer un projet Windows Phone.

    SDC10188

    la propriété SortDirection du GridView vaut toujours Ascending

    On m’a récemment posé une question concernant la propriété SortDirection du GridView. Lorsque l’on binde un gridview en utilisant la propriété DataSource et non en utilisant un DataSourceControl, alors la propriété SortDirection retourne toujours Ascending. Il en va de même pour l’eventArgs que l’on récupere lors de l’événement Sorting du Gridview.

    Après un petit tour dans Reflector, j’ai trouvé le code suivant :

    1 // code provenant de Reflector 2 private void HandleSort(string sortExpression, SortDirection sortDirection) 3 { 4 bool isBoundUsingDataSourceID = base.IsBoundUsingDataSourceID; 5 GridViewSortEventArgs e = 6 new GridViewSortEventArgs(sortExpression, sortDirection); 7 this.OnSorting(e); 8 if (!e.Cancel) 9 { 10 // ??? 11 if (isBoundUsingDataSourceID) 12 { 13 this.ClearDataKeys(); 14 if (this.GetData() == null) 15 { 16 throw new HttpException(...); 17 } 18 this.EditIndex = -1; 19 this.SortExpressionInternal = e.SortExpression; 20 this.SortDirectionInternal = e.SortDirection; 21 this._pageIndex = 0; 22 } 23 this.OnSorted(EventArgs.Empty); 24 base.RequiresDataBinding = true; 25 } 26 }

    A la ligne 11, on voit que la propriété SortDirection est modifié seulement lorsque l’on utilise un DataSourceControl. Cela confirme donc mes constatations. Je ne comprends pas pourquoi l’équipe ASP.net à fait ce choix.

    Afin de pouvoir changer l’odre du tri, il faut manuellement persister le SortDirection dans le ViewState. Pour cela, on peut utiliser le code suivant :

    protected SortDirection CurrentDirection { get { if (this.ViewState["CurrentDirection"] != null) { return (SortDirection)this.ViewState["CurrentDirection"]; } return SortDirection.Ascending; } set { this.ViewState["CurrentDirection"] = value; } } protected void gvPouet_Sorting(object sender, GridViewSortEventArgs e) { this.CurrentDirection = CurrentDirection == SortDirection.Ascending ? SortDirection.Descending : SortDirection.Ascending; this.BindData(); }

    Au niveau de la méthode BindData, il faudra alors récuperer les données en fonction de la propriété CurrentDirection.

    Attention, ce bout de code ne fait que gérer le tri sur une seule colonne, si vous souhaitez gérer le tri sur plus d’une colonne, il faudra alors persister une collection contenant la colonne et la direction du tri.

    Vous pouvez télécharger l’intégralité des sources ici : Utilisation de la méthode Sort et SortDirection avec un GridView et ajout des flèches haut/bas sur le nom des colonnes



    Les 10 derniers blogs postés

    - Office 365: Nettoyage des versions de List Item avant migration depuis SharePoint On Premise vers SharePoint Online par Blog Technique de Romelard Fabrice le 08-08-2017, 15:36

    - Office 365: Comment supprimer des éléments de liste SharePoint Online via PowerShell par Blog Technique de Romelard Fabrice le 07-26-2017, 17:09

    - Nouveau blog http://bugshunter.net par Blog de Jérémy Jeanson le 07-01-2017, 16:56

    - Office 365: Script PowerShell pour assigner des droits Full Control à un groupe défini par Blog Technique de Romelard Fabrice le 04-30-2017, 09:22

    - SharePoint 20XX: Script PowerShell pour exporter en CSV toutes les listes d’une ferme pour auditer le contenu avant migration par Blog Technique de Romelard Fabrice le 03-28-2017, 17:53

    - Les pièges de l’installation de Visual Studio 2017 par Blog de Jérémy Jeanson le 03-24-2017, 13:05

    - UWP or not UWP sur Visual Studio 2015 ? par Blog de Jérémy Jeanson le 03-08-2017, 19:12

    - Désinstallation de .net Core RC1 Update 1 ou SDK de Core 1 Preview 2 par Blog de Jérémy Jeanson le 03-07-2017, 19:29

    - Office 365: Ajouter un utilisateur ou groupe dans la liste des Site collection Administrator d’un site SharePoint Online via PowerShell et CSOM par Blog Technique de Romelard Fabrice le 02-24-2017, 18:52

    - Office 365: Comment créer une document library qui utilise les ContentTypeHub avec PowerShell et CSOM par Blog Technique de Romelard Fabrice le 02-22-2017, 17:06