Dot.Blog

C#, XAML, WinUI, WPF, Android, MAUI, IoT, IA, ChatGPT, Prompt Engineering

Mieux utiliser les "Master Page" de ASP.NET

Quelle belle invention que les pages maîtres (Master Page) introduites sous ASP.NET 2.0 ! Quand on pense aux contorsions nécessaires pour avoir un menu ou des bandeaux lattéraux sans cet ajout décisif, et pire quand on sait comment il fallait faire ( et qu'il faut encore faire) sous d'autres environnements...

Bref les pages maître c'est super. Mais voilà, il arrive que les pages de contenu doivent accéder à des champs de la page maître, soit pour y lire certaines informations, soit pour en écrire (cas d'un label d'info se trouvant sur une MP dont le contenu est changé par la page courante par exemple).

La (mauvaise) méthode habituelle 

Prenons l'exemple du label (que vous remplacerez mentalement par ce que vous voulez du moment qu'il s'agit d'un objet de la MP). On rencontre très souvent un code qui ressemble à cela dans les pages détails :

Label info = this.Master.Page.FindControl("labelInfo") as Label;
if (info != null) { info.Text = "information sur la page en cours..."; }

 Et encore, le test sur le null est plutôt un luxe qui ne se voit pas dans tous les codes !

Bien entendu cette méthode fonctionne, mais elle n'est franchement pas propre. Au moins pour une raison, c'est qu'une simple erreur de frappe dans le FindControl et c'est le bug, pas trop grave si le test sur null est ajouté comme dans l'exemple de code ci-dessus, mais bug quand même. En aucun cas le compilateur ne peut détecter l'erreur. Dommage pour un environnement fortement typé !

Mais ne riez pas trop vite, on rencontre des horreurs bien pire que le code montré ici : certains n'hésitent pas à transtyper la propriété this.Master.Page pour accéder directement à l'objet ! Et comme un mauvais chemin ne peut mener qu'à faire des âneries de plus en plus grosses, les éléments d'interface étant protected par défaut, pour que ça passe (en force!) les mêmes sont donc contraints de modifier la visibilité de l'objet convoité en le faisant passer en public. Dire que c'est du bricolage est très largement en dessous de la réalité.

