Jan 11

Je me suis récemment lancé dans le développement en WPF et MVVM et j’ai vite constaté un problème : c’est bien beau tout ce binding de propriétés, tout ces éléments automatiques mais du coup cela devient très difficile de suivre ce qu’il se passe, de mettre des points d’arrêt et de déboguer tout ce petit monde.

Pour cela, j’ai trouvé pas mal d’outil permettant de pallier ce problème. D’ailleurs je n’ai pas trouvé grand chose qui soit réellement intégré à la Visual Studio, j’imagine que c’est encore un peu trop « récent » pour que Microsoft soit correctement outillé.

Bref, le meilleur outil que j’ai trouvé à ce jour, c’est WPF Inspector.

Le principe (pour ce logiciel et généralement pour les autres) : il s’agit d’une application standalone qui affiche la liste des applications WPF actuellement lancées afin de s’attacher à son processus. Une fois la liaison établie, l’outil affiche une arborescence des éléments de l’application (fenêtres, contrôles…) avec toutes leurs propriétés.

Elle permet donc :

  • D’analyser la structure des contrôles,
  • De voir et modifier les propriétés des différents contrôles,
  • D’appliquer un point d’arrêt lorsqu’une propriété change de valeur,
  • D’accéder au DataContext et ainsi pouvoir analyser les objets sur lesquels sont mappés les contrôles, ce qui facilite l’identification de problèmes de binding,
  • De déboguer les triggers,
  • D’analyser des styles et des différents héritages afin d’identifier la cause de problèmes visuels,
  • D’analyser des ressources disponibles pour un contrôle,
  • D’identifier des problèmes de performance, maintenabilité ou stabilité grâce à un outil d’analyse qui vérifie qu’un certain nombre de règles sont respectées.

Cet outil m’a plusieurs fois sauvé la mise, donc je le recommande chaudement.

Il y a également un autre outils du même acabit : Snoop – the WPF Spy Utility qui semble fournir à peu près les mêmes fonctionnalités que WPF Inspector.

Jan 06

Dans la dernière version de ASP.NET, une fonctionnalité vraiment pratique est apparue : la transformation XML du fichier web.config.
C’est une fonctionnalité toute bête et pourtant très pratique : elle permet de modifier le fichier de configuration en fonction de l’environnement cible utilisé pour la compilation / publication du projet.
La mise en œuvre est simple, il suffit d’ajouter au projet des fichiers web.[environnement_cible].config  et d’inclure dans ces fichiers les instructions de modification (ajout de clés, changements de valeurs, suppression de clés).

Malheureusement, cette fonctionnalité n’est pas disponible pour les applications lourdes (WinForm, WPF) et leur App.Config. Enfin, pas nativement.

En effet, la structure du fichier est proche et tout ce qui est fait, c’est simplement modifier des éléments d’une structure XML, rien d’extraordinaire et il n’y a donc pas de raison que ce ne soit pas possible. Donc même si l’interface de la Visual Studio ne fournit pas ces fonctionnalités, il existe forcément un moyen !

Bon apparemment, il en existe même plusieurs car dans mes recherches j’ai croisé plusieurs plugins Visual Studio ou billets de blog expliquant l’une ou l’autre technique. J’en ai essayé plusieurs sans succès (certaines ne fonctionnent pas avec tous les modes de publication, notamment ClickOnce).

Voici une solution que j’utilise quotidiennement sur un projet donc qui semble fonctionner, même avec ClickOnce. La solution est fournie par le billet de ExceptionalCode dont je me suis fortement inspiré pour cet article.

Ajouter le support des transformations XML dans un projet non Web

Toute la magie réside dans le projet MSBuild (AppConfig.Transformation.targets / Copie locale du fichier au 10/01/2012) créé par João Angelo de ExceptionalCode.

MàJ : Comme expliqué ici, ce fichier ne fonctionne pas avec la Visual Studio 2010 SP1, pour cette version, il faut utiliser un autre fichier, corrigé par le même auteur : AppConfig.Transformation.targets / Copie locale du fichier au 03/01/2013).

