web-dev-qa-db-fra.com

MVC4 - Le regroupement ne fonctionne pas lorsque les optimisations sont définies sur true

Je me demande ce que je ne fais pas correctement ici. J'utilise ASP.NET C # MVC4 et je souhaite utiliser la nouvelle fonctionnalité d'optimisation css/js.

Voici ma partie HTML

@Styles.Render("~/content/css")

Voici ma partie BunduleConfig.cs

bundles.Add(new StyleBundle("~/content/css").Include(
                        "~/content/css/reset.css",
                        "~/content/css/bla.css"));

// BundleTable.EnableOptimizations = true;

Sortie (travaux):

<link href="/content/css/reset.css" rel="stylesheet"/>
<link href="/content/css/bla.css" rel="stylesheet"/>

Cependant, lorsque je ne commente pas BundleTable.EnableOptimizations = true;, la sortie html ressemble à ceci

<link href="/content/css?v=5LoJebKvQJIN-fKjKYCg_ccvmBC_LF91jBasIpwtUcY1" rel="stylesheet"/>

Et c’est bien sûr 404 ans. Je ne sais pas du tout où j’ai fait quelque chose de mal, aidez-moi, travaillez pour la première fois avec MVC4.

42
stan

J'imagine que le problème est que vous placez le paquet sur une URL virtuelle qui existe, mais qui est un répertoire.

MVC crée un fichier virtuel à partir de votre bundle et le diffuse à partir du chemin que vous spécifiez comme chemin du bundle.

La solution correcte à ce problème consiste à utiliser un chemin d'ensemble qui ne mappe pas directement vers un répertoire existant, mais utilise plutôt un nom de fichier virtuel (qui ne mappe pas non plus vers un nom de fichier réel) dans ce répertoire.

Exemple:

Si votre site contient un dossier nommé/content/css, créez votre bundle css comme suit:

Dans BundleConfig.cs:

bundles.Add(new StyleBundle("~/content/css/AllMyCss.css").Include(
                        "~/content/css/reset.css",
                        "~/content/css/bla.css"));

Et sur la page:

@Styles.Render("~/content/css/AllMyCss.css")

Notez que cela suppose que vous n'avez PAS un fichier nommé AllMyCss.css dans votre dossier css.

67
dodexahedron

Je ne sais pas si c'est l'optimisation Web, ou WebGrease, qui est si difficile, mais l'un (ou les deux) l'est et vous devez faire extrêmement attention. 

Tout d’abord, il n’ya rien de mal avec votre code:

bundles.Add(new StyleBundle("~/content/css").Include(
                        "~/content/css/reset.css",
                        "~/content/css/bla.css"));

En fait, c’est exactement ce que fait Microsoft. La principale raison pour laquelle ils n'ont pas utiliser ~/bundles pour les CSS est que les chemins relatifs sont fouillés pour les images. Réfléchissez à la manière dont votre navigateur perçoit un ensemble - exactement de la même manière que toute autre URL et que toutes les règles normales relatives au chemin d'accès s'appliquent toujours aux chemins relatifs. Imaginez que votre css ait un chemin d’image vers ../images/bullet.png. Si vous utilisiez ~/bundles, le navigateur chercherait dans un répertoire au-dessus de bundles qui n'existe pas réellement. Il finira probablement par regarder dans ~/images où vous l'avez probablement dans ~/content/images

J'ai trouvé quelques choses qui peuvent vraiment casser et causer des erreurs 404:

  • FYI: Ma structure de répertoire est Content/CSS qui contient un dossier images pour les images CSS.
  • J'ai EnableOptimizations=true pour forcer l'utilisation des bundles lors des tests
  • La première chose à faire est de consulter la source et de cliquer sur les liens CSS pour voir s’ils fonctionnent.

Disons que nous développons un site sur les chats. Vous pouvez avoir ceci

 @Styles.Render("~/Content/css/cats.css")    // dont do this - see below why

 bundles.Add(new StyleBundle("~/content/css/cats.css").Include(
                    "~/content/css/reset.css",
                    "~/content/css/bla.css"));

