16

I am just trying out ASP.NET MVC 4 but I can't figure out how to disable Javascript/CSS minification feature. Especially for development environment this will help greatly on debugging. I would imagine it would be a switch in web.config but since ASP.NET MVC 4 is still in beta stage at the moment there's really not much information out there. Would appreciate if someone can help or point to the right blog posts etc.

Hao Kung
  • 28,040
  • 6
  • 84
  • 93
Jeff
  • 13,079
  • 23
  • 71
  • 102

10 Answers10

18

In Global.asax.cs

#if DEBUG
        foreach (var bundle in BundleTable.Bundles)
        {
            bundle.Transform = new NoTransform();
        }
#endif
Socardo
  • 520
  • 6
  • 14
  • 1
    This has now changed in the latest version, see this answer for details: http://stackoverflow.com/a/11270224 – Michael Aug 03 '12 at 00:09
  • @Michael: Yes, but the answer is correct *for beta* as the OP requested :-) I still have an MVC 4 beta website that is yet to be upgraded and glad I found this answer :-) – Eric J. Feb 07 '13 at 03:18
4

Another option would be to create an HTML Helper that you could use to build the script and link tags. Here is what I have implemented for the Javascript, which can also be done for the CSS:

public static class BundleHelper
    {
        public static MvcHtmlString JsBundle(this HtmlHelper helper, string bundlePath)
        {
            var jsTag = new TagBuilder("script");
            jsTag.MergeAttribute("type", "text/javascript");

            return ReferenceBundle(helper, bundlePath, jsTag);
        }

        public static MvcHtmlString ReferenceBundle(this HtmlHelper helper, string bundlePath, TagBuilder baseTag)
        {
            var httpContext = helper.ViewContext.HttpContext;
            var urlHelper = new UrlHelper(helper.ViewContext.RequestContext);

            Bundle bundle = BundleTable.Bundles.GetBundleFor(bundlePath);
            var htmlString = new StringBuilder();

            if (bundle != null)
            {
                var bundleContext = new BundleContext(helper.ViewContext.HttpContext, BundleTable.Bundles, urlHelper.Content(bundlePath));

                if (!httpContext.IsDebuggingEnabled)
                {
                    baseTag.MergeAttribute("href", System.Web.Optimization.BundleTable.Bundles.ResolveBundleUrl(bundlePath));
                    return new MvcHtmlString(baseTag.ToString());
                }

                foreach (var file in bundle.EnumerateFiles(bundleContext))
                {
                    var basePath = httpContext.Server.MapPath("~/");
                    if (file.FullName.StartsWith(basePath))
                    {
                        var relPath = urlHelper.Content("~/" + file.FullName.Substring(basePath.Length));
                        baseTag.MergeAttribute("href", relPath, true);
                        htmlString.AppendLine(baseTag.ToString());
                    }
                }

            }

            return new MvcHtmlString(htmlString.ToString());
        }
    }

Now all that you have to do is call it in your view:

<head>
    <meta charset="utf-8" />
    <title>@ViewBag.Title - My ASP.NET MVC Application</title>
    <link href="~/favicon.ico" rel="shortcut icon" type="image/x-icon" />
    <link href="~/Content/css" rel="stylesheet" type="text/css" />
    <link href="~/Content/themes/base/css" rel="stylesheet" type="text/css" />
    @Html.JsBundle("~/scripts/js")
    <meta name="viewport" content="width=device-width" />
</head>

And it will render the scripts as separate references, or use the new bundling/minification feature depending on what the debug setting is in your web.config . I used some of the code from http://codecutout.com/resource-minify-bundling as a reference when creating my helper if you wanted to see some more examples. Their helper is written a little better, throwing exceptions when invalid arguments are supplied, etc.... I just haven't gotten around to cleaning mine up yet.

Russell Durham
  • 624
  • 6
  • 18
4

You could register your own bundles in the Global.asax and use the NoTransform class if you do not want the content to be minified.

I personally don't want my script to be transformed at all. I just create two script directories. One with the debug script versions and one with the originally downloaded minified versions.

The MVC 4 out of the box minifier (JsMinify) breaks jQuery 1.7.1 for Opera, so I do not want to use that one. I just put the following lines in my Global.asax: Application_Start() method:

Bundle debugScripts = new Bundle("~/DebugScripts", 
    new NoTransform("text/javascript"));
debugScripts.AddDirectory("~/Scripts/Debug", "*.js");
BundleTable.Bundles.Add(debugScripts);

