sept. 19 2011

[ASP.NET] Présentation d'ASP.NET 4.5 Developer Preview

ASP.NET vNextOn peut dire que la conférence Build a été riche en nouveautés. Bien sûr la Developer Preview de Windows 8 et de Visual Studio 11 ont fait couler beaucoup d'encre et représentent à eux seuls la majeure partie du buzz autour de la Build. Mais les nouveautés côté ASP.NET et développement Web ne sont pas en reste ! C'est ce que nous allons voir dans ce billet. 

La Developer Preview apporte de nombreux changements et nouveautés, de même que la preview de Visual Studio 11 inclut des améliorations pour le développement Web. Avant de présenter ces différentes nouveautés, il est bon de rappeler qu'il s'agit ici de version Developer Preview. Ce ne sont pas des releases officielles et elles peuvent faire l'objet de modifications futures. Toutefois, comme vu par le passé, il ne devrait pas y avoir de gros changements d'ici la release. Pour commencer voici les liens de téléchargement. Il est à noter que la preview du Framework 4.5 est incluse avec VS11 :

Concernant les nouveautés, la référence absolue reste le document officiel de Microsoft : What's New in ASP.NET 4.5 Developer Preview. Je vais décrire ci-dessous les principales nouveautés concernant le runtime ASP.NET. Là où il n'y a pas grand-chose de plus à ajouter, je me contenterais simplement de la traduction du document officiel. Dans un second billet nous verrons les nouveautés propres à ASP.NET 4.5 Web Forms et dans un troisième celles propres à ASP.NET MVC 4.

 

HttpModules et HttpHandler asynchrones à l'aide de await et async

Vous n'êtes pas sans savoir que .NET 4 a introduit la Task Parallel Library (TPL) afin d'aider le développeur à gérer facilement les threads au sein de ses applications. La TPL a introduit un nouveau namespace : System.Threading.Tasks qui contient la classe principale de la librairie : la classe Task. Cette dernière représente une opération asynchrone. Vous avez surement entendu parlé aussi des nouveaux mots clés async et await. Ceux-ci font désormais partie intégrante du Framework .NET dans la version 4.5. Au passage je vous conseille de lire l'article de Stéphanie Hertrich : Différences entre la TPL et async/await par l'exemple.

La Developer Preview du Framework .NET 4.5 s'appuie donc sur la TPL, async et await pour rendre bien plus facile l'écriture de code asynchrone. Quel rapport avec ASP.NET me direz-vous ? Et bien tout simplement : ASP.NET tire partie de ces nouvelles API afin de permettre d'écrire des HttpModules et des HttpHanlders asynchrones ! Nous allons voir ci-dessous deux petits exemples afin de se rendre compte plus facilement de l'avantage que cela va procurer aux développeurs ASP.NET

Exemple d'HttpModule asynchrone

Supposons que vous voulez effectuer des travaux asynchrones au sein d'une méthode qui retourne un objet Task. L'exemple de code ci-dessous définit une méthode asynchrone qui fait un appel asynchrone pour télécharger la page d'accueil du site Microsoft. Notez l'utilisation du mot-clé async dans la signature de notre méthode, ainsi que l'utilisation du mot-clé await lors de l'appel à la méthode DownloadStringTaskAsync.

private async Task ScrapeHtmlPage(object caller, EventArgs e)
{
WebClient wc = new WebClient();
var result = await wc.DownloadStringTaskAsync("http://www.microsoft.com");
// Do something with the result
}

C'est tout ce que vous avez à écrire ! Le Framework .NET gérera automatiquement le déroulement de la pile d'appel en attendant la fin du téléchargement, ainsi que restaurera automatiquement la pile d'appel une fois le téléchargement terminé.

