CssRewriteUrlTransform with or without virtual directory

前端 未结 4 811
囚心锁ツ
囚心锁ツ 2020-11-28 22:35

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

相关标签:
4条回答
  • 2020-11-28 23:10

    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

    0 讨论(0)
  • 2020-11-28 23:19

    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.

    0 讨论(0)
  • 2020-11-28 23:26

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

    0 讨论(0)
  • 2020-11-28 23:33

    I have problems with url that contains "data" and even a url inner another one, so I have to re-do the regex, this is my solution:

    public string Process(string includedVirtualPath, string input)
        {
            if (includedVirtualPath == null)
            {
                throw new ArgumentNullException(nameof(includedVirtualPath));
            }
    
            if (string.IsNullOrWhiteSpace(input))
            {
                return input;
            }
    
            var directory = VirtualPathUtility.GetDirectory(includedVirtualPath);
            if (!directory.EndsWith("/", StringComparison.OrdinalIgnoreCase))
            {
                directory += "/";
            }
    
            return new Regex(@"url\s*\(\s*([\'""]?)(?<scheme>(?:(?:data:)|(?:https?:))?)(?<url>(\\\1|.)*?)\1\s*\)")
                .Replace(input, match => string.Concat(
                    "url(",
                    match.Groups[1].Value,
                    match.Groups["scheme"].Value,
                    match.Groups["scheme"].Value == "" ?
                        RebaseUrlToAbsolute(directory, match.Groups["url"].Value) :
                        match.Groups["url"].Value,
                    match.Groups[1].Value,
                    ")"
                ));
        }
    
        private static string RebaseUrlToAbsolute(string baseUrl, string url)
        {
            if (string.IsNullOrWhiteSpace(url) || string.IsNullOrWhiteSpace(baseUrl)
                || url.StartsWith("/", StringComparison.OrdinalIgnoreCase))
            {
                return url;
            }
    
            return VirtualPathUtility.ToAbsolute(string.Concat(baseUrl, url));
        }
    }
    

    based on RegEx: Grabbing values between quotation marks

    0 讨论(0)
提交回复
热议问题