Mvc4 Stylebundle Not Resolving Images

MVC4 StyleBundle not resolving images

According to this thread on MVC4 css bundling and image references, if you define your bundle as:

bundles.Add(new StyleBundle("~/Content/css/jquery-ui/bundle")
.Include("~/Content/css/jquery-ui/*.css"));

Where you define the bundle on the same path as the source files that made up the bundle, the relative image paths will still work. The last part of the bundle path is really the file name for that specific bundle (i.e., /bundle can be any name you like).

This will only work if you are bundling together CSS from the same folder (which I think makes sense from a bundling perspective).

Update

As per the comment below by @Hao Kung, alternatively this may now be achieved by applying a CssRewriteUrlTransformation (Change relative URL references to CSS files when bundled).

NOTE: I have not confirmed comments regarding issues with rewriting to absolute paths within a virtual directory, so this may not work for everyone (?).

bundles.Add(new StyleBundle("~/Content/css/jquery-ui/bundle")
.Include("~/Content/css/jquery-ui/*.css",
new CssRewriteUrlTransform()));

Images in CSS not loading while using Bundling in MVC4

Finally got the answer after a small struggle.

I just replaced the image url as ' images/Greenish_sprite.png ' instead of 'Content/css/Customcss/images/Greenish_sprite.png'.

It is working well now :)

mvc bundling and relative css image when website is deployed to an application

If there are no virtual directories involved the following code would do:

bundles.Add(new StyleBundle("~/bundles/css").Include(
"~/Content/css/*.css", new CssRewriteUrlTransform()));

but when VirtualDirectory is used CssRewriteUrlTransform will rewrite to Host instead of Host/VirtualDirectory. the solution is to derive CssRewriteUrlTransform which is fully discussed here: ASP.NET MVC4 Bundling with Twitter Bootstrap:

public class CssRewriteUrlTransformWrapper : IItemTransform
{
public string Process(string includedVirtualPath, string input)
{
return new CssRewriteUrlTransform().Process("~" + VirtualPathUtility.ToAbsolute(includedVirtualPath), input);
}
}

MVC4 StyleBundle doesn't render the bundle in the correct order

Bundling is not supposed to render the CSS files in the exact same order, it follows a different logic. If you need to render them as defined, then you should create a custom IBundleOrderer and set it to the bundle as the required Orderer:

public class AsDefinedBundleOrderer : IBundleOrderer
{
public IEnumerable<FileInfo> OrderFiles(BundleContext context, IEnumerable<FileInfo> files)
{
return files;
}
}

And

var bundle = new StyleBundle("~/stylesheet");
bundle.Orderer = new AsDefinedBundleOrderer();
bundles.Add(bundle);

Then this will do nothing with the list so Render will render them exactly in the same order.

Update on default ordering

Bundling uses the concept of IBundleOrderer to sort the items within a Bundle.
The Bundle class has it's Orderer property which looks like this:

public IBundleOrderer Orderer
{
get
{
if (this._orderer == null)
return (IBundleOrderer) DefaultBundleOrderer.Instance;
else
return this._orderer;
}
set
{
this._orderer = value;
this.InvalidateCacheEntries();
}
}

So the default orderer is actually a DefaultBundleOrderer until you overwrite it with your custom orderer.

The IBundleOrderer has the following signature:

public interface IBundleOrderer
{
IEnumerable<FileInfo> OrderFiles(BundleContext context, IEnumerable<FileInfo> files);
}

The DefaultBundleOrderer implementation of this orders the files by the BundleContext, here is a snippet from the implementation of OrderFiles:

  foreach (BundleFileSetOrdering ordering in (IEnumerable<BundleFileSetOrdering>) context.BundleCollection.FileSetOrderList)
DefaultBundleOrderer.AddOrderingFiles(ordering, (IEnumerable<FileInfo>) list, fileMap, foundFiles, result);

So the different result happens because this. This is of course not a random sort algorithm :)
The rules are defined in the BUndleCollection class:

