Archives par mot-clé : .NET

.NET : Génération de jeu de données avec Nbuilder et Faker.Net

Nous avons parfois besoin de jeu de données factices pour nos tests unitaires, peupler une base de données ou pour simuler un service externe par exemple. Il peut être complexe et assez lourd de créer des jeu de données. Je vais vous présenter NBuilder et Faker.Net qui sont 2 librairies pour vous aider à générer vos jeux de données. Ces 2 librairies sont disponibles sous forme de package NuGet.

NBuilder

NBuilder est une librairie qui permet de créer facilement et rapidement des objets, basé sur le design pattern builder. Il va renseigner automatiquement pour vous les propriétés publiques de vos objets. Vous pouvez bien entendu préciser comment générer certaines propriétés.
Par défaut, NBuilder crée des valeur séquentielle dans le cas des liste (Name1, Name2, …)
NBuilder fournit une classe GetRandom qui permet de générer des données aléatoire pour un certains type de données (url, nom , pays, …).

//Création d'un objet
var product = Builder<Product>
    .CreateNew()
        .With(x => x.Name = "Nexus 5")	
	.With(x => x.Price = 199)
    .Build();

//Création d'une liste
var products = Builder<Product>
  .CreateListOfSize(10)
  .All()
  .With(x => x.Name = GetRandom.String(10))	
  .With(x => x.Price = GetRandom.Int(100, 400))
  .Build();

NBuilder fournit également Pick qui permet de sélectionner un objet dans une autre liste

//Sélection d'1 seul élément
Pick<Category>.RandomItemFrom(categories))
//Sélection d'un sous ensemble d'élément
Pick<Category>.UniqueRandomList(With.Between(5).And(10).Elements).From(categories);

Faker.NET

Faker.Net est un bon complément à NBuilder car il permet de générer des valeurs plus réaliste pour les données. Faker.Net contient plus de type de données que NBuilder.

Il contient des générateurs pour:

  • Addresse: (pays, code postal, ville, …)
  • Téléphone
  • Internet (email, password, IP, …)
  • Nom
  • Date
  • Entreprise
  • Finance (Prix, Compte, …)
//Utilisation de Faker.Net avec NBuilder
var customers = Builder<Customer>.CreateListOfSize(100)
        .All()
            .With(c => c.FirstName = Faker.Name.First())
            .With(c => c.LastName = Faker.Name.Last())
            .With(c => c.EmailAddress = Faker.Internet.Email())
            .With(c => c.TelephoneNumber = Faker.Phone.Number())
        .Build();

Un petit exemple d’utilisation avec .Net Fiddle

Liens

ASP.NET MVC : Display et Editor Templates

ASP.NET MVC est un outil puissant pour créer des sites web, basés sur des conventions (Conventions over configurations). Nous allons voir dans cet article les notions de display et editor templates qui permettent la gestion du rendu d’un objet/propriété en mode affichage et édition.

Utilisation

ASP.NET MVC fournit par défaut des méthodes dans le helper Html permettant la gestion de l’affichage (DisplayFor) et l’édition (EditorFor).

@Html.DisplayFor(model => model.Title)

@Html.EditorFor(model => model.Title, new { htmlAttributes = new { @class = "form-control" } })

Par défaut, le helper générera un input en fonction du type des propriétés de votre objet. Ainsi, dans le cas d’une propriété de type string, un input de type text sera généré et dans le cas d’un bool, une case à cocher. Il est possible d’avoir un contrôle plus fin de la génération des input. Pour cela, le helper HTML met à disposition des méthodes pour chaque type de input :

  • Html.TextBox
  • Html.DropDownList

Cela est très pratique et permet de mieux contrôler le HTML généré mais vous êtes obligé de le faire dans chaque vue. Afin de palier à ce problème, il existe les DisplayTemplates et EditorTemplates. Ils permettent de définir pour chaque type comment il sera rendu en mode affichage (display) ou édition (editor). Pour cela, il faut créer des dossiers DisplayTemplates et EditorTemplates dans le dossier Views/Shared puis placer un fichier par type en le nommant type.cshtml.

Dossiers Display et Editor Template

