[Témoignage] Voluntis : Comment passer du WebForms au MVC sans risque : ASP.NET MVC & Testing

Suite à notre récente formation sur le passage de l’ASP.NET WebForms à l’ASP.NET MVC en exploitant le testing, notre client, Erwan de Cadoudal (Team leader chez Voluntis [éditeur de logiciels dans le domaine médical], et demandeur de cette formation), a eu l’amabilité de répondre à nos questions.

Soft’it – Quelles sont vos motivations à l’origine de ce besoin de formation MVC et Testing MVC ?

E. de Cadoudal : « Voluntis met en œuvre des applications médicales dont le code peut présenter un risque pour les patients. Par exemple nos solutions mettent en œuvre des algorithmes médicaux complexes qui permettent d’aider le patient dans sa décision thérapeutique.

Les solutions de Voluntis sont au carrefour du numérique et du thérapeutique. Dans ce contexte, MVC nous parait une solution moderne et efficace pour des déploiements dans de multiples contextes d’usage, depuis le smartphone du patient jusqu’à l’écran du médecin. Par ailleurs nous sommes convaincus que l’approche MVC et les tests unitaires sont des solutions aujourd’hui très efficaces et très pertinentes pour développer rapidement des solutions industrialisées dans le contexte très réglementé des dispositifs médicaux. »

Soft’it – De quelle manière Soft’it y a répondu ? Qu’est-ce qui vous a plu dans la réponse de Soft’it à votre besoin ?

E. de Cadoudal : « L’approche de Soft’it nous a convaincu car le plan proposé a été était fait sur mesure avec une prise en compte de nos besoins et de nos équipes. La décision de suivre la formation dans nos locaux pour un nombre significatif de développeurs a été déterminante.
De plus certains exemples illustrant les exercices étaient proches de notre métier et nous parlaient bien. Par exemple pour nous il est plus clair de parler de liste de patients que de liste de bons de commande. Bien que cette session nous a paru un peu trop concentrée, chacun d’entre nous est reparti avec bases communes et des exemples concrets : du code et des présentations.

Nous avons également pu apprécier le dynamisme, l’expertise et le professionnalisme des équipes de formation, qui ont permis de conserver un bon rythme et de faciliter des échanges constructifs, et ont été des facteurs clés du succès des formations que nous avons suivies.« 

Soft’it – Quels sont les résultats et/ou quelle dynamique cette approche a-t-elle amené ?

E. de Cadoudal : « L’intégration des patterns « MVC », initiés par nos équipes de R&D en 2014, devient le modèle de référence pour les nouveaux projets de Voluntis. La formation nous a permis de mieux appréhender cette technologie et ses impacts sur notre méthodologie de travail.

En parallèle, nous travaillons en étroite collaboration avec nos équipes de tests et validation pour augmenter la couverture de notre code par du test unitaire. Nous anticipons que l’automatisation de ceux-ci, couplée à nos méthodologies Agile, nous permettra de réduire significativement notre investissement de tests tout en améliorant la qualité de nos produits. »

Soft’it – Nous recommanderiez-vous ? Comptez-vous refaire appel à nous ?

E. de Cadoudal : « Seulement une partie des développeurs a suivi la formation, nous comptons remonter une session identique à la précédente.
L’approche de Soft’it a été la bonne dans notre contexte et je recommande la formule pour des équipes techniques qui travaillent sur un framework partagé avec les développeurs. »

 

Un grand merci à Erwan pour ces réponses et ce feedback positif. L’équipe ayant suivie la formation a par ailleurs donné un 4/4 au ROTI pour Marien et Rémi !

L’équipe Soft’it se plie donc en quatre pour vous fournir les meilleures formations adaptées à vos besoins.
Contactez-nous si vous souhaitez avoir plus de renseignements.

[Formation] Comment passer du WebForms au MVC sans risque : ASP.NET MVC & Testing

L’ASP.NET MVC est la technologie web .NET depuis plusieurs années maintenant. Cette plateforme nous permet de mieux maîtriser le rendu HTML, le découplage métier/interface et surtout le testing.

Voici donc 2 sujets bien connus de l’équipe et qui tiennent à cœur à Soft’it : les applications web (ASP.NET MVC) et la qualité (testing).

Un de nos clients, Voluntis (éditeur de logiciels dans le domaine médical), a eu une problématique que grand nombre de sociétés rencontrent actuellement : comment passer de l’ASP.NET WebForms à l’ASP.NET MVC sans régression, et sans impacter les utilisateurs.

Même si une application WebForms fonctionne correctement depuis des années, il y a un moment où la dette technique devient un frein aux améliorations et vous coûte plus cher que les évolutions ne peuvent vous apporter.
Nous l’avons constaté avec tous nos clients, il est nécessaire de toujours prendre le temps de rester « aux goûts du jour » afin d’être en mesure de toujours proposer des nouveautés, et surtout de ne pas décourager vos développeurs en travaillant sur des technos « moins sexy ».