Il faut donc ajouter ce fichier au projet, pour cela il faut éditer le fichier du projet de démarrage:

  • Faire un clic-droit sur le projet en question et choisir Décharger le projet (Unload Project)
  • Toujours sur le même projet, faire à nouveau un clic-droit et choisir Editer [nom du projet]. Cette action va ouvrir le fichier XML du projet et permettre son édition.
  • Effectuer les modifications suivantes :
    Avant modification :

        ...
        <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
        <Target Name="BeforeBuild">
        </Target>
        <Target Name="AfterBuild";>
        </Target>
    </Project>

    Après modification :

        ...
        <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
        <Import Project="..\Librairies\AppConfig.Transformation.targets" />
        <Target Name="BeforeBuild">
        </Target>
        <Target Name="AfterBuild">
        </Target>
    </Project>

    Ici je considère que le fichier AppConfig.Transformation.targets se trouve dans un répertoire Librairies à la racine de la solution, dans le répertoire parent du projet.

Et voilà, il ne reste plus qu’à créer un fichier de configuration pour chaque environnement cible, en respectant le format de nommage App.[environnement_cible].config comme ici :

Par contre, en suivant la procédure jusqu’ici, par défaut la Visual Studio n’affiche pas les différents fichiers App.[env].config de manière hiérarchique comme c’est le cas sur la capture d’écran ci-dessus.

Pour cela, il faut :

  • Repasser en mode édition XML du fichier du projet (comme déjà fait dans la section précédente)
  • Repérer les déclarations pour les fichiers App.[env].config, par exemple :
    <None Include="App.Debug.config" />
  • Pour chaque fichier de configuration (sauf App.config bien sûr), il faut ajouter un sous-élément indiquant que ce fichier est dépendant de App.config
    <None Include="App.Debug.config">
        <DependentUpon>App.config</DependentUpon>
    </None>

Lorsque le projet sera rechargé, tous les fichiers de configuration seront bien affichés de manière hiérarchique sous App.config.

Les instructions de modification à mettre dans ces fichiers sont détaillées ici et seront peut-être l’objet d’un autre billet.

Nov 25

Ce billet présente quelques astuces permettant de rendre les instructions Linq plus lisibles, plus facilement maintenables et plus performantes.
J’ai déjà utilisé ces astuces dans des cas réels, avec parfois des résultats assez impressionnants !

Where().Count() > 0

Il s’agit d’une instruction très fréquemment rencontrée :

if(myList.Where(p => p.Age > 18).Count() > 0)

Or, ce que veut savoir le développeur c’est s’il y a un élément dans la liste qui correspond au critère, pas le nombre d’élément.
Sur une énumération, le Count() n’est performant que si le type sous-jacent implémente ICollection (Linq s’applique à tous les types implémentant IEnumerable) car dans ce cas, Count() va renvoyer la propriété ICollection.Count, la complexité sera O(1) dans ce cas spécifique.
Pour les autres cas, l’ensemble des éléments de la liste seront comptés un à un, la complexité sera de O(n).

De plus, dans notre cas avec le Where(), Linq va parcourir l’intégralité de la liste myList pour appliquer son filtre, puis compter le nombre de résultats. Deux opérations totalement inutiles.

Ce code devrait être remplacé par :

if(myList.Any(p => p.Age > 18))

Car Any() va renvoyer True dès qu’elle va rencontrer un élément correspondant au critère, donc il n’est pas nécessaire de parcourir toute la liste (sauf s’il n’y a aucun élément correspondant, mais dans ce cas la complexité est au pire de O(n), au mieux elle est de O(1))

A noter qu’il est toujours plus intéressant d’utiliser Any() plutôt que Count() même lorsqu’il n’y a pas de Where(), car Any() sans paramètres (permettant de savoir si l’énumération contient au moins 1 élément) a toujours une complexité de O(1).

