Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

CssRewriteUrlTransform with or without virtual directory

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 but http://localhost/ does. This is because the CssRewriteUrlTransform tranform does not take the virtual folder into account when rewriting the url. So if a image real path is localhost/vdir/content/img/foo.png it will rewrite it to localhost/content/img/foo.png which is wrong

like image 752
Anders Avatar asked Nov 04 '13 09:11

Anders


3 Answers

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

like image 117
BernardG Avatar answered Nov 15 '22 12:11

BernardG


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...

like image 40
Vilx- Avatar answered Nov 15 '22 12:11

Vilx-


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.

like image 36
Phan Đức Bình Avatar answered Nov 15 '22 11:11

Phan Đức Bình