L’un des gros avantages du MVC est la facilité à appliquer du test sur la plupart des couches de votre application (Modèle, Contrôleur, voire Vue). Pourquoi ne pas utiliser cet avantage précis pour migrer sans risque ?!

formation-mvc-voluntisC’est sur cette base que nous avons construit une formation sur-mesure pour 10 développeurs/architectes de chez Voluntis :

  • jour 1 : introduction à l’ASP.NET MVC et aux bonnes pratiques, puis exemples de passage du WebForms au MVC
  • jour 2 : introduction à la notion de testing et comment tester une application MVC

La pratique étant le meilleur moyen d’apprendre, chaque jour fut composé en moyenne de 40% d’atelier !

Pour remplir cette mission, nous avons envoyé 2 membres de l’équipe Soft’it :

Marien Monnier
Rémi Lesieur-Bridel

Le résultat : une formation sur-mesure calée aux besoins de Voluntis, un travail exemplaire de Marien et Rémi, une équipe très satisfaite (4/4 au ROTI pour tout le monde) et un client ravi :

De plus, Erwan de Cadoudal (Team leader chez Voluntis, et demandeur de cette formation), nous a fait un témoignage très positif.

Si vous souhaitez faire une formation technique et/ou qualité sur-mesure, contactez-nous.

Eviter les « Duplicate Headers » (error 349) lors de l’envoi d’un fichier dans la HTTP Response

Pour offrir la possibilité aux utilisateurs de télécharger un fichier généré depuis un navigateur, il faut en général envoyer le flux ou un chemin de fichier directement dans la HTTP Response, tout en enrichissant les Headers HTTP pour définir le nom du fichier et son type MIME.

Exemple en ASP.NET

// définit au navigateur que c'est un fichier à télécharger, et que son nom est "monfichier.pdf"
Response.AddHeader("Content-Disposition", "attachments; filename=monfichier.pdf");
// spécifie au navigateur que le fichier doit être traité comme un PDF
Response.ContentType = "application/pdf";
// envoi du flux ou d'un fichier physique
Response.OutputStream.Write(monstream); ou Response.WriteFile(chemin_vers_mon_fichier);

Si vous rencontrez une erreur « Duplicate Headers » (ou « En-têtes doubles envoyés par le serveur ») lors du téléchargement d’un fichier, c’est que vos entêtes HTTP ne respectent probablement pas les normes standard RFC 2231/5987.

Duplicate Headers Error 349
(net::ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_DISPOSITION)

Pour plus d’informations, je vous invite à lire ces normes mais en ce qui nous concerne dans cet exemple, les headers HTTP, et plus particulièrement la valeur du paramètre « filename », ne doivent tout simplement pas contenir de caractère unicode (« é, %, ‘,’, ‘;’….).

A l’heure actuelle, seul le navigateur Chrome intercepte ces mauvais formatages d’header en erreur; les autres navigateurs quant à eux les ignorent (pour l’instant, je suppose). Par conséquent, vous ne devriez rencontrer cette erreur que sur Chrome.

Tentez alors de suivre ces 2 recommandations pour éviter les « duplicate headers »:

1. Encadrer le nom de votre fichier avec des  » (double-quotes)

Response.AddHeader("Content-Disposition", "attachments; filename="monfichier.pdf"");
au lieu de 
Response.AddHeader("Content-Disposition", "attachments; filename=monfichier.pdf");

2. Formater le nom de votre fichier en respectant les normes RFC 2231/5987
Votre fichier ne doit par exemple pas contenir de : ‘,’ , ‘.’, ‘;’…

attachments; filename=mon_fichier_test.pdf
au lieu de
attachments; filename=mon,fichier.test.pdf

A noter qu’en ASP.NET MVC, l’envoi de fichier vers la réponse est géré par FileResult et FileStreamResult (qui hérite du premier).
Si on décompile les sources de ces classes, on peut voir qu’il y a une méthode servant à formater directement le nom du fichier (
System.Web.Mvc.FileResult):

public static string GetHeaderValue(string fileName)
{
// If fileName contains any Unicode characters, encode according
// to RFC 2231 (with clarifications from RFC 5987)

foreach (char c in fileName)
{
if ((int)c > 127)
        {
             return CreateRfc2231HeaderValue(fileName);
        }
    }
// Knowing there are no Unicode characters in this fileName, rely on
    // ContentDisposition.ToString() to encode properly.
    // In .Net 4.0, ContentDisposition.ToString() throws FormatException if
    // the file name contains Unicode characters.
    // In .Net 4.5, ContentDisposition.ToString() no longer throws FormatException
    // if it contains Unicode, and it will not encode Unicode as we require here.
    // The Unicode test above is identical to the 4.0 FormatException test,
    // allowing this helper to give the same results in 4.0 and 4.5.        
 
    ContentDisposition disposition = new ContentDisposition() { FileName = fileName };
    return disposition.ToString();
}
private static string CreateRfc2231HeaderValue(string filename)
{
StringBuilder builder = new StringBuilder("attachment; filename*=UTF-8''");
    byte[] filenameBytes = Encoding.UTF8.GetBytes(filename);
    foreach (byte b in filenameBytes)
    {
        if (IsByteValidHeaderValueCharacter(b))
        {
        builder.Append((char)b);
        }
        else
        {
             AddByteToStringBuilder(b, builder);
        }
    }
    return builder.ToString(); }