Where().First()

Problème similaire au précédent :

var item = myList.Where(p => p.Age > 18).First()

L’objectif ici est de récupérer le premier élément correspondant à un critère.
Le souci avec ce code est le même qu’avec le Count(), c’est que cette opération implique forcément de parcourir l’intégralité des éléments, pour ensuite ne prendre que le premier.

Ainsi, utiliser le code suivant peut améliorer les performances et simplifie nettement le code :

var item = myList.First(p => p.Age > 18)

Cette astuce peut être appliquée à de nombreuses méthodes Linq, donc il est toujours intéressant de jeter un oeil aux surcharges disponibles.

via James Michael Hare

Nov 02

Une grande majorité des développeurs .Net connaissent Reflector, un excellent outil permettant de décompiler une dll ou un exe en .Net.

Personnellement, cela m’a permis d’analyser le code du Framework afin de comprendre certains comportements étranges ou bien d’analyser le code d’une dll dont je n’ai pas la source sous la main.

Malheureusement, depuis plusieurs mois Reflector est devenu payant. Il est vrai que l’outil n’est pas particulièrement cher (par rapport à son utilité pour moi, si) mais je n’ai pas du tout apprécié la manière dont cela s’est passé.
Le développeur de Reflector avait pour habitude de coder une time bomb dans son programme afin de forcer les utilisateurs à mettre à jour le logiciel (ce qui est déjà un comportement un peu limite) et avait promis que la dernière version gratuite avant la mise à place de la version payante n’en comporterait pas.

J’imagine qu’il a dû changer d’avis puisqu’il est aujourd’hui impossible de trouver une version gratuite (facilement en tout cas).
Du coup, je me suis lancé à la recherche d’un outil de remplacement, et il semblerait que de nombreuses personnes se soient lancées sur le créneau.

J’en ai testé plusieurs et le meilleur que j’ai trouvé est ILSpy.

ILSpy est open source, distribué sous licence MIT (qui dit en gros que l’on peut tout faire avec), ce qui garantit qu’il existera toujours une version gratuite. Il supporte les plugins et est visuellement et fonctionnellement quasi identique à Reflector (avant qu’il devienne payant).

Donc aucune raison de ne pas l’utiliser !

Juil 08

[.Net] Améliorations pour les SEO en ASP.NET 4

By kg DotNet, Web Commentaires fermés sur [.Net] Améliorations pour les SEO en ASP.NET 4

seoEn asp.net 4, sont apparues un certains nombre de nouvelles fonctionnalités au sujet des SEO (Search Engine Optimizations, en gros pour améliorer la qualité du référencement d’un site). Il faut dire que dans l’ensemble cela manquait pas mal car la plupart des conseils que l’on peut trouver sur les sites pour améliorer son référencement forçaient les développeurs .net à faire des bidouilles.

Donc voici quelques points qui ont été mis en place ou améliorés en asp.net 4

  • Lancement d’un nouvel outil permettant de mesurer la capacité d’un site web à être référencé correctement et qui peut faire des suggestions d’améliorations, le SEO Toolkit. Cet outil marche aussi pour des sites qui ne sont pas en ASP.NET et nécessite IIS7 sur le poste client. Par contre, récemment IIS Express est sorti, il permet de faire tourner IIS7 sur Windows XP, et peut s’installer sans être administrateur de son poste.
  • La possibilité de modifier des informations « meta » de l’entête de la page via du code (notamment Keywords et Description)
  • L’amélioration des fonctionnalités de redirection d’URL (ajouté en 3.5)
  • La méthode Response.RedirectPermanent() qui renvoie un code HTTP 301 (redirection permanente) au lieu du code HTTP 302 (redirection temporaire) qui était renvoyé avant.

Ces fonctionnalités, ainsi que des astuces pour les utiliser et améliorer la capacité de référencement d’un site asp.net, sont présentées sur ces billets :