Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

MVC4 Bundles - No Twitter Bootstrap icons

Tags:

Running my MVC4 app in debug mode (so no minification of css/scripts) works fine. As soon as I run without debug (css/scripts minified), my Twitter Bootstrap icons do not get displayed. Another thread on here suggested using bundles.IgnoreList.Clear(). But that does not seem to work for me. My BundleConfig.RegisterBundles(...) looks like this:

public static void RegisterBundles(BundleCollection bundles)
{
    bundles.IgnoreList.Clear();

    // Some JavaScript bundles only
    // ...

    bundles.Add(new StyleBundle("~/bundles/maincss").Include(
        "~/Content/bootstrap.css",
        "~/Content/bootstrap-responsive.css",
       "~/Content/my.css"));
    }
}

All packages were installed using Nuget (as I say, it works fine in debug mode). My Content folder also contains the minified versions of both the bootstrap...css files, but not a minified version of my.css. The glyph icons are in the images sub-folder.

My _Layout.cshtml looks like this:

<head>
    ...
    @Styles.Render("~/bundles/maincss")
</head>

I should add, that by "non-debug" mode, I mean setting the debug="false" option in the Web.config file:

<compilation debug="false" targetFramework="4.5" />

Does anyone have any idea why the twitter bootstrap icons do not show in "non-debug" mode?

Thanks Rob

like image 530
Rob L Avatar asked Jul 27 '13 00:07

Rob L


2 Answers

I'm on mobile so my apologies for brief response but I'll update later.

Read this

Long story short it had to do with relative path being fouled after bundling. But the good news is the latest bundle library resolves it.

Update

To fill in the blanks, essentially what's happening is that the CSS files have relative paths to resources (in this case an icon sprite). When in debug mode, the files are output separately to the page so the references are retained (/Content/bootstrap.css with a reference to images/glyphicons-halflings.png (making the full path /Content/images/glyphicons-halflings.png). However, when debug is removed the files are bundled and the path is now relative to whatever virtual path you gave your bundle. In the case of above, you now originate from /bundles/maincss which makes for an erroneous /bundles/maincss/images/glyphicons-halflings.png path.

The good news is that this was a resolved bug and as of Microsoft.AspNet.Web.Optimization v1.1.0 you now have CssRewriteUrlTransform that will replace all relative paths (within the CSS files) with their absolute-pathed counterpart. This means that no matter what you call the bundle, the resources will still be resolved.

So, to fix the issue, you can simple do the following:

IItemTransform cssFixer = new CssRewriteUrlTransform();

bundles.Add(
    new StyleBundle("~/bundles/maincss")
        .Include("~/Content/bootstrap.css", cssFixer)
        .Include("~/Content/bootstrap-responsive.css", cssFixer)
        .Include("~/Content/my.css", cssFixer)
);

My only qualm is how ugly this looks when you want multiple files, so to solve this you can simplify it with an extension method:

/// <summary>
/// Includes the specified <paramref name="virtualPaths"/> within the bundle and attached the
/// <see cref="System.Web.Optimization.CssRewriteUrlTransform"/> item transformer to each item
/// automatically.
/// </summary>
/// <param name="bundle">The bundle.</param>
/// <param name="virtualPaths">The virtual paths.</param>
/// <returns>Bundle.</returns>
/// <exception cref="System.ArgumentException">Only available to StyleBundle;bundle</exception>
/// <exception cref="System.ArgumentNullException">virtualPaths;Cannot be null or empty</exception>
public static Bundle IncludeWithCssRewriteTransform(this Bundle bundle, params String[] virtualPaths)
{
    if (!(bundle is StyleBundle))
    {
        throw new ArgumentException("Only available to StyleBundle", "bundle");
    }
    if (virtualPaths == null || virtualPaths.Length == 0)
    {
        throw new ArgumentNullException("virtualPaths", "Cannot be null or empty");
    }
    IItemTransform itemTransform = new CssRewriteUrlTransform();
    foreach (String virtualPath in virtualPaths)
    {
        if (!String.IsNullOrWhiteSpace(virtualPath))
        {
            bundle.Include(virtualPath, itemTransform);
        }
    }
    return bundle;
}

Which makes the above code a little cleaner. (Arguably I picked a long method name, but I like to keep the method names clear with regards to purpose)

bundles.Add(
    new StyleBundle("~/bundles/maincss").IncludeWithCssRewriteTransform(
        "~/Content/bootstrap.css",
        "~/Content/bootstrap-responsive.css",
        "~/Content/my.css"
    )
);
like image 147
Brad Christie Avatar answered Nov 08 '22 06:11

Brad Christie


I ran into the same thing using Bootstrap 3.0. @brad-christie's answer solved my problem until I used NuGet to upgrade to Microsoft ASP.Net Web optimisation Framework 1.1.1. This seemed to stop the CssRewriteUrlTransform fix from working. I solved the problem by removing the references to CssRewriteUrlTransform and by creating a style sheet, bootstrap-bundle-font-fix.css, containing just the following:

@font-face {
  font-family: 'Glyphicons Halflings';
  src: url('../../Content/fonts/glyphicons-halflings-regular.eot');
  src: url('../../Content/fonts/glyphicons-halflings-regular.eot?#iefix') format('embedded-opentype'), 
       url('../../Content/fonts/glyphicons-halflings-regular.woff') format('woff'),
       url('../../Content/fonts/glyphicons-halflings-regular.ttf') format('truetype'), 
       url('../../Content/fonts/glyphicons-halflings-regular.svg#glyphicons-halflingsregular') format('svg');
}

And then including it in my bootstrap css bundle:

bundles.Add(new StyleBundle("~/bundles/Content/bootstrap")
    .Include("~/Content/bootstrap/bootstrap.css")
    .Include("~/Content/bootstrap/bootstrap-theme.css")
    .Include("~/Content/bootstrap-bundle-font-fix.css")
    .Include("~/Content/sticky-footer-navbar.css"));
like image 30
daveb Avatar answered Nov 08 '22 06:11

daveb