C# 带或不带虚拟目录的 CssRewriteUrlTransform

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/19765238/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-10 15:49:25  来源:igfitidea点击:

CssRewriteUrlTransform with or without virtual directory

c#asp.net-mvc-4bundling-and-minificationweb-optimization

提问by Anders

We are using MVC Bundling in our site, CssRewriteUrlTransformmakes sure that the image urls work from the dynamic bundle css file.

我们在我们的站点中使用 MVC 捆绑,CssRewriteUrlTransform确保图像 url 可以从动态捆绑 css 文件中工作。

But this only works when not using a virtual directory, i.e

但这仅在不使用虚拟目录时才有效,即

http://localhost/VirttualDirdoes not work but http://localhost/does. This is because the CssRewriteUrlTransformtranform does not take the virtual folder into account when rewriting the url. So if a image real path is localhost/vdir/content/img/foo.pngit will rewrite it to localhost/content/img/foo.pngwhich is wrong

http://localhost/VirttualDir不起作用,但http://localhost/确实如此。这是因为CssRewriteUrlTransform在重写 url 时,转换没有考虑虚拟文件夹。所以如果图像的真实路径是localhost/vdir/content/img/foo.png它会重写它localhost/content/img/foo.png是错误的

采纳答案by BernardG

I am not sure to fully understand your problem, but seeing http://localhosthere seems wrong. You should never use an absolute URL for your bundles.

我不确定是否完全理解您的问题,但看到http://localhost这里似乎是错误的。你永远不应该为你的包使用绝对 URL。

For me CssRewriteUrlTransform works perfectly, here is how I use it:

对我来说 CssRewriteUrlTransform 工作完美,这是我如何使用它:

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.

我对“VirtualDir”的东西感到困惑,因为你在谈论 IIS VirtualDir,我在想 Bundle VirtualDir!在这种情况下,CssRewriteUrlTransform 确实会将 URL 重写为 Host,而不是 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

为此,您必须派生 CssRewriteUrlTransform 以使其执行您需要的操作。这里有一个很好的讨论:ASP.NET MVC4 Bundling with Twitter Bootstrap

Seems the best answer is there:http://aspnetoptimization.codeplex.com/workitem/83

似乎最好的答案是: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

使用此类代替 CssRewriteUrlTransform

回答by Vilx-

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 CssRewriteUrlTransformdoes), but so far it holds...

我知道它远非完美,并且有很多边缘情况可能会出错(我不确定您是否可以首先使用正则表达式解析 CSS 文件 - 尽管这正是原始文件CssRewriteUrlTransform所做的),但是所以远它持有...

回答by Phan ???c Bi?nh

The 'CssRewriteUrlTransform' works just fine for applications that DOESN'T run on top of a virtual directory.

“CssRewriteUrlTransform”适用于不在虚拟目录之上运行的应用程序。

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

因此,如果您的应用程序在http://your-site.com/上运行,它运行得很好,但如果在http://your-site.com/your-app/ 上运行,您的所有图像都会有 404,因为默认的“CssFixRewriteUrlTransform”使用“/”引用您的图像。

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.

注意:用 .min.css 删除所有文件 css,因为如果不删除它不会修复。

回答by Chrisdreams13

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:

我对包含“数据”的 url 有问题,甚至还有一个内部的 url,所以我必须重新做正则表达式,这是我的解决方案:

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>(\|.)*?)\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

基于正则表达式:在引号之间抓取值