4

According to an article I read earlier by Scott Guthrie, and a video posted by Mads Kristensen, I should be able to auto-bundle/minify in ASP.net MVC 4 by replacing this:

<link href="Styles/reset.css" rel="stylesheet" type="text/css" />
<link href="Styles/normalize.css" rel="stylesheet" type="text/css" />
<link href="Styles/styles.css" rel="stylesheet" type="text/css" />

<script src="Scripts/jquery-1.8.0.min.js" type="text/javascript"></script>
<script src="Scripts/jquery-validation.min.js" type="text/javascript"></script>

With this:

<link href="Styles/css" rel="stylesheet" type="text/css" />

<script src="Scripts/js" type="text/javascript"></script>

I've tried targeting both .Net 4.0 and 4.5 and it doesn't seem to make a difference. I get 404 errors and the link and script tags are never directed at the bundled resources.

Did this feature get dropped from the final version?

I'd like to utilize this feature for "Themes".


This is how I ended up implementing. Hopefully it makes sense...

 /// <summary>
 /// Render stylesheets HTML for the given theme. Utilizes System.Web.Optimization for bundling and minification
 /// </summary>
 /// <param name="themeName">Name of theme</param>
 /// <returns>HtmlString containing link elements</returns>
 public static IHtmlString RenderThemeStyles(string themeName)
 {
     IHtmlString retValue = null;

     // If no theme name is passed, return null
     if (!themeName.HasValue())
         return retValue;

     var ctxt = HttpContext.Current;
     string themePath = "~/Themes/" + themeName;
     string themeKey = themePath + "/css";

     if (ctxt.Cache[themeKey] != null)
         return (IHtmlString)ctxt.Cache[themeKey];

     // Check to see if the theme directory exists. Throw error if it does not
     string themeSysPath = HttpContext.Current.Server.MapPath(themePath);
     DirectoryInfo themeDir = new DirectoryInfo(themeSysPath);
     if (!themeDir.Exists)
         throw new ApplicationException(string.Format("Theme directory \"{0}\" does not exist", themePath));

     // Remove the old bundle if it already exists
     var old_bundle = BundleTable.Bundles.FirstOrDefault(b => b.Path == themeKey);
     if (old_bundle != null)
         BundleTable.Bundles.Remove(old_bundle);

     if (themeDir.GetFiles("*.css").Length > 0)
     {
         // If there are css files, add them to the bundler and save the rendered output to cache
         Bundle styles = new StyleBundle(themeKey).IncludeDirectory(themePath, "*.css");
         BundleTable.Bundles.Add(styles);
         retValue = Styles.Render(themeKey);
         ctxt.Cache.Insert(themeKey, retValue, new System.Web.Caching.CacheDependency(themeSysPath));
     }
     else
     {
         // If there are no css files, save empty string to cache
         ctxt.Cache.Insert(themeKey, new HtmlString(string.Empty), new System.Web.Caching.CacheDependency(themeSysPath));
     }

     return retValue;
 }
Hao Kung
  • 28,040
  • 6
  • 84
  • 93
Sam
  • 9,933
  • 12
  • 68
  • 104
  • 2
    Yes, this feature is removed in the RC version although I could not find any announcement about it. Only [Hanselman](http://www.hanselman.com/blog/VisualStudio2012RCIsReleasedTheBigWebRollup.aspx) mentions it : "There's been some significant changes to the web optimization (minification and bundling) framework since beta. There wasn't enough control over what was bundled and in what order in the beta, so that's been moved into a BundleConfig.cs (or .vb) where you have total control" – nemesv Sep 02 '12 at 20:56
  • nemesv. Add as an answer and I'll accept. Kind of wish they would have left the auto-stuff in place and allowed people to specify in the BundleConfig if they needed that type of granularity. Now I have to look at recreating something similar, or figure out how to do the bundles dynamically with a cache dependency on my theme folders. – Sam Sep 02 '12 at 21:35
  • you can still add whole folders with the `IncludeDirectory` call you can even use wildcards see [Bundling and Minification - Creating a Bundle](http://www.asp.net/mvc/tutorials/mvc-4/bundling-and-minification) – nemesv Sep 03 '12 at 06:47
  • See http://stackoverflow.com/questions/20347098/declarative-dynamic-bundling-minification-for-mvc , some momentum may be building to include this in SquishIt – shannon Dec 06 '13 at 06:30

2 Answers2

6

Yes, this feature is removed in the MVC4 RC version although I could not find the RC release notes anymore.

Rick Anderson 's blog post on upgrade MVC4 beta to RC describes the process:

Remove the "autobundling" references and create/copy a BundleConfig.cs with your bundle configs and call it from Global.asax with BundleConfig.RegisterBundles(BundleTable.Bundles);.

Hanselman mentions some backround info about the decision:

There's been some significant changes to the web optimization (minification and bundling) framework since beta. There wasn't enough control over what was bundled and in what order in the beta, so that's been moved into a BundleConfig.cs (or .vb) where you have total control

nemesv
  • 138,284
  • 16
  • 416
  • 359
6

Not exactly, so we removed EnableDefaultBundles which is what you refer to 'autobundling', but the underlying functionality is still there.

You can do the equivalent of what that method was doing by registering:

BundleTable.Bundles.Add(new DynamicFolderBundle("js", "*.js");
BundleTable.Bundles.Add(new DynamicFolderBundle("css", "*.css");

We removed the method since this is a fairly problematic approach as alphabetical ordering is not usually the desired ordering.

Hao Kung
  • 28,040
  • 6
  • 84
  • 93
  • Yes but it seems that It's not possible to put the `dynamicFolderBundle` _after_ my `Includes`. I mean — Currently I'm using `bundles.Add(new DynamicFolderBundle("userScripts", "*.js",new JsMinify()).Include("~/Scripts/YGeneral.js").Include("~/Scripts/ZGeneral.js"))` - .But for some reason first it puts the script from the `DynamicFolderBundle` output first , **and THEN** it puts the other Includes.Is there any way to first put the `Includes` and THEN the `DynamicFolderBundle` ? – Royi Namir Sep 08 '15 at 16:55