web-dev-qa-db-fra.com

CssRewriteUrlTransform avec ou sans répertoire virtuel

Nous utilisons MVC Bundling sur notre site, CssRewriteUrlTransform s'assure que les URL des images fonctionnent à partir du fichier css du bundle dynamique.

Mais cela ne fonctionne que lorsque vous n'utilisez pas de répertoire virtuel, c'est-à-dire

http://localhost/VirttualDir ne fonctionne pas mais http://localhost/ Est-ce que. En effet, la transformation CssRewriteUrlTransform ne prend pas en compte le dossier virtuel lors de la réécriture de l'URL. Donc, si un chemin réel d'image est localhost/vdir/content/img/foo.png il le réécrira dans localhost/content/img/foo.png ce qui est faux

61
Anders

Je ne suis pas sûr de bien comprendre votre problème, mais en voyant http://localhost ici semble mal. Vous ne devez jamais utiliser une URL absolue pour vos offres groupées.

Pour moi, CssRewriteUrlTransform fonctionne parfaitement, voici comment je l'utilise:

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

"Bundles" est virtuel.

Est-ce que cela aide?

Mise à jour

J'ai été confondu avec la chose "VirtualDir", car vous parlez de IIS VirtualDir, et je pensais Bundle VirtualDir! Il est vrai que dans ce cas CssRewriteUrlTransform réécrira les URL sur l'hôte, pas pour l'URI Host/VirtualDir.

Pour ce faire, vous devez dériver CssRewriteUrlTransform pour lui faire faire ce dont vous avez besoin. Il y a une bonne discussion ici: Bundle ASP.NET MVC4 avec Twitter Bootstrap

Semble la meilleure réponse est là: 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);           
    }
}

Utilisez cette classe au lieu de CssRewriteUrlTransform

92
BernardG

J'ai eu le même problème. Voici comment je l'ai corrigé:

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

Je sais que c'est loin d'être parfait et il y a beaucoup de cas Edge où cela peut mal tourner (je ne suis pas sûr que vous puissiez analyser un fichier CSS avec une expression régulière - bien que ce soit exactement ce que l'original CssRewriteUrlTransform le fait), mais jusqu'à présent, il tient ...

5
Vilx-

Le 'CssRewriteUrlTransform' fonctionne très bien pour les applications qui NE s'exécutent PAS au-dessus d'un répertoire virtuel.

Donc, si votre application fonctionne sur http://your-site.com/ elle fonctionne très bien, mais si elle fonctionne sur http://your-site.com/your-app / vous aurez 404 pour toutes vos images, car la valeur par défaut 'CssFixRewriteUrlTransform' fait référence à vos images avec un '/'.

Utilisez ceci:

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

Remarque: supprimez tous les fichiers css avec .min.css, car sinon, cela ne sera pas corrigé.

5

J'ai des problèmes avec une URL qui contient des "données" et même une URL interne à une autre, donc je dois refaire l'expression régulière, voici ma 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));
    }
}

basé sur RegEx: saisie des valeurs entre guillemets

0
Chrisdreams13