Dans les exemples suivant, nous allons utiliser une classe Album (les annotations de validations sont volontairement omises) :

public class Album
{
    public int ID { get; set; }

    public string Title { get; set; }

    public DateTime ReleaseDate { get; set; }

    public bool isDoubleDisc { get; set; }
}

Par exemple, pour surcharger le template utilisé pour les types DateTime et bool, on créera respectivement un fichier DateTime.cshtml et Boolean.cshtml.

Nous avons vu que les booléens sont affichés sous la forme de checkbox. Voyons comment rendre votre application un peu plus jolie avec des composants ayant un meilleur rendu.
J’ai parlé dans un article précédent des web components et de polymer.

Polymer fournit une bibliothèque de composant (elements dans le jargon Polymer) prêt à l’emploi, notamment les Paper Elements, composant graphiques Material Design.

Voyons comment utiliser des paper-checkbox (la page de démo) pour les booléens grâce aux display templates.

Afin d’utiliser polymer et les elements, il faut les ajouter à la solution. Voici la documentation de polymer permettant de le faire.

Ajoutons un fichier Boolean.cshtml dans le dossier Views/Shared/DisplayTemplates :

@model System.Boolean
@if(@Model) {
    <paper-checkbox disabled checked></paper-checkbox>
} else {
    <paper-checkbox disabled></paper-checkbox>
}

L’affichage utilise maintenant un élement paper-checkbox pour les booléens.

Display Template sous la forme d'un Checkbox

Vous avez peut être remarqué que Polymer propose également un élément paper-toggle-button qui convient également pour les booléens.
ASP.NET MVC contient un attribut UIHint qui permet de spécifier un template à appliquer pour une propriété.

Ajoutons l’attribut UIHint avec la valeur Toggle sur la propriété IsDoubleDisc.

[UIHint("Toggle")]
public bool IsDoubleDisc { get; set; }

Définissons maintenant un fichier Toggle.cshtml dans le dossier DisplayTemplates avec le code suivant :

@model System.Boolean
@if(@Model) {
    <paper-toggle-button disabled checked></paper-toggle-button>
} else {
    <paper-toggle-button disabled></paper-toggle-button>
}

Automatiquement, le champs IsDoubleDisc sera affiché avec un toggle !

Display Template sous la forme d'un Toggle

Il est également possible de créer des templates pour vos propres modèles.

Voici un exemple avec une classe Address :

@model DemoMVC5.Models.Address
 <dl class="dl-horizontal">     
     <dt>
         @Html.DisplayNameFor(model => model.Street)
      </dt>
      <dd>
         @Html.DisplayFor(model => model.Street)
      </dd>
      <dt>
         @Html.DisplayNameFor(model => model.ZipCode)
      </dt>
      <dd>
         @Html.DisplayFor(model => model.ZipCode)
      </dd>
      <dt>
         @Html.DisplayNameFor(model => model.City)
      </dt>
      <dd>
         @Html.DisplayFor(model => model.City)
      </dd>
      <dt>
         @Html.DisplayNameFor(model => model.Country)
      </dt>
      <dd>
         @Html.DisplayFor(model => model.Country)
      </dd>
  </dl>

Vous pourrez alors utiliser @Html.DisplayForModel et éviter de dupliquer votre code dans plusieurs vues.

@model DemoMVC5.Models.Address
<div>
    <h4>Your Address</h4>
    Html.DisplayForModel()
</div>

Si un de vos objets a une propriété Address, l’affichage se fera via :

@model DemoMVC5.Models.User
<div>
    <h4>Your Information</h4>
    Html.DisplayFor(model => model.Name)

    Html.DisplayFor(model => model.Address)
</div>

Conclusion

Display et Editor templates sont des fonctionnalités méconnues de ASP.NET MVC. Elle permettent de facilement modifier l’affichage d’une classe dans votre site de manière simple et sans duplication de code.

Liens

.Net : Utilisation de Aggregate de LINQ

La version 3.5 de .NET a introduit LINQ qui permet de faciliter le requetage de source de données hétérogène (base de données, fichier XML, objects, …).

LINQ s’inspire beaucoup de la programmation fonctionnelle.

