私たちのサイトではMVC Bundlingを使用しています。CssRewriteUrlTransform
は、画像のURLが動的バンドルcssファイルから機能することを確認します。
ただし、これは仮想ディレクトリを使用しない場合にのみ機能します。つまり、
http://localhost/VirttualDir
は機能しませんが、http://localhost/
は機能します。これは、URLを書き換えるときにCssRewriteUrlTransform
tranformが仮想フォルダーを考慮しないためです。したがって、画像の実際のパスがlocalhost/vdir/content/img/foo.png
の場合、localhost/content/img/foo.png
に書き換えられますが、これは間違っています
あなたの問題を完全に理解しているのかどうかはわかりませんが、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の代わりにこのクラスを使用します
同じ問題がありました。これは私がそれを修正した方法です:
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
はそうです)、しかし今のところは...
「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を削除します。削除しないと修正されないためです。
「データ」と別の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:引用符で囲まれた値の取得 に基づく