Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Did Auto-Bundling/Minification Get Tossed in Final Release of MVC 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;
 }
like image 529
Sam Avatar asked Dec 15 '22 19:12

Sam


2 Answers

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

like image 78
nemesv Avatar answered Jan 30 '23 09:01

nemesv


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.

like image 22
Hao Kung Avatar answered Jan 30 '23 09:01

Hao Kung