public static void AddDefaultFileOrderings(IList<BundleFileSetOrdering> list)
{
if (list == null)
throw new ArgumentNullException("list");
BundleFileSetOrdering bundleFileSetOrdering1 = new BundleFileSetOrdering("css");
bundleFileSetOrdering1.Files.Add("reset.css");
bundleFileSetOrdering1.Files.Add("normalize.css");
list.Add(bundleFileSetOrdering1);
BundleFileSetOrdering bundleFileSetOrdering2 = new BundleFileSetOrdering("jquery");
bundleFileSetOrdering2.Files.Add("jquery.js");
bundleFileSetOrdering2.Files.Add("jquery-min.js");
bundleFileSetOrdering2.Files.Add("jquery-*");
bundleFileSetOrdering2.Files.Add("jquery-ui*");
bundleFileSetOrdering2.Files.Add("jquery.ui*");
bundleFileSetOrdering2.Files.Add("jquery.unobtrusive*");
bundleFileSetOrdering2.Files.Add("jquery.validate*");
list.Add(bundleFileSetOrdering2);
BundleFileSetOrdering bundleFileSetOrdering3 = new BundleFileSetOrdering("modernizr");
bundleFileSetOrdering3.Files.Add("modernizr-*");
list.Add(bundleFileSetOrdering3);
BundleFileSetOrdering bundleFileSetOrdering4 = new BundleFileSetOrdering("dojo");
bundleFileSetOrdering4.Files.Add("dojo.*");
list.Add(bundleFileSetOrdering4);
BundleFileSetOrdering bundleFileSetOrdering5 = new BundleFileSetOrdering("moo");
bundleFileSetOrdering5.Files.Add("mootools-core*");
bundleFileSetOrdering5.Files.Add("mootools-*");
list.Add(bundleFileSetOrdering5);
BundleFileSetOrdering bundleFileSetOrdering6 = new BundleFileSetOrdering("prototype");
bundleFileSetOrdering6.Files.Add("prototype.js");
bundleFileSetOrdering6.Files.Add("prototype-*");
bundleFileSetOrdering6.Files.Add("scriptaculous-*");
list.Add(bundleFileSetOrdering6);
BundleFileSetOrdering bundleFileSetOrdering7 = new BundleFileSetOrdering("ext");
bundleFileSetOrdering7.Files.Add("ext.js");
bundleFileSetOrdering7.Files.Add("ext-*");
list.Add(bundleFileSetOrdering7);
}

So when you call this from Application_Start:

BundleConfig.RegisterBundles(BundleTable.Bundles);

Actually you pass the default BundleCollection defined in the library.

So we have the BundleFileSetOrdering instances passed one-by-one into:

private static void AddOrderingFiles(BundleFileSetOrdering ordering, IEnumerable<FileInfo> files, Dictionary<string, HashSet<FileInfo>> fileMap, HashSet<FileInfo> foundFiles, List<FileInfo> result)
{
foreach (string key in (IEnumerable<string>) ordering.Files)
{
if (key.EndsWith("*", StringComparison.OrdinalIgnoreCase))
{
string str = key.Substring(0, key.Length - 1);
foreach (FileInfo fileInfo in files)
{
if (!foundFiles.Contains(fileInfo) && fileInfo.Name.StartsWith(str, StringComparison.OrdinalIgnoreCase))
{
result.Add(fileInfo);
foundFiles.Add(fileInfo);
}
}
}
else if (fileMap.ContainsKey(key))
{
List<FileInfo> list = new List<FileInfo>((IEnumerable<FileInfo>) fileMap[key]);
list.Sort((IComparer<FileInfo>) FileInfoComparer.Instance);
foreach (FileInfo fileInfo in list)
{
if (!foundFiles.Contains(fileInfo))
{
result.Add(fileInfo);
foundFiles.Add(fileInfo);
}
}
}
}
}

Conclusion

If we want to simplify the process we can say that the library prefers some kind of files and makes some sorting on the other files if multiple possibilities found. This is the expected behavior most of the time but as you can see it is easly overridable with the AsDefinedBundleOrderer so it does nothing with the given file set so the order remains the original.

MVC4 Bundling misdirect background-image url

You're gonna need to apply the CssRewriteUrlTransform to fix this:

bundles.Add(new StyleBundle("~/styles/style1")
.Include("~/Content/styles/style1", new CssRewriteUrlTransform())

Alternatively, you can also use absolute paths in your stylesheets.

P.S: As stated in the comments, you have to add the Web Optimization Package to your project through Codeplex or NuGet to be able to use the CssRewriteUrlTransform class

ASP.NET MVC 4 Minification & Background Images

Might have a look at RequestReduce. It's another .net based minifier/bundler and it will rewrite all urls in the minified/bundled css to be absolute. This includes fonts and background images. It will also automatically expand any imports in the css. Additionally, where it thinks it can, it will sprite the background images.

Why are my style bundles not rendering correctly in ASP.NET MVC 4?

The default behaviour is for the IgnoreList to ignore any minified scripts.

You can either remove the '.min' from their names, or clear the IgnoreList.

MVC jQuery UI CSS urls not resolving after deployment

Ufuk's answer got me thinking. Appending the app name to the front of the bundle's virtual path broke all my styles.

The bundle function takes all the CSS files inside the include statement and minifies them into one file located at the URL specified in the bundle's virtual path. The urls specified in the CSS files included in this bundle uses the bundle's given virtual path to build up its URL at runtime. This works fine in dev because dev does not utilize the bundles, it references each css file individually/directly.

The solution was to create a bundle with the correct virtual path:

bundles.Add(new StyleBundle("~/Content/themes/base/css").Include(
"~/Content/themes/base/jquery-ui.css")):

Thanks Ufuk for the advice and guidance.



Related Topics



Leave a reply



Submit