web-dev-qa-db-ja.com

仮想ディレクトリの有無にかかわらずCssRewriteUrlTransform

私たちのサイトではMVC Bundlingを使用しています。CssRewriteUrlTransformは、画像のURLが動的バンドルcssファイルから機能することを確認します。

ただし、これは仮想ディレクトリを使用しない場合にのみ機能します。つまり、

http://localhost/VirttualDirは機能しませんが、http://localhost/は機能します。これは、URLを書き換えるときにCssRewriteUrlTransform tranformが仮想フォルダーを考慮しないためです。したがって、画像の実際のパスがlocalhost/vdir/content/img/foo.pngの場合、localhost/content/img/foo.pngに書き換えられますが、これは間違っています

61
Anders

あなたの問題を完全に理解しているのかどうかはわかりませんが、http://localhostここは間違っているようです。バンドルに絶対URLを使用しないでください。

私にとってCssRewriteUrlTransformは完璧に動作します、私はそれをどのように使用するかです:

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

「バンドル」は仮想です。

これは役立ちますか?

更新

IIS VirtualDirについて話しているように、私は "VirtualDir"の事と混同しました、そして私はBundle VirtualDirを考えていました!この場合、 Host/VirtualDir URI。

そのためには、CssRewriteUrlTransformを派生させて、必要な処理を実行する必要があります。ここに良い議論があります: ASP.NET MVC4 Bundling with Twitter Bootstrap

そこに最良の答えがあるようです: http://aspnetoptimization.codeplex.com/workitem/8

public class CssRewriteUrlTransformWrapper : IItemTransform
{
    public string Process(string includedVirtualPath, string input)
    {           
        return new CssRewriteUrlTransform().Process("~" + VirtualPathUtility.ToAbsolute(includedVirtualPath), input);           
    }
}

CssRewriteUrlTransformの代わりにこのクラスを使用します

92
BernardG

同じ問題がありました。これは私がそれを修正した方法です:

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はそうです)、しかし今のところは...

5
Vilx-

「CssRewriteUrlTransform」は、仮想ディレクトリ上で実行しないアプリケーションに対しては正常に機能します。

したがって、アプリが http://your-site.com/ で実行される場合は問題なく実行されますが、 http://your-site.com/your-appで実行される場合は、 / デフォルトの「CssFixRewriteUrlTransform」は「/」を使用して画像を参照しているため、すべての画像に404が設定されます。

これを使って:

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を削除します。削除しないと修正されないためです。

5

「データ」と別の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:引用符で囲まれた値の取得 に基づく

0
Chrisdreams13