69

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

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

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

4

4 回答 4

106

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

对我来说 CssRewriteUrlTransform 工作得很好,我是这样使用它的:

bundles.Add(new StyleBundle("~/bundles/css").Include(
                "~/Content/css/*.css", new CssRewriteUrlTransform()));

“捆绑”是虚拟的。

这有帮助吗?

更新

当您谈论 IIS VirtualDir 时,我对“VirtualDir”的事情感到困惑,我在想 Bundle VirtualDir!确实,在这种情况下,CssRewriteUrlTransform 会将 URL 重写到 Host,而不是 Host/VirtualDir URI。

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

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

使用此类而不是 CssRewriteUrlTransform

于 2013-11-04T10:06:08.717 回答
6

我有同样的问题。这就是我修复它的方法:

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) + ")");
    }
}

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

于 2013-11-04T10:16:37.143 回答
5

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

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

用这个:

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));
    }
}

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

于 2015-04-20T07:42:58.383 回答
0

我对包含“数据”的 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>(\\\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));
    }
}

基于RegEx:在引号之间抓取值

于 2016-08-10T15:03:58.697 回答