Quelques outils que tout bon développeur .Net devrait utiliser sur ses projets

icon Tags de l'article : , , , ,

Mai 15, 2018
J'ai entendu dire, il y a longtemps, que Bill Gates avait dit :



Et c'est vrai. Quelqu'un qui n'aime pas travailler inutilement trouvera toujours des voies pour travailler plus efficacement et supprimer les tâches chiantes inutiles.

Au fil des années, je me suis rendu compte que trop peu de développeurs se posaient une question pourtant évidente : quelle tâche quotidienne et contraignante pourrais-je simplifier dans mon process de développement/test ?

La réponse est souvent : ben merde y'en a plein en fait !!!

Qu'il s'agisse de purger la base de données, de créer un compte utilisateur, de remplir la BDD avec de fausses données... il y a souvent énormément de tâches qu'un développeur pourrait automatiser pour vite gagner un maximum de temps. Et si en plus ce développement est mutualisé entre les développeurs... ben c'est un gain énorme pour toute l'équipe.

Pour ça, je voulais partager avec vous les outils que tout bon développeur .Net devrait utiliser pour ça.

1) Une extension Visual Studio

Coder sa propre extension Visual Studio n'est pas forcément évident... mais ça peut vous permettre de gagner un maximum de temps en ajoutant directement dans VS les choses chiantes que vous devez faire régulièrement.

Quelques exemples (dont certains tirés de l'extension VS de mon poste actuel) :
  • purger la base de données
  • créer un compte utilisateur de test
  • démarrer le noeud Selenium
  • tuer tous les process Chrome Selenium qui restent
  • changer la configuration de la BDD (local / tests de perfs / preprod)
  • etc.

Avoir ces options directement dans votre Visual Studio peut vous faire gagner un temps précieux. Car même juste 2 minutes par jour, sur une année ça représente une journée entière de travail...

2) Le #if DEBUG

En local, on a parfois besoin d'avoir des fonctionnements différents du fonctionnement en production. Que ce soit à cause du cache, de la quantité de données, ou même de l'initialisation de la base de données... on a parfois envie d'avoir un fonctionnement différent, pour se simplifier la vie.

Voici quelques exemples d'actions que j'ai pu automatiser par le passé, grâce au #if DEBUG :
  • au lieu d'aller chercher le catalogue complet de données en BDD (ce qui prenait 2 minutes à chaque lancement de l'application), on le stocke sérialisé sur le disque dur et on l'utilise comme tel (bim, 10 secondes de chargement au lieu de 2 minutes)
  • création automatique d'un compte par défaut si aucun compte n'existe déjà
  • connexion automatique au compte par défaut
  • extraction, anonymisation et stockage sérialisé dans des fichiers de données venant de la production, afin de pouvoir faire des calculs statistiques sans avoir à requêter directement la BDD de prod
  • forcer la connexion à la BDD locale

3) Un dossier de ressources

Là on est dans l'évidence, mais parfois ça ne fait pas de mal de rappeler les évidences : prenez des notes.

Vous galérez à trouver une procédure spécifique ? Notez là quand vous avez enfin trouvé.
Un collègue vous montre une procédure compliquée pour faire quelque chose ? Notez là.
Vous découvrez gadget super cool que vous pourriez avoir à utiliser plus tard ? Mettez le de côté.

Quand on développe, il faut aussi savoir prendre des notes. Personnellement, j'ai toujours un dossier de ressources (personnelles) chiffré.

Qu'est ce qu'on trouve dans le mien ? Enormément de choses :
  • Les logins/mdp pour chaque compte partagé lié à notre application
  • Des scripts windows/powershell pour certaines actions (backup d'une base de données, restauration, création d'un certificat)
  • Comment faire certaines actions simples/complexes dans la solution
  • Des scripts SQL pour certaines actions BDD (purge et réindex Azure, identifier la fragmentation des index, batch de suppression des anciens logs, etc.)
  • Des rappels sur certains concepts qui ont du mal à rentrer (oui, même après plus de 15 ans de dev, ça doit être le grand âge)

Ca peut sembler idiot, car souvent en 2/3 minutes sur stackoverflow on peut retrouver la solution... mais :
1) Ca permet d'avoir du spécifique pour notre situation
2) Si nos fichiers sont bien triés et nommés, on gagne du temps même par rapport à stackoverflow
3) Ca peut vous sauver la vie si vous devez refaire une opération compliquée (prévue à l'origine comme un one-shot, vous savez, le célèbre "ne t'en fais pas, c'est juste pour cette fois" d'il y a 6 mois)

4) Les tests unitaires