Maintenant disons que vous souhaitez utiliser cette méthode asynchrone (ie ScrapeHtmlPage) dans un HttpModule asynchrone. ASP.NET 4.5 inclut désormais la méthode EventHandlerTaskAsyncHelper et le type nouveau délégué TaskEventHandler que vous pouvez utiliser pour intégrer facilement les méthodes asynchrones basées sur les objets Task avec l'ancien modèle de programmation asynchrone du pipeline HTTP ASP.NET (en attendant la nouvelle version du pipeline, qui se verra refondre complètement niveau programmation asynchrone.... peut-être avec ASP.NET 5.0 ?). L'exemple ci-dessous montre comme utiliser ces nouveautés pour écrire un HttpModule asyncrhone :

public void Init(HttpApplication context)
{
// Wrap the Task-based method so that it can be used with
// the older async programming model.
EventHandlerTaskAsyncHelper helper = new EventHandlerTaskAsyncHelper(ScrapeHtmlPage);

// The helper object makes it easy to extract Begin/End methods out of
// a method that returns a Task object. The ASP.NET pipeline calls the
// Begin and End methods to start and complete calls on asynchronous HTTP modules.
context.AddOnPostAuthorizeRequestAsync(helper.BeginEventHandler, helper.EndEventHandler);
}

 

Exemple d'un HttpHandler asynchrone

L'approche traditionnelle pour écrire un HttpHandler asynchrone est d'implémenter l'interface IHttpAsyncHandler. ASP.NET 4.5 introduit un nouveau type de base asynchrone : HttpTaskAsyncHandler, dont on peut faire dériver nos Handlers, ce qui rend beaucoup plus facile l'écriture de HttpHandler asynchrone.

Le type HttpTaskAsyncHandler est abstrait et vous oblige à surcharger la méthode ProcessRequestAsync. En interne ASP.NET s'occupe tout seul d'intégrer la signature de retour de la méthode ProcessRequestAsync basé sur Task (comme pour notre méthode ScrapeHtmlPage vu précédemment) avec le modèle de programmation asynchrone utilisé par le pipeline ASP.NET. L'exemple suivant montre comment vous pouvez facilement utiliser la TPL dans un HttpHandler asynchrone :

public class MyAsyncHandler : HttpTaskAsyncHandler
{
// ...

// ASP.NET automatically takes care of integrating the Task based override
// with the ASP.NET pipeline.
public override async Task ProcessRequestAsync(HttpContext context)
{
WebClient wc = new WebClient();
var result =
await wc.DownloadStringTaskAsync("http://www.microsoft.com");
// Do something with the result
}
}


Nouvelles fonctionnalités pour la validation des requêtes

Par défaut, ASP.NET effectue une validation des requêtes. C'est à dire qu'il vérifie l'absence de script ou bout de code malicieux dans les champs du formulaire, les headers de la requête HTTP, les cookies, etc... Si quelque chose est détecté, alors ASP.NET lève une exception. Cela agit comme une première ligne de défense contre d'éventuelles attaques cross-site scripting.

Cette fonctionnalité de validation est très pratique et indispensable pour la sécurité. Cependant, dans de nombreux cas... elle peut se révéler gênante. C'est pourquoi de nombreux développeurs ASP.NET ont demandé par le passer la possibilité de pouvoir désactiver à la demande cette validation. Par exemple, pour un forum ou un blog  en ASP.NET, on veut permettre aux utilisateurs de soumettre des messages ou des commentaires au format HTML, donc qu'il n'y ait pas de validation sur cette partie (avec tout de même une vérification de tout le reste).

Avec ASP.NET 4.5 les choses s'améliorent sur ce point. D'une part la nouvelle version intègre désormais la bibliothèque AntiXSS, qui était jusqu'à présent disponible sur Codeplex (connue également sous le nom de Microsoft Web Protection Library). D'autre part, ASP.NET 4.5 introduit deux nouvelles fonctionnalités qui vont nous faciliter la vie par rapport aux requêtes non validées : la validation de requête différée et l'accès aux données des requêtes non validées. Nous allons voir plus en détails ces deux fonctionnalités ainsi que l'intégration de la librairie AntiXSS.

 