Heureusement il existe une solution très simple qui marche et qui permet d'écrire un code de bien meilleur qualité, c'est la directive MasterType, trop peu connue et encore moins utilisée (il y a même des pervers qui en ont entendu parlé mais qui ne s'en servent pas, si, ça existe!).

La (bonne) méthode à utiliser

Elle se décompose en deux temps :

  • Temps 1 : Créer des propriétés dans la page maître
  • Temps 2 : utiliser la directive MasterType

La propriété 

Continuons sur notre exemple du label, il conviendra alors d'écrire quelque chose du genre (dans le code de la page maître donc) :

 public Label InfoLabel { get { return labelInfo; } }

Honnêtement il y a encore mieux à faire, personnellement je n'aime pas voir des objets exposés de la sorte. On créera plutôt une propriété de ce type :

public string Info { get { return labelInfo.Text; } set { labelInfo.Text=value;} }

Chacun ses préférences et ses justifications, nous venons en tout cas de répondre à la première exigence pour faire un code plus propre.

La directive

Dans le fichier .aspx de la page de contenu, il suffit d'ajouter la directive suivante :

<%@ MasterType VirtualPath="~/blabla/LaMasterPageDeMonSite.master" %>

Cette simple directement va instruire l'environnement du vrai type de la page master, et, Ô magie !, c'est la propriété this.Master qui est automatiquement typée correctement !

On peut dès lors reprendre le même code que celui proposé en introduction (celui utilisant FindControl) et le réécrire proprement en bénéficiant d'un typage fort et de tous les contrôles dignes d'un environnement comme ASP.NET :

this.Master.InfoLabel.Text = "info affiché sur la page maître";

On suppose ici avoir utiliser la méthode consistant à publier le label via une propriété. Avec la seconde méthode proposée, encore plus propre, le code sera encore plus simple et lisible :

this.Master.Info = "info affiché sur la page maître";

Conclusion

C'est pas plus joli comme ça ? ! Si, forcément...

Alors maintenant que vous savez que MasterType existe, n'hésitez pas à vous en servir... et ...

Stay Tuned !

Donner du peps à Linq ! (Linq dynamique et parser d'expressions)

J'ai eu moulte fois ici l'occasion de dire tout le bien que  je pense de LINQ, de sa puissance, de sa souplesse, de sa versatilité (de xml à SQL en passant par les objets et l'Entity Framework).

Mais une petite chose me chagrinait : toute cette belle puissance s'entendait "hard coded". Je veux dire par là que les expressions et requêtes LINQ s'écrivent en C# dans le code et qu'il semblait très difficile de rendre la chose très dynamique, sous entendu dépendant d'expressions tapées à l'exécution de l'application. En un mot, faire du LINQ dynamique comme on fait du SQL dynamique.

Ce besoin est bien réel et ne concerne pas que les sources SQL. Prenez une simple liste d'objets que l'utilisateur peut vouloir trier selon l'une des propriétés ou filtrer selon le contenu des objets... Comment implémenter une telle feature ?

Contourner ce manque en écrivant des parsers, en jonglant avec les expressions lamba et la réflexion n'est pas, il faut l'avouer, ce qu'il y a de plus simple. Mais rassurez-vous chez Microsoft des gens y ont pensé pour nous ! Seulement voila, la chose est assez confidentielle il faut bien le dire, et on ne tombe pas dessus par hasard. Ou alors c'était un jour à jouer au Lotto, voire à contrôler, selon les mauvaises langues, l'emploi du temps de sa femme !

La chose s'appelle "LINQ Dynamic Query Library", un grand nom pour une petite chose puisqu'il s'agit en réalité d'un simple fichier source C# à ajouter à ses applications.  Mais quel fichier source !

Toute la difficulté consiste donc à savoir que ce fichier existe et mieux, où il se cache... C'est là que c'est un peu vicieux, la chose se cache dans un sous-répertoire d'un zip d'exemples Linq/C#, fichier lui-même astucieusement planqué dans la jungle des milliers de téléchargement de MSDN...

Sans plus attendre allez chercher le fichier cliquant ici.

Une fois que vous aurez accepté les termes de la licence ("I Accept" tout en bas à gauche) vous recevrez le fichier "CSharpSamples.zip". Dans ce dernier (dont tout le contenu est vraiment intéressant) aller dans le répertoire "LinqSamples" puis dans le projet "DynamicQuery" vous descendrez dans une autre sous-répertoire appelé lui aussi "DynamicQuery" (non, ce n'est pas un jeu de rôle, juste un téléchargement MSDN!). Et là, le Graal s'y trouve, "Dynamic.cs".

Copiez-le dans vos projets, et ajouter un "using System.Linq.Dynamic". A partir de là vous pourrez utiliser la nouvelle syntaxe permettant de faire du LINQ dynamique. A noter que dans le répertoire de la solution vous trouverez aussi un fichier "Dynamic Expressions.html" qui explique la syntaxe du parser.

Quelles sont les possibilités de LINQ Dynamic Query Library ?

C'est assez simple, pour vous expliquer en deux images je reprend deux captures écrans tirées du blog de Scott Guthrie (un excellent blog à visiter si vous parlez l'anglais).

Voici un exemple de requête LINQ (en VB.NET, si j'avais refait la capture cela aurait été du C#, mais je ne vais pas rouspéter hein ! )

Maintenant voici la même requête utilisant du LINQ dynamique :

Vous voyez l'astuce ? Le filtrage et le tri sont maintenant passés en chaîne de caractères... Bien entendu cette chaîne peut avoir été construite dynamiquement par code (c'est tout l'intérêt) ou bien saisie depuis un TextBox rempli par l'utilisateur.

Ici pas de risque d'attaque par "SQL injection", d'abord parce que LINQ n'est pas limité à SQL et que le problème ne se pose que dans ce cas, mais surtout parce que LINQ to SQL utilise des classes issues d'un modèle de données "type safe" et que par défaut LINQ to SQL est protégé contre les attaques de ce type. Pas de souci à se faire donc.

Pour terminer j'insisterai lourdement sur le fait que LINQ ne se limite pas aux données SQL, et que l'astuce de LINQ dynamique ici décrite s'applique même à LINQ to Object par exemple. Laisser la possibilité à un utilisateur de trier une List<> ou une Collection<>, de la filtrer, tout cela en mémoire et sans qu'il y ait la moindre base de données est bien entendu possible.

LINQ est vraiment une innovation majeure en matière de programmation, pouvoir le dynamiser simplement c'est atteindre le nirvana...

Je vous laisse vous jeter sur vos claviers pour expérimenter du LINQ dynamique, amusez-vous bien !

..et surtout.. Stay tuned !

 

TDD utopie ou géniale avancée ?

Perdu dans mes pensées lors d'une pause amplement méritée je pensais à la méthode TDD et j'ai eu envie de vous livrer le fruit de mes réflexions. Après tout, bloguer c'est ça aussi.
...C'est sûr je vais passer pour un ET, aucun être humain normalement constitué n'irait penser à de telles choses pendant une pause. Mais j'assume !

Le Test-Driven Development ou développement piloté par les tests, n'est pas réellement un sujet récent, cette méthodologie est dérivée du concept "tester en premier" de l'Extreme programming, lui même une forme dérivée de l'Agile Software Development datant de 1996, dans la même veine que Scrum ou RAD en 1991, ce qui ne nous rajeunit pas.
Tout cela pouvant remonter certainement au néolithique de proche en proche. Par exemple taper sur la tête de son voisin avec la massue toute neuve qu'on vient de fabriquer histoire de tester si elle sera assez solide pour aller à la chasse était certainement le grand début de l'Agile ou piquer un silex tout taillé à un copain est finalement le début de la réutilisation voire du RAD. Dieu lui-même en reprenant les plans de fabrication et une côte d'Adam pour faire Eve faisait de la réutilisation et du design pattern. Confondre grand ordonnateur et grand ordinateur est un exercice de style osé, j'en conviens.

Bref le TDD, comme toute méthodologie, n'est que le fruit d'une lente maturation au fil des ans. Et parmi toutes celles proposées ces 20 dernières années c'est celle qui apparaît la plus sage, la mieux adaptée. Elle recentre le développement sur l'essentiel : le besoin réel et donc l'utilisateur. Techniquement elle prône une économie de mouvement évitant les errances : on ne code que ce qui est nécessaire pour que ça marche et surtout pas plus. On s'éloigne ainsi des grandes généralisation, fantasme d'informaticien, donnant lieu à des développements complexes et coûteux qui, une fois terminés, sont déjà obsolètes.

Mais est-ce une nouvelle utopie et subira-t-elle le même sort que toutes les autres méthodes de développement (à savoir se limiter à quelques termes pompeux sur les propositions commerciales et à quelques discussions autour des machines à café) ?

UML est un bon exemple du triste sort réservé aux meilleures idées de nos têtes pensantes. Même si cette mode tend à passer (remplacer par d'autres) il fut un moment ou toute "propal" se devait de faire apparaître ce terme comme toute lessive se doit au minimum d'avoir la mention "deux en un" (voire plus) sur son emballage pour se vendre.

Avant que d'excellentes méthodes comme TDD puissent s'imposer, il sera donc nécessaire de changer les mentalités, celles des dirigeants de SSII et de leurs commerciaux qui se retranchent souvent derrière la loi du marché et de la concurrence pour offrir au client ce qu'il demande au lieu de lui conseiller ce dont il a besoin, et celle des clients qui ne peuvent continuer à se dédouaner de leur ignorance s'ils désirent obtenir des logiciels fiables, maintenables et adaptés à leurs besoins et ce au meilleur prix (mais pas en dessous, la qualité se paye). 

Un long voyage nous attend donc avant qu'un tel bouleversement se produise, et TDD, comme l'XP ou l'Agile development et bien d'autres dont nous avons tous oublié les noms, finira peut-être aussi dans les nymbes brumeuses où s'évanouïssent les idées trop en avance sur les mentalités...

En attendant, essayez de développer selon TDD :  vous y gagnerez en efficace et en qualité.
Visual Studio se plie fort bien au Unit Testing, mais beaucoup moins bien au TDD. Il est fort simple de créer un test pour une méthode existante mais pas l'inverse, base du TDD. Néanmois, avec un peu d'imagination, il est tout à fait possible de créer un squelette de classe, d'y ajouter une méthode ne faisant rien puis de générer le test unitaire pour enfin revenir sur l'implémentation de la méthode. Il n'y a pas de temps perdu, il n'y a qu'à changer un peu l'ordre dans lequel les choses sont faites.

Essayez, vous verrez, c'est étonnant comme le code final d'une classe est assez différent de celui qu'il aurait été créé par la méthode "classique".

Happy coding !

Simplifier l'utilisation des expressions régulières avec Expresso

Les expressions régulières semblent être ignorées par bon nombre de développeurs malgré leur puissance. Une raison à cela : c'est aux antipodes de la programmation moderne qui se veut claire et lisible...

Les expressions régulières c'est un peu comme XSLT, balèze mais incompréhensible à moins de ne faire que ça tous les jours. Le problème avec ces "langages" c'est que justement on n'en a pas besoin tous les jours ! Et ce n'est pas en pratiquant une fois de temps en temps qu'on acquiert l'habilité nécessaire. Au final, les plus courageux qui ont essayé plusieurs fois finissent par laisser tomber...

Dommage. D'autant que les expressions régulières sont parfaitement intégrées aux frameworks modernes comme .NET, et que leur bonne utilisation permet des choses quasi magiques en une ou deux lignes d'intruction : tester la conformité d'une donnée complexe et même, ce que beaucoup ignorent, découper une données en groupes ou extraire une information dans un flot (par exemple repérer automatiquement les adresses web dans tout un texte).

Mais j'ai une solution pour vous !

J'ai trouvé un soft, gratuit, qui permet de saisir des expressions régulières, de les tester, et de les analyser (pour le debug c'est parfait, mais aussi pour.. apprendre!). Ce soft est vraiment bien fait et vaut le coup d'oeil dans tous les cas.

Je vous conseille donc de le télécharger et de le tester, vous pourrez insérer des expressions régulières complexes dans votre code et passer pour un héro à la machine à café, c'est pas cool ça ?

Ca s'appelle "Expresso" et ça se trouve là http://www.ultrapico.com/Expresso.htm.

LINQ à toutes les sauces !

Je suis en train de boucler mon article de présentation de LINQ. Au départ je pensais m'en sortir en une dizaine de pages, mais j'en suis à plus du double... juste pour faire le tour des principales possibilités et sans détailler la syntaxe (ce n'est pas le but de cet article).

J'ai eu maintes fois l'occasion de vous dire ici que LINQ est l'innovation la plus fantastique que j'ai vue depuis longtemps dans un langage. Vous en saurez plus en lisant le prochain article qui sera en ligne ce week-end, mais pour vous prouver que LINQ peut servir partout et tout le temps voici deux exemples à contre-courant de l'idée qu'on se fait des utilisations possibles de LINQ :

Cas 1 : Lister les services actifs de Windows.

C'est bête mais balayer et filtrer une simple liste comme celle là (et de bien d'autres du même genre retournées par le framework .NET ou par vos applications), c'est produire du code pas très marrant... Avec LINQ ça devient :

using System.ServiceProcess; 
var srv = from s in ServiceController.GetServices()
         where s.Status == ServiceControllerStatus.Running
         select s.DisplayName;
ListBox1.DataSource = srv.ToList();

 
Je trouve ça élégant, pas vous ?

Cas 2 : Remettre à unchecked tous les Checkbox d'une form

Balayer certains contrôles d'une fiche n'est là non plus pas l'endroit où l'on s'attend à trouver du LINQ... Et pourtant ! Imaginons une fiche de saisie avec des tas de checkbox et un bouton "raz" de remise à zéro de la fiche. Balayer tous les contrôles de la fiche pour ne sélectionner que les checkbox n'est pas un code bien complexe mais avec LINQ ça devient tellement plus chouette !

var cb = (from Control c in this.Controls select c).OfType<CheckBox>();
foreach (var c in cb) c.Checked=false;
 

C'est pas plus joli et plus clair écrit comme ça ? (et encore on pourrait se passer de la variable "cb" et intégrer directement la requête LINQ après le "in" du "foreach")?

Bref, LINQ j'adore. Et j'espère bien que le papier à venir va vous transformez en fans vous aussi ! alors... Stay tuned !

Les nouveautés syntaxiques de C# 3.0

Les expressions Lambda vous connaissez ?

Et l'inférence des types locaux, les méthodes d'extension, les expressions d'initialisation des objets ou les types anonymes ?

Si tout cela sonne bizarrement à vos oreilles, n'hésitez plus une seconde : téléchargez le nouvel article que j'ai mis en ligne gratuitement !

Voici le lien, il n'y a qu'à cliquer ici !

Vous êtes encore là ?

... Alors ne loupez pas le tout dernier article "Présentation de LINQ avec C#", un papier de 32 pages riche en exemples !