// Application of RFC 2231 Encoding to Hypertext Transfer Protocol (HTTP) Header Fields, sec. 3.2
// http://greenbytes.de/tech/webdav/draft-reschke-rfc2231-in-http-latest.html

private static bool IsByteValidHeaderValueCharacter(byte b)
{
if ((byte)'0' <= b && b <= (byte)'9')
    {
    return true; // is digit
    }
    if ((byte)'a' <= b && b <= (byte)'z')
    {
    return true; // lowercase letter
    }
    if ((byte)'A' <= b && b <= (byte)'Z')
    {
    return true; // uppercase letter
    }
    switch (b)
    {
    case (byte)'-':
        case (byte)'.':
        case (byte)'_':
        case (byte)'~':
        case (byte)':':
        case (byte)'!':
        case (byte)'$':
        case (byte)'&':
        case (byte)'+':
        return true;
    }
    return false;
}

Avec tout ça, vous devriez donc pouvoir éviter les erreurs Duplicate Headers.

Source: http://www.gangarasa.com/lets-Do-GoodCode/tag/err_response_headers_multiple_content_disposition/

[MVC] Corriger les liens CSS relatifs dans un StyleBundle

Récemment, pour un nouveau projet en MVC 5, nous avons utilisé Bootstrap et jQuery DataTables.

Afin de mieux s’intégrer à « l’esprit » Boostrap, DataTables intègre un fichier JavaScript (dataTables.bootstrap.js) et un fichier CSS (dataTables.bootstrap.css).

Nous avions décidé d’ajouter ce fichier CSS à un StyleBundle dans BundleConfig.RegisterBundles :

bundles.Add(new StyleBundle("~/Content/bootstrap-datatable").Include(
            "~/Content/DataTables-1.10.0/css/dataTables.bootstrap.css"));

En local tout fonctionnait correctement, mais une fois sur le serveur d’intégration, les images de tri de DataTables n’apparaissaient pas. En regardant avec l’outil de développeur de Chrome, on peut voir que nous avions des erreurs 404 sur nos images :

Failed to load resource: the server responded with a status of 404 (Not Found) http://xxx/images/sort_desc.png

Après analyses, nous avons détecté que dataTables.bootstrap.css spécifie des chemins relatifs pour ses images :

table.table thead .sorting { backgroundurl('../images/sort_both.png') no-repeat center right; }
table.table thead .sorting_asc { backgroundurl('../images/sort_asc.png') no-repeat center right; }
table.table thead .sorting_desc { backgroundurl('../images/sort_desc.png') no-repeat center right; }

Le navigateur Web recherche donc les images en relatif par rapport au chemin de notre Bundle (~/Content/boostrap-datatable) et non pas en fonction du chemin relatif du fichier css (~/Content/DataTables-1.10.0/css/dataTables.boostrap.css).

Pour régler ce problème, la solution est très simple : il suffit de passer un IItemTransform à votre StyleBundle, et plus spécifiquement, le CssRewriteUrlTransform qui réécrit automatiquement les URLs des fichiers CSS inclus dans le StyleBundle.
Il vous suffit juste d’ajouter le CssRewriteUrlTransform à votre Include:

bundles.Add(new StyleBundle("~/Content/bootstrap-datatable").Include(
  "~/Content/DataTables-1.10.0/css/dataTables.bootstrap.css"new CssRewriteUrlTransform()));

A présent, nos images ont réapparu, et nous n’avons plus d’erreur 404. En analysant le CSS généré avec Chrome, on peut voir que les URLs du bundle ont été réécrites en fonction du chemin du fichier CSS :

table.table thead .sorting_desc {
    backgroundurl(/Content/DataTables-1.10.0/images/sort_desc.png) no-repeat center right;
}

Edit du 1er octobre 2014 :

Si vous utilisez une application dans un virtual directory (autre que dans la racine /), cette solution ne fonctionne pas. En effet, il n’ajoute pas le préfixe de l’application.

Dans ce cas, vous devez créer votre propre IItemTransform tout en utilisant CssRewriteUrlTransform auquel vous fournissez le chemin corrigé :

public class CssRewriteUrlTransformWrapper : IItemTransform
{
    public string Process(string includedVirtualPath, string input)
    {
        return new CssRewriteUrlTransform().Process("~" + VirtualPathUtility.ToAbsolute(includedVirtualPath), input);
    }
}

Source : http://aspnetoptimization.codeplex.com/workitem/83