Validation différée des requêtes

Par défaut, avec ASP.NET 4.5, toutes les données des requêtes sont soumises à validation. Cependant, il est possible configurer l'application afin de différer cette validation pour une donnée spécifique jusqu'à ce que notre code y accède. Pour configurer la validation en mode différé, rien de plus simple, il suffit d'utiliser la balise requestValidationMode comme ci-dessous :

<httpRuntime requestValidationMode="4.5" ... />

Lorsque le mode de validation des requêtes est paramétré sur 4.5, la validation ne se déclenche que pour une valeur spécifique et seulement lorsque votre code accède à cette valeur. Par exemple, si votre code récupère la valeur de Request.Form["forum_post"], la validation n'est invoquée que pour cet élément dans la collection Request.Form. Aucun des autres éléments de la collection ne seront validés. Cela change pas mal par rapport aux anciennes versions d'ASP.NET où la validation s'exécutait sur toute la collection.

Support des requêtes non validées

La validation différée des requêtes ne suffit pas à elle seule de résoudre le problème de bypass selectif de la validation, c'est à dire lorsqu'on ne veut justement pas déclencher la validation sur une donnée précise. Si on reprend l'exemple ci-dessous avec la valeur Request.Form ["forum_post"], même si on a activé la validation différée, la validation sera exécutée lors de la lecture de la valeur. Or dans certains cas, on ne souhaite pas déclencher la validation pour permettre l'utilisation de balises HTML par exemple (voir l'exemple pour un blog ou un forum plus haut).

Pour palier cela, ASP.NET 4.5 supporte maintenant l'accès sans validation à des données de la requête, grâce à la nouvelle collection Unvalidated de la classe HttpRequest. Cette collection fournit un accès à toutes les valeurs usuelles de la requêtes (comme par exemple le formulaire, les QueryString, les Cookies, etc.). Attention, pour utiliser l'accès aux données sans validation, il est nécessaire de configurer également le requestValidationMode sur 4.5 comme décris plus haut. Une fois fait, un simple accès à la collection Unvalidated permet de lire les données sans validation, comme on peut le voir ci-dessous :

var s = context.Request.Unvalidated.Form["forum_post"];

Anti-XSS Library

En raison de la popularité de la bibliothèque Microsoft AntiXSS, celle-ci fait désormais partie intégrante d'ASP.NET 4.5  Les routines d'encodage sont implémentées via le type AntiXssEncoder du nouveau namespace System.Web.Security.AntiXss. Vous pouvez utiliser le type AntiXssEncoder directement en appelant l'une des méthodes statique d'encodage. Toutefois, l'approche la plus simple pour utiliser les nouvelles routines Anti-XSS consiste à configurer une application ASP.NET pour utiliser l'AntiXssEncoder par défaut. Dans le web.config, il suffit de spécifier le paramètre encoderType pour la balise httpRuntime comme ci-dessous :

<httpRuntime ... encoderType="System.Web.Security.AntiXss.AntiXssEncoder, System.Web, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />

Voici les parties de la bibliothèque AntiXSS qui ont été incorporées dans ASP.NET 4.5 :

  • HtmlEncode, HtmlFormUrlEncode et HtmlAttributeEncode
  • XmlAttributeEncode et XmlEncode
  • UrlEncode et UrlPathEncode
  • CssEncode

Ne confondez pas ces méthodes avec celle du même nom déjà présentes dans ASP.NET 4.0 et les versions précédentes. Par exemple la méthode HtmlEncode a toujours été disponible au niveau de la classe System.Web.HttpUtility.HtmlEncode, et ce n'est pas la même que la nouvelle méthode qu'on utilisera via la classe System.Web.Security.AntiXss.AntiXssEncoder. Je vous invite à consulter ce petit article montrant la différence entre les deux (du moins entre ASP.NET et la librairie AntiXSS avant son intégration dans ASP.NET 4.5)


Support du protocole WebSocket

Cette spécification permet d'ouvrir une connexion bi-directionnelle permanente entre un client et un serveur, afin de résoudre certains problèmes posés par le caractère unidirectionnel et déconnecté du protocole HTTP. Les WebSockets autorisent ainsi le développement de véritables applications temps-réel performantes telles que des sites d'informations ou de suivi des cours boursiers, ou des applications multi-utilisateurs (chat, jeux en ligne...). La spécification permettant d'utiliser les WebSockets est développée par le W3C, tandis que le protocole de communication est standardisé par l'IETF dont fait partie Microsoft.

Il faut souligner que les WebSockets représentent une avancée très importante dans la communication client-serveur. Le protocole HTTP est un protocole non connecté et sans état, et n'a pas été prévu pour établir des connexions permanentes ni le push de données : en HTTP, il faut que le client demande explicitement les données au serveur. Bien-entendu, plusieurs techniques ont été développées pour contourner cette barrière et permettre la réception des données mises à jour quasi-instantanément (polling, long-polling...) ; mais elles surchargent le réseau en headers HTTP inutiles. Les WebSocket permettront bientôt d'y remédier, une fois la spécification définitive (et oui, comme pour HTML5 il faut patienter). Toutefois, ASP.NET 4.5 va nous permettre de les utiliser.

ASP.NET 4.5 et IIS 8 incluent le support de bas-niveau des WebSockets, permettant ainsi aux développeurs ASP.NET d'utiliser les API managées de manière asynchrone en lecture et écriture à la fois sur des données de type string ou binaires via un objet WebSockets. ASP.NET 4.5 se voit donc doté d'un nouveau namespace System.Web.WebSockets qui contient toutes les classes pour travailler avec le protocole WebSocket.

Un navigateur client établit une connexion WebSocket en créant un objet WebSocket DOM qui pointe vers une URL d'une application ASP.NET, comme dans l'exemple ci-dessous :

socket = new WebSocket("ws://contoso.com/MyWebSocketApplication.ashx");

Vous pouvez créer des endpoints WebSockets avec ASP.NET en utilisant n'importe quel type de HttpModule ou d'HttpHandler (dans l'exemple précédent, un fichier. Ashx a été utilisé, ie un HttpHandler). Pour qu'ASP.NET réceptionne une requête de type WebSocket, il est nécessaire de faire appel à la méthode AcceptWebSocketRequest comme ci-dessous :

HttpContext.Current.AcceptWebSocketRequest(// Ajout d'une fonction déléguée WebSocket ici)

La méthode AcceptWebSocketRequest accepte une fonction déléguée car ASP.NET déroule la requête HTTP en cours, puis en transfère le contrôle à la fonction du délégué. Conceptuellement cette approche est similaire à la façon dont on utilise System.Threading.Thread, où on définit une fonction déléguée dans laquelle le travail de fond est effectué.

Pour expliquer un peu mieux le principe, on peut dire que suite à cette première requête, ASP.NET et le client ont échangé une poignée de main en WebSocket. ASP.NET appelle notre délégué et l'application WebSockets démarre. L'exemple de code suivant montre une simple application qui utilise support de bas-niveau des WebSockets dans ASP.NET :

public async Task MyWebSocket(AspNetWebSocketContext context)
{
WebSocket socket = context.WebSocket;
while (true)
{
ArraySegment<byte> buffer = new ArraySegment<byte>(new byte[1024]);

//Attendre de manière asynchronie qu'un message arrive du client
WebSocketReceiveResult result = await socket.ReceiveAsync(buffer, CancellationToken.None);

//Si le socket est toujours ouvert, alors on renvoit un message de confirmation au client
if (socket.State == WebSocketState.Open)
{
string userMessage = Encoding.UTF8.GetString(buffer.Array, 0, result.Count);
userMessage = "You sent: " + userMessage + " at " + DateTime.Now.ToLongTimeString();
buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(userMessage));

//Envoi asynchrone du message au client
await socket.SendAsync(buffer, WebSocketMessageType.Text, true, CancellationToken.None);
}
else { break; }
}
}

Vous remarquerez ici l'utilisation des mots-clés async et await, nouvellement intégrés dans le Framework 4.5. Vu la facilité qu'ils apportent pour gérer des tâches asynchrones, leur utilisation conjointe avec les WebSockets est un choix logique. L'exemple de code ci-dessus montre qu'une requête WebSocket est exécutée de façon complètement asynchrone au sein d'ASP.NET. L'application attend de façon asynchrone un message qui sera envoyé à partir d'un client en appelant await socket.ReceiveAsync. De même, vous pouvez envoyer un message asynchrone à un client en appelant await socket.SendAsync.

Côté client, en javascript donc, on utilise la fonction onmessage pour recevoir un message WebSocket. De même pour envoyer un message on utilisera la méthode send du type WebSocket, comme le montre cet exemple :

// Receive a string message from the server.
socket.onmessage = function(msg)
{
document.getElementById("serverData").innerHTML = msg.data;
};

// Send a string message from the browser.
socket.send(document.getElementById("msgText"));

Bref, vous l'avez compris le support des WebSockets dans ASP.NET 4.5 ouvre la voie à des applications temps-réel bien sympathiques, comme des dashboards, des jeux, ou encore des réseaux sociaux. Couplé à HTML 5, ça doit ... poutrer comme on dit :-)


Améliorations des performances pour l'hébergement Web

La version 4.5 du Framework .NET et Windows 8 (je me lance même pas sur le sujet, vu tout ce qu'il y a à dire !) introduisent des nouvelles fonctionnalités qui peuvent aider à réaliser une amélioration significative des performances sur les charges de travail du serveur web. Cela comprend une réduction (jusqu'à 35% d'après Microsoft, mais j'attends de le constater par moi même) et du temps de démarrage et de la consommation mémoire pour l'hébergement de sites ASP.NET.

Dans l'idéal, tous les sites doivent être actifs et en mémoire afin d'assurer une réponse rapide aux requêtes. Les facteurs qui peuvent affecter la réactivité du site sont principalement les suivants :

  • le temps qu'il faut pour un site de redémarrer après un recyclage de l'AppPool. C'est le temps qu'il faut pour lancer un processus sur le serveur Web pour notre site lorsque les Assemblies du site ne sont plus en mémoire. Donc un démarrage à froid du site ;
  • quelle quantité de mémoire le site occupe.

Les nouvelles fonctionnalités pour l'amélioration des performances se focalisent donc sur ces deux facteurs clés et sont les suivantes :

  • partage des Assemblies communes pour accélérer le démarrage des sites ;
  • utilisation de la compilation Just-In-Time multi-core pour accélérer le démarrage des sites ;
  • tuning du Garbage Collector afin d'optimiser l'utilisation de la mémoire.


Partage des assemblies communes

Sur un même serveur il y a souvent, si ce n'est toujours, des sites qui utilisent les mêmes Assemblies. Et chacun de ces sites possède sa propre copie de l'Assembly partagée dans son répertoire Bin. Même si le code est identique, ils sont physiquement distincts (car pas le même fichier .dll ni le même emplacement). Du coup il y a duplication de ces Assemblies en mémoire mais aussi duplication du temps de chargement de ces Assembies pour chaque site à démarrer sur le serveur Web.

Désormais (et il était plus que temps !), ce problème est résolu par une nouvelle fonctionnalité. Ainsi, il y a réduction de la consommation mémoire sur le serveur Web, de même qu'il y a réduction du temps de chargement des sites. Le principe est simple : Windows conserve une seule et unique copie de chaque Assembly dans le système de fichiers et remplace les copies identiques des Assemblies présentes dans les répertoire Bin par un lien symbolique. Microsoft a bien entendu prévu le cas où, pour un site précis, on a besoin d'utiliser un version distincte d'une Assembly partagée (par exemple la nouvelle version lors d'une mise à jour du site, ou une ancienne pour raison de compatibilité). Dans ce cas, le lien symbolique est mis à jour et seul le site concerné est touché.

Bref, c'est un grand pas en avant (qui aurait dû déjà être fait avant je le répète) qui va en ravir plus d'un. Cette nouveauté n'est pas propre au Framework .NET 4.5 mais bel et bien à Visual Studio 11 (mais il vous faut tout de même .NET 4.0 au minimum). Le partage des liens est assuré par un nouvel outil nommé aspnet_intern.exe.


Utilisation de la compilation Just-In-Time multi-core

Pour un démarrage à froid d'un site, non seulement les Assemblies doivent être lues à partir du disque, mais le site doit aussi être compilé. Dans le cas d'un site complexe, le temps de démarrage peut se révéler extrêmement long. C'est là qu'intervient la nouvelle fonctionnalité du Framework 4.5. Afin de réduire ce temps de chargement, le compilateur JIT permet maintenant de réduire ces retards par la diffusion de la compilation JIT dans tous les cœurs disponibles du processeur. Elle le fait autant et aussi tôt que possible en utilisant les informations recueillies lors des lancements précédents du site. Cette fonctionnalité est mise en œuvre par la méthode System.Runtime.ProfileOptimization.StartProfile.

Et justement, comme il y a peu de raisons de ne pas en profiter, cette fonctionnalité est activée par défaut dans ASP.NET. Toutefois si vous souhaitez la désactiver il suffit de rajouter ceci dans le Web.config :

<configuration>
<!-- ... -->
<system.web>
<compilation profileGuidedOptimizations="None" />
<!-- ... -->


Tuning du Garbage Collector afin d'optimiser l'utilisation de la mémoire

Lorsqu'un site est en cours d'exécution, son utilisation du Garbage Collector peut avoir un certain impact sur sa consommation mémoire. Le GC du Framework .NET fait des compromis entre le temps CPU et la consommation de mémoire. Pour les versions précédentes du Framework, Microsoft avez fourni des conseils sur la façon de configurer le GC afin d'atteindre un juste équilibre (par exemple, voir cet article : ASP.NET 2.0/3.5 Shared Hosting Configuration).

Avec la nouvelle version du Framework 4.5, au lieu d'avoir une multitude de paramètres à configurer, il sera possible d'utiliser une configuration générale prédéfinie qui reprendra tous les réglages précédemment recommandés par Microsoft, ainsi que d'autres configurations. Pour activer un de ces réglages du GC il faut modifier le fichier aspnet.config du serveur ( ce fichier se trouve dans le répertoire Windows\Microsoft.NET\Framework\v4.0.30319\).

<configuration>
<!-- ... -->
<runtime>
<performanceScenario value="HighDensityWebHosting" />
<!-- ... -->

Il manque encore des informations sur ces différentes configurations et leur impact sur la consommation mémoire. Mais globalement, si on résume, avec le partage des Assemblies, la compilation JIT multi-core et le tuning du GC, on peut s'attendre à de bien meilleures performances niveau temps de chargement des sites et consommation mémoire du serveur Web ! J'avoue avoir vraiment hâte de voir ce que cela donne sur une application en production (ce sera l'occasion de faire un comparatif avant/après).


Meilleur support des requêtes et réponses HTTP

ASP.NET 4 avait introduit la possibilité de lire une requête HTTP comme un stream en utilisant la méthode HttpRequest.GetBufferlessInputStream. Cette méthode renvoie un objet Stream qui permet de lire le corps de l'entité HTTP entrante, mais comme elle s'exécute de façon synchrone, un thread est alors bloqué tout le long de la requête HTTP. Ce qui est quand même gênant ! La version 4.5 d'ASP.NET permet désormais de le faire de manière asynchrone.

La référence Stream retournée par la méthode HttpRequest.GetBufferlessInputStream supporte maintenant les méthodes de lecture et synchrone et asynchrone. L'objet Stream retourné implémente donc les méthodes BeginRead et EndRead. Ces méthodes asynchrones sur le stream vous permettent désormais de lire de manière asynchrone l'entité de la requête HTTP par morceaux, tandis qu'ASP.NET libère le thread courant entre chaque itération de la boucle de lecture asynchrone.


Flush asynchrone d'une réponse HTTP

Envoyer une réponse HTTP à un client peut prendre un temps considérable lorsque le client est à l'autre bout du monde ou a tout simplement une faible bande passante. Normalement ASP.NET utilise des buffers pour renvoyer le contenu de la réponse et, tout à la fin du traitement de la requête, envoie le cumul de ces buffers en une seule opération.

Si la réponse bufferisée est volumineuse (par exemple, le streaming d'un gros fichier à un client), il est nécessaire d'appeler périodiquement HttpResponse.Flush pour envoyer la sortie bufferisée au client et de ne pas exploser la mémoire du serveur. Cependant, comme la méthode Flush est synchrone, l'appeler de manière itérative bloque le thread pour toute la durée de la demande. Pour résumer, actuellement avec ASP.NET 4, qui dit envoi d'un gros fichier au client, dit thread bloqué longtemps sur le serveur...

Avec ASP.NET 4.5 ce problème n'en est plus un, puisque désormais la classe HttpResponse se voit ajouter deux nouvelles méthodes : BeginFlush et EndFlush. Comme vous l'avez deviné, celles-ci vont permettre de faire un flush de manière asynchrone et ainsi de libérer le thread.


Regroupement et Minification de fichiers

Il y a un an j'avais commencé une petite série sur l'amélioration des performances dans une application ASP.NET où j'évoquais certains principes comme la combinaison de fichiers, la minification, la mise en cache et la compression :

ASP.NET 4.5 rend la majeure partie de ces articles obsolètes puisqu'il permet désormais de combiner des fichiers JavaScript ou CSS, le tout avec minification ! Cette nouvelle fonctionnalité est disponible bien sûr avec ASP.NET Web Forms mais également ASP.NET MVC et ASP.NET Web Pages. Elle permet de référencer un dossier entier au lieu de fichiers individuels. Supposons que vous ayez les fichiers suivants dans votre application Web :

Vous pouvez regrouper tous les fichiers JavaScript dans le dossier Scripts. Pour ce faire, vous pouvez maintenant référencer le dossier et ajoutez /js dans la propriété source, comme ci-dessous :

<script src="scripts/js"></script>

Vous pouvez également faire la même chose pour regrouper tous les fichiers CSS comme ceci :

<link href="styles/css" rel="stylesheet" />

Lorsque les fichiers sont regroupés, ils sont d'abord triées par ordre alphabétique. Ils sont ensuite organisées afin que les bibliothèques connues et leurs extensions personnalisées (telles que jQuery, Mootools et Dojo) soient chargées en premier. Par exemple, l'ordre final pour le regroupement des scripts du dossier visible ci-dessus sera :

  1. jquery-1.6.2.js
  2. jquery-ui.js
  3. jquery.tools.js
  4. a.js

Les fichiers CSS sont également classés par ordre alphabétique et réorganisés afin que reset.css et normalize.css viennent avant n'importe quel autre fichier. L'ordre final du regroupement des CSS vus plus haut sera donc :

  1. reset.css
  2. content.css
  3. forms.css
  4. globals.css
  5. menu.css
  6. styles.css

Il est à noter que l'algorithme de classement est customisable.

Vous pouvez enregistrer vos propres regroupements de fichier via le module Global.asax. Cela permettra de spécifier quels fichiers on désire avoir dans tel regroupement et quelle URL aura ce regroupement. Le code ci-dessous montre un exemple ;

//Créer un nouveau regroupement de fichier avec l'URL "[host]/customscript"
//Le regroupement utilisera la class JsMinify pour la minification (plus simple non ?)
var b = new Bundle("~/CustomScript", typeof(JsMinify));

//On ajoute tous les fichiers avec extension .js du folder nommé "Scripts", et sans inclure les sous-folders
b.AddDirectory("~/scripts", "*.js", false);

//On ajoute un fichier quelconque d'un autre folder
b.AddFile("~/MesScriptsPerso/monscript.js");

//Enfin on entregistre ce regroupement dans la table de regroupements
BundleTable.Bundles.Add(b);

Ce regroupement customisé peut maintenant être référencé dans notre page comme ceci :

<script src="/customscript"></script>

Notez qu'en plus de pouvoir créer nos propres regroupements, la BundleTable accepte aussi un nouveau type : le DynamicFolderBundle. C'est en gros le même principe, à la différence près qu'il est possible de remplacer l'outil de minification par défaut par un ou outil de minification ou de modification de notre choix. En gros, via les regroupements on peut également customiser nos fichiers javascripts et css. On peut vraiment dire que la nouvelle fonctionnalité de regroupement et de minification de fichier est souple et très extensible !

 

C'est tout pour aujourd'hui, et c'est déjà pas mal ! Nous n'avons fait que survoler les nouveautés propres au runtime d'ASP.NET 4.5. Le maître mot pour résumer celle-ci est simple PERFORMANCE ! Mais ce n'est pas fini, la Developer Preview apporte aussi des améliorations et nouveautés propres aux Web Forms ou à MVC (sans parler du fait que la version 4 pointe le bout de son nez). Rendez-vous très prochainement pour les deux prochains billets :

  • [ASP.NET] Présentation d'ASP.NET 4.5 Web Forms
  • [ASP.NET] Présentation d'ASP.NET MVC 4

 

Tags: , ,

Commentaires

1.
Christophe Argento Christophe Argento France says:

Merci Nicolas pour cet excellent article.
De nombreuses améliorations très attendues qui vont nous permettre de supprimer pas mal de bidouillages qu'on avait dû mettre en place pour palier le manque. Par contre pour websockets, tu sais quel navigateur les supporte? Il me semblait que le support des websockets avait été retiré de firefox pour des problèmes de sécurité et qu'il n'était pas implémenté dans ie9. Ça représente comme tu le dis une avancée majeure on pourra enfin faire de la communication bi-directionnelle sur le web les applications sont innombrables.

2.
Nicolas Esprit Nicolas Esprit France says:

Salut,

En effet, cette fonctionnalité ouvre de nombreuses portes ! Ce n'est pas encore supporté par tous les navigateurs (mais de toute façon la release d'ASP.NET 4.5 n'est pas pour tout de suite). Il y a plusieurs versions du protocole (7 et 10 étant les dernières principales). La version 7 est supportée par Firefox 6, tandis que la dernière version est supportée par Chrome 14, Firefox 7 et IE 10 (Developer Preview).

Après... il va falloir encore patienter un petit peu avant de se lancer dans un projet avec WebSocket. Mais cela nous permet déjà de nous familiariser avec et de tester. Vivement !

3.
Jean Michel Ormes Jean Michel Ormes France says:

Super article Nicolas ! Perso j'ai commencé une petite série sur MVC 4, j'espère que t'y jetteras un oeil (toi l'expert) quand tu auras le temps Smile

4.
trackback Nicolas Esprit says:

[ASP.NET] Introduction MVC 4 - Part 2 : Un peu d'histoire

[ASP.NET] Introduction MVC 4 - Part 2 : Un peu d'histoire

5.
trackback ASP.NET Français Blogs says:

[ASP.NET] Introduction MVC 4 - Part 3 : MVC c'est quoi ? Quels avantages ?

Le patron de conception Modèle-Vue-Contrôleur est un patron de conception architectural

Les commentaires sont clos