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
Format Text in a ≪Textarea≫
Size of Html5 Canvas Via CSS Versus Element Attributes
How to Remove the Stripes That Appears When Using Linear Gradient Property
What's So Bad About In-Line Css
Why Aren't My Grid-Template-Areas With Ascii Art Not Working
Css Transform Doesn't Work on Inline Elements
Bootstrap Navbar With Left, Center or Right Aligned Items
Align Inline-Block Divs to Top of Container Element
Transitions on the CSS Display Property
How to Transition Height: 0; to Height: Auto; Using Css
How to Disable Text Selection Highlighting
Using CSS For a Fade-In Effect on Page Load
Change a Html5 Input'S Placeholder Color With Css
Bootstrap Dropdown Sub Menu Missing
How to Change Paper Size in Headless Chrome - Print-To-Pdf
How to Vertically Center ≪Div≫ Inside the Parent Element With Css