Bon, je ne vais pas insister sur l'importance des tests unitaires dans un projet, mais sachez ceci : vous pouvez très bien utiliser des tests unitaires pour automatiser certaines actions de dev/debug.

Quelques exemples :
  • Tester la connectionstring du projet
  • Vérifier que toutes les procédures stockées appelées sont bien présentes dans la BDD
  • Tester une procédure stockée
  • Vérifier qu'une convention de codage est bien respectée sur le projet (quand on a des règles spécifiques)

Ou même encore : créer des données en dur en base. Après tout pourquoi pas ?

4) Un logiciel d'automatisation dans le navigateur

Lorsqu'on fait du dev web, on a souvent besoin de remplir des formulaires pour tester certaines choses. Et remplir 10 fois d'affilée les même 10 champs... ben ça fatigue très vite.

Or... il existe une solution simple : les extensions Chrome/Firefox d'automatisation. Par exemple iMacros.

Ces extensions permettent d'enregistrer un enchainement d'actions faites dans le navigateur pour les reproduire ensuite. Grâce à ça, vous pourrez créer un compte, vous logger, remplir en formulaire, etc... en un seul clic.

5) Les tests Selenium

Même si les tests Selenium sont, à la base, conçus pour tester votre application, vous pouvez les utiliser pour de nombreuses choses pas forcément évidentes à première vue :
  • Tester une API
  • Tester l'interconnexion entre 2 applications
  • Aller vérifier l'état d'un autre service en ligne
  • Créer une surcouche de monitoring (quand vous n'avez qu'un board figé de monitoring et pas d'API)
  • ...

6) Les macros de Notepad++

Si vous ne les avez jamais utilisé, sachez que Notepad++ permet d'enregistrer toutes les actions produites sur une ligne, pour ensuite les reproduire sur toutes les lignes d'un fichier.

Vous avez un fichier où le format ne va pas du tout, vous devez passer un bloc à gauche, supprimer quelques caractères et rajouter un morceau à la fin ? Record => modifications => Fin => Jouer en boucle jusqu'à la fin => terminé.

Voilà, je pense que ça fait déjà pas mal,

Je vous ai épargné les grands classiques, comme les environnements d'intégration continue, car si vous n'en avez pas déjà, il y a de fortes chances que ce soit indépendant de votre volonté (je voulais concentrer cet article sur ce que les développeurs peuvent faire eux-même, sur leur poste).

J'espère que cet article vous a plu, bonne journée et bon dev à tous et toutes !

S'authentifier en POST avec un WebClient

icon Tags de l'article : ,

Aout 09, 2016
Hello,

Lorsqu'on est comme moi, on a tendance à aimer faire des tools qui vont scraper des pages web à l'aide d'un WebClient C#.

Sauf que voilà, il faut parfois pouvoir s'authentifier pour accéder à des pages qu'on aimerait parser... Et pour ça. Il y a une solution ! :)

Déjà, il va vous falloir une classe dérivée de WebClient qui gère les cookies et l'authentification :

// source : http://stackoverflow.com/questions/11118712/webclient-accessing-page-with-credentials
public class CookieAwareWebClient : WebClient
{
    public CookieAwareWebClient()
    {
        CookieContainer = new CookieContainer();
    }
    public CookieContainer CookieContainer { get; private set; }

    protected override WebRequest GetWebRequest(Uri address)
    {
        var request = (HttpWebRequest)base.GetWebRequest(address);
        request.CookieContainer = CookieContainer;
        return request;
    }
}

Maintenant, vous n'avez plus qu'à utiliser cette classe pour vous authentifier avec un UploadValues (en lui passant vos paramètres POST) :

using (var client = new CookieAwareWebClient())
{                
    // on spécifie que c'est du POST
    client.Headers.Add("Content-Type", "application/x-www-form-urlencoded");

    // cette ligne est ajoutée car parfois les authentifications vérifient le referer
    client.Headers.Add("Referer", "https://referer/if/needed");

    // on crée notre table clef / valeur
    var values = new NameValueCollection
    {
        { "username", "us3rn4me" },
        { "password", "p4ssw0rd" }
    };

    // on s'authentifie
    client.UploadValues("https://url/de/la/page/d/authentification", values);

    // et voilà, on n'a plus qu'à appeler les pages qui nous intéressent, accessibles désormais vu qu'on s'est authentifiés avec le UploadValues !
    var pageContent = client.DownloadString(url);
}

Et le tour est joué !

Bon dev à tous !

Modifier ses AppSettings et ConnectionStrings via les fichiers de config en .Net

icon Tags de l'article : , , ,

Juin 24, 2016
Hello,

