CssRewriteUrlTransform с виртуальным каталогом или без него
Мы используем объединение MVC на нашем сайте, CssRewriteUrlTransform
гарантирует, что URL-адреса изображений будут работать из файла css динамического пакета.
Но это работает только при использовании виртуального каталога, т.е.
http://localhost/VirttualDir
не работает, но http://localhost/
делает. Это связано с тем, что tranform CssRewriteUrlTransform
не учитывает виртуальную папку при переписывании URL-адреса. Поэтому, если реальный путь изображения localhost/vdir/content/img/foo.png
, он перепишет его на localhost/content/img/foo.png
, что неверно
Ответы
Ответ 1
Я не уверен, чтобы полностью понять вашу проблему, но видеть http://localhost
здесь кажется неправильным. Вы никогда не должны использовать абсолютный URL для своих пакетов.
Для меня CssRewriteUrlTransform работает отлично, вот как я его использую:
bundles.Add(new StyleBundle("~/bundles/css").Include(
"~/Content/css/*.css", new CssRewriteUrlTransform()));
"Связки" является виртуальным.
Помогает ли это?
Update
Я был замешан в "VirtualDir", поскольку вы говорите об IIS VirtualDir, и я думал о Bundle VirtualDir! Верно, что в этом случае CssRewriteUrlTransform будет переписывать URL-адреса на хост, а не на URI хоста /VirtualDir.
Чтобы сделать это, вы должны получить CssRewriteUrlTransform, чтобы заставить его делать то, что вам нужно.
Здесь есть хорошая дискуссия: ASP.NET MVC4 Объединение с Twitter-загрузкой
Кажется, лучший ответ: 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
Ответ 2
"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));
}
}
Примечание. Удалите весь файл css с .min.css, потому что, если он не исправляется.
Ответ 3
У меня была та же проблема. Вот как я его исправил:
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
делает), но до сих пор он держится...
Ответ 4
У меня проблемы с 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: захват значений между кавычками