LINQ contient Lesplusieurs fonctions d’agrégations comme : Sum, Average, Count, Max et Min. Aggregate est la plus flexible et générique méthode d’agrégation.

la fonction Aggregrate permet d’itérer sur la collection et d’appliquer une fonction sur chaque élément afin de calculer un résultat. Dans les langages (JavaScript, F#, …) ou librairies fonctionnelles (lodash/underscore), la fonction s’appelle généralement reduce.

Voici un petit exemple d’utilisation de Aggregate qui permet de calculer la somme totale des prix * quantité d’une liste de produits :

Dans l’exemple ci dessus, current corespond a la valeur calculée suite à l’exécution des éléments précédents de la collection.
Ainsi dans notre exemple, pour le premier élément, current vaut 0. Puis 3 * 399,99 soit 1199,97 pour le deuxième et 3 * 399,99 + 100 * 399,99 soit 5199,87 pour le troisième élément.

Sachez qu’Aggregate a également une signature qui permet de passer une valeur par défaut pour current.

Liens

.NET : Améliorez vos tests unitaires avec Moq et NFluent

Une des bonnes pratiques d’un projet informatique est la mise en place de tests unitaires. Je vais vous présentez 2 librairies, disponible sous forme de package NuGet, pour vous aidez dans l’écriture de tests.

Moq

Le but d’un test unitaire est de tester un composant isolé, d’où la nécessité d’utiliser une librairie permettant de faire du Mock. J’utilise pour cela Moq.

Les exemples de tests suivant utilisent NUnit comme framework de tests unitaires. Afin de pouvoir facilement remplacer les dépendances des classes à tester, j’utilise Unity comme container d’injection de dépendance (IoC). Vous allez ainsi pouvoir facilement passer à votre classe dans le constructeur votre Mock.

Voyons comment configurer et effectuez des assertions sur vos mock avec Moq :

using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using NFluent;
using NUnit.Framework;

namespace Demo.Tests
{
    [TestFixture]
    public class MyServiceTests : BaseServicesTests
    {
        private Mock<IMyService> myServiceMock;
        private Mock<ILogger> loggerMock;
        
        private IMyClass myClass;

        [SetUp]
        public override void SetUp()
        {
            base.SetUp();

            //Create Mocks
            myServiceMock = new Mock<IMyService>();
            loggerMock = new Mock<ILogger>();
                                  
           //We pass our mock to the instance to test
           myClass = new MyClass(myServiceMock, loggerMock);
        }

        [Test]
        public void MyMethodShouldReturnTrue()
        {
            //Setup method on service to return expected value to test our case
            //Here we setup to return an empty list of string
            myServiceMock.Setup(m => m.GetData()).Returns(new List<string>());
            
            var result = myClass.MyMethod();
            //Verify the result is what is expected
            Check.That(result).IsTrue();
            //Verify that our mock has been called
            myServiceMockSetup.Verify(m => m.GetData(), Times.Once);
        }
    }
}

Moq fournit un ensemble de méthodes permettant de configurer (Setup + Returns/Callbacks) et d’effectuer des tests sur les mocks (Verify).
On peut par exemple vérifier le nombre d’appel d’une méthode, les paramètres, …

Voici comment vérifier qu’un méthode prenant un paramètre de type string a bien été appelé 2 fois avec comme valeur de paramètre « MyTestString »

myServiceMock.Verify(r => r.MyMethod(It.Is<string>(x => x == "MyTestString")), Times.Exactly(2));

Le guide de démarrage de Moq

NFluent

Comme vous avez pu peut être le remarquer, je fais pas mal de JavaScript en ce moment et j’aime beaucoup les librairies de tests style jasmine, should, … qui permettent de décrire les assertions de manière plus lisibles. En .Net, j’utilise NFluent qui permet d’avoir une API d’assertion fluent où l’on peut chaîner les assertions à la suite les une des autres.

Check.That(julien)
    .IsNotNull()
    .And.IsNotEqualTo(david)
    .And.IsInstanceOf<Person>();

Dans l’exemple ci-dessus, je vérifie que le l’objet julien n’est pas null, n’est pas égal à david et que cet objet est une instance de la classe Person.

D’autres exemples d’assertions :

//Collections
//Nombre d'élément d'une collection
Check.That(persons).HasSize(3); 
//Il existe une personne ayant la propriété Name égale à Julien
Check.That(persons.Extracting("Name")).Contains("Julien"); 

//Test des exceptions
Check.ThatCode(() => myService.MyMethod())
    .Throws<MyException>()
    .WithMessage("MyMessage")
    .And.WithProperty("MessageKey", "MyMessageKey");

Voici des exemples d’assertion avec NFluent.

Liens

Bon tests 🙂 …

.Net : Améliorer la qualité de votre code avec NDepend

Je vais vous parler de NDepend qui est un outil très complet d’analyse de code .NET à l’instar de Microsoft Code Analysis (ex FxCop) / ReSharper.

NDepend est un outil payant offrant un grand nombre de fonctionnalités :

  • Faire des requêtes CQLInq (style LINQ) sur son code. (près de 200 sont fournies par défaut)
  • Détection des dépendances cycliques
  • Créer des règles CQLinq
  • Qualité de code avec plus de 80 règles inclues de base.
  • De nombreux graphiques : matrice de dépendances, …
  • Code Quality regression : comparaison entre 2 snapshots de code

Le plus simple pour découvrir cet outil est de regarder la présentation de NDpend par son créateur lors des Techdays 2014 :

NDepend est très pratique pour assurer un code de qualité sur la durée d’un projet avec des métriques pertinentes et configurable. C’est également un outil puissant lors d’audit de code d’un projet.

Liens

.NET / Unity : Récupérer un type parmi plusieurs implémentations

Une application est souvent séparée en plusieurs couches, chacune ayant une responsabilité bien définie :

  • Présentation
  • Accès aux données
  • Gestion des règles métiers

Afin d’avoir une application maintenable et testable il est nécessaire d’avoir un faible couplage entre les différentes briques de votre application.
Ce découplage passe par des interfaces qui vont définir le rôle de chaque brique et ce quelles sont capable de faire. Ainsi une brique ne sera pas dépendante d’une implémentation mais d’une interface. Par exemple, la couche présentation est liée via des interfaces à des services. Elle ne sait pas qui implémente ses services. La couche de présentation n’a pas de référence à une implémentation particulière des interfaces des services. On pourra ainsi facilement bouchonner (mock : renvoi de données de test) afin de tester plus facilement son application.

C’est la qu’intervient Unity.

Présentation de Unity

Unity est un conteneur d’injection de dépendances. Il fait partie des patterns & pratices de Microsoft. Unity va vous permettre de définir dans votre application qu’elle est la classe qui implémente une interface et va vous retourner pour vous une instance de cette classe.

La configuration de Unity peut se faire de 2 façons :

  • par code (via le méthode RegisterType)
  • par fichier xml

Je préconise de passer par un fichier XML qui lui permet de ne pas recompiler l’application.

Voici un exemple de configuration qui permet de définir qu’il faut utiliser la classe MonService lorsque l’on a besoin d’une interface IMonService.

<unity xmlns="http://schemas.microsoft.com/practices/2010/unity">
    <containers>
      <container>
        <types>
          <!-- Business services -->
          <type type="MyInterfaces.IMonService,MyInterfaces" mapTo="MyServices.MonService, MyServices"></type>
        </types>
      </container>
    </containers>
</unity>

La résolution par code se fait via la méthode Resolve sur le conteneur :

myContainer.Resolve<MyInterfaces.IMonService>();

Implémentation multiples d’une interface

Dans certains cas, il est possible que vous ayez besoin de plusieurs implémentations d’une même interface. (exemple : communication avec des machines ayant un protocole différents. On va ainsi utiliser le design pattern Commande qui va nous permettre d’avoir une seule interface de communication. Les implémentations permettent de masquer les différences de protocoles).
Il est possible de différentier les implémentations d’une même interface en spécifiant lors de la configuration de Unity un nom via l’attribut name.

Configuration par xml

<type type="MyInterfaces.IMonService, MyInterfaces" mapTo="MyServices.MonService1, MyServices" name="MonInterface1"></type>
<type type="MyInterfaces.IMonService, MyInterfaces" mapTo="MyServices.MonService2, MyServices" name="MonInterface2"></type>
<type type="MyInterfaces.IMonService, MyInterfaces" mapTo="MyServices.MonService, MyServices" name="MonInterface3"></type>

Configuration par code

myContainer.RegisterType<MyInterfaces.IMonService, MyServices.MonService1>("MonInterface1" ) ;

La résolution se fera via le code suivant :

myContainer.Resolve<MyInterfaces.IMonService>("MonInterface1");

Liens

.NET : Partager un numéro de version entre plusieurs projets

Lors de la création d’une application .net, il est commun de la séparer en plusieurs projets au sein d’une même solution (IHM, Service, DataAccess, Model, …). Il existe plusieurs stratégie concernant le versionning de chaque composant. Voyons comment associer un numéro de version commun à un ensemble de dll. (Je remercie mon collègue Ludovic qui a mis en place ce mécanisme sur les projets sur lesquels je travaille)

Pour mon exemple, J’ai créé une solution contenant 2 projets :

  • Un projet de type Class Library
  • Un projet de type Console Application.

L’application console a une référence vers le projet MyClassLibrary.

ShareVersion_Projects

Le numéro de version est définit par les attributs AssemblyVersion et AssemblyFileVersion présent dans le fichier AssemblyInfo.cs (dans le dossier Properties du projet).

using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;

// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("ConsoleApplication")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("ConsoleApplication")]
[assembly: AssemblyCopyright("Copyright ©  2013")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]

// Setting ComVisible to false makes the types in this assembly not visible
// to COM components.  If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]

// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("b9380bae-102a-4a41-b981-bfecfa948bcc")]

// Version information for an assembly consists of the following four values:
//
//      Major Version
//      Minor Version
//      Build Number
//      Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]

Chaque projet contient le fichier AssemblyInfo.cs et la mise à jour de chaque fichier est nécessaire pour mettre à jour les versions de chaque projet. Cela peut définir vite fastidieux dans le cas d’un grand nombre de projet (à partir de 2, en fait … 🙂 ).
Voyons comment avoir des dlls ayant un numéro de version partagé.
Dans un premier temps, nous allons créer un dossier Common à la racine du projet qui contiendra un fichier SharedAssemblyVersion.cs

ShareVersion_SharedAssemblyInfo

Supprimez le contenu et coller la partie du fichier AssemblyInfo.cs concernant la gestion des versions.

using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;

// Version information for an assembly consists of the following four values:
//
//      Major Version
//      Minor Version
//      Build Number
//      Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]

Pour chaque Projet pour lesquels vous souhaitez avoir un numéro de version commun, ouvrez le fichier AssemblyInfo.cs et supprimez la partie concernant la gestion de version.
Puis pour chaque Projet, ajouter en tant que lien le fichier SharedAssemblyVersion.cs. Pour cela, faites un clic-droit sur le projet, puis Add > Existing Item … .

ShareVersion_AddExistingItem

Sélectionnez le fichier SharedAssembly et ajoutez le en tant que lien (Cliquer sur la flèche du bouton Add et sélectionner Add as Link)

ShareVersion_AddAsLink

L’ajout en tant que lien est très important car sinon le fichier est copié et les modifications apportés au fichier commun ne seront pas prises en compte pour les fichiers non ajoutés en tant que lien.
Le fichier étant ajouté à la racine, déplacez-le dans le dossier Properties du Projet.

ShareVersion_SharedFileLinked

L’icône du fichier contient une flèche bleue indiquant que ce fichier est un lien vers un fichier existant.
La modification du numéro de version du fichier commun mettra à jour la version de tous les projets. (ici mise à jour vers un numéro de version 1.1.2.0)

Version des dlls

ASP.NET MVC3 : Mise en place du bundling et minification

La minification est une technique permettant de minifier (allégement du poids d’un fichier) et le Bundling, de regrouper des fichiers CSS et JavaScript afin d’optimiser les performances d’un site Web en limitant les appels aux serveurs.

Il faut savoir que votre navigateur va effectuer un appel au serveur pour chaque fichier de votre page. Plus le nombre sera élevé, plus le chargement de votre page sera long. Qui plus est, un navigateur possède une limite concernant le nombre de téléchargement de fichiers simultanés pour un même domaine. Ainsi, une fois cette limite attente, les fichiers suivant devront attendre la fin du chargement des fichiers précédents. Cette limite est actuellement à 6 pour la majorité des navigateurs.

La minification et le bundling vont permettre d’améliorer le temps de chargement de vos pages. MVC4 inclut la bibliothèque permettant de mettre en place ces techniques. Voyons comment l’installer sur un projet MVC3.

Installation de la librairie de Bundling

Il faut installer le package Microsoft ASP.NET Web Optimization Framework via le gestionnaire de paquet NuGet, qui se chargera d’installer les dépendances du package.

Il est posssible de l’installer via la console Nuget soit via le gestionnaire graphique de NuGet.

Via la console

Ouvrir la console Nuget

Lancer la commande :

Install-Package Microsoft.AspNet.Web.Optimization -Pre

Via le gestionnaire graphique

Il faut lancer le gestionnaire graphique en faisant un clic droit sur le projet ASP.NET et cliquer sur Gérer les packages NuGet ….

Lancement du gestionnaire NuGet

NuGetPackager-MVCOptimization

Le paquet étant actuellement en version alpha, il faut sélectionner « Inclure les versions préliminaires » et effectuer une recherche avec le terme Optimization. Il faut ensuite installer le paquet Microsoft ASP.NET Web Optimization Framework.

Utilisation

Il est possible de définir nos bundles via des bundles static. (Il existait auparavant une méthode permettant de créer des bundles de manières automatique via des conventions qui a été à priori supprimée).

On peut ainsi définir un bundle en ajoutant les fichiers 1 par 1 ou par dossier :

Création d’un bundle pour un fichier

ScriptBundle jQueryBundle = new ScriptBundle("~/bundles/jquery");
jQueryBundle.Include("~/Scripts/jquery-1.8.3.js");
bundles.Add(jQueryBundle);

Création d’un bundle pour un dossier avec un pattern sur les fichiers à sélectionner

StyleBundle cssBundle = new StyleBundle("~/Content/css");
cssBundle.IncludeDirectory("~/Content/", "*.css", false);
bundles.Add(cssBundle);

Les bundles doivent être ajoutés dans BundleTable.Bundles

Le plus simple est de définir une classe BundleConfig dans le dossier AppStart qui permet de gérer les bundles comme cela est fait par défaut dans MVC4, ce qui facilitera une migration. Voici le corps de la classe

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Optimization;

namespace MonApplication.MVCApplication.App_Start
{
    public class BundleConfig
    {
        public static void RegisterBundles(BundleCollection bundles)
        {
            ScriptBundle jQueryBundle = new ScriptBundle("~/bundles/jquery");
            jQueryBundle.Include("~/Scripts/jquery-1.8.3.js");
            bundles.Add(jQueryBundle);

            // ....
        }
    }
}

Il faut ensuite rajouter dans la méthode Application_Start du fichier Global.asax.cs l’appel à la méthode d’enregistrement des bundles via le code suivant

BundleConfig.RegisterBundles(BundleTable.Bundles);

Déclaration dans le HTML

Il faut ajouter le using suivant (en razor)

@using System.Web.Optimization

Il faut ensuite utiliser les helpers mis à disposition

@Styles.Render("~/Content/css")
@Scripts.Render("~/bundles/jquery")

Il faut savoir que par défaut, l’optimisation n’est pas activée par défaut en debug (mais en release oui). Vous pouvez l’activer via :

BundleTable.EnableOptimizations = true;

Enfin, si vous avez déjà des fichiers minifiés (.min) dans votre projet, il faut déclarer les versions non minifiées dans le bundle, l’optimiseur chargera de lui même les fichiers .min de façon transparente en fonction si l’optimisation est activée ou non.

Allez plus loin

Vous pouvez créer votre propre transformation en implémentant l’interface IBundleTransform. Sachez qu’il existe déjà des implémentations pour LESS, SASS, CoffeeScript, TypeScript, … disponible sous forme de package NuGet. Il est également possible d’inclure des librairies JavaScript via des CDN avec support local. Pour en savoir plus, je vous invite à lire cet article sur le site officiel de asp.net qui présente cette fonctionnalité pour MVC4 mais qui est valable après installation du package pour les projet MVC3.

ASP.NET MVC : Adaptez vos vues selon le device

On parle de plus en plus de Responsive Web Design (RWD) afin d’adapter l’affichage d’un site en fonction du périphérique de l’utilisateur. Il existe également le Web Design Adaptatif qui permet notamment de renvoyer un contenu adapté au terminal. En effet, le poids de la page a une importance lorsque l’on a un terminal avec une connectivité limitée (un téléphone par exemple). Il se peut également que les fonctionnalités d’une version mobile soient différentes d’une version classique par exemple.

ASP.NET MVC apporte avec la version 4 la possibilité d’avoir des Display Modes adaptés en fonction du périphériques. Ainsi, vous pouvez avoir plusieurs vues (1 pour la version mobile et 1 pour la version normale par exemple) sans modifier toute votre application.

Par défaut, 2 modes sont gérés : classique et mobile. ASP.NET MVC étant très configurable et extensible, il est possible de définir ses propres modes. Le tutorial sur le site officiel sur les fonctionnalités pour le mobiles, montre comment ajouter ces modes.

WURFL / 51Degrees

Wurfl et 51Degrees sont 2 librairies qui permettent une plus grande flexibilité dans la détection des devices mobiles (en proposant une base de données permettant d’identifier les navigateurs mobiles de façon plus précise et plus sûre) et donc une gestion des définitions des modes plus précis.

Quelques liens sur l’utilisation de ces librairies avec ASP.NET MVC :

WURFL

51Degrees

/!\ Si vous utilisez T4MVC, il faut utiliser  Views.ViewNames.Index (qui renvoie le nom de la vue Index dans notre exemple) et non pas Views.Index (qui renvoi le chemin vers le fichier de la vue ex : ~/Home/Index.cshtml). En effet, le moteur renverra,  dans ce cas, tout le temps vers la vue spécifiée par le chemin et non pas la vue correspondant à votre device.

MVC3

Comme précisé précédemment, cette fonctionnalité n’a été apportée qu’avec la  version 4 de MVC. J’ai eu à mettre en place ce type de gestion avec un site en MVC 3. Il existe une extension NuGet, MobileViewEngine, qui permet le support basique de cette fonctionnalité (L’article de présentation du package sur le blog de l’auteur Scott Hanselman, membre de la Web Platform Team chez Microsoft). En effet, Il n’est pas possible d’ajouter des modes et la détection se fait via Browser.IsMobileDevice d’ASP.NET (dont la base de données n’est pas la plus à jour). Cette gestion n’étant pas adaptée dans mon cas, je suis donc parti du code source de ce package afin de le modifier et l’adapter à mon besoin en utilisant WURFL.

ASP.NET MVC : Supprimer les moteurs de vues inutilisés

En ASP.NET MVC, il y a 2 moteurs de vues (View Engine) configurés par défaut (Vous pouvez créer vos propres moteurs de vue ou en utiliser d’autres moteurs existants) :

  • WebFormsViewEngine pour les vues en .aspx (et .acsx)
  • RazorViewEngine pour les pages en Razor .cshtml.

Dans la plupart des cas, une application n’utilisera qu’un seul moteur de vue (ma préférence va à Razor que je trouve plus lisible). Cela sera d’autant intéressant dans le cas du moteur Razor car celui-ci est enregistré en second. En effet, le moteur de vue WebFormsViewEngine sera appelé en premier. Celui-ci va rechercher un fichier aspx ou ascx correspondant à la vue à afficher. Ne le trouvant pas, le moteur de vue WebFormsViewEngine pour générer la vue en cshtml.

Voyons comment supprimer le moteur de vue pour WebForms dans le cas où on code les vues en Razor :

// On supprime tous les moteurs de vue enregistré
ViewEngines.Engines.Clear();
// On rajoute le moteur pour les vues en Razor
ViewEngines.Engines.Add(new RazorViewEngine());

Pour finir, voici un lien avec un comparatif des différents moteurs de vue pour MVC.