Cela génère un lien CSS vers ce chemin dans votre code HTML:

/Content/css/cats.css?v=JMoJspikowDah2auGQBfQAWj1OShXxqAlXxhv_ZFVfQ1

Cependant, cela donnera un 404 car je mets une extension .css et IIS (je pense) devient confus.

Si je le change en ceci alors cela fonctionnera bien:

 @Styles.Render("~/Content/css/cats")

 bundles.Add(new StyleBundle("~/content/css/cats").Include(
                    "~/content/css/reset.css",
                    "~/content/css/bla.css"));

Un autre problème déjà signalé par d’autres est que vous ne devez pas faire

 @Styles.Render("~/Content/css")

si vous avez un répertoire ou un fichier css (il est peu probable que vous ayez un fichier appelé css sans extension) dans votre répertoire Content.

Une astuce supplémentaire est que vous devez vous assurer que votre HTML généré a un numéro de version.

<link href="/Content/css/cats?v=6GDW6wAXIN5DJCxVtIkkxLGpojoP-tBQiKgBTQMSlWw1" rel="stylesheet"/>

Si ce n'est pas le cas et que cela ressemble à ceci, vous n'avez probablement pas de correspondance exacte pour le nom de l'ensemble entre votre table Bundle et votre fichier cshtml.

<link href="/Content/css/cats" rel="stylesheet"/>
26
Simon_Weaver

N'oubliez pas de vous assurer que le paquetage HttpModule est présent.

<modules>  
  <remove name="BundleModule" />  
  <add name="BundleModule" type="System.Web.Optimization.BundleModule" />  
</modules>

Cela m'a piqué la première fois. Pas sûr que la configuration nécessaire doive être ajoutée par le paquet NuGet, mais ce n'était pas dans mon cas.

4
Andy McCluggage

Cela me semble correct. Lorsque les optimisations sont activées, vous n’avez plus qu’une seule référence et ce sera pour le nom que vous avez spécifié dans StyleBundle (/ content/css). En mode débogage (ou plus précisément avec debug = false dans votre configuration Web), vous obtiendrez les fichiers non optimisés comme d'habitude. Si vous regardez, vous verrez qu'ils sont simplement du texte brut au fur et à mesure que vous les tapez. Toutefois, lorsque les optimzations sont activées (généralement lorsque vous exécutez le mode de publication), vous obtenez une URL plutôt étrange.

Si vous regardez le résultat, cela sera réduit au minimum. La chaîne de requête? V = 5KLoJ .... est basée sur un hachage des fichiers de l'ensemble. Ainsi, la référence peut être mise en cache HTTP en toute sécurité aussi longtemps que vous le souhaitez. Pour toujours si vous voulez, mais je pense le défaut est un an. Cependant, si vous modifiez l'une de vos feuilles de style, un nouveau hachage sera généré. Il s'agit d'un "contournement de la mémoire cache". Vous aurez ainsi une nouvelle copie du navigateur.

Cela dit, je ne sais pas pourquoi vous obtenez un 404. Je soupçonne que cela a quelque chose à voir avec votre configuration de routage ou votre configuration IIS. Utilisez-vous Visual Studio avec IISExpress?

3
cirrus

Je viens de résoudre un problème similaire. Le problème était le suivant: j'ai installé 'choisi' via NuGet. Et dans la classe BundleConfig, la ligne contenant le fichier CSS ressemblait à ceci:

bundles.Add(new StyleBundle("~/Content/css").Include("~/Content/site.css",)); 
bundles.Add(new StyleBundle("~/Content/css").Include("~/Content/chosen.css"));

Certains dans cette classe, j'avais cette ligne:

BundleTable.EnableOptimizations = true;

Le correctif consistait à combiner le 2 bundles.Add() comme suit:

bundles.Add(new StyleBundle("~/Content/css").Include(
                            "~/Content/site.css", 
                            "~/Content/chosen.css"
                        ));

Et cela a réglé le problème pour moi.

3
Yustme

Cela peut également être dû au fait que vous n’avez pas déployé bundleconfig.json sur le serveur pour une raison quelconque.

0
DJA