Bundle productionScripts = new Bundle("~/ProductionScripts", 
    new NoTransform("text/javascript"));
productionScripts.AddDirectory("~/Scripts/Minified", "*.js");
BundleTable.Bundles.Add(productionScripts);

With that in place I can simply add either one of two lines in my _layouts.cshtml:

<script src="@System.Web.Optimization.BundleTable.Bundles.ResolveBundleUrl("~/DebugScripts")" type="text/javascript"></script>
<script src="@System.Web.Optimization.BundleTable.Bundles.ResolveBundleUrl("~/ProductionScripts")" type="text/javascript"></script>

Of course we could get a little more funky with this in place. We could generate just one bundle and depending on the built type select what files to include.

Nick Josevski
  • 4,156
  • 3
  • 43
  • 63
3

On newer versions of ASP.NET MVC just add

#if DEBUG
            foreach (var bundle in BundleTable.Bundles)
            {
                bundle.Transforms.Clear();
            }
#endif

right after

BundleConfig.RegisterBundles(...);
Roman Pushkin
  • 5,639
  • 3
  • 40
  • 58
3

After the call to EnableDefaultBundles() in Global.asax, you can do this ...

        if ( ... running in development environment ...)
        {
            var registeredBundles = BundleTable.Bundles.GetRegisteredBundles();
            foreach (var bundle in registeredBundles)
            {
                if (bundle.Transform is System.Web.Optimization.JsMinify)
                    bundle.Transform = new NoTransform();
            }
        }

Not pretty (modifying state set by the system), but it's a lot less code than all the other suggestions, still lets you use the standard bundling behavior and it doesn't involve any changes to your views.

Ian Mercer
  • 38,490
  • 8
  • 97
  • 133
2

you can turn it off from config:

<system.web>
    <compilation debug="true" />
    <!-- Lines removed for clarity. -->
</system.web>

http://www.asp.net/mvc/tutorials/mvc-4/bundling-and-minification

Jon
  • 15,110
  • 28
  • 92
  • 132
1

Rather than replace instances of JsMinify and CssMinify, one can instead use interfaces. This option was not available in earlier releases because the second constructor parameter was a type rather than an interface.

IBundleTransform jsTransform;
IBundleTransform cssTransform;

#if DEBUG
    jsTransform = new NoTransform("text/javascript");
    cssTransform = new NoTransform("text/css");
#else
    jsTransform = new JsMinify();
    cssTransform = new CssMinify();
#endif

Bundle jsBundle = new Bundle("~/JsB", jsTransform);
Bundle cssBundle = new Bundle("~/CssB", cssTransform);

Perhaps also worth noting, for scripts that are shipped with minified and non-minified versions e.g. jQuery, one can use a helper method to optionally strip out the ".min" for DEBUG builds to facilitate debugging:

private string Min(string scriptNameIncludingMin)
{
#if DEBUG
    return scriptNameIncludingMin.Replace(".min", ""); // Remove .min from debug builds
#else
    return scriptNameIncludingMin;
#endif
}

// ...
jsBundle.AddFile(Min("~/Scripts/jquery-1.7.2.min.js"));
Eric J.
  • 147,927
  • 63
  • 340
  • 553
  • Does this stop the js concatenation as well as the minifying? It is also annoying debugging a single giant js file. – Alex May 30 '12 at 06:28
1

I think it would be right, if such feature will be available "out of the box".

I posted a feedback on UserVoice.com: http://aspnet.uservoice.com/forums/41201-asp-net-mvc/suggestions/2702000-improve-system-web-optimization-bundle

Give it your "voices".

resnyanskiy
  • 1,607
  • 1
  • 24
  • 24
0

Another alternative (tested with v1.1.0.0 and MVC5):

public class BundleConfig
{
    public static void Register()
    {
        ScriptBundle jsBundle = new ScriptBundle("~/Scripts/myscript.min.js");
        jsBundle.Include("~/Scripts/myscript.js");
        DisableInDebugMode(jsBundle);

        BundleTable.Bundles.Add(jsBundle);
    }

    private static void DisableInDebugMode(ScriptBundle jsBundle)
    {
    #if DEBUG
        // Don't minify in debug mode
        jsBundle.Transforms.Clear();
    #endif
    }
}
Chris S
  • 64,770
  • 52
  • 221
  • 239
0

Try a new extension for System.Web.Optimization - Bundle Transformer. In Bundle Transformer implemented a number of opportunities to simplify debugging (see documentation).

Andrey Taritsyn
  • 1,286
  • 11
  • 26