Pages Menu
TwitterRssFacebook

Posted by on Feb 20, 2013 in Development

Fixing Relative CSS Paths when using .NET MVC 4 Bundling

Fixing Relative CSS Paths when using .NET MVC 4 Bundling

I’ve been using the Bundling and Minification stuff that comes with .NET MVC 4 for a while, but I never really dug into it much. When you create a Script or a Style bundle you give it a name, which in all the templates and examples seems to look like a URL, but I didn’t ever wonder exactly what it was for. I just thought it was a nice way to differentiate groups of styles and scripts.

Recently, I hit a known problem with deploying to IIS virtual directories. It’s not a problem for ASP.NET which understands virtual directories and so if you ask for “~” or “/” will return “yoursite/virtualfolder”. However, JavaScript is run under IIS, which doesn’t understand this idea so well. Do “/” in JS and you’ll get back “yoursite” NOT “yoursite/virtualfolder”. It’s a pain – especially as you only really notice once you’ve deployed somewhere with virtual directories… like Live!

shock

So what’s the fix? Well, for JavaScript there are a couple of answers. The one I went for in the end was to use MVC to correctly give me the real root, then store that in a global javascript varialbe. Based on this answer, I came up with this:

  1. Add a hidden field to a masterpage:
      @Html.Hidden("HiddenCurrentUrl",  Url.Content("~"))
  2. As one of the first things you do, ensure this JS runs. All it does it take the value in the field and store it:
    var baseUrl = "";
    baseUrl = $("#HiddenCurrentUrl").val();
  3. Use baseUrl wherever you need to call things in JavaScript:
    Silverlight.createObject(
                baseUrl + "ClientBin/SilverlightBridge.xap",  // source
                ...
            );

Anyway

That wasn’t what I was going to talk about at all. The real problem then was images specified in CSS file:

    .link-button.cancel {
        background-image: url('../Images/appbar.cancel.darkgrey.png');
    }

A similar problem occures where these URLs start with a slash(/) because IIS interprets that incorrectly. You can’t invoke ASP.NET, which does know the right root into a CSS file (well, you could, but I think this solution is overkill).

“”Partial URLs are interpreted relative to the source of the style sheet, not relative to the document.””

After some messing around, I came to this compromise, which works well. It also exposes some of the hidden power of using Bundling:

  1. For any images you reference in CSS, move them into a relative folder, such as /images near the CSS. I know, this may be an unacceptable compromise for you. But actually, it makes a lot of sense. The image is probably only used by the CSS so it makes sense to have it nearby, not in some global /images folder.  By the way, this works because ”Partial URLs are interpreted relative to the source of the style sheet, not relative to the document.” (thanks to Phil Haack for this)
  2. In order to make this work, you need to get your CSS (which you’ve bundled up) into the same place relative to the images you’re reference, or at least, you need to cheat the browser into thinking this happening.

    After playing with Fiddler, I realised that the name you give the Style Bundle when you create it becomes the virtual path it is served up on.

    So, for instance:

  bundles.Add(new StyleBundle("~/Content/DataTableStyle").Include(

comes out the other end as:

StyleBundleOutput

Don’t forget that all your “static” content, such as images won’t be affected by Bundling and can be referenced using the folder structure you expect, i.e. the one you’ve set up in Visual Studio.

So… when you create the Style Bundle you give it a name which reflects where you have it in your Visual Studio folder structure, then it will pop out the other end in the same place, relatively, to the image files which it’s references! And because the Bundling is happening via ASP.NET, the URL of the CSS file, and wherever it is referenced, works fine in virtual directories!  Panic over!

Written by Tom Morgan

Tom is a Microsoft Teams Platform developer and Microsoft MVP who has been blogging for over a decade. Find out more.
Buy the book: Building and Developing Apps & Bots for Microsoft Teams. Now available to purchase online with free updates.

Post a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.