CssRewriteUrlTransform with or without virtual directory
Solution 1
I am not sure to fully understand your problem, but seeing http://localhost
here seems wrong. You should never use an absolute URL for your bundles.
For me CssRewriteUrlTransform works perfectly, here is how I use it:
bundles.Add(new StyleBundle("~/bundles/css").Include(
"~/Content/css/*.css", new CssRewriteUrlTransform()));
"Bundles" is virtual.
Does this helps?
Update
I was confused with the "VirtualDir" thing, as you are talking about IIS VirtualDir, and I was thinking Bundle VirtualDir! It's true that in this case CssRewriteUrlTransform will rewrite URLs to the Host, not to the Host/VirtualDir URI.
To do that, you have to derive CssRewriteUrlTransform to make it do what you need it to. There is a good discussion here: ASP.NET MVC4 Bundling with Twitter Bootstrap
Seems the best answer is there:http://aspnetoptimization.codeplex.com/workitem/83
public class CssRewriteUrlTransformWrapper : IItemTransform
{
public string Process(string includedVirtualPath, string input)
{
return new CssRewriteUrlTransform().Process("~" + VirtualPathUtility.ToAbsolute(includedVirtualPath), input);
}
}
Use this class instead of CssRewriteUrlTransform
Solution 2
I had the same problem. This is how I fixed it:
private class ProperUrlRewrite : IItemTransform
{
private static string RebaseUrlToAbsolute(string baseUrl, string url)
{
if (string.IsNullOrWhiteSpace(url) || string.IsNullOrWhiteSpace(baseUrl) || url.StartsWith("/", StringComparison.OrdinalIgnoreCase) || url.Contains(':'))
return url;
return VirtualPathUtility.Combine(baseUrl, url);
}
private static Regex UrlPattern = new Regex("url\\s*\\(['\"]?(?<url>[^)]+?)['\"]?\\)");
public string Process(string includedVirtualPath, string input)
{
if (includedVirtualPath == null)
throw new ArgumentNullException("includedVirtualPath");
if (string.IsNullOrWhiteSpace(input))
return input;
string directory = VirtualPathUtility.GetDirectory(VirtualPathUtility.ToAbsolute(includedVirtualPath));
if (!directory.EndsWith("/", StringComparison.OrdinalIgnoreCase))
directory += "/";
return UrlPattern.Replace(input, match => "url(" + ProperUrlRewrite.RebaseUrlToAbsolute(directory, match.Groups["url"].Value) + ")");
}
}
I know it's far from perfect and there are plenty of edge cases where this can go wrong (I'm not sure you can parse a CSS file with a regex in the first place - though this is exactly what the original CssRewriteUrlTransform
does), but so far it holds...
Solution 3
The 'CssRewriteUrlTransform' works just fine for applications that DOESN'T run on top of a virtual directory.
So, if your app runs on http://your-site.com/ it runs just fine, but if runs on http://your-site.com/your-app/ you'll have 404 for all your images, because the default 'CssFixRewriteUrlTransform' is referencing your images with a '/'.
Use this:
public class CssFixRewriteUrlTransform: IItemTransform {
private static string ConvertUrlsToAbsolute(string baseUrl, string content) {
if (string.IsNullOrWhiteSpace(content)) {
return content;
}
var regex = new Regex("url\\(['\"]?(?<url>[^)]+?)['\"]?\\)");
return regex.Replace(content, match = > string.Concat("url(", RebaseUrlToAbsolute(baseUrl, match.Groups["url"].Value), ")"));
}
public string Process(string includedVirtualPath, string input) {
if (includedVirtualPath == null) {
throw new ArgumentNullException("includedVirtualPath");
}
var directory = VirtualPathUtility.GetDirectory(includedVirtualPath);
return ConvertUrlsToAbsolute(directory, input);
}
private static string RebaseUrlToAbsolute(string baseUrl, string url) {
if (string.IsNullOrWhiteSpace(url) || string.IsNullOrWhiteSpace(baseUrl) || url.StartsWith("/", StringComparison.OrdinalIgnoreCase)) {
return url;
}
if (!baseUrl.EndsWith("/", StringComparison.OrdinalIgnoreCase)) {
baseUrl = string.Concat(baseUrl, "/");
}
return VirtualPathUtility.ToAbsolute(string.Concat(baseUrl, url));
}
}
Note: delete all file css with .min.css, because if don't it doesn't fix.
Anders
I'm a committed and driven consultant who enjoy working in customer-oriented projects. I have good experience in designing and developing customer-specific IT solutions in .NET. I'm passionate about "Continuous learning" and read blogs and test new technologies regulary. I'm aiming at always leaving my projects with well structured code, which together with well-balanced design solutions makes them easy to maintain.
Updated on July 05, 2022Comments
-
Anders almost 2 years
We are using MVC Bundling in our site,
CssRewriteUrlTransform
makes sure that the image urls work from the dynamic bundle css file.But this only works when not using a virtual directory, i.e
http://localhost/VirttualDir
does not work buthttp://localhost/
does. This is because theCssRewriteUrlTransform
tranform does not take the virtual folder into account when rewriting the url. So if a image real path islocalhost/vdir/content/img/foo.png
it will rewrite it tolocalhost/content/img/foo.png
which is wrong -
Vilx- over 10 yearsThe problem appears when your application isn't hosted at the server root, but in a virtual directory. Like
/path/to/my/appRoot/
. -
Anders over 10 yearsThanks will check it out!
-
Ole Tolshave about 8 yearsThe idea of removing the ".min.css" file helped me out. I guess if the file exists then that file is included directly as an optimization and then the rewriting never takes place.
-
Robert Slaney about 8 yearsYou need to take into account data uri formats. Ignore urls starting with "data:" in your RebaseUrlToAbsolute function
-
jonmeyer over 6 yearsThis put me on the right track but did not work for url( ) that contained a AbsoluteUri already, i needed to detect that so i added a Uri.TryCreate inside a custom version of CssRewriteUrlTranform instead of using a wrapper.
-
Mahanthesh Kumbar over 4 years@jonmeyer Do you have sample code how it is achieved without the transform.
-
Thulasiram about 4 yearsWorking Fine. Thanks :)
-
this.myself almost 3 yearsThe problem may also appear when your application is behind a portal where some forwarding and so on is done (don't know exact offical wording for our setup).