<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Le blog de Hinault Romaric Donfack &#187; ASP.NET MVC 3</title>
	<atom:link href="https://blog.developpez.com/lilroma/pcategory/net/asp-net/asp-net-mvc-3/feed" rel="self" type="application/rss+xml" />
	<link>https://blog.developpez.com/lilroma</link>
	<description>Bienvenue sur ce blog. Vous y trouverez du .NET, du .NET...  encore du .NET, toujours du .NET et très peu de chose sur moi</description>
	<lastBuildDate>Sat, 27 Aug 2016 14:24:30 +0000</lastBuildDate>
	<language>fr-FR</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>https://wordpress.org/?v=4.1.42</generator>
	<item>
		<title>Optimisation du temps de chargement d’une page ASP.NET MVC Part 2 : La mise en cache</title>
		<link>https://blog.developpez.com/lilroma/p11207/net/optimisation_du_temps_de_chargement_d_un</link>
		<comments>https://blog.developpez.com/lilroma/p11207/net/optimisation_du_temps_de_chargement_d_un#comments</comments>
		<pubDate>Wed, 08 Aug 2012 10:01:09 +0000</pubDate>
		<dc:creator><![CDATA[Hinault Romaric]]></dc:creator>
				<category><![CDATA[.NET]]></category>
		<category><![CDATA[ASP.NET]]></category>
		<category><![CDATA[ASP.NET MVC 3]]></category>
		<category><![CDATA[ASP.NET MVC 4]]></category>
		<category><![CDATA[C#]]></category>

		<guid isPermaLink="false"></guid>
		<description><![CDATA[Pour améliorer les performances de leur application, les développeurs ont couramment recours à l’optimisation côté client et côté serveur. L’optimisation d’une application Web regroupe l’ensemble des techniques qui peuvent aider à accélérer le temps de téléchargement d’une page Web. Parmi &#8230; <a href="https://blog.developpez.com/lilroma/p11207/net/optimisation_du_temps_de_chargement_d_un">Lire la suite <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<p>Pour améliorer les performances de leur application, les développeurs ont couramment recours à l’optimisation côté client et côté serveur. L’optimisation d’une application Web regroupe l’ensemble des techniques qui peuvent aider à accélérer le temps de téléchargement d’une page Web. Parmi ces techniques, on retrouve la minification et la compression du CSS et JavaScript, la mise en cache, l’utilisation des CDN, etc.</p>
<p>Ce billet est le second d’une série sur les techniques d’optimisation du temps de chargement d’une application ASP.NET MVC. Le premier article sur la compression et la minification du CSS et JavaScript peut être consulté sur <a href="http://blog.developpez.com/lilroma/p10462/net/asp-net/microsoft-web-optimisation-ou-comment-op/">cette page</a>.</p>
<p><span id="more-44"></span></p>
<p>Les requêtes des utilisateurs sur une page d’un site Web qu’il soit statistique ou dynamique engendre couramment le chargement de plusieurs éléments et de nombreuses opérations (chargement des images, CSS, JavaScript, données depuis une en base de données, etc.). Imaginez un intervalle de temps pendant lequel près de 100 requêtes sont effectuées sur votre site, et que durant cette période, le même contenu est retourné par votre application. Tout le long ce moment, votre application reprend 100 fois les mêmes opérations pour retourner un contenu identique.</p>
<p>La mis en cache est un procédé permettant d’améliorer considérablement le temps de chargement d’une page Web et économiser la bande passante, en évitant d’exécuter plusieurs fois certaines opérations (chargement des données, lecture d’une information dans la base de données, etc.) en stockant le contenu de cette page quelque part.</p>
<p><strong>Activer la mise en cache</strong></p>
<p>Le Framework ASP.NE MVC depuis la version 1 dispose d’un mécanisme pour la mise en a cache d’une application, qui repose essentiellement sur la même technique utilisée par ASP.NET. Il a été amélioré à partir de la version 3 pour coller avec les spécificités de la plateforme.</p>
<p>L’activation de la mise en cache se fait via l’attribut <strong>[OutputCache]</strong> qui peut être ajoutée soit individuellement à une action contrôleur, ou alors à une classe entière d&rsquo;un contrôleur</p>
<p>Le code ci-dessous permet de mettre en cache pendant 30 secondes la sortie de l’action Index.</p>
<div style="border-bottom: silver 1px solid; text-align: left; border-left: silver 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; max-height: 200px; font-size: 8pt; overflow: auto; border-top: silver 1px solid; cursor: text; border-right: silver 1px solid; padding-top: 4px" id="codeSnippetWrapper">
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px" id="codeSnippet">[OutputCache(Duration = 30)] <span style="color: #008000">//mise en cache pour 30 secondes</span><br /><span style="color: #0000ff">public</span> ActionResult Index()<br />{<br />    ViewBag.Message = <span style="color: #006080">&quot;Cette page a été mise e cache à &quot;</span> + DateTime.Now;<br /><br />    <span style="color: #0000ff">return</span> View();<br />}<br /><br /></pre>
<p></div>
<p>Pour mettre en  cache une classe entière d’un contrôleur, il suffit de décorer la classe avec l’attribut OutputCache comme l’illustre le code ci-dessous :</p>
<div style="border-bottom: silver 1px solid; text-align: left; border-left: silver 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; max-height: 400px; font-size: 8pt; overflow: auto; border-top: silver 1px solid; cursor: text; border-right: silver 1px solid; padding-top: 4px" id="codeSnippetWrapper">
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px" id="codeSnippet">[OutputCache(Duration = 30)] <span style="color: #008000">//mise en cache pour 30 secondes</span><br />    <span style="color: #0000ff">public</span> <span style="color: #0000ff">class</span> HomeController : Controller<br />    {<br />       <br />        <span style="color: #0000ff">public</span> ActionResult Index()<br />        {<br />            ViewBag.Message = <span style="color: #006080">&quot;Cette page a été mise e cache à &quot;</span> + DateTime.Now;<br /><br />            <span style="color: #0000ff">return</span> View();<br />        }<br /><br />        <span style="color: #0000ff">public</span> ActionResult About()<br />        {<br />            ViewBag.Message = <span style="color: #006080">&quot;Your app description page.&quot;</span>;<br /><br />            <span style="color: #0000ff">return</span> View();<br />        }<br />}<br /></pre>
<p></div>
<p>Si vous exécutez ce code, vous vous rendrez compte que la date et l’heure affichées ne vont pas varier chaque fois que vous allez actualiser la page, jusqu’à ce que les 30 secondes soient écoulées.</p>
<p>NB: Il faut noter que le temps de sauvegarde des données de la page n’est pas garanti. En cas de manque de ressources mémoires, le cache va commencer à vider automatiquement son contenu.</p>
<p><strong>Personnaliser la mise en cache</strong></p>
<p>En dehors de la propriété Duration qui permet de définir le temps de mise en cache, d’autres propriétés dont il est important de connaitre sont disponibles pour vous permettre de personnaliser la mise en cache des données de votre page selon votre convenance et les spécificités de la page.</p>
<p><strong>Location</strong></p>
<p>La propriété location permet de définir l’emplacement pour enregistrer l’objet mis en cache. Il est possible d’enregistre l’objet mis en  cache sur le serveur, le client, les deux ou toutes les autres options de l’enum <strong>OutputCacheLocation</strong>. Les différentes valeurs qu’elle peut prendre sont :</p>
<p>&#8211; Any<br />
&#8211; Client<br />
&#8211; Downstream<br />
&#8211; Server<br />
&#8211; None<br />
&#8211; ServerAndClient </p>
<p>Par défaut, la valeur Any est utilisée lorsque cette propriété n’est pas spécifiée. L’orientation vers la mise en cache côté client, côté serveur ou les deux doit se faire suivant vos besoins. Si vous souhaitez afficher par exemple des informations personnalisées à l’utilisation comme son heure de connexion, son login, ses statistiques, etc. vous devez utiliser dans ce cas la mise en cache côté client.</p>
<p>Le code ci-dessous permet de mettre en cache la méthode d’action Index uniquement chez le client.</p>
<div style="border-bottom: silver 1px solid; text-align: left; border-left: silver 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; max-height: 200px; font-size: 8pt; overflow: auto; border-top: silver 1px solid; cursor: text; border-right: silver 1px solid; padding-top: 4px" id="codeSnippetWrapper">
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px" id="codeSnippet">[OutputCache(Duration = 10, Location = OutputCacheLocation.Client)]<br /> <span style="color: #0000ff">public</span> ActionResult Index()<br /> {<br />     ViewBag.Message = <span style="color: #006080">&quot;Cette page a été mise en cache à &quot;</span> + DateTime.Now;<br /><br />     <span style="color: #0000ff">return</span> View();<br /> }<br /></pre>
<p></div>
<p><strong>VaryByParam</strong></p>
<p>Supposons un instant que vous voulez afficher les détails sur un produit à partir de son identifiant. Cela suppose qu’à chaque fois que l’identifiant du produit va changer, les détails affichés doivent également changer. Comment modifier la mise en cache pour que le contenu change automatiquement lorsque l’ID change. C’est à ce stade qu’intervient la propriété VaryByParam.  Cette propriété permet de créer différentes versions d&rsquo;un même contenu, dès que l&rsquo;un des paramètres du formulaire ou de l&rsquo;URL change. </p>
<p>Le code ci-dessous illustre comment vous pouvez l’utiliser.</p>
<div id="codeSnippetWrapper" style="background-color: #f4f4f4; font-family: 'Courier New', Courier, Monospace; font-size: 8pt; line-height: 12pt; border: solid 1px silver; cursor: text; margin: 20px 0px 10px 0px; max-height: 200px; overflow: auto; padding: 4px; width: 97.5%; direction: ltr; text-align: left;">
<pre id="codeSnippet" style="background-color: #f4f4f4; font-family: 'Courier New', Courier, Monospace; font-size: 8pt; line-height: 12pt; border-style: none; color: black; overflow: visible; padding: 0px; width: 100%; margin: 0em; direction: ltr; text-align: left;">[OutputCache(Duration = 3600, VaryByParam=<span style="color: #006080;">"id"</span>)]<br />        <span style="color: #0000ff;">public</span> ViewResult Details(<span style="color: #0000ff;">short</span> id)<br />        {<br />            Articles article = db.Articles.Find(id);<br />            <span style="color: #0000ff;">return</span> View(article);<br />        }</pre>
<p></div>
<p>En procédant ainsi, plusieurs versions du contenu de la méthode d’action sont mises en cache jusqu’à expiration de la période de mise en cache.</p>
<p><strong>Créer un profil de cache dans le Web.Config</strong></p>
<p>Le fichier de configuration de votre application peut être utilisé pour créer un profil un cache. L’utilisation de cette technique présente plusieurs avantages :</p>
<p>&#8211; vous pouvez créer un profil de cache et appliquer celui-ci à plusieurs actions ou contrôleurs.</p>
<p>&#8211; vous pouvez modifier le comportement de votre profil de cache dans le Web.config sans avoir besoin de recompiler votre application.</p>
<p>Par exemple, la section de configuration Web « caching » définit un profil de cache nommé MyCacheProfil. Cette section « caching » doit apparaître dans la section « system.web » du fichier Web.Config.</p>
<div id="codeSnippetWrapper" style="background-color: #f4f4f4; font-family: 'Courier New', Courier, Monospace; font-size: 8pt; line-height: 12pt; border: solid 1px silver; cursor: text; margin: 20px 0px 10px 0px; max-height: 200px; overflow: auto; padding: 4px; width: 97.5%; direction: ltr; text-align: left;">
<pre id="codeSnippet" style="background-color: #f4f4f4; font-family: 'Courier New', Courier, Monospace; font-size: 8pt; line-height: 12pt; border-style: none; color: black; overflow: visible; padding: 0px; width: 100%; margin: 0em; direction: ltr; text-align: left;">&lt;system.web&gt;<br />    &lt;caching&gt;<br />      &lt;outputCacheSettings&gt;<br />        &lt;outputCacheProfiles&gt;<br />          &lt;add name=<span style="color: #006080;">"MyCacheProfile"</span>  duration=<span style="color: #006080;">"60"</span> /&gt;<br />        &lt;/outputCacheProfiles&gt;<br />      &lt;/outputCacheSettings&gt;<br />    &lt;/caching&gt;<br />  &lt;/system.web&gt;</pre>
<p></div>
<p>Le contrôleur suivant illustre comment appliquer le profil MyCacheProfile sur une action contrôleur à l&rsquo;aide de l&rsquo;attribut [OutputCache].</p>
<div id="codeSnippetWrapper" style="background-color: #f4f4f4; font-family: 'Courier New', Courier, Monospace; font-size: 8pt; line-height: 12pt; border: solid 1px silver; cursor: text; margin: 20px 0px 10px 0px; max-height: 200px; overflow: auto; padding: 4px; width: 97.5%; direction: ltr; text-align: left;">
<pre id="codeSnippet" style="background-color: #f4f4f4; font-family: 'Courier New', Courier, Monospace; font-size: 8pt; line-height: 12pt; border-style: none; color: black; overflow: visible; padding: 0px; width: 100%; margin: 0em; direction: ltr; text-align: left;">[OutputCache(CacheProfile=<span style="color: #006080;">"MyCacheProfile"</span>)]<br />        <span style="color: #0000ff;">public</span> ActionResult Index()<br />        {<br />            ViewBag.Message = <span style="color: #006080;">"Cette page a été mise en cache à "</span> + DateTime.Now;<br /><br />            <span style="color: #0000ff;">return</span> View();<br />        }</pre>
<p></div>
<p>Le cache de sortie fournir un moyen simple pour améliorer radicalement les performances de vos applications ASP.Net MVC. Au travers de cet article, vous avez découvert comment vous pouvez utiliser cette technique. Restez connecté à mon blog pour la suite des astuces sur l’optimisation du temps de chargement d’une page Web.</p>
]]></content:encoded>
			<wfw:commentRss></wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Entity Framework : que faire face à l’erreur «new transaction is not allowed because there are other threads running »</title>
		<link>https://blog.developpez.com/lilroma/p11182/net/entity_framework_que_faire_face_a_l_erre</link>
		<comments>https://blog.developpez.com/lilroma/p11182/net/entity_framework_que_faire_face_a_l_erre#comments</comments>
		<pubDate>Fri, 27 Jul 2012 16:58:48 +0000</pubDate>
		<dc:creator><![CDATA[Hinault Romaric]]></dc:creator>
				<category><![CDATA[.NET]]></category>
		<category><![CDATA[ASP.NET]]></category>
		<category><![CDATA[ASP.NET MVC 3]]></category>
		<category><![CDATA[Entity Framework]]></category>

		<guid isPermaLink="false"></guid>
		<description><![CDATA[Je travaillais il y a de cela quelques jours sur une application ASP.NET MVC 3, avec l’ORM Entity Framework. J’ai été confronté lors de l’écriture de mon code à l’erreur suivante : «new transaction is not allowed because there are &#8230; <a href="https://blog.developpez.com/lilroma/p11182/net/entity_framework_que_faire_face_a_l_erre">Lire la suite <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<p>Je travaillais il y a de cela quelques jours sur une application ASP.NET MVC 3, avec l’ORM Entity Framework. J’ai été confronté lors de l’écriture de mon code à l’erreur suivante : «new transaction is not allowed because there are other threads running ». </p>
<p>Comme il n’est pas exclu que je tombe encore sur le même type de problème à l’avenir, je vais partager sur mon blog  &#8211; qui est avant tout mon rappel mémoire favori &#8211; les causes de cette erreur et comment contourner cela.</p>
<p><span id="more-83"></span></p>
<p><strong>Ce que j’essayais de faire dans mon application.</strong></p>
<p>Pour une facture, je voulais récupérer la liste des produits, et pour chaque produit, avoir  la fiche produit correspondante, y effectuer des modifications, ensuite appliquer la mise à jour à la base de données.</p>
<p>Le code source de cette partie est le suivant :</p>
<p>&#160;</p>
<div style="border-bottom: silver 1px solid; text-align: left; border-left: silver 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; max-height: 400px; font-size: 8pt; overflow: auto; border-top: silver 1px solid; cursor: text; border-right: silver 1px solid; padding-top: 4px" id="codeSnippetWrapper">
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px" id="codeSnippet">var lp = from l <span style="color: #0000ff">in</span> db.Liste_produit.Include(l =&gt; l.Article)<br />         <span style="color: #0000ff">where</span> l.Id_facture == facture.Id_facture<br />         select l;<br /><span style="color: #0000ff">foreach</span>(Liste_produit liste_produit <span style="color: #0000ff">in</span> lp)<br />     {<br />       article = liste_produit.Article;<br />       <span style="color: #008000">//bla bla bla</span><br />       <span style="color: #008000">//bla bla bla</span><br />       db.Entry(article).State = EntityState.Modified;<br />       db.SaveChanges();<br />                        <br />     }<br /></pre>
<p></div>
<p>À l’exécution de ce code, au moment de l’enregistrement des modifications dans la base de données (db.SaveChanges()), l’exception ci-dessous est levée.</p>
<p><img src="http://blog.developpez.com/media/exception.png" width="580" height="317" alt="" /></p>
<p><strong>Les causes :</strong></p>
<p>Après avoir observé le problème de près et effectué quelques recherches, je me suis rendu compte que le souci était au niveau du foreach.</p>
<p>Il semblerait que pour la lecture de chaque élément dans « lp », la bouche ait recours à une transaction pour le Context en cours. Hor, lorsque j’appelle la procédure SaveChanges(), une nouvelle transaction veut être créée pour le même Context. Ce qui n’est pas autorisé par Entity Famework.</p>
<p><strong>Solutions</strong></p>
<p>De prime abord, j’ai opté pour la sauvegarde de mes données dans une IList. Ainsi, lors de la lecture de celles-ci, je n’aurais plus besoin d’avoir recours à une transaction.<br />
Le code que j’ai utilisé est le suivant :</p>
<div id="codeSnippetWrapper" style="background-color: #f4f4f4; font-family: 'Courier New', Courier, Monospace; font-size: 8pt; line-height: 12pt; border: solid 1px silver; cursor: text; margin: 20px 0px 10px 0px; max-height: 400px; overflow: auto; padding: 4px; width: 97.5%; direction: ltr; text-align: left;">
<pre id="codeSnippet" style="background-color: #f4f4f4; font-family: 'Courier New', Courier, Monospace; font-size: 8pt; line-height: 12pt; border-style: none; color: black; overflow: visible; padding: 0px; width: 100%; margin: 0em; direction: ltr; text-align: left;">var lp = from l <span style="color: #0000ff;">in</span> db.Liste_produit.Include(l =&gt; l.Article)<br />         <span style="color: #0000ff;">where</span> l.Id_facture == fa.Id_facture<br />         select l;<br />IList&lt;Liste_produit&gt; ListeP = lp.ToList();<br /><span style="color: #0000ff;">foreach</span>(Liste_produit liste_produit <span style="color: #0000ff;">in</span> ListeP)<br />   {<br />      article = liste_produit.Article;<br />      <span style="color: #008000;">//bla bla bla</span><br />      <span style="color: #008000;">//bla bla bla</span><br />      db.Entry(article).State = EntityState.Modified;<br />      db.SaveChanges();<br />                        <br />  }<br /></pre>
<p></div>
<p>Cette solution marche. Mais, côté performance, elle n’est pas du tout satisfaisante. Si la quantité de données est importante, imaginez un peu la consommation de la mémoire en chargeant toutes ces données dans une liste.</p>
<p>En tout cas, elle ne m’arrange pas.  J’ai donc opté pour une solution beaucoup plus simple et performante. J’ai simplement appelé la procédure SaveChanges() en dehors de la boucle et le problème a été résolu avec de meilleures performances.</p>
<div id="codeSnippetWrapper" style="background-color: #f4f4f4; font-family: 'Courier New', Courier, Monospace; font-size: 8pt; line-height: 12pt; border: solid 1px silver; cursor: text; margin: 20px 0px 10px 0px; max-height: 400px; overflow: auto; padding: 4px; width: 97.5%; direction: ltr; text-align: left;">
<pre id="codeSnippet" style="background-color: #f4f4f4; font-family: 'Courier New', Courier, Monospace; font-size: 8pt; line-height: 12pt; border-style: none; color: black; overflow: visible; padding: 0px; width: 100%; margin: 0em; direction: ltr; text-align: left;">var lp = from l <span style="color: #0000ff;">in</span> db.Liste_produit.Include(l =&gt; l.Article)<br />         <span style="color: #0000ff;">where</span> l.Id_facture == facture.Id_facture<br />         select l;<br /><span style="color: #0000ff;">foreach</span>(Liste_produit liste_produit <span style="color: #0000ff;">in</span> lp)<br />   {<br />      article = liste_produit.Article;<br />      <span style="color: #008000;">//bla bla bla</span><br />      <span style="color: #008000;">//bla bla bla</span><br />      db.Entry(article).State = EntityState.Modified;<br />   }<br />db.SaveChanges();<br /></pre>
<p></div>
<p>En procédant ainsi, j’apporte des modifications à l’entité dans le foreach, et c’est à la suite de cette instruction (lorsque la transaction a été bouclée) que j’appelle la procédure SaveChanges().</p>
<p>Voila le problème est résolu, et la prochaine fois que je serais face à ce problème (ce qui est fort probable), et que je ne me souviendrais plus de comment j’avais procédé (ce qui est également fort probable), je saurais ou chercher e premier ;).</p>
]]></content:encoded>
			<wfw:commentRss></wfw:commentRss>
		<slash:comments>22</slash:comments>
		</item>
		<item>
		<title>ASP.NET MVC et Entity Framework : résoudre l’erreur  System.Reflection.ReflectionTypeLoadException: Unable to load one or more of the requested types</title>
		<link>https://blog.developpez.com/lilroma/p11148/net/asp_net_mvc_et_entity_framework_resoudre</link>
		<comments>https://blog.developpez.com/lilroma/p11148/net/asp_net_mvc_et_entity_framework_resoudre#comments</comments>
		<pubDate>Fri, 13 Jul 2012 10:22:03 +0000</pubDate>
		<dc:creator><![CDATA[Hinault Romaric]]></dc:creator>
				<category><![CDATA[.NET]]></category>
		<category><![CDATA[ASP.NET]]></category>
		<category><![CDATA[ASP.NET MVC 3]]></category>
		<category><![CDATA[C#]]></category>
		<category><![CDATA[Entity Framework]]></category>

		<guid isPermaLink="false"></guid>
		<description><![CDATA[Lors du déploiement de mon application ASP.NET MVC 3 chez un client, j’ai eu l’erreur « System.Reflection.ReflectionTypeLoadException » pendant l’exécution de celle-ci. Pourtant, l’application fonctionnait correctement sur ma machine de développement. En dehors d’un foutu message “Unable to load one &#8230; <a href="https://blog.developpez.com/lilroma/p11148/net/asp_net_mvc_et_entity_framework_resoudre">Lire la suite <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<p>Lors du déploiement de mon application ASP.NET MVC 3 chez un client, j’ai eu l’erreur « System.Reflection.ReflectionTypeLoadException » pendant l’exécution de celle-ci. Pourtant, l’application fonctionnait correctement sur ma machine de développement.</p>
<p>En dehors d’un foutu message “Unable to load one or more of the requested types. Retrieve the LoaderExceptions property for more information”, rien ne permet d’identifier clairement la source de cette erreur.</p>
<p><span id="more-43"></span></p>
<p>Après plusieurs recherches, il semblerait que l’erreur soit générée par Entity Framework. En effet, lorsque vous utilisez Entity Framework, celui-ci est configuré par défaut pour charger tous les types des assemblys référencées, afin d’identifier les différents types des entités pour votre modèle objet.  Si l’un des types ne peut être chargé, alors Entity Framework va générer cette erreur.</p>
<p>Il existe plusieurs solutions pour fixer ce problème :</p>
<p>&#8211; vous pouvez marquer la copie locale de toutes les assemblys référencées dans votre application à True ;</p>
<p>&#8211; dans une autre mesure, il suffit de supprimer toutes les DLL dans le dossier bin et procéder à une nouvelle génération de votre application.</p>
<p>&#8211; il est également possible que les bibliothèques System.Data.Entity et System.Web.Entity soient corrompues.  Pour mon cas par exemple, lors du déploiement de mon application, après investigation, je me suis rendu compte que les fichiers System.Data.Entity.dll et System.Web.Entity.dll avaient respectivement pour tailles 1640 Ko et 63 ko, pourtant dans le framework .NET, ces fichiers avaient pour tailles 4360 Ko et 135 Ko. En les remplaçant simplement avant le déploiement de l’application, cela a résolu ce bug.</p>
<p>Mais, le véritable problème ici, c’est d’identifier réellement l’assemblys qui pose problème. Pour cela, vous  pouvez simplement utiliser le code suivant :</p>
<div style="border-bottom: silver 1px solid; text-align: left; border-left: silver 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; max-height: 600px; font-size: 8pt; overflow: auto; border-top: silver 1px solid; cursor: text; border-right: silver 1px solid; padding-top: 4px" id="codeSnippetWrapper">
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px" id="codeSnippet"><span style="color: #0000ff">try</span><br />{<br />    <span style="color: #008000">//Le code qui pose problème.</span><br />}<br /><span style="color: #0000ff">catch</span> (ReflectionTypeLoadException ex)<br />{<br />    StringBuilder sb = <span style="color: #0000ff">new</span> StringBuilder();<br />    <span style="color: #0000ff">foreach</span> (Exception exSub <span style="color: #0000ff">in</span> ex.LoaderExceptions)<br />    {<br />        sb.AppendLine(exSub.Message);<br />        <span style="color: #0000ff">if</span> (exSub <span style="color: #0000ff">is</span> FileNotFoundException)<br />        {<br />            FileNotFoundException exFileNotFound = exSub <span style="color: #0000ff">as</span> FileNotFoundException;<br />            <span style="color: #0000ff">if</span>(!<span style="color: #0000ff">string</span>.IsNullOrEmpty(exFileNotFound.FusionLog))<br />            {<br />                sb.AppendLine(<span style="color: #006080">&quot;Fusion Log:&quot;</span>);<br />                sb.AppendLine(exFileNotFound.FusionLog);<br />            }<br />        }<br />        sb.AppendLine();<br />    }<br />    <span style="color: #0000ff">string</span> errorMessage = sb.ToString();<br />   }<br /></pre>
<p></div>
<p>N’oubliez pas d’ajouter une référence à System.IO et System.Reflection;</p>
<p>Et voilà. Dorénavant, lorsque vous allez exécuter votre application et qu’il y’aura un problème avec le chargement d’un composant, vous aurez un message clair et les détails sur l’assembly qui pose problème.</p>
<p>À noter que ce bug n’existe plus lorsque l’on utilise Entity Framework avec le framework .NET 4.5, il ne scanne plus toutes les assemblys de l’application lors de son exécution.</p>
]]></content:encoded>
			<wfw:commentRss></wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Entity Framework Code First : activer la migration automatique</title>
		<link>https://blog.developpez.com/lilroma/p11097/net/entity_framework_code_first_activer_la_m</link>
		<comments>https://blog.developpez.com/lilroma/p11097/net/entity_framework_code_first_activer_la_m#comments</comments>
		<pubDate>Sat, 16 Jun 2012 10:35:58 +0000</pubDate>
		<dc:creator><![CDATA[Hinault Romaric]]></dc:creator>
				<category><![CDATA[.NET]]></category>
		<category><![CDATA[ASP.NET]]></category>
		<category><![CDATA[ASP.NET MVC 3]]></category>
		<category><![CDATA[ASP.NET MVC 4]]></category>
		<category><![CDATA[Entity Framework]]></category>
		<category><![CDATA[SGBD]]></category>
		<category><![CDATA[Visual Studio]]></category>

		<guid isPermaLink="false"></guid>
		<description><![CDATA[Pendant le développement ou le cycle de vie d’une application, le développeur est très souvent confronté à des situations pouvant entrainer des modifications de son modèle objet et de la base de données. Avec Entity Framework, cette tâche peut s’avérer &#8230; <a href="https://blog.developpez.com/lilroma/p11097/net/entity_framework_code_first_activer_la_m">Lire la suite <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<p>Pendant le développement ou le cycle de vie d’une application, le développeur est très souvent confronté à des situations pouvant entrainer des modifications de son modèle objet et de la base de données. Avec Entity Framework, cette tâche peut s’avérer assez complexe et voir même frustrant pour certains.</p>
<p>Une des nouveautés les plus intéressantes qu’apporte Entity Framework 4.3 est la migration pour les mises à jour de la base de données.</p>
<p>Cette fonctionnalité offre aux développeurs des outils permettant d’appliquer avec souplesse et facilité des mises à jour à la base de données à partir des modifications apportées à l’application. </p>
<p><span id="more-80"></span></p>
<p>Dans <a href="http://blog.developpez.com/lilroma/p10807/">un précédent billet de blog</a>, j’ai présenté cette fonctionnalité et comment l’on pouvait l’utiliser pour effectuer des mises à jour de la base de données.</p>
<p>Cet article présentait uniquement l’un des modes de mises à jour qu’offre Entity Framework : le mode basé sur le code.</p>
<p>Supposons que vous disposez déjà d’une application utilisant Entity Framework Code First. Procédez à la mise à jour de celle-ci pour utiliser la version 4.3 d’Entity Framework si ce n’est pas encore le cas.</p>
<p>Vous pouvez utiliser la commande :</p>
<blockquote><p>PM>  install-package EntityFramework
</p></blockquote>
<p><strong>Activer la migration</strong></p>
<p>La première étape est d’activer la migration pour votre DbContext, en utilisant la console du gestionnaire de packages (menu Outils/Gestionnaire de package/Package Manager Console de Visual Studio). Vous allez exécuter la commande «  Enabled-Migrations ».</p>
<p><img src="http://blog.developpez.com/media/enablemigration.png" alt="" title="" /></p>
<p>L’activation de la migration crée un nouveau dossier Migrations dans votre application contenant un fichier Configurations.cs permettant de définir le comportement de la migration pour le DbContext qui est utilisé.</p>
<div style="border-bottom: silver 1px solid; text-align: left; border-left: silver 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; max-height: 200px; font-size: 8pt; overflow: auto; border-top: silver 1px solid; cursor: text; border-right: silver 1px solid; padding-top: 4px" id="codeSnippetWrapper">
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px" id="codeSnippet"><span style="color: #0000ff">namespace</span> DatabaseMigration.Migrations<br />{<br />    <span style="color: #0000ff">using</span> System;<br />    <span style="color: #0000ff">using</span> System.Data.Entity;<br />    <span style="color: #0000ff">using</span> System.Data.Entity.Migrations;<br />    <span style="color: #0000ff">using</span> System.Linq;<br /><br />    <span style="color: #0000ff">internal</span> <span style="color: #0000ff">sealed</span> <span style="color: #0000ff">class</span> Configuration : DbMigrationsConfiguration&lt;DatabaseMigration.DatabaseMigrationContext&gt;<br />    {<br />        <span style="color: #0000ff">public</span> Configuration()<br />        {<br />            AutomaticMigrationsEnabled = <span style="color: #0000ff">false</span>;<br />        }<br /><br />        <span style="color: #0000ff">protected</span> <span style="color: #0000ff">override</span> <span style="color: #0000ff">void</span> Seed(DatabaseMigration.DatabaseMigrationContext context)<br />        {<br />            <br />        }<br />    }<br />}<br /></pre>
<p></div>
<p>Si vous avez défini plusieurs «DbContext » dans votre application, il suffira juste de modifier  DbMigrationsConfiguration(T), en remplaçant T par le nom du DbContext que vous voulez utiliser.</p>
<p><strong>Configurer la migration automatique</strong></p>
<p>Par défaut, la propriété AutomaticMigrationsEnabled est définie à false. Pour utiliser la migration automatique, vous devez affecter la valeur « true » à cette propriété.</p>
<p>Il également possible de définir cette propriété à true lors de l’activation de la migration. Pour cela, vous devez ajouter le paramètre EnableAutomaticMigrations à la commande permettant d’activer la migration :</p>
<blockquote><p>PM> Enable-Migrations -EnableAutomaticMigrations</p></blockquote>
<p>Par défaut, la migration automatique n’autorise pas les mises à jour pouvant entrainer des pertes de données. Pour activer cette option, vous devez éditer le fichier Configuration.cs en y ajoutant la propriété  « AutomaticMigrationDataLossAllowed » qui sera définie à true.</p>
<div id="codeSnippetWrapper" style="background-color: #f4f4f4; font-family: 'Courier New', Courier, Monospace; font-size: 8pt; line-height: 12pt; border: solid 1px silver; cursor: text; margin: 20px 0px 10px 0px; max-height: 200px; overflow: auto; padding: 4px; width: 97.5%; direction: ltr; text-align: left;">
<pre id="codeSnippet" style="background-color: #f4f4f4; font-family: 'Courier New', Courier, Monospace; font-size: 8pt; line-height: 12pt; border-style: none; color: black; overflow: visible; padding: 0px; width: 100%; margin: 0em; direction: ltr; text-align: left;"><span style="color: #0000ff;">public</span> Configuration()<br />        {<br />            AutomaticMigrationsEnabled = <span style="color: #0000ff;">true</span>;<br />            AutomaticMigrationDataLossAllowed = <span style="color: #0000ff;">true</span>;<br />        }</pre>
<p></div>
<p>Editez ensuite votre DbContext et ajoutez-y la procédure onModelCreating  :</p>
<div id="codeSnippetWrapper" style="background-color: #f4f4f4; font-family: 'Courier New', Courier, Monospace; font-size: 8pt; line-height: 12pt; border: solid 1px silver; cursor: text; margin: 20px 0px 10px 0px; max-height: 200px; overflow: auto; padding: 4px; width: 97.5%; direction: ltr; text-align: left;">
<pre id="codeSnippet" style="background-color: #f4f4f4; font-family: 'Courier New', Courier, Monospace; font-size: 8pt; line-height: 12pt; border-style: none; color: black; overflow: visible; padding: 0px; width: 100%; margin: 0em; direction: ltr; text-align: left;"><span style="color: #0000ff;">protected</span> <span style="color: #0000ff;">override</span> <span style="color: #0000ff;">void</span> OnModelCreating(DbModelBuilder modelBuilder)<br />        {<br />            Database.SetInitializer(<span style="color: #0000ff;">new</span> MigrateDatabaseToLatestVersion&lt;DatabaseMigrationContext, Configuration&gt;());<br />        }</pre>
<p></div>
<p>Et voilà, c’est tout ;). Toute modification de votre modèle objet (nouvelle entité, ajout d’une propriété, suppression d’une propriété, etc.) sera automatiquement appliquée à la base de données à l’exécution de votre application.</p>
<p><strong>Inconvénients de la migration automatique</strong></p>
<p>La migration automatique permet d’apporter assez rapidement et simplement des mises à jour à une base de données en utilisant Entity Framework Code First. Cette option présente cependant des inconvénients, et personnellement, je ne recommanderais pas son utilise en environnement de production ou sur un système critique.</p>
<p>L’utilisation du mode automatique en environnement de production peut s’avérer assez dangereuse, avec un risque de perte de données, car les modifications apportées à la base de données sont imprévisibles par le développeur, et celui-ci n’a aucune visibilité sur ces changements.</p>
<p>Néanmoins, vous pouvez limiter ces risques en environnement de production en désactivant l’autorisation des mises à jour pouvant entrainer des pertes de données.</p>
]]></content:encoded>
			<wfw:commentRss></wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Internationalisation d’une application ASP.NET MVC 3 Razor  part 3 : Mécanisme de sélection de la langue dans l’IU</title>
		<link>https://blog.developpez.com/lilroma/p10732/net/internationalisation_d_une_application_a_3</link>
		<comments>https://blog.developpez.com/lilroma/p10732/net/internationalisation_d_une_application_a_3#comments</comments>
		<pubDate>Mon, 20 Feb 2012 10:04:19 +0000</pubDate>
		<dc:creator><![CDATA[Hinault Romaric]]></dc:creator>
				<category><![CDATA[.NET]]></category>
		<category><![CDATA[ASP.NET]]></category>
		<category><![CDATA[ASP.NET MVC 3]]></category>
		<category><![CDATA[Visual Studio]]></category>

		<guid isPermaLink="false"></guid>
		<description><![CDATA[Dans les parties précédentes, nous avons introduit l’internationalisation sur la plateforme .NET et nous avons vu comment procéder à la localisation des vues, des messages d’erreur de validation et des attributs Display dans le modèle. Cependant, jusqu’ici, lors de nos &#8230; <a href="https://blog.developpez.com/lilroma/p10732/net/internationalisation_d_une_application_a_3">Lire la suite <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<p>Dans les parties précédentes, nous avons <a href="http://blog.developpez.com/lilroma/p10697/">introduit l’internationalisation</a> sur la plateforme .NET et nous avons vu comment procéder à <a href="http://blog.developpez.com/lilroma/p10702/">la localisation des vues, des messages d’erreur de validation et des attributs Display dans le modèle</a>.</p>
<p>Cependant, jusqu’ici, lors de nos tests, vous pouvez vous rendre compte que notre application ne dispose d’aucun mécanisme permettant à un l’utilisateur à partir de l’interface de choisir une langue ou de basculer d’une langue à une autre à tout moment.</p>
<p>Cet aspect de l’internationalisation d’une application Web ASP.NET MVC 3 Razor fera l’objet de ce billet de blog.</p>
<p><span id="more-42"></span></p>
<p>Nous allons utiliser l’application que nous avons créée précédemment.</p>
<p>Dans notre cas, nous allons définir la langue qui est utilisée dans L’URL.  Pour cela, nous allons commencer par définir la stratégie de routage qui sera utilisée dans notre application, en spécifiant la langue. L’URL que nous allons utilisera sous la forme suivante :</p>
<p>http://localhost/fr-fr/home/index pour le français<br />
et<br />
http://localhost/en-us/home/index pour l’anglais.</p>
<p>La route par défaut dans ASP.NET MVC 3 est définie sous la forme : http://localhost/controller/action/id.  À partir de là, nous allons définir de nouveaux paramètres de route qui permettront de générer l’URL avec la langue. Pour cela, nous allons définir la route sous la forme suivante : http://localhost/lang/controller/action/id.</p>
<p>Pour atteindre ce résultat, il suffit de modifier le fichier Global.ascx.cs, et enregistrer une nouvelle route. Le code pour faire cela est le suivant :</p>
<div id="codeSnippetWrapper">
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px" id="codeSnippet"><span style="color: #0000ff">public</span> <span style="color: #0000ff">static</span> <span style="color: #0000ff">void</span> RegisterRoutes(RouteCollection routes)<br />        {<br />            routes.IgnoreRoute(<span style="color: #006080">&quot;{resource}.axd/{*pathInfo}&quot;</span>);<br />            routes.IgnoreRoute(<span style="color: #006080">&quot;favicon.ico&quot;</span>);<br /><br />            routes.MapRoute(<br />               <span style="color: #006080">&quot;LocalizedDefault&quot;</span>, <span style="color: #008000">// Route name</span><br />               <span style="color: #006080">&quot;{lang}/{controller}/{action}/{id}&quot;</span>, <span style="color: #008000">// URL with parameters</span><br />               <span style="color: #0000ff">new</span> { controller = <span style="color: #006080">&quot;Home&quot;</span>, action = <span style="color: #006080">&quot;Index&quot;</span>, id = UrlParameter.Optional } <span style="color: #008000">// Parameter defaults</span><br />           );<br /><br />            routes.MapRoute(<br />                <span style="color: #006080">&quot;Default&quot;</span>, <span style="color: #008000">// Route name</span><br />                <span style="color: #006080">&quot;{controller}/{action}/{id}&quot;</span>, <span style="color: #008000">// URL with parameters</span><br />                <span style="color: #0000ff">new</span> { controller = <span style="color: #006080">&quot;Home&quot;</span>, action = <span style="color: #006080">&quot;Index&quot;</span>, id = UrlParameter.Optional } <span style="color: #008000">// Parameter defaults</span><br />            );<br />        }<br /></pre>
<p></div>
<p> Maintenant, vous devez ajouter un nouveau contrôleur (BaseController) qui héritera de System.Web.Mvc.Controller. Sa fonction principale sera de changer la langue du Thread d’exécution courant selon la valeur de la langue dans l’URL ou dans un cookie existant, et de sauvegarder le choix linguistique de l’utilisateur dans un cookie si ce n’est pas déjà fait. Si aucune langue n’est spécifiée dans l’URL, la langue  du Thread d’exécution sera modifiée en utilisant par défaut la langue du navigateur de l’utilisateur. </p>
<p>Le code pour faire cela est le suivant :</p>
<div id="codeSnippetWrapper">
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px" id="codeSnippet"><span style="color: #0000ff">using</span> System;<br /><span style="color: #0000ff">using</span> System.Collections.Generic;<br /><span style="color: #0000ff">using</span> System.Linq;<br /><span style="color: #0000ff">using</span> System.Web;<br /><span style="color: #0000ff">using</span> System.Web.Mvc;<br /><span style="color: #0000ff">using</span> System.Text;<br /><span style="color: #0000ff">using</span> System.Threading;<br /><span style="color: #0000ff">using</span> System.Globalization;<br /><br /><span style="color: #0000ff">namespace</span> MvcApplication1.Controllers<br />{<br />    <span style="color: #0000ff">public</span> <span style="color: #0000ff">class</span> BaseController : Controller<br />    {<br />        <span style="color: #008000">//</span><br />        <span style="color: #008000">// GET: /Base/</span><br /><br />        <span style="color: #0000ff">protected</span> <span style="color: #0000ff">override</span> <span style="color: #0000ff">void</span> ExecuteCore()<br />         {<br />             <span style="color: #0000ff">if</span> (RouteData.Values[<span style="color: #006080">&quot;lang&quot;</span>] != <span style="color: #0000ff">null</span> &amp;&amp;<br />              !<span style="color: #0000ff">string</span>.IsNullOrWhiteSpace(RouteData.Values[<span style="color: #006080">&quot;lang&quot;</span>].ToString()))<br />             {<br />                 <span style="color: #008000">// modification de la culture dans les données de la route</span><br />                 var lang = RouteData.Values[<span style="color: #006080">&quot;lang&quot;</span>].ToString();<br />                 Thread.CurrentThread.CurrentUICulture = CultureInfo.CreateSpecificCulture(lang);<br />             }<br />             <span style="color: #0000ff">else</span><br />             {<br />                 <span style="color: #008000">// chargement de la culture depuis un cookie</span><br />                 var cookie = HttpContext.Request.Cookies[<span style="color: #006080">&quot;MvcApplication1.CurrentUICulture&quot;</span>];<br />                 var langHeader = <span style="color: #0000ff">string</span>.Empty;<br />                 <span style="color: #0000ff">if</span> (cookie != <span style="color: #0000ff">null</span>)<br />                 {<br />                     <span style="color: #008000">// modification de la culture avec la valeur dans le cookie</span><br />                     langHeader = cookie.Value;<br />                     Thread.CurrentThread.CurrentUICulture = CultureInfo.CreateSpecificCulture(langHeader);<br />                 }<br />                 <span style="color: #0000ff">else</span><br />                 {<br />                     <span style="color: #008000">// utilisation de la langue par défaut du naviageteur si la culture n'est pas spécifiée</span><br />                     langHeader = HttpContext.Request.UserLanguages[0];<br />                     Thread.CurrentThread.CurrentUICulture = CultureInfo.CreateSpecificCulture(langHeader);<br />                 }<br />                 <span style="color: #008000">// modification de la culture dans les données de la route</span><br />                 RouteData.Values[<span style="color: #006080">&quot;lang&quot;</span>] = langHeader;<br />             }<br /><br />             <span style="color: #008000">// sauvegarde de la culture dans un cookie</span><br />             HttpCookie _cookie = <span style="color: #0000ff">new</span> HttpCookie(<span style="color: #006080">&quot;MvcApplication1.CurrentUICulture&quot;</span>, Thread.CurrentThread.CurrentUICulture.Name);<br />             _cookie.Expires = DateTime.Now.AddYears(1);<br />             HttpContext.Response.SetCookie(_cookie);<br /><br />             <span style="color: #0000ff">base</span>.ExecuteCore();<br />         }<br /><br />    }<br />}<br /><br /></pre>
<p></div>
<p>Tous les contrôleurs de l’application doivent être modifiés pour hériter de ce contrôleur (Basecontrolleur).</p>
<div id="codeSnippetWrapper">
<pre id="codeSnippet" style="background-color: #f4f4f4; font-family: 'Courier New', Courier, Monospace; font-size: 8pt; line-height: 12pt; border-style: none; color: black; overflow: visible; padding: 0px; width: 100%; margin: 0em; direction: ltr; text-align: left;"><span style="color: #0000ff;">public</span> <span style="color: #0000ff;">class</span> HomeController : BaseController</pre>
<p></div>
<p>Après avoir enregistré la route localisée, nous devons procéder à l’écriture d’une fonction permettant de générer l’URL localisée en fonction du choix de la langue de l’utilisateur.<br />
Pour cela, nous allons ajouter un HTML Helper dans notre projet.  Les Helpers HTML sont des méthodes d’extensions pour les classes HtmlHelper. Ces méthodes sont accessibles dans une vue à partir de la méthode HTML.</p>
<p>Le code pour notre Helper HTML est le suivant :</p>
<div id="codeSnippetWrapper">
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px" id="codeSnippet"><span style="color: #0000ff">public</span> <span style="color: #0000ff">static</span> <span style="color: #0000ff">class</span> SwitchLanguageHelper<br />    {<br />        <span style="color: #0000ff">public</span> <span style="color: #0000ff">class</span> Language<br />        {<br />            <span style="color: #0000ff">public</span> <span style="color: #0000ff">string</span> Url { get; set; }<br />            <span style="color: #0000ff">public</span> <span style="color: #0000ff">string</span> ActionName { get; set; }<br />            <span style="color: #0000ff">public</span> <span style="color: #0000ff">string</span> ControllerName { get; set; }<br />            <span style="color: #0000ff">public</span> RouteValueDictionary RouteValues { get; set; }<br />            <span style="color: #0000ff">public</span> <span style="color: #0000ff">bool</span> IsSelected { get; set; }<br /><br />            <span style="color: #0000ff">public</span> MvcHtmlString HtmlSafeUrl<br />            {<br />                get<br />                {<br />                    <span style="color: #0000ff">return</span> MvcHtmlString.Create(Url);<br />                }<br />            }<br />        }<br /><br />        <span style="color: #0000ff">public</span> <span style="color: #0000ff">static</span> Language LanguageUrl(<span style="color: #0000ff">this</span> HtmlHelper helper, <span style="color: #0000ff">string</span> cultureName,<br />            <span style="color: #0000ff">string</span> languageRouteName = <span style="color: #006080">&quot;lang&quot;</span>, <span style="color: #0000ff">bool</span> strictSelected = <span style="color: #0000ff">false</span>)<br />        {<br />            <br />            cultureName = cultureName.ToLower();<br />            <span style="color: #008000">// récuperation des valeurs de ka route depuis le view context</span><br />            var routeValues = <span style="color: #0000ff">new</span> RouteValueDictionary(helper.ViewContext.RouteData.Values);<br />            <br />            <span style="color: #008000">//copie de la chaine de requête dans les valeurs de route pour générer le nouveau lien</span><br />            var queryString = helper.ViewContext.HttpContext.Request.QueryString;<br />            <span style="color: #0000ff">foreach</span> (<span style="color: #0000ff">string</span> key <span style="color: #0000ff">in</span> queryString)<br />            {<br />                <span style="color: #0000ff">if</span> (queryString[key] != <span style="color: #0000ff">null</span> &amp;&amp; !<span style="color: #0000ff">string</span>.IsNullOrWhiteSpace(key))<br />                {<br />                    <span style="color: #0000ff">if</span> (routeValues.ContainsKey(key))<br />                    {<br />                        routeValues[key] = queryString[key];<br />                    }<br />                    <span style="color: #0000ff">else</span><br />                    {<br />                        routeValues.Add(key, queryString[key]);<br />                    }<br />                }<br />            }<br />            var actionName = routeValues[<span style="color: #006080">&quot;action&quot;</span>].ToString();<br />            var controllerName = routeValues[<span style="color: #006080">&quot;controller&quot;</span>].ToString();<br />            <span style="color: #008000">//modification de la langue dans les valeurs de route</span><br />            routeValues[languageRouteName] = cultureName;<br />            <span style="color: #008000">//génération de l'url avec la langue</span><br />            var urlHelper = <span style="color: #0000ff">new</span> UrlHelper(helper.ViewContext.RequestContext, helper.RouteCollection);<br />            var url = urlHelper.RouteUrl(<span style="color: #006080">&quot;LocalizedDefault&quot;</span>, routeValues);<br />            <span style="color: #008000">// vérification si la culture courante correspond à celle passée en paramètre</span><br />            var current_lang_name = Thread.CurrentThread.CurrentUICulture.Name.ToLower();<br />            var isSelected = strictSelected ?<br />                current_lang_name == cultureName :<br />                current_lang_name.StartsWith(cultureName);<br />            <span style="color: #0000ff">return</span> <span style="color: #0000ff">new</span> Language()<br />            {<br />                Url = url,<br />                ActionName = actionName,<br />                ControllerName = controllerName,<br />                RouteValues = routeValues,<br />                IsSelected = isSelected<br />            };<br />        }<br /><br />        <br />        <span style="color: #0000ff">public</span> <span style="color: #0000ff">static</span> MvcHtmlString LanguageSelectorLink(<span style="color: #0000ff">this</span> HtmlHelper helper,<br />           <span style="color: #0000ff">string</span> cultureName, <span style="color: #0000ff">string</span> selectedText, <span style="color: #0000ff">string</span> unselectedText,<br />           IDictionary htmlAttributes, <span style="color: #0000ff">string</span> languageRouteName = <span style="color: #006080">&quot;lang&quot;</span>, <span style="color: #0000ff">bool</span> strictSelected = <span style="color: #0000ff">false</span>)<br />        {<br />            var language = helper.LanguageUrl(cultureName, languageRouteName, strictSelected);<br />            var link = helper.RouteLink(language.IsSelected ? selectedText : unselectedText,<br />                <span style="color: #006080">&quot;LocalizedDefault&quot;</span>, language.RouteValues);<br />            <span style="color: #0000ff">return</span> link;<br />        }<br /><br />       <br />    }<br /></pre>
<p></div>
<p>Enfin, dans le dossier View/Shared, nous allons ajouter une vue partielle (_SelectLanguage.cshtml) pour la sélection de la langue par l’utilisateur.<br />
Le code pour cette  page est le suivant :</p>
<div id="codeSnippetWrapper">
<pre id="codeSnippet" style="background-color: #f4f4f4; font-family: 'Courier New', Courier, Monospace; font-size: 8pt; line-height: 12pt; border-style: none; color: black; overflow: visible; padding: 0px; width: 100%; margin: 0em; direction: ltr; text-align: left;">@<span style="color: #0000ff;">using</span> MvcApplication1.MyHelper<br /><br />@Html.LanguageSelectorLink(<span style="color: #006080;">"en-US"</span>, <span style="color: #006080;">"[English]"</span>, <span style="color: #006080;">"English"</span>, <span style="color: #0000ff;">null</span>)<br />@Html.LanguageSelectorLink(<span style="color: #006080;">"fr-FR"</span>, <span style="color: #006080;">"[Français]"</span>, <span style="color: #006080;">"Français"</span>, <span style="color: #0000ff;">null</span>)<br /></pre>
<p></div>
<p>La vue partielle doit être appelée dans le Layout de votre projet :</p>
<div id="codeSnippetWrapper">
<pre id="codeSnippet" style="background-color: #f4f4f4; font-family: 'Courier New', Courier, Monospace; font-size: 8pt; line-height: 12pt; border-style: none; color: black; overflow: visible; padding: 0px; width: 100%; margin: 0em; direction: ltr; text-align: left;">&lt;div id=<span style="color: #006080;">"logindisplay"</span>&gt;<br />                @Html.Partial(<span style="color: #006080;">"_LogOnPartial"</span>)<br />                @Html.Partial("_SelectLanguage<br />&lt;/div&gt;</pre>
<p></div>
<p>Nous pouvons maintenant exécuter l’application pour voir le résultat produit comme l’illustrent les captures suivantes :</p>
<p><img src="http://blog.developpez.com/media/lasttesten.png" width="601" height="551" alt="" /></p>
<p><img src="http://blog.developpez.com/media/lasttestfr.png" width="598" height="540" alt="" /></p>
<p>Et voilà, nous venons de finir avec la dernière étape d&rsquo;internationalisation de notre application. J&rsquo;espère que ce tutoriel vous sera d&rsquo;une grande utilité pour créer des applications ASP.NET MVC 3 multilingues ;). </p>
]]></content:encoded>
			<wfw:commentRss></wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Internationalisation d’une application ASP.NET MVC 3 Razor Part 1 : ressources et vues</title>
		<link>https://blog.developpez.com/lilroma/p10697/net/internationalisation_d_une_application_a_1</link>
		<comments>https://blog.developpez.com/lilroma/p10697/net/internationalisation_d_une_application_a_1#comments</comments>
		<pubDate>Sat, 04 Feb 2012 10:29:46 +0000</pubDate>
		<dc:creator><![CDATA[Hinault Romaric]]></dc:creator>
				<category><![CDATA[.NET]]></category>
		<category><![CDATA[ASP.NET]]></category>
		<category><![CDATA[ASP.NET MVC 3]]></category>
		<category><![CDATA[RAZOR]]></category>
		<category><![CDATA[Visual Studio]]></category>

		<guid isPermaLink="false"></guid>
		<description><![CDATA[Plusieurs articles sont déjà disponibles sur developpez.com ou sur le Web qui traitent de l’internationalisation d’une application Web ASP.NET. Cependant, pour ASP.NET MVC, il en existe très peu, et il n’y a pas de méthode reconnue comme standard pour écrire &#8230; <a href="https://blog.developpez.com/lilroma/p10697/net/internationalisation_d_une_application_a_1">Lire la suite <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<p>Plusieurs articles sont déjà disponibles sur developpez.com ou sur le Web qui traitent de l’internationalisation d’une application Web ASP.NET. Cependant, pour ASP.NET MVC, il en existe très peu, et il n’y a pas de méthode reconnue comme standard pour écrire un site multilingue avec le framework Web de Microsoft.</p>
<p>En me basant donc du meilleur que j’ai pu tirer de quelques articles par-ci par-là et mon expérience, j’ai mis au point une solution qui répondait à mes besoins pour une application ASP.NET MVC Razor. Cette méthode n’est pas standard, et peut-être pas la meilleure, mais elle répond pleinement aux exigences de mon projet et aux objectifs que je voulais atteindre.</p>
<p><img src="http://blog.developpez.com/media/internationalisation.jpg" width="450" height="299" alt="" /></p>
<p><span id="more-41"></span></p>
<p><strong>Ce qu&rsquo;il faut savoir sur l’internationalisation dans l&rsquo;écosystème .NET </strong></p>
<p>Avant de se lancer dans la création d’un site multilingue en ASP.NET, il y a un certain nombre de concepts que vous devriez au préalable savoir.  Lorsqu’on parle d’internationalisation d’une application sur la plateforme .NET, cela implique la mise en œuvre de deux mécanismes principaux à savoir : la mondialisation et la localisation.</p>
<p><strong>La mondialisation</strong> est le processus de conception et de développement d&rsquo;un produit logiciel adapté à plusieurs cultures. Une application mondialisée prend en charge des interfaces utilisateurs localisées et des données régionales pour tous les utilisateurs. Par exemple, le format de la date en zone francophone est jj/mm/aaaa. Dans les pays anglophones, nous avons plutôt le format mm/jj/aaaa. La mondialisation va consister à afficher le bon format dans une page en fonction de la langue du navigateur d’un utilisateur ou des options choisies par celui-ci.</p>
<p><strong>La localisation</strong> est le processus d&rsquo;adaptation de votre application à une culture et aux paramètres régionaux donnés. Vous devez pendant cette étape, personnaliser votre application pour les cultures  auxquelles vous la destinez. Cette étape doit consister essentiellement en une traduction de l&rsquo;interface utilisateur vers les langues cibles.</p>
<p><strong>Différentes possibilités d’internationalisation d’une application ASP.NET</strong></p>
<p>  Il existe sur la plateforme .NET plusieurs procédés pour rendre son site multilingue. L’internationalisation d’une application peut donc être faite en utilisant soi :</p>
<p>&#8211; Les fichiers de ressources ;</p>
<p>&#8211; Des vues différentes pour chaque culture (traduction dans le code) ;</p>
<p>&#8211; Des fichiers texte ;</p>
<p>&#8211; Utiliser à la place des fichiers de ressources une base de données ;</p>
<p>&#8211; Ou combiner la première et la seconde méthode.</p>
<p>Chacune de ces techniques à ses avantages et ses inconvénients, et l’orientation vers l’une d’entre elles dépend aussi entre autres des spécifications de votre projet et des contraintes techniques auxquelles vous êtes confrontés. Personnellement je préfère les fichiers de ressources que j’utilise couramment lorsque je suis confronté à cette problématique.</p>
<p>Les fichiers ressources sont des fichiers textes optimisés. Au chargement, ils sont entièrement triés afin de limiter les accès que ce soit au niveau de la mémoire ou des différents disques.<br />
C’est pourquoi, dans le cadre de ce tutoriel, nous nous limiterons uniquement à l’utilisation des fichiers de ressources.</p>
<p><strong>Prérequis</strong></p>
<p>&#8211; Visual Web Developer 2010 ;</p>
<p>&#8211; ASP.NET MVC 3 ;</p>
<p>&#8211; Connaissance de base en C# et sur le moteur de vue Razor.</p>
<p><strong>Création de l’application</strong></p>
<p>Nous allons commencer dès la base même, par la création d’une nouvelle application qui sera utilisée tout au long de l’article.<br />
Pour ce faire, vous allez démarrer votre EDI Visual Studio. Cliquez sur le menu Fichier, ensuite sur la commande Nouveau projet. Dans la fenêtre qui va s’afficher, sélectionnez le Template de projet ASP.NET MVC 3 Web Application, renseignez le nom de l’application et l’emplacement ou celle-ci va être stockée et cliquez sur OK.</p>
<p><img src="http://rdonfack.developpez.com/tutoriels/dotnet/creation-pages-web-asp-net-utilisant-moteur-vue-razor/images/startrazorprojet.PNG" alt="" title="" /></p>
<p>Sélectionnez ensuite dans la fenêtre qui va s’afficher le modèle de projet Internet Application, en vous assurant que le moteur de vue qui sera utilisé est Razor.</p>
<p><img src="http://rdonfack.developpez.com/tutoriels/dotnet/creation-pages-web-asp-net-utilisant-moteur-vue-razor/images/ViewEngine.PNG" alt="" title="" /></p>
<p>Cliquez ensuite sur OK pour que Visual Studio procède à la création de votre application.</p>
<p>Si vous exécutez l’application à ce stade, vous vous rendrez compte que le texte affiché par défaut dans vos pages est en anglais.</p>
<p><img src="http://rdonfack.developpez.com/tutoriels/dotnet/creation-pages-web-asp-net-utilisant-moteur-vue-razor/images/test1.PNG" alt="" title="" /></p>
<p>Puisque vous souhaitez que l’internaute qu’il soit  anglophone ou francophone puissent se sentir à l’aise dans la navigation sur votre site, vous allez ajouter à celui-ci en plus du support de l’anglais, la prise en charge du français.</p>
<p>Pour atteindre ce résultat, les premières étapes suivantes sont nécessaires :</p>
<p>&#8211; Création des fichiers de ressources ;</p>
<p>&#8211; Modification des vues ;</p>
<p>&#8211; Définition de la culture.</p>
<p><strong>Création des fichiers de ressources</strong></p>
<p>Pour gérer efficacement l’internationalisation dans notre application, nous avons opté pour l’utilisation des fichiers de ressources pour stocker les valeurs qui doivent être localisées. </p>
<p><strong>Ce qu’il faut savoir sur les fichiers de ressources</strong></p>
<p>Une ressource est une donnée non exécutable qui est déployée logiquement avec une application. Les ressources peuvent contenir des données sous plusieurs formes, telles que des chaînes, des images ou des objets rendus persistants. Le stockage de vos données dans un fichier de ressources vous permet de changer les données sans avoir à recompiler l&rsquo;intégralité de votre application.</p>
<p>Le format de fichier de ressources .resx se compose d&rsquo;entrées XML, qui spécifient des objets et des chaînes dans des balises XML. Le .NET Framework fournit une prise en charge complète pour la création et la localisation des ressources. Ceux-ci doivent être créés d’une façon particulière  pour fonctionner correctement. </p>
<p>Les fichiers de ressources de la langue par défaut de votre application doivent être nommés comme suit : nom_du_fichiers.resx.</p>
<p>Les fichiers pour les autres langues doivent suivre le format suivant : nom_du_fichier.culture.resx. </p>
<p><strong>Ce qu’il faut savoir sur la culture</strong></p>
<p>La culture ici doit définir le code la langue. Un code de langue est une convention symbolique permettant d’identifier une langue ou une variété dialectale ou régionale, ou un ensemble de langues par un identifiant défini dans un code, sans avoir à nommer la langue désignée elle-même.</p>
<p>La culture peut être neutre. Dans ce cas, elle sera codée sur deux caractères. </p>
<p><strong>Exemple :</strong> en pour l’Anglais et fr pour le français.</p>
<p>Ou être stricte. Dans ce cas, elle sera codée sur quatre caractères ayant le format suivant « xx-XX », deux caractères minuscules pour la langue, et les deux suivantes en majuscules pour la variante régionale.</p>
<p><strong>Exemple :</strong> fr-FR pour le français de France, en-US pour l’anglais des États-Unis et en-GB pour l’anglais de la Grande-Bretagne.</p>
<p><strong>NB :</strong> Le fichier de ressource par défaut est utilisé si aucune culture n’est définie dans l’application ou si aucune ressource n’existe pour la culture qui a été définie.</p>
<p><strong>Architecture.</strong></p>
<p>Pour rester dans la logique de regroupement qu’impose ASP.NET MVC, il est préférable que l’arborescence de vos fichiers de ressources soit  semblable à la capture ci-dessous :</p>
<p><img src="http://blog.developpez.com/media/folderview.PNG" width="641" height="349" alt="" /></p>
<p>Vous allez donc créer un dossier Ressources, en faisant un clic droit dans l’explorateur de projet et  en cliquant sur Ajouter, puis en sélectionnant l’option Nouveau dossier.</p>
<p>Dans ce dossier vous allez procéder de même pour créer les dossiers Models, Views, etc.</p>
<p>Par la suite, vous devez créer les différents fichiers de ressources.<br />
Je vous recommande de commencer par celui de la page Layout.chtml.  Pour cela, vous allez créer les fichiers Layout.resx pour la langue par défaut et Layout.fr.resx pour le français. </p>
<p>Pour créer ces fichiers,  faites un clic droit sur le sous-dossier Shared, sélectionnez l’option Ajouter, puis cliquez sur Ajouter un nouvel élément.<br />
Dans la boite de dialogue qui va s’afficher, sélectionnez le type de fichier Ressources File, et renseignez le nom _Layout.resx dans la zone réserver à cet effet, puis cliquez sur Ajouter.</p>
<p><img src="http://blog.developpez.com/media/CreationFichierRessources.PNG" width="801" height="456" alt="" /></p>
<p>Faites de même pour créer le fichier Layout.fr.resx et les autres fichiers de ressources.</p>
<p>Maintenant, vous devez déplacer les textes qui sont dans votre fichier _Layout.cshtml dans le fichier de ressources, en renseignant le nom (comme celui d’une variable), la valeur (qui est le texte contenu dans le page) et une description s’il y a lieu.</p>
<p>Prenez la peine de vérifier que la zone « <strong>Acces Modifier</strong> » est définie à Public. Sinon, les valeurs que vous avez définies ne seront pas accessibles dans les vues.</p>
<p><img src="http://blog.developpez.com/media/DefaultLayoutRessources.PNG" width="624" height="316" alt="" />  </p>
<p>Renseignez également la traduction de ces textes pour le fichier _Layout.fr.resx.</p>
<p>Attention, le nom doit être le même que celui que vous avez défini dans le fichier de ressources par défaut pour cette page.</p>
<p><img src="http://blog.developpez.com/media/FrLayoutRessources.PNG" width="628" height="321" alt="" /> </p>
<p>NB : Contrairement à ASP.NET WebForms où il est conseillé de créer les fichiers de ressources dans les dossiers  App_GlobalResources et App_LocalResources, avec ASP.NET MVC, l’utilisation de ces dossiers sera une source de problèmes pour vous. Je vous  conseille donc d’utiliser un dossier différent (comme ce que nous avons fait plus haut), ou créer les ressources dans une librairie séparée.</p>
<p>Pour plus de détail sur le sujet, je vous invite à lire cet excellent billet de blog de K. Scott Allen : <a href="http://odetocode.com/Blogs/scott/archive/2009/07/16/resource-files-and-asp-net-mvc-projects.aspx">Resource Files and ASP.NET MVC Projects</a>.  </p>
<p><strong>Modification de la vue</strong></p>
<p>Maintenant que vous avez transféré le texte de la vue vers les fichiers de ressources, vous devez maintenant faire pointer les zones d’affichage de ces textes vers les ressources correspondantes.</p>
<p>Pour cela, ouvrez le fichier Layout.chstml et remplacez le texte suivant :</p>
<div id="codeSnippetWrapper">
<pre id="codeSnippet" style="background-color: #f4f4f4; font-family: 'Courier New', Courier, Monospace; font-size: 8pt; line-height: 12pt; border-style: none; color: black; overflow: visible; padding: 0px; width: 100%; margin: 0em; direction: ltr; text-align: left;"><span style="color: #0000ff;">&lt;</span><span style="color: #800000;">div</span> <span style="color: #ff0000;">id</span><span style="color: #0000ff;">="title"</span><span style="color: #0000ff;">&gt;</span><br />   <span style="color: #0000ff;">&lt;</span><span style="color: #800000;">h1</span><span style="color: #0000ff;">&gt;</span>My MVC Application<span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">h1</span><span style="color: #0000ff;">&gt;</span><br /><span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">div</span><span style="color: #0000ff;">&gt;</span><br /></pre>
<p></div>
<p>Par </p>
<div id="codeSnippetWrapper">
<pre id="codeSnippet" style="background-color: #f4f4f4; font-family: 'Courier New', Courier, Monospace; font-size: 8pt; line-height: 12pt; border-style: none; color: black; overflow: visible; padding: 0px; width: 100%; margin: 0em; direction: ltr; text-align: left;"><span style="color: #0000ff;">&lt;</span><span style="color: #800000;">div</span> <span style="color: #ff0000;">id</span><span style="color: #0000ff;">="title"</span><span style="color: #0000ff;">&gt;</span><br />   <span style="color: #0000ff;">&lt;</span><span style="color: #800000;">h1</span><span style="color: #0000ff;">&gt;</span> @MvcApplication1.Resources.Views.Shared._Layout.Title<span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">h1</span><span style="color: #0000ff;">&gt;</span><br /><span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">div</span><span style="color: #0000ff;">&gt;</span></pre>
<p></div>
<p>En observant ces lignes de code, vous pouvez constater que la valeur est accessible comme une propriété de classe.  En effet, toutes les ressources sont compilées vers une DLL (MvcApplication1.Resources.Views.Shared). Le nom du fichier (_Layout) est utilisé comme nom de la classe et le nom donné au texte est considéré comme celui de la propriété de la classe.</p>
<p><strong>Premier aperçu</strong></p>
<p>À ce stade, si tout est correct, vous pouvez déjà obtenir un premier aperçu de votre application localisée en définissant juste la culture qui est utilisée par celle-ci. </p>
<p>Pour cela, vous pouvez simplement définir la culture dans le fichier Globla.aspx en utilisant la méthode Application_BeginRequest qui est exécutée lors du lancement de l’application. Le code permettant de faire cela est le suivant :</p>
<div id="codeSnippetWrapper">
<pre id="codeSnippet" style="background-color: #f4f4f4; font-family: 'Courier New', Courier, Monospace; font-size: 8pt; line-height: 12pt; border-style: none; color: black; overflow: visible; padding: 0px; width: 100%; margin: 0em; direction: ltr; text-align: left;"><span style="color: #0000ff;">protected</span> <span style="color: #0000ff;">void</span> Application_BeginRequest(<span style="color: #0000ff;">object</span> sender, EventArgs e)<br />{<br />          <br />    Thread.CurrentThread.CurrentUICulture = CultureInfo.CreateSpecificCulture(<span style="color: #006080;">"fr"</span>);<br />} </pre>
<p></div>
<p>En modifiant le paramètre qui est passé à la fonction, CreateSpecificCulture() entre l’anglais(en) et le français(fr), on obtient le résultat suivant :</p>
<p><img src="http://blog.developpez.com/media/Secondtest.PNG" width="632" height="638" alt="" /> </p>
<p>Nous avons défini une seule valeur localisée pour la vue Layout. Vous pouvez faire de même pour les autres vues.</p>
<p>Voilà, nous venons de finir avec les premières étapes d’internationalisation de notre application, qui nous ont permis de créer les fichiers de ressources et localiser nos vues. Dans la partie suivante, nous verrons comment procéder pour les fichiers du modèle avec les messages d&rsquo;erreur de validation et comment mettre en ouvre un mécanisme de basculer entre les cultures sur l’interface utilisateur.</p>
<p>Lire la partie suivante : <a href="http://blog.developpez.com/lilroma/p10697/">Internationalisation d’une application ASP.NET MVC 3 Razor part 2 : messages d’erreur de validation et DisplayAttribute</a></p>
]]></content:encoded>
			<wfw:commentRss></wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Internationalisation d’une application ASP.NET MVC 3 Razor part 2 : messages d’erreur de validation et DisplayAttribute</title>
		<link>https://blog.developpez.com/lilroma/p10702/net/internationalisation_d_une_application_a_2</link>
		<comments>https://blog.developpez.com/lilroma/p10702/net/internationalisation_d_une_application_a_2#comments</comments>
		<pubDate>Fri, 10 Feb 2012 08:46:15 +0000</pubDate>
		<dc:creator><![CDATA[Hinault Romaric]]></dc:creator>
				<category><![CDATA[.NET]]></category>
		<category><![CDATA[ASP.NET]]></category>
		<category><![CDATA[ASP.NET MVC 3]]></category>
		<category><![CDATA[RAZOR]]></category>
		<category><![CDATA[Visual Studio]]></category>

		<guid isPermaLink="false"></guid>
		<description><![CDATA[Dans mon précédent billet de blog, nous nous sommes familiarisés avec les différents concepts qui sont liés à l’internationalisation d’une application sur l’écosystème .NET. Nous avons également procédé à la création des fichiers de ressources et obtenu un premier aperçu &#8230; <a href="https://blog.developpez.com/lilroma/p10702/net/internationalisation_d_une_application_a_2">Lire la suite <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<p>Dans mon <a href="http://blog.developpez.com/lilroma/p10697/">précédent billet de blog</a>, nous nous sommes familiarisés avec les différents concepts qui sont liés à l’internationalisation d’une application sur l’écosystème .NET. Nous avons également procédé à la création des fichiers de ressources et obtenu un premier aperçu de notre application.</p>
<p>Cependant, avec ASP.NET MVC, il est possible de définir les messages des erreurs de validation dans le modèle, au sein des attributs fournis par l’espace de noms DataAnnotations utilisé pour la validation des données utilisateur.  Il est également possible de définir les textes par défaut qui seront affichés dans les vues pour les intitulés des champs des formulaires.</p>
<p>Si vous avez donc défini ces infirmations dans votre modèle, vous allez vous rendre compte que ce que nous avons fait jusqu’ici ne permet pas de localiser ces champs texte.</p>
<p>Nous verrons donc dans ce billet comment internationaliser les messages des erreurs de validation et les intitulés des champs des formulaires définis dans le modèle.</p>
<p><span id="more-39"></span></p>
<p>Pour cet exemple, nous allons créer dans l’application que nous avons utilisée précédemment (dans la partie 1) un formulaire permettant l’enregistrement des produits. La classe qui sera utilisée est la suivante :</p>
<div id="codeSnippetWrapper">
<pre id="codeSnippet" style="background-color: #f4f4f4; font-family: 'Courier New', Courier, Monospace; font-size: 8pt; line-height: 12pt; border-style: none; color: black; overflow: visible; padding: 0px; width: 100%; margin: 0em; direction: ltr; text-align: left;"><span style="color: #0000ff;">public</span> <span style="color: #0000ff;">class</span> ProductModel<br />    {<br />        <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">string</span> Name { get; set; }<br />        <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">string</span> Description { get; set; }<br />        <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">decimal</span> Price { get; set; }<br />    }</pre>
<p></div>
<p>Pour créer le modèle correspondant, ajoutez au dossier Model  un fichier de classe ProductModel.cs qui contiendra le code ci-dessus.</p>
<p>À ce stade, aucune logique de validation des données n’est implémentée. À l’aide de DataAnnotations nous allons mettre en œuvre la validation des données pour cette classe.</p>
<p>Le nouveau code de la classe ProductModel produit est le suivant :</p>
<div id="codeSnippetWrapper">
<div id="codeSnippetWrapper">
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"><span style="color: #0000ff">public</span> <span style="color: #0000ff">class</span> ProductModel<br />    {<br />        [Required(ErrorMessage = <span style="color: #006080">&quot;Le libellé du produit est obligatoire&quot;</span>)]<br />        [Display(Name = <span style="color: #006080">&quot;Nom&quot;</span>)]<br />        <span style="color: #0000ff">public</span> <span style="color: #0000ff">string</span> Name { get; set; }<br />        [Required(ErrorMessage = <span style="color: #006080">&quot;La description du produit est obligatoire&quot;</span>)]<br />        [Display(Name = <span style="color: #006080">&quot;Description&quot;</span>)]<br />        <span style="color: #0000ff">public</span> <span style="color: #0000ff">string</span> Description { get; set; }<br />        [Required(ErrorMessage = <span style="color: #006080">&quot;La prix est obligatoire&quot;</span>)]<br />        [Display(Name = <span style="color: #006080">&quot;Prix&quot;</span>)]<br />        [Range(0.01, 400.00, ErrorMessage = <span style="color: #006080">&quot;Le prix doit être compris entre 0.01 et 400.00&quot;</span>)]<br />        <span style="color: #0000ff">public</span> <span style="color: #0000ff">decimal</span> Price { get; set; }<br />    }</pre>
<p></div>
<p></div>
<p>Nous allons commencer par internationaliser les messages des erreurs de  validation.</p>
<p>Pour cela, dans le sous-dossier Model du dossier Resources, vous allez créer deux nouveaux fichiers de ressources ProductModel, dans lesquels vous allez définir les messages d’erreurs de validation pour cette classe comme l’illustre la capture ci-dessous :</p>
<p><img src="http://blog.developpez.com/media/DefaultModelResources.PNG" width="573" height="306" alt="" /></p>
<p><img src="http://blog.developpez.com/media/ModelResourcesfr.PNG" width="581" height="309" alt="" /> </p>
<p>Pour localiser ces valeurs, nous allons utiliser les propriétés <strong>ErrorMessageResourceType</strong> et <strong>ErrorMessageResourceName</strong>.</p>
<p>La propriété ErrorMessageResourceType permet de spécifier le type de message d’erreur qui est associé à un contrôle de validation.<br />
La propriété ErrorMessageResourceName, quant à elle, sera utilisée pour définir le nom de la ressource pour recherche le message d’erreur.</p>
<p>Le nouveau code de la classe ProductModel permettant donc de faire cela est le suivant :</p>
<div id="codeSnippetWrapper">
<div id="codeSnippetWrapper">
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"><span style="color: #0000ff">public</span> <span style="color: #0000ff">class</span> ProductModel<br />    {<br />        [Required(ErrorMessageResourceType = <span style="color: #0000ff">typeof</span>(MvcApplication1.Resources.Models.ProductModel),<br />             ErrorMessageResourceName = <span style="color: #006080">&quot;NameRequired&quot;</span>)]<br />        [Display(Name = <span style="color: #006080">&quot;Nom&quot;</span>)]<br />        <span style="color: #0000ff">public</span> <span style="color: #0000ff">string</span> Name { get; set; }<br />         [Required(ErrorMessageResourceType = <span style="color: #0000ff">typeof</span>(MvcApplication1.Resources.Models.ProductModel),<br />             ErrorMessageResourceName = <span style="color: #006080">&quot;DescriptionRequired&quot;</span>)]<br />        [Display(Name = <span style="color: #006080">&quot;Description&quot;</span>)]<br />        <span style="color: #0000ff">public</span> <span style="color: #0000ff">string</span> Description { get; set; }<br />         [Required(ErrorMessageResourceType = <span style="color: #0000ff">typeof</span>(MvcApplication1.Resources.Models.ProductModel),<br />             ErrorMessageResourceName = <span style="color: #006080">&quot;PriceRequired&quot;</span>)]<br />        [Display(Name = <span style="color: #006080">&quot;Prix&quot;</span>)]<br />        [Range(0.01, 400.00, ErrorMessageResourceType = <span style="color: #0000ff">typeof</span>(MvcApplication1.Resources.Models.ProductModel),<br />             ErrorMessageResourceName = <span style="color: #006080">&quot;PriceRange&quot;</span>)]<br />        <span style="color: #0000ff">public</span> <span style="color: #0000ff">decimal</span> Price { get; set; }<br />    }<br /></pre>
<p></div>
<p></div>
<p>À ce stade, si nous exécutons notre application, nous obtenons le résultat suivant :</p>
<p>Pour l’anglais </p>
<p><img src="http://blog.developpez.com/media/Errormessagelocalisation.PNG" width="593" height="398" alt="" /> </p>
<p>Pour le français </p>
<p><img src="http://blog.developpez.com/media/Errormessagelocalisationfr.PNG" width="621" height="435" alt="" /></p>
<p>Nous avons finalisé avec les messages des erreurs de validation. Passons maintenant à la localisation des attributs Display.</p>
<p>Avec la version précédente d’ASP.NET MVC,  la définition des noms des propriétés qui seront affichées dans l’interface utilisateur se faisait en décorant la propriété avec la classe DisplayNameAttribute. Cependant, elle ne possède qu’un seul constructeur et ne supporte pas de ce fait la localisation. </p>
<p>Pour internationaliser donc ces valeurs, il fallait du code personnalisé après beaucoup d’effort de programmation. Ce problème est résolu avec ASP.NET MVC 3. La localisation des noms des propriétés peut se faire assez aisément dans le modèle en utilisant la classe DisplayAttribute.</p>
<p>Cette classe possède plusieurs propriétés, y compris les propriétés ResourceType, permettant de définir le type de ressource pour les propriétés localisées et Name pour définir le nom de la ressource.</p>
<p>Le nouveau code de la classe ProductModel sera donc le suivant :</p>
<div id="codeSnippetWrapper">
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"><span style="color: #0000ff">public</span> <span style="color: #0000ff">class</span> ProductModel<br />    {<br />        [Required(ErrorMessageResourceType = <span style="color: #0000ff">typeof</span>(MvcApplication1.Resources.Models.ProductModel),<br />             ErrorMessageResourceName = <span style="color: #006080">&quot;NameRequired&quot;</span>)]<br />        [Display(Name = <span style="color: #006080">&quot;DisplayName&quot;</span>, ResourceType = <span style="color: #0000ff">typeof</span>(MvcApplication1.Resources.Models.ProductModel))]<br />         <span style="color: #0000ff">public</span> <span style="color: #0000ff">string</span> Name { get; set; }<br />         [Required(ErrorMessageResourceType = <span style="color: #0000ff">typeof</span>(MvcApplication1.Resources.Models.ProductModel),<br />             ErrorMessageResourceName = <span style="color: #006080">&quot;DescriptionRequired&quot;</span>)]<br />         [Display(Name = <span style="color: #006080">&quot;DisplayDescription&quot;</span>, ResourceType = <span style="color: #0000ff">typeof</span>(MvcApplication1.Resources.Models.ProductModel))]<br />        <span style="color: #0000ff">public</span> <span style="color: #0000ff">string</span> Description { get; set; }<br />         [Required(ErrorMessageResourceType = <span style="color: #0000ff">typeof</span>(MvcApplication1.Resources.Models.ProductModel),<br />             ErrorMessageResourceName = <span style="color: #006080">&quot;PriceRequired&quot;</span>)]<br />         [Display(Name = <span style="color: #006080">&quot;DisplayPrice&quot;</span>, ResourceType = <span style="color: #0000ff">typeof</span>(MvcApplication1.Resources.Models.ProductModel))]<br />        [Range(0.01, 400.00, ErrorMessageResourceType = <span style="color: #0000ff">typeof</span>(MvcApplication1.Resources.Models.ProductModel),<br />             ErrorMessageResourceName = <span style="color: #006080">&quot;PriceRange&quot;</span>)]<br />        <span style="color: #0000ff">public</span> <span style="color: #0000ff">decimal</span> Price { get; set; }<br />    }</pre>
<p></div>
<p>Les fichiers de ressources utilisés seront modifiés comme suit :</p>
<p><img src="http://blog.developpez.com/media/Displaylocalisation.PNG" width="573" height="287" alt="" /></p>
<p><img src="http://blog.developpez.com/media/Displaylocalisationfr.PNG" width="569" height="283" alt="" /> </p>
<p>À ce stade, si nous exécutons notre application, nous obtenons le résultat suivant :</p>
<p>Pour l’anglais </p>
<p><img src="http://blog.developpez.com/media/DisplayAttribute.PNG" width="591" height="402" alt="" /></p>
<p>Pour le français </p>
<p><img src="http://blog.developpez.com/media/DisplayAttributefr.PNG" width="603" height="402" alt="" /> </p>
<p>Et voilà, nous venons de finir avec la localisation des textes du modèle.  Vous pouvez vous rendre compte combien il est facile grâce aux nouveautés introduites par ASP.NET MVC 3 d’internationaliser les messages d’erreur de validation et les intitulés des  champs des formulaires dans la vue.</p>
<p>La prochaine étape sera la mise au point sur l’interface utilisateur d’un mécanisme permettant à l’internaute de modifier la culture pour faire passer l’application d’une langue à une autre.</p>
]]></content:encoded>
			<wfw:commentRss></wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Critique : Professional ASP.NET MVC 3</title>
		<link>https://blog.developpez.com/lilroma/p10664/net/critique_professional_asp_net_mvc_3</link>
		<comments>https://blog.developpez.com/lilroma/p10664/net/critique_professional_asp_net_mvc_3#comments</comments>
		<pubDate>Fri, 20 Jan 2012 15:46:11 +0000</pubDate>
		<dc:creator><![CDATA[Hinault Romaric]]></dc:creator>
				<category><![CDATA[.NET]]></category>
		<category><![CDATA[ASP.NET MVC 3]]></category>

		<guid isPermaLink="false"></guid>
		<description><![CDATA[j&#8217;ai enfin trouvé un peu de temps pour rediger une critique du livre Professional ASP.NET MVC 3 que j&#8217;ai lu y a de cela plusieurs mois. Au vu de mon orientation de plus en plus vers ASP.NET MVC pour la &#8230; <a href="https://blog.developpez.com/lilroma/p10664/net/critique_professional_asp_net_mvc_3">Lire la suite <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<p>j&rsquo;ai enfin trouvé un peu de temps pour rediger une critique du livre <strong><em>Professional ASP.NET MVC 3</em></strong> que j&rsquo;ai lu y a de cela plusieurs mois.</p>
<p><img src="http://ecx.images-amazon.com/images/I/51NlVWhGtoL._BO2,204,203,200_PIsitb-sticker-arrow-click,TopRight,35,-76_AA300_SH20_OU01_.jpg" alt="Profesional ASP.NET MVC 3" title="" /></p>
<blockquote><p>Au vu de mon orientation de plus en plus vers ASP.NET MVC pour la conception de mes applications, je me suis dit qu&rsquo;il était temps pour moi malgré tous les articles que j&rsquo;ai lus en ligne sur les nouvelles fonctionnalités de la version 3 du Framework, de me mettre à la lecture d&rsquo;un livre qui traite du sujet.</p>
<p>Mon choix s&rsquo;est porté sur Professional ASP.NET MVC 3, qui est écrit par Phil Haack et Brad Wilson, qui font partie de l&rsquo;équipe de développement du framework, ainsi que Jon Galloway et K. Scott Allen, des pionniers de la technologie. Ce livre est le guide parfait pour toute personne désireuse de maitriser le framework ASP.NET MVC 3.</p>
<p>Contrairement au titre qui donne l&rsquo;impression d&rsquo;un livre réservé aux professionnels, le chapitre 1 un présente de façon détaillée le framework (description, installation, création d&rsquo;une première application, etc.) et effectue une comparaison avec ASP.NET et les raisons qui ont entrainé sa création. Le chapitre 2, également un chapitre introductif pour moi, revient en détail sur la notion de contrôleur. C&rsquo;est à compter des chapitres trois et quatre présentant respectivement la vue et le modèle, que le lecteur découvrira les nouveautés intéressantes comme le moteur de vue Razor, l&rsquo;échafaudage et Entity Framework Code First. L&rsquo;utilisation des formulaires, des helpers HTML et les améliorations apportées à la validation des données utilisateur notamment avec DataAnnotations seront décrites dans les deux chapitres suivants.</p></blockquote>
<p>           <strong> <a href="http://rdonfack.developpez.com/livres/#L9781118076583">     >>Lire la suite! </a> </strong></p>
]]></content:encoded>
			<wfw:commentRss></wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Microsoft.Web.Optimisation : ou comment optimiser une application ASP.NET en utilisant le regroupement et la minification à la volée du JavaScript et CSS</title>
		<link>https://blog.developpez.com/lilroma/p10462/net/microsoft_web_optimisation_ou_comment_op</link>
		<comments>https://blog.developpez.com/lilroma/p10462/net/microsoft_web_optimisation_ou_comment_op#comments</comments>
		<pubDate>Thu, 03 Nov 2011 16:55:00 +0000</pubDate>
		<dc:creator><![CDATA[Hinault Romaric]]></dc:creator>
				<category><![CDATA[.NET]]></category>
		<category><![CDATA[ASP.NET]]></category>
		<category><![CDATA[ASP.NET MVC 3]]></category>
		<category><![CDATA[ASP.NET MVC 4]]></category>
		<category><![CDATA[C#]]></category>
		<category><![CDATA[Nuget]]></category>
		<category><![CDATA[Visual Basic .NET]]></category>

		<guid isPermaLink="false"></guid>
		<description><![CDATA[Le temps de chargement d’une page est un facteur important dans l’évaluation des performances d’un site Web. Il a un impact non négligeable sur l’expérience utilisateur et même sur le référencement naturel. Plusieurs techniques peuvent être utilisées pour optimiser les &#8230; <a href="https://blog.developpez.com/lilroma/p10462/net/microsoft_web_optimisation_ou_comment_op">Lire la suite <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<p>Le temps de chargement d’une page est un facteur important dans l’évaluation des performances d’un site Web. Il a un impact non négligeable sur l’expérience utilisateur et même sur le référencement naturel.</p>
<p>Plusieurs techniques peuvent être utilisées  pour optimiser les performances d’une application Web (mise en cache, compression des fichiers, minification, etc). Je vais me pencher aujourd’hui sur le package NuGet d’optimisation d’un site Web « <strong><a href="http://nuget.org/List/Packages/Microsoft.Web.Optimization">ASP.NET Optimization – Bundling</a></strong> » qui a été publié récemment par Microsoft.</p>
<p>Ce package ajoute le support du regroupement et de la minification des fichiers JavaScript et CSS &#8211; qui sont des caractéristiques d’ASP.NET 4.5 et ASP.NET MVC 4 (disponibles actuellement en version Developper Preview) – avec le minimum d’effort pour les applications ASP.NET 4 et ASP.NET MVC.</p>
<p><img src="http://blog.developpez.com/media/minification.png" width="235" height="235" alt="" /></p>
<p><span id="more-37"></span></p>
<p>Le regroupement et la minification sont des procédés de réduction de la taille des fichiers en les combinant, et en supprimant les espaces et autres caractères  inutiles. Ces méthodes permettent de rendre l’exécution d’une page Web plus rapide avec le moins de demandes de chargement des fichiers. </p>
<p>Nous verrons dans ce billet de blog comment améliorer les performances d’une application Web ASP.NET MVC en utilisant les techniques de regroupement et de minification introduites par le package Microsoft.Web.Optimisation.</p>
<p>Pour commencer, nous allons créer un nouveau projet ASP.NET MVC 3.<br />
Comme l’illustre l’image ci-dessous, nous constatons que notre application contient par défaut un nombre déjà assez important de fichiers JavaScript et CSS.</p>
<p><img src="http://blog.developpez.com/media/capture1.PNG" width="497" height="339" alt="" /> </p>
<p>En exécutant une page de cette application (LogOn.chtml), nous obtenons les statistiques suivantes issues de l’analyse d’un outil de mesure de performance comme <a href="http://developer.yahoo.com/yslow/help/">YSlow</a>.</p>
<p><img src="http://blog.developpez.com/media/test1_01.PNG" width="640" height="196" alt="" /></p>
<p>Pour cette page,  nous avons un nombre total de 7 requêtes HTTP qui ont été effectuées, avec 4 fichiers JavaScript d’une taille totale de 119,9K qui ont été chargés.</p>
<p>Nous allons maintenant essayer de réduire le nombre de requêtes et la taille des fichiers qui sont chargés en utilisant ASP.NeT Optimisation Bundle.</p>
<p>Pour cela, nous allons  dans un premier temps ajouter une référence à Microsoft.Web.Optimisation dans notre application.</p>
<p>L’ajout de ce composant se fera via NuGet. Pour installer le package en utilisant NuGet voir <a href="http://rdonfack.developpez.com/tutoriels/dotnet/presentation-gestionnaire-packages-net-nuget/">mon article sur NuGet</a>.</p>
<p><img src="http://blog.developpez.com/media/nugetdwnload.PNG" width="620" height="107" alt="" /> </p>
<p>Après avoir installé le package, nous pouvons démarrer le regroupement et la minificatioon de nos fichiers en ajoutant tout simplement la ligne de code suivant dans la procédure Application_Start() du fichier Global.asax.cs.</p>
<div id="codeSnippetWrapper" style="background-color: #f4f4f4; font-family: 'Courier New', Courier, Monospace; font-size: 8pt; line-height: 12pt; border: solid 1px silver; cursor: text; margin: 20px 0px 10px 0px; max-height: 200px; overflow: auto; padding: 4px; width: 97.5%; direction: ltr; text-align: left;">
<pre id="codeSnippet" style="background-color: #f4f4f4; font-family: 'Courier New', Courier, Monospace; font-size: 8pt; line-height: 12pt; border-style: none; color: black; overflow: visible; padding: 0px; width: 100%; margin: 0em; direction: ltr; text-align: left;">BundleTable.Bundles.EnableDefaultBundles();</pre>
<p></div>
<p>Et c’est tout ;).</p>
<p>N’oubliez pas d’ajouter une référence à Microsoft.Web.Optimization dans le fichier Global.asax.cs :</p>
<div id="codeSnippetWrapper" style="background-color: #f4f4f4; font-family: 'Courier New', Courier, Monospace; font-size: 8pt; line-height: 12pt; border: solid 1px silver; cursor: text; margin: 20px 0px 10px 0px; max-height: 200px; overflow: auto; padding: 4px; width: 97.5%; direction: ltr; text-align: left;">
<pre id="codeSnippet" style="background-color: #f4f4f4; font-family: 'Courier New', Courier, Monospace; font-size: 8pt; line-height: 12pt; border-style: none; color: black; overflow: visible; padding: 0px; width: 100%; margin: 0em; direction: ltr; text-align: left;"><span style="color: #0000ff;">using</span> Microsoft.Web.Optimization;</pre>
<p></div>
<p>Tous les fichiers JavaScript contenus dans le répertoire Scripts (les sous dossiers ne sont pas pris en compte) de notre application seront regroupés, compressés et traités comme un seul fichier.  Ces fichiers seront regroupés par défaut dans un dossier Script.</p>
<p>Ils seront désormais référencés en utilisant la ligne de code suivante :</p>
<div id="codeSnippetWrapper" style="background-color: #f4f4f4; font-family: 'Courier New', Courier, Monospace; font-size: 8pt; line-height: 12pt; border: solid 1px silver; cursor: text; margin: 20px 0px 10px 0px; max-height: 200px; overflow: auto; padding: 4px; width: 97.5%; direction: ltr; text-align: left;">
<pre id="codeSnippet" style="background-color: #f4f4f4; font-family: 'Courier New', Courier, Monospace; font-size: 8pt; line-height: 12pt; border-style: none; color: black; overflow: visible; padding: 0px; width: 100%; margin: 0em; direction: ltr; text-align: left;"><span style="color: #0000ff;">&lt;</span><span style="color: #800000;">script</span> <span style="color: #ff0000;">src</span><span style="color: #0000ff;">="@Url.Content("</span>/<span style="color: #ff0000;">Scripts</span>/<span style="color: #ff0000;">js</span><span style="color: #0000ff;">")"</span> <span style="color: #ff0000;">type</span><span style="color: #0000ff;">="text/javascript"</span><span style="color: #0000ff;">&gt;&lt;/</span><span style="color: #800000;">script</span><span style="color: #0000ff;">&gt;</span></pre>
<p></div>
<p>De même, les fichiers CSS contenus dans le répertoire Content seront également compactés par défaut dans un dossier Content.</p>
<p>Ils seront référencés en utilisant la ligne de code suivante :</p>
<div id="codeSnippetWrapper" style="background-color: #f4f4f4; font-family: 'Courier New', Courier, Monospace; font-size: 8pt; line-height: 12pt; border: solid 1px silver; cursor: text; margin: 20px 0px 10px 0px; max-height: 200px; overflow: auto; padding: 4px; width: 97.5%; direction: ltr; text-align: left;">
<pre id="codeSnippet" style="background-color: #f4f4f4; font-family: 'Courier New', Courier, Monospace; font-size: 8pt; line-height: 12pt; border-style: none; color: black; overflow: visible; padding: 0px; width: 100%; margin: 0em; direction: ltr; text-align: left;"><span style="color: #0000ff;">&lt;</span><span style="color: #800000;">link</span> <span style="color: #ff0000;">href</span><span style="color: #0000ff;">="@Url.Content("</span>/<span style="color: #ff0000;">Content</span>/<span style="color: #ff0000;">css</span><span style="color: #0000ff;">")"</span> <span style="color: #ff0000;">rel</span><span style="color: #0000ff;">="stylesheet"</span> <span style="color: #ff0000;">type</span><span style="color: #0000ff;">="text/css"</span> <span style="color: #0000ff;">/&gt;</span></pre>
<p></div>
<p>Après avoir appliqué ces modifications, exécutons à nouveau la page précédente. Nous obtenons le résultat suivant :</p>
<p><img src="http://blog.developpez.com/media/test3_01.PNG" width="640" height="233" alt="" /></p>
<p>En comparant avec le résultat précédent, nous constatons que le nombre de requêtes est passé de 7 à 4, avec l’utilisation d’un fichier JavaScript unique, contre quatre précédemment.<br />
C’est déjà une bonne chose. Par contre, on se rend compte que la taille du JavaScript a plutôt augmenté, passant de 119,9k à 437,5k.</p>
<p>Pourquoi avons-nous plutôt une augmentation de la taille du JavaScript ?</p>
<p>En utilisant le dossier Scripts par défaut, ce sont environ une vingtaine de fichiers JavaScript contenus dans notre application ASP.NET MVC qui sont regroupés, minifiés et référencés dans une page qui n’utilise que quatre de ces fichiers.<br />
C’est tout à fait normal donc que malgré l’opération d’optimisation, on se retrouve avec une taille totale de ces fichiers supérieure à celle des quatre référencés dans notre page.  </p>
<p>Pour pallier à cela, nous pouvons définir nos propres regroupements de fichiers.</p>
<p>Avec cette option, nous avons la liberté dans le choix des fichiers qui seront dans un regroupement, ainsi que l’URL qu’aura le regroupement. À ce stade, le choix des dossiers de regroupement doit être fonction de la récurrence des fichiers JavaScript et CSS dans les pages de votre application.</p>
<p>Nous pouvons définir nos regroupements personnalisés en procédant comme suit dans la procédure Application_Start() du fichier Global.asax.cs :</p>
<div style="border-bottom: silver 1px solid; text-align: left; border-left: silver 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; max-height: 400px; font-size: 8pt; overflow: auto; border-top: silver 1px solid; cursor: text; border-right: silver 1px solid; padding-top: 4px" id="codeSnippetWrapper">
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet">BundleTable.Bundles.EnableDefaultBundles();<br /><br />Bundle jsBundle = <span style="color: #0000ff">new</span> Bundle(<span style="color: #006080">&quot;~/Scripts&quot;</span>,<span style="color: #0000ff">typeof</span>(JsMinify));<br />jsBundle.AddFile(<span style="color: #006080">&quot;~/Scripts/jquery-1.5.1.min.js&quot;</span>);<br />jsBundle.AddFile(<span style="color: #006080">&quot;~/Scripts/modernizr-1.7.min.js&quot;</span>);<br />jsBundle.AddFile(<span style="color: #006080">&quot;~/Scripts/jquery.validate.min.js&quot;</span>);<br />jsBundle.AddFile(<span style="color: #006080">&quot;~/Scripts/jquery.validate.unobtrusive.min.js&quot;</span>);<br /><br />BundleTable.Bundles.Add(jsBundle);<br /><br />Bundle cssBundle = <span style="color: #0000ff">new</span> Bundle(<span style="color: #006080">&quot;~/Style&quot;</span>, <span style="color: #0000ff">typeof</span>(CssMinify));<br />cssBundle.AddFile(<span style="color: #006080">&quot;~/content/themes/site.css&quot;</span>);<br />cssBundle.AddFile(<span style="color: #006080">&quot;~/content/themes/base/jquery.ui.all.css&quot;</span>);<br /><br />BundleTable.Bundles.Add(cssBundle);<br /></pre>
<p></div>
<p>Nous allons désormais  référencer ces regroupements dans notre page comme suit :</p>
<div id="codeSnippetWrapper" style="background-color: #f4f4f4; font-family: 'Courier New', Courier, Monospace; font-size: 8pt; line-height: 12pt; border: solid 1px silver; cursor: text; margin: 20px 0px 10px 0px; max-height: 200px; overflow: auto; padding: 4px; width: 97.5%; direction: ltr; text-align: left;">
<pre id="codeSnippet" style="background-color: #f4f4f4; font-family: 'Courier New', Courier, Monospace; font-size: 8pt; line-height: 12pt; border-style: none; color: black; overflow: visible; padding: 0px; width: 100%; margin: 0em; direction: ltr; text-align: left;"><br /><span style="color: #0000ff;">&lt;</span><span style="color: #800000;">link</span> <span style="color: #ff0000;">href</span><span style="color: #0000ff;">="@Url.Content("</span>~/<span style="color: #ff0000;">Style</span> <span style="color: #0000ff;">")"</span> <span style="color: #ff0000;">rel</span><span style="color: #0000ff;">="stylesheet"</span> <span style="color: #ff0000;">type</span><span style="color: #0000ff;">="text/css"</span> <span style="color: #0000ff;">/&gt;</span><br /><span style="color: #0000ff;">&lt;</span><span style="color: #800000;">script</span> <span style="color: #ff0000;">src</span><span style="color: #0000ff;">="@Url.Content("</span>~/<span style="color: #ff0000;">Scripts</span><span style="color: #0000ff;">")"</span> <span style="color: #ff0000;">type</span><span style="color: #0000ff;">="text/javascript"</span><span style="color: #0000ff;">&gt;&lt;/</span><span style="color: #800000;">script</span><span style="color: #0000ff;">&gt;</span><br /></pre>
<p></div>
<p>Et en exécutant la page précédente, nous obtenons le résultat suivant :</p>
<p><img src="http://blog.developpez.com/media/test2_01.PNG" width="640" height="223" alt="" /></p>
<p>Et voilà, la taille de nos fichiers JavaScript passe de 119,9K à 2,3K, soit une réduction de plus de 95 %.</p>
<p>Vous pouvez également ajouter à votre regroupement tous les fichiers JavaScript d’un répertoire en procédant comme suit :</p>
<div id="codeSnippetWrapper" style="background-color: #f4f4f4; font-family: 'Courier New', Courier, Monospace; font-size: 8pt; line-height: 12pt; border: solid 1px silver; cursor: text; margin: 20px 0px 10px 0px; max-height: 200px; overflow: auto; padding: 4px; width: 97.5%; direction: ltr; text-align: left;">
<pre id="codeSnippet" style="background-color: #f4f4f4; font-family: 'Courier New', Courier, Monospace; font-size: 8pt; line-height: 12pt; border-style: none; color: black; overflow: visible; padding: 0px; width: 100%; margin: 0em; direction: ltr; text-align: left;">jsBundle.AddDirectory(<span style="color: #006080;">"~/Scripts"</span>, <span style="color: #006080;">"*.js"</span>, <span style="color: #0000ff;">false</span>);</pre>
<p></div>
<p>Nous avons maintenant de quoi compresser et réduire au maximum le nombre de hits de nos pages Web avec souplesse. </p>
<p>Seul bémol, la minification des fichiers contenant du code CSS3 semble ne pas fonctionner pour l&rsquo;instant.</p>
]]></content:encoded>
			<wfw:commentRss></wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>ASP.NET MVC : résoudre l’erreur « A circular reference was detected while serializing an object of type… »</title>
		<link>https://blog.developpez.com/lilroma/p10448/net/asp_net_mvc_resoudre_l_erreur_l_a_circul</link>
		<comments>https://blog.developpez.com/lilroma/p10448/net/asp_net_mvc_resoudre_l_erreur_l_a_circul#comments</comments>
		<pubDate>Thu, 27 Oct 2011 17:39:12 +0000</pubDate>
		<dc:creator><![CDATA[Hinault Romaric]]></dc:creator>
				<category><![CDATA[.NET]]></category>
		<category><![CDATA[ASP.NET]]></category>
		<category><![CDATA[ASP.NET MVC 3]]></category>
		<category><![CDATA[ASP.NET MVC 4]]></category>
		<category><![CDATA[C#]]></category>
		<category><![CDATA[Visual Studio]]></category>

		<guid isPermaLink="false"></guid>
		<description><![CDATA[En travaillant sur une application Web ASP.NET MVC dans laquelle j’utilise Entity Framework 4 Code First, j’ai eu l’erreur suivante : «A circular reference was detected while serializing an object of type… » lorsque j’ai essayé de retourner une classe &#8230; <a href="https://blog.developpez.com/lilroma/p10448/net/asp_net_mvc_resoudre_l_erreur_l_a_circul">Lire la suite <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<p> En travaillant sur une application Web ASP.NET MVC dans laquelle j’utilise Entity Framework 4 Code First, j’ai eu l’erreur suivante : «<strong>A circular reference was detected while serializing an object of type…</strong> »  lorsque j’ai essayé de retourner une classe Entité au client comme un document JSON.</p>
<p><img src="http://blog.developpez.com/media/circulaire.jpg" width="228" height="221" alt="" align="center"/></p>
<p><span id="more-36"></span></p>
<p>À première vue, il semblerait qu’il y ait une référence circulaire dans ma hiérarchie d’objets qui n’est pas prise en charge par le sérialiseur JSON.</p>
<p>En essayant de procéder au débogage de la procédure, je me suis rendu compte que le problème n’était pas au niveau de mon code, mais plutôt au niveau de la classe qui s’occupe de la sérialisation. </p>
<p>Quelle est donc la cause de cette erreur :</p>
<p>Pour les tables ayant des relations, l’utilitaire de mappage objet relationnel, génère des propriétés de référence dans chaque entité. </p>
<p>Prenons par exemple le schéma suivant de ma base de données :</p>
<p><img src="http://blog.developpez.com/media/schema.PNG" width="573" height="261" alt="" /> </p>
<p>Pour la table Liste_produit, L’objet  généré aura une propriété Facture. Cependant, pour la table Facture, l’objet généré aura également une propriété Liste_produit. Conséquence : l’objet facture est lié à l’objet Liste_produit et vice-versa. </p>
<p>Ce scénario permet bien évidemment de bénéficier de beaucoup plus d’options lors du traitement de ces entités, mais crée cependant une ambiguïté pour le sérialiseur JSON lors de l’opération de sérialisation. D’où la génération de cette erreur.</p>
<p>Comment résoudre cela ?</p>
<p>Pour résoudre ce type de problème, nous pouvons utiliser deux solutions.</p>
<p>La première solution qui est plutôt simple est de marquer la relation comme une propriété interne. </p>
<p><img src="http://blog.developpez.com/media/schema1.PNG" width="323" height="297" alt="" /> </p>
<p>Perso, je préfère ne pas utiliser cette méthode, car elle m’oblige à modifier mon EDM (Entity Data Model). </p>
<p>La seconde solution, qui est celle pour laquelle j’ai opté, consiste en l’utilisation d’un autre ViewModel en lieu et place de celui généré automatiquement par l’utilitaire de mappage objet/relationnel (ORM).</p>
<p>Cette approche est plus élégante dans la mesure ou elle permettra de sélectionner uniquement les données dont nous avons besoin et sérialiser uniquement celles qui nous intéressent. La conséquence directe est la réduction de la taille des données qui seront retournées dans notre vue et une amélioration de performance de notre application.</p>
<p>Pour utiliser cette méthode, nous devons :</p>
<p>&#8211; Dans un premier temps, créer une nouvelle classe qui contiendra uniquement les propriétés dont nous avons besoin.</p>
<div style="border-bottom: silver 1px solid; text-align: left; border-left: silver 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; max-height: 800px; font-size: 8pt; overflow: auto; border-top: silver 1px solid; cursor: text; border-right: silver 1px solid; padding-top: 4px" id="codeSnippetWrapper">
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"><span style="color: #0000ff">public</span> <span style="color: #0000ff">partial</span> <span style="color: #0000ff">class</span> ProduitL<br />    {<br /><br />        <span style="color: #0000ff">public</span> <span style="color: #0000ff">short</span> Id_produit <br />        {<br />            get; <br />            set; <br />        }<br />        <span style="color: #0000ff">public</span> <span style="color: #0000ff">string</span> Libelle_produit <br />        { <br />            get; <br />            set; <br />        }<br />        <span style="color: #0000ff">public</span> <span style="color: #0000ff">string</span> Conditionnement <br />        { <br />            get; <br />            set; <br />        }<br />        <span style="color: #0000ff">public</span> <span style="color: #0000ff">int</span> Quantite <br />        { <br />            get; <br />            set; <br />        }<br />        <span style="color: #0000ff">public</span> <span style="color: #0000ff">decimal</span> Prix <br />        { <br />            get; <br />            set; <br />        }<br />    }</pre>
<p></div>
<p>Nous allons ensuite modifier la méthode d’action de notre contrôleur comme suit :</p>
<div style="border-bottom: silver 1px solid; text-align: left; border-left: silver 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; max-height: 400px; font-size: 8pt; overflow: auto; border-top: silver 1px solid; cursor: text; border-right: silver 1px solid; padding-top: 4px" id="codeSnippetWrapper">
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"><span style="color: #0000ff">public</span> JsonResult Facture(<span style="color: #0000ff">short</span> id)<br />        {<br /><br />            var results = from lp <span style="color: #0000ff">in</span> db.Liste_produit<br />                    <span style="color: #0000ff">where</span> lp.Id_facture == id<br />                    select <span style="color: #0000ff">new</span> ProduitL<br />                    {<br />                        Id_produit = lp.Id_produit,<br />                        Libelle_produit = lp.produit.Libelle_ produit,<br />                        Conditionnement = lp. produit.Conditionnement,<br />                        Quantite = lp.Quantite,<br />                        Prix = lp.Prix  <br />                        <br />                    };<br />            <span style="color: #0000ff">return</span> Json(results);<br />        }</pre>
<p></div>
<p>ET voilà, à l’exécution de notre application, nous n’aurons plus cette erreur qui peut s’avérer désorientant pour certains.</p>
]]></content:encoded>
			<wfw:commentRss></wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