Petit article, ça faisait longtemps :)

Aujourd'hui on va parler .Net, AppSettings et ConnectionStrings.

Lorsqu'on développe, la bonne pratique est d'utiliser les fichiers de configuration pour stocker nos paramètres d'application et nos chaines de connexion. Ce fichier de configuration s'appelle, pour ceux qui ne le savent pas, Web.Config ou App.Config. Exemple :

<appSettings>
     <add key="MyValue" value="42"/>
     <add key="MyIPAddress" value="::1"/>
</appSettings>
<connectionStrings>
     <add name="MyConnectionString" connectionString="Data Source=.\;Initial Catalog=MyDB;Persist Security Info=True;User ID=MyLogin;Password=MyPassword;MultipleActiveResultSets=True" />
</connectionStrings>

Classique vous me direz. Maintenant, savez vous comment faire pour que les valeurs de vos AppSettings et ConnectionStrings changent lorsque vous publiez en mode Release ?

Et oui, il faut modifier le fichier Web.Release.Config (ou App.Release.Config).

Dans ce fichier, vous pouvez ajouter de nouveaux AppSettings ou ConnectionStrings, mais vous pouvez aussi modifier les valeurs par défaut (du Web.config ou App.config)

Voici un exemple qui va :
  • Supprimer l'AppSettings MyValue
  • Modifier la valeur de l'AppSettings MyIPAddress
  • Modifier la valeur de la ConnectionString MyConnectionString

<appSettings>
     <add key="MyValue" xdt:Transform="Remove" xdt:Locator="Match(key)"/>
     <add key="MyIPAddress" value="1.2.3.4" xdt:Transform="SetAttributes" xdt:Locator="Match(key)" />
</appSettings>
<connectionStrings>
     <add name="MyConnectionString" connectionString="Server=tcp:myserver.database.windows.net,1433;Database=mydb;User ID=mylogin@mydb;Password=mypassword;Trusted_Connection=False;Encrypt=True;Connection Timeout=30;" xdt:Transform="SetAttributes" xdt:Locator="Match(name)"/>
</connectionStrings>

Simple non ?

En résumé, lors de la publication dans une config sélectionnée (debug, release ou autre) :
  • Supprimer une ligne: xdt:Transform="Remove" xdt:Locator="Match(key)"
  • Modifier la valeur d'une ligne : xdt:Transform="SetAttributes" xdt:Locator="Match(key)"
  • Ajouter une ligne : il suffit de l'ajouter dans le fichier concerné

Une dernière chose, non négligeable : ces modifications / suppressions n'impacteront pas votre application lorsque vous la lancez en local, même dans la configuration sélectionnée ! Pour ça, il faut faire les modifications à la main dans le web.config ou app.config.

Bon dev à tous !

Le célèbre bug du cookie ASP.Net qui disparait

icon Tags de l'article : , ,

Septembre 18, 2015
Tout le monde se fait avoir, et ça vient de m'arriver.

Alors que je développais tranquillement ma solution, je me suis rendu compte que ma connexion à l'application cassait juste après que je me sois connecté.

Après vérification, il s'avérait que mon cookie disparaissait sans raison dès que je faisais la moindre action après ma connexion.

J'ai tout vérifié, mon code de création de cookie était bon :

Response.Cookies["UserSettings"]["IdUser"] = user.Id.ToString();
Response.Cookies["UserSettings"]["Token"] = user.Token;
Response.Cookies["UserSettings"]["Name"] = user.FirstName + " " + user.LastName;

Response.Cookies["UserSettings"].Expires = DateTime.UtcNow.AddDays(WebAppConstants.COOKIE_LIFETIME);

D'où ça vient ? C'est très simple : je devais probablement faire un Response.Cookies à un endroit au lieu d'un Request.Cookies pour lire le contenu de mon cookie.

Et effectivement c'était le cas, à un endroit où j'essayais de lire mon cookie :
if(Response.Cookies["UserSettings"] != null && Response.Cookies["UserSettings"]["Name"] != null) 
{
     //...
}

En effet, en ASP.Net, dès qu'on essaie de lire un cookie avec Response.Cookies, un cookie qui sera automatiquement renvoyé au navigateur est créé.

Or comme on ne spécifie pas la date d'expiration du cookie... il s'agit du 01/01/0001. Et du coup, quand le navigateur recevra ce cookie, il se dira que son cookie existant est obsolète... et le supprimera.

Donc rappelez-vous en : dès qu'un cookie disparait sans raison après avoir été créé, il y a de fortes chances que vous ayez essayé d'y accéder en passant par Response.Cookies au lieu de Request.Cookies !