MVC4 StyleBundle no resuelve las imágenes

Mi pregunta es similar a esto:

Miniatura e imágenes de fondo de ASP.NET MVC 4

Excepto que quiero seguir con el paquete de MVC si puedo. Estoy teniendo un accidente cerebrovascular tratando de averiguar cuál es el patrón correcto para especificar los paquetes de estilos, de modo que funcionen los css independientes y los conjuntos de imágenes como jQuery UI.

Tengo una estructura de sitio MVC típica con /Content/css/ que contiene mi base CSS como styles.css . Dentro de esa carpeta css también tengo subcarpetas como /jquery-ui que contiene su archivo CSS más una carpeta /images . Las rutas de imagen en jQuery UI CSS son relativas a esa carpeta y no quiero meterme con ellas.

Tal como lo entiendo, cuando especifico un StyleBundle , necesito especificar una ruta virtual que no coincida con una ruta de contenido real, porque (suponiendo que ignoro las rutas hacia el Contenido), IIS intentaría resolver esa ruta como un archivo físico. . Así que estoy especificando:

 bundles.Add(new StyleBundle("~/Content/styles/jquery-ui") .Include("~/Content/css/jquery-ui/*.css")); 

representado usando:

 @Styles.Render("~/Content/styles/jquery-ui") 

Puedo ver la solicitud de salida a:

 http://localhost/MySite/Content/styles/jquery-ui?v=nL_6HPFtzoqrts9nwrtjq0VQFYnhMjY5EopXsK8cxmg1 

Esto devuelve la respuesta CSS correcta y miniaturizada. Pero luego el navegador envía una solicitud de una imagen relativamente vinculada como:

 http://localhost/MySite/Content/styles/images/ui-bg_highlight-soft_100_eeeeee_1x100.png 

Que es un 404 .

Entiendo que la última parte de mi URL jquery-ui es una URL sin extensión, un controlador para mi paquete, por lo que puedo ver por qué la solicitud relativa para la imagen es simplemente /styles/images/ .

Entonces mi pregunta es ¿cuál es la forma correcta de manejar esta situación?

De acuerdo con este hilo en MVC4 css bundling y referencias de imágenes , si define su paquete como:

 bundles.Add(new StyleBundle("~/Content/css/jquery-ui/bundle") .Include("~/Content/css/jquery-ui/*.css")); 

Cuando defina el paquete en la misma ruta que los archivos fuente que formaron el paquete, las rutas relativas de la imagen seguirán funcionando. La última parte de la ruta del paquete es realmente el file name del file name para ese paquete específico (es decir, /bundle puede ser cualquier nombre que desee).

Esto solo funcionará si está agrupando CSS de la misma carpeta (lo cual creo que tiene sentido desde una perspectiva de agrupamiento).

Actualizar

Según el siguiente comentario de @Hao Kung, alternativamente, esto ahora puede lograrse aplicando una CssRewriteUrlTransformation ( Cambie las referencias URL relativas a los archivos CSS cuando se incluyen ).

NOTA: No he confirmado los comentarios sobre problemas con la reescritura en rutas absolutas dentro de un directorio virtual, por lo que es posible que esto no funcione para todos (?).

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

La solución de Grinn / ThePirat funciona bien.

No me gustó que haya actualizado el método Include en el paquete, y que haya creado archivos temporales en el directorio de contenido. (terminaron siendo controlados, implementados, ¡entonces el servicio no se inició!)

Entonces, para seguir el diseño de Bundling, elegí realizar esencialmente el mismo código, pero en una implementación de IBundleTransform:

 class StyleRelativePathTransform : IBundleTransform { public StyleRelativePathTransform() { } public void Process(BundleContext context, BundleResponse response) { response.Content = String.Empty; Regex pattern = new Regex(@"url\s*\(\s*([""']?)([^:)]+)\1\s*\)", RegexOptions.IgnoreCase); // open each of the files foreach (FileInfo cssFileInfo in response.Files) { if (cssFileInfo.Exists) { // apply the RegEx to the file (to change relative paths) string contents = File.ReadAllText(cssFileInfo.FullName); MatchCollection matches = pattern.Matches(contents); // Ignore the file if no match if (matches.Count > 0) { string cssFilePath = cssFileInfo.DirectoryName; string cssVirtualPath = context.HttpContext.RelativeFromAbsolutePath(cssFilePath); foreach (Match match in matches) { // this is a path that is relative to the CSS file string relativeToCSS = match.Groups[2].Value; // combine the relative path to the cssAbsolute string absoluteToUrl = Path.GetFullPath(Path.Combine(cssFilePath, relativeToCSS)); // make this server relative string serverRelativeUrl = context.HttpContext.RelativeFromAbsolutePath(absoluteToUrl); string quote = match.Groups[1].Value; string replace = String.Format("url({0}{1}{0})", quote, serverRelativeUrl); contents = contents.Replace(match.Groups[0].Value, replace); } } // copy the result into the response. response.Content = String.Format("{0}\r\n{1}", response.Content, contents); } } } } 

Y luego envuelto esto en una Implementación de paquete:

 public class StyleImagePathBundle : Bundle { public StyleImagePathBundle(string virtualPath) : base(virtualPath) { base.Transforms.Add(new StyleRelativePathTransform()); base.Transforms.Add(new CssMinify()); } public StyleImagePathBundle(string virtualPath, string cdnPath) : base(virtualPath, cdnPath) { base.Transforms.Add(new StyleRelativePathTransform()); base.Transforms.Add(new CssMinify()); } } 

Uso de la muestra:

 static void RegisterBundles(BundleCollection bundles) { ... bundles.Add(new StyleImagePathBundle("~/bundles/Bootstrap") .Include( "~/Content/css/bootstrap.css", "~/Content/css/bootstrap-responsive.css", "~/Content/css/jquery.fancybox.css", "~/Content/css/style.css", "~/Content/css/error.css", "~/Content/validation.css" )); 

Aquí está mi método de extensión para RelativeFromAbsolutePath:

  public static string RelativeFromAbsolutePath(this HttpContextBase context, string path) { var request = context.Request; var applicationPath = request.PhysicalApplicationPath; var virtualDir = request.ApplicationPath; virtualDir = virtualDir == "/" ? virtualDir : (virtualDir + "/"); return path.Replace(applicationPath, virtualDir).Replace(@"\", "/"); } 

Mejor aún (IMHO) implementar un paquete personalizado que corrige las rutas de las imágenes. Escribí uno para mi aplicación.

 using System; using System.Collections.Generic; using IO = System.IO; using System.Linq; using System.Text.RegularExpressions; using System.Web; using System.Web.Optimization; 

 public class StyleImagePathBundle : Bundle { public StyleImagePathBundle(string virtualPath) : base(virtualPath, new IBundleTransform[1] { (IBundleTransform) new CssMinify() }) { } public StyleImagePathBundle(string virtualPath, string cdnPath) : base(virtualPath, cdnPath, new IBundleTransform[1] { (IBundleTransform) new CssMinify() }) { } public new Bundle Include(params string[] virtualPaths) { if (HttpContext.Current.IsDebuggingEnabled) { // Debugging. Bundling will not occur so act normal and no one gets hurt. base.Include(virtualPaths.ToArray()); return this; } // In production mode so CSS will be bundled. Correct image paths. var bundlePaths = new List(); var svr = HttpContext.Current.Server; foreach (var path in virtualPaths) { var pattern = new Regex(@"url\s*\(\s*([""']?)([^:)]+)\1\s*\)", RegexOptions.IgnoreCase); var contents = IO.File.ReadAllText(svr.MapPath(path)); if(!pattern.IsMatch(contents)) { bundlePaths.Add(path); continue; } var bundlePath = (IO.Path.GetDirectoryName(path) ?? string.Empty).Replace(@"\", "/") + "/"; var bundleUrlPath = VirtualPathUtility.ToAbsolute(bundlePath); var bundleFilePath = String.Format("{0}{1}.bundle{2}", bundlePath, IO.Path.GetFileNameWithoutExtension(path), IO.Path.GetExtension(path)); contents = pattern.Replace(contents, "url($1" + bundleUrlPath + "$2$1)"); IO.File.WriteAllText(svr.MapPath(bundleFilePath), contents); bundlePaths.Add(bundleFilePath); } base.Include(bundlePaths.ToArray()); return this; } } 

Para usarlo, hazlo:

 bundles.Add(new StyleImagePathBundle("~/bundles/css").Include( "~/This/Is/Some/Folder/Path/layout.css")); 

…en lugar de…

 bundles.Add(new StyleBundle("~/bundles/css").Include( "~/This/Is/Some/Folder/Path/layout.css")); 

Lo que hace es (cuando no está en modo de depuración) busca url() y lo reemplaza con url() . Lo escribí hace 10 segundos, por lo que podría necesitar un pequeño ajuste. Tomé en cuenta las URL totalmente calificadas y las URL de datos de base64 al asegurarme de que no haya dos puntos (:) en la ruta de la URL. En nuestro entorno, las imágenes normalmente residen en la misma carpeta que sus archivos css, pero lo he probado con las dos carpetas principales ( url(../someFile.png) ) y carpetas secundarias ( url(someFolder/someFile.png ).

No es necesario especificar una transformación o tener rutas de subdirectorios locos. Después de mucha resolución de problemas lo aislé de esta regla “simple” (¿es un error?) …

Si la ruta del paquete no comienza con la raíz relativa de los elementos que se incluyen, entonces la raíz de la aplicación web no se tendrá en cuenta.

Suena como un error más para mí, pero de todos modos así es como lo arreglas con la versión actual de .NET 4.51. Quizás las otras respuestas fueron necesarias en versiones anteriores de ASP.NET, no puedo decir que no tengo tiempo para probarlas todo de manera retrospectiva.

Para aclarar, aquí hay un ejemplo:

Tengo estos archivos …

 ~/Content/Images/Backgrounds/Some_Background_Tile.gif ~/Content/Site.css - references the background image relatively, ie background: url('Images/...') 

Luego configura el paquete como …

 BundleTable.Add(new StyleBundle("~/Bundles/Styles").Include("~/Content/Site.css")); 

Y renderíalo como …

 @Styles.Render("~/Bundles/Styles") 

Y obtener el “comportamiento” (error), los archivos CSS tienen la raíz de la aplicación (por ejemplo, “http: // localhost: 1234 / MySite / Content / Site.css”) pero la imagen CSS dentro de todo comienza “/ Content / Images / … “o” / Images / … “dependiendo de si agrego la transformación o no.

Incluso intentó crear la carpeta “Bundles” para ver si tenía que ver con la ruta existente o no, pero eso no cambió nada. La solución al problema es realmente el requisito de que el nombre del paquete debe comenzar con la ruta raíz.

Lo que significa que este ejemplo se soluciona registrando y renderizando la ruta del paquete como …

 BundleTable.Add(new StyleBundle("~/Content/StylesBundle").Include("~/Content/Site.css")); ... @Styles.Render("~/Content/StylesBundle") 

Así que, por supuesto, podría decir que se trata de RTFM, pero estoy bastante seguro de que yo y otros recogimos esta ruta “~ / Bundles / …” desde la plantilla predeterminada o en algún lugar de la documentación en el sitio web MSDN o ASP.NET, o acaba de tropezar con él porque en realidad es un nombre bastante lógico para una ruta virtual y tiene sentido elegir rutas virtuales que no entren en conflicto con los directorios reales.

De todos modos, esa es la forma en que es. Microsoft no ve ningún error. No estoy de acuerdo con esto, o bien debería funcionar como se esperaba o se debería lanzar alguna excepción, o una anulación adicional para agregar la ruta del paquete que opta por incluir la raíz de la aplicación o no. No puedo imaginar por qué alguien no querría incluir la raíz de la aplicación cuando la hay (normalmente, a menos que haya instalado su sitio web con un alias DNS / raíz del sitio web predeterminado). De hecho, ese debería ser el valor predeterminado de todos modos.

Descubrí que CssRewriteUrlTransform no se ejecuta si hace referencia a un archivo *.min.css y tiene el archivo *.min.css asociado en la misma carpeta.

Para solucionar esto, elimine el archivo *.min.css o *.min.css directamente en su paquete:

 bundles.Add(new Bundle("~/bundles/bootstrap") .Include("~/Libs/bootstrap3/css/bootstrap.min.css", new CssRewriteUrlTransform())); 

Después de hacer eso, sus URL se transformarán correctamente y sus imágenes se resolverán correctamente.

Aunque la respuesta de Chris Baxter ayuda con el problema original, no funciona en mi caso cuando la aplicación está alojada en un directorio virtual . Después de investigar las opciones, terminé con la solución de bricolaje.

ProperStyleBundle clase ProperStyleBundle incluye código tomado de CssRewriteUrlTransform original para transformar adecuadamente las rutas relativas dentro del directorio virtual. También arroja si el archivo no existe e impide el reordenamiento de los archivos en el paquete (código tomado de BetterStyleBundle ).

 using System; using System.Collections.Generic; using System.IO; using System.Text.RegularExpressions; using System.Web; using System.Web.Optimization; using System.Linq; namespace MyNamespace { public class ProperStyleBundle : StyleBundle { public override IBundleOrderer Orderer { get { return new NonOrderingBundleOrderer(); } set { throw new Exception( "Unable to override Non-Ordered bundler" ); } } public ProperStyleBundle( string virtualPath ) : base( virtualPath ) {} public ProperStyleBundle( string virtualPath, string cdnPath ) : base( virtualPath, cdnPath ) {} public override Bundle Include( params string[] virtualPaths ) { foreach ( var virtualPath in virtualPaths ) { this.Include( virtualPath ); } return this; } public override Bundle Include( string virtualPath, params IItemTransform[] transforms ) { var realPath = System.Web.Hosting.HostingEnvironment.MapPath( virtualPath ); if( !File.Exists( realPath ) ) { throw new FileNotFoundException( "Virtual path not found: " + virtualPath ); } var trans = new List( transforms ).Union( new[] { new ProperCssRewriteUrlTransform( virtualPath ) } ).ToArray(); return base.Include( virtualPath, trans ); } // This provides files in the same order as they have been added. private class NonOrderingBundleOrderer : IBundleOrderer { public IEnumerable OrderFiles( BundleContext context, IEnumerable files ) { return files; } } private class ProperCssRewriteUrlTransform : IItemTransform { private readonly string _basePath; public ProperCssRewriteUrlTransform( string basePath ) { _basePath = basePath.EndsWith( "/" ) ? basePath : VirtualPathUtility.GetDirectory( basePath ); } public string Process( string includedVirtualPath, string input ) { if ( includedVirtualPath == null ) { throw new ArgumentNullException( "includedVirtualPath" ); } return ConvertUrlsToAbsolute( _basePath, input ); } private static string RebaseUrlToAbsolute( string baseUrl, string url ) { if ( string.IsNullOrWhiteSpace( url ) || string.IsNullOrWhiteSpace( baseUrl ) || url.StartsWith( "/", StringComparison.OrdinalIgnoreCase ) || url.StartsWith( "data:", StringComparison.OrdinalIgnoreCase ) ) { return url; } if ( !baseUrl.EndsWith( "/", StringComparison.OrdinalIgnoreCase ) ) { baseUrl = baseUrl + "/"; } return VirtualPathUtility.ToAbsolute( baseUrl + url ); } private static string ConvertUrlsToAbsolute( string baseUrl, string content ) { if ( string.IsNullOrWhiteSpace( content ) ) { return content; } return new Regex( "url\\(['\"]?(?[^)]+?)['\"]?\\)" ) .Replace( content, ( match => "url(" + RebaseUrlToAbsolute( baseUrl, match.Groups["url"].Value ) + ")" ) ); } } } } 

Úselo como StyleBundle :

 bundles.Add( new ProperStyleBundle( "~/styles/ui" ) .Include( "~/Content/Themes/cm_default/style.css" ) .Include( "~/Content/themes/custom-theme/jquery-ui-1.8.23.custom.css" ) .Include( "~/Content/DataTables-1.9.4/media/css/jquery.dataTables.css" ) .Include( "~/Content/DataTables-1.9.4/extras/TableTools/media/css/TableTools.css" ) ); 

Tal vez estoy predispuesto, pero me gusta bastante mi solución ya que no hace ninguna transformación, expresiones regulares etc. y tiene la menor cantidad de código 🙂

Esto funciona para un sitio alojado como un directorio virtual en un sitio web de IIS y como un sitio web raíz en IIS.

Así que creé una Implementación de IItemTransform encapsulada en CssRewriteUrlTransform y usé VirtualPathUtility para arreglar la ruta y llamar al código existente:

 ///  /// Is a wrapper class over CssRewriteUrlTransform to fix url's in css files for sites on IIS within Virutal Directories /// and sites at the Root level ///  public class CssUrlTransformWrapper : IItemTransform { private readonly CssRewriteUrlTransform _cssRewriteUrlTransform; public CssUrlTransformWrapper() { _cssRewriteUrlTransform = new CssRewriteUrlTransform(); } public string Process(string includedVirtualPath, string input) { return _cssRewriteUrlTransform.Process("~" + VirtualPathUtility.ToAbsolute(includedVirtualPath), input); } } //App_Start.cs public static void Start() { BundleTable.Bundles.Add(new StyleBundle("~/bundles/fontawesome") .Include("~/content/font-awesome.css", new CssUrlTransformWrapper())); } 

¿Parece funcionar bien para mi?

A partir de v1.1.0-alpha1 (paquete de prelanzamiento), la infraestructura utiliza VirtualPathProvider para acceder a los archivos en lugar de tocar el sistema de archivos físicos.

El transformador actualizado se puede ver a continuación:

 public class StyleRelativePathTransform : IBundleTransform { public void Process(BundleContext context, BundleResponse response) { Regex pattern = new Regex(@"url\s*\(\s*([""']?)([^:)]+)\1\s*\)", RegexOptions.IgnoreCase); response.Content = string.Empty; // open each of the files foreach (var file in response.Files) { using (var reader = new StreamReader(file.Open())) { var contents = reader.ReadToEnd(); // apply the RegEx to the file (to change relative paths) var matches = pattern.Matches(contents); if (matches.Count > 0) { var directoryPath = VirtualPathUtility.GetDirectory(file.VirtualPath); foreach (Match match in matches) { // this is a path that is relative to the CSS file var imageRelativePath = match.Groups[2].Value; // get the image virtual path var imageVirtualPath = VirtualPathUtility.Combine(directoryPath, imageRelativePath); // convert the image virtual path to absolute var quote = match.Groups[1].Value; var replace = String.Format("url({0}{1}{0})", quote, VirtualPathUtility.ToAbsolute(imageVirtualPath)); contents = contents.Replace(match.Groups[0].Value, replace); } } // copy the result into the response. response.Content = String.Format("{0}\r\n{1}", response.Content, contents); } } } } 

Aquí hay una Transformada de paquete que reemplazará urls css con urls relativas a ese archivo css. Solo agrégalo a tu paquete y debería solucionar el problema.

 public class CssUrlTransform: IBundleTransform { public void Process(BundleContext context, BundleResponse response) { Regex exp = new Regex(@"url\([^\)]+\)", RegexOptions.IgnoreCase | RegexOptions.Singleline); foreach (FileInfo css in response.Files) { string cssAppRelativePath = css.FullName.Replace(context.HttpContext.Request.PhysicalApplicationPath, context.HttpContext.Request.ApplicationPath).Replace(Path.DirectorySeparatorChar, '/'); string cssDir = cssAppRelativePath.Substring(0, cssAppRelativePath.LastIndexOf('/')); response.Content = exp.Replace(response.Content, m => TransformUrl(m, cssDir)); } } private string TransformUrl(Match match, string cssDir) { string url = match.Value.Substring(4, match.Length - 5).Trim('\'', '"'); if (url.StartsWith("http://") || url.StartsWith("data:image")) return match.Value; if (!url.StartsWith("/")) url = string.Format("{0}/{1}", cssDir, url); return string.Format("url({0})", url); } } 

Otra opción sería usar el módulo Reescribir URL de IIS para asignar la carpeta de imágenes del paquete virtual a la carpeta de imágenes físicas. A continuación se muestra un ejemplo de una regla de reescritura que puede usar para un paquete llamado “~ / bundles / yourpage / styles”: tenga en cuenta que la expresión regular coincide con los caracteres alfanuméricos y los guiones, guiones bajos y puntos, que son comunes en los nombres de los archivos de imagen .

         

Este enfoque crea una pequeña sobrecarga adicional, pero le permite tener más control sobre los nombres de sus paquetes, y también reduce el número de paquetes que puede tener que hacer referencia en una página. Por supuesto, si tiene que hacer referencia a múltiples archivos css de terceros que contienen referencias de ruta de imagen relativa, aún no puede evitar la creación de múltiples paquetes.

La solución Grinn es genial.

Sin embargo, no funciona para mí cuando hay referencias relativas a la carpeta principal en la url. es decir, url('../../images/car.png')

Por lo tanto, modifiqué ligeramente el método Include para resolver las rutas para cada coincidencia de expresiones regex, permitiendo rutas relativas y también incrustando opcionalmente las imágenes en el CSS.

También cambié el IF DEBUG para comprobar BundleTable.EnableOptimizations lugar de HttpContext.Current.IsDebuggingEnabled .

  public new Bundle Include(params string[] virtualPaths) { if (!BundleTable.EnableOptimizations) { // Debugging. Bundling will not occur so act normal and no one gets hurt. base.Include(virtualPaths.ToArray()); return this; } var bundlePaths = new List(); var server = HttpContext.Current.Server; var pattern = new Regex(@"url\s*\(\s*([""']?)([^:)]+)\1\s*\)", RegexOptions.IgnoreCase); foreach (var path in virtualPaths) { var contents = File.ReadAllText(server.MapPath(path)); var matches = pattern.Matches(contents); // Ignore the file if no matches if (matches.Count == 0) { bundlePaths.Add(path); continue; } var bundlePath = (System.IO.Path.GetDirectoryName(path) ?? string.Empty).Replace(@"\", "/") + "/"; var bundleUrlPath = VirtualPathUtility.ToAbsolute(bundlePath); var bundleFilePath = string.Format("{0}{1}.bundle{2}", bundlePath, System.IO.Path.GetFileNameWithoutExtension(path), System.IO.Path.GetExtension(path)); // Transform the url (works with relative path to parent folder "../") contents = pattern.Replace(contents, m => { var relativeUrl = m.Groups[2].Value; var urlReplace = GetUrlReplace(bundleUrlPath, relativeUrl, server); return string.Format("url({0}{1}{0})", m.Groups[1].Value, urlReplace); }); File.WriteAllText(server.MapPath(bundleFilePath), contents); bundlePaths.Add(bundleFilePath); } base.Include(bundlePaths.ToArray()); return this; } private string GetUrlReplace(string bundleUrlPath, string relativeUrl, HttpServerUtility server) { // Return the absolute uri Uri baseUri = new Uri("http://dummy.org"); var absoluteUrl = new Uri(new Uri(baseUri, bundleUrlPath), relativeUrl).AbsolutePath; var localPath = server.MapPath(absoluteUrl); if (IsEmbedEnabled && File.Exists(localPath)) { var fi = new FileInfo(localPath); if (fi.Length < 0x4000) { // Embed the image in uri string contentType = GetContentType(fi.Extension); if (null != contentType) { var base64 = Convert.ToBase64String(File.ReadAllBytes(localPath)); // Return the serialized image return string.Format("data:{0};base64,{1}", contentType, base64); } } } // Return the absolute uri return absoluteUrl; } 

Espero que ayude, saludos.

Simplemente puede agregar otro nivel de profundidad a la ruta de su paquete virtual

  //Two levels deep bundle path so that paths are maintained after minification bundles.Add(new StyleBundle("~/Content/css/css").Include("~/Content/bootstrap/bootstrap.css", "~/Content/site.css")); 

Esta es una respuesta de muy baja tecnología y una especie de truco, pero funciona y no requiere ningún procesamiento previo. Dada la longitud y la complejidad de algunas de estas respuestas, prefiero hacerlo de esta manera.

Tuve este problema con los paquetes que tienen una ruta de acceso incorrecta a las imágenes y CssRewriteUrlTransform no resolvió las rutas padre relativas .. correctamente (también hubo problemas con recursos externos como webfonts). Es por eso que escribí esta transformación personalizada (parece hacer todo lo anterior correctamente):

 public class CssRewriteUrlTransform2 : IItemTransform { public string Process(string includedVirtualPath, string input) { var pathParts = includedVirtualPath.Replace("~/", "/").Split('/'); pathParts = pathParts.Take(pathParts.Count() - 1).ToArray(); return Regex.Replace ( input, @"(url\(['""]?)((?:\/??\.\.)*)(.*?)(['""]?\))", m => { // Somehow assigning this to a variable is faster than directly returning the output var output = ( // Check if it's an aboslute url or base64 m.Groups[3].Value.IndexOf(':') == -1 ? ( m.Groups[1].Value + ( ( ( m.Groups[2].Value.Length > 0 || !m.Groups[3].Value.StartsWith('/') ) ) ? string.Join("/", pathParts.Take(pathParts.Count() - m.Groups[2].Value.Count(".."))) : "" ) + (!m.Groups[3].Value.StartsWith('/') ? "/" + m.Groups[3].Value : m.Groups[3].Value) + m.Groups[4].Value ) : m.Groups[0].Value ); return output; } ); } } 

Editar: No me di cuenta, pero utilicé algunos métodos de extensión personalizados en el código. El código fuente de esos es:

 ///  /// Based on: http://stackoverflow.com/a/11773674 ///  public static int Count(this string source, string substring) { int count = 0, n = 0; while ((n = source.IndexOf(substring, n, StringComparison.InvariantCulture)) != -1) { n += substring.Length; ++count; } return count; } public static bool StartsWith(this string source, char value) { if (source.Length == 0) { return false; } return source[0] == value; } 

Por supuesto, debería ser posible reemplazar String.StartsWith(char) con String.StartsWith(string) .

Después de poca investigación, concluí lo siguiente: Tienes 2 opciones:

  1. ir con transformaciones. Un paquete muy útil para esto: https://bundletransformer.codeplex.com/ necesita la siguiente transformación para cada paquete problemático:

     BundleResolver.Current = new CustomBundleResolver(); var cssTransformer = new StyleTransformer(); standardCssBundle.Transforms.Add(cssTransformer); bundles.Add(standardCssBundle); 

Advantages: of this solution, you can name your bundle whatever you want => you can combine css files into one bundle from different directories. Disadvantages: You need to transform every problematic bundle

  1. Use the same relative root for the name of the bundle like where the css file is located. Advantages: there is no need for transformation. Disadvantages: You have limitation on combining css sheets from different directories into one bundle.

CssRewriteUrlTransform fixed my problem.
If your code still not loading images after using CssRewriteUrlTransform , then change your css filename’s from:

 .Include("~/Content/jquery/jquery-ui-1.10.3.custom.css", new CssRewriteUrlTransform()) 

A:

 .Include("~/Content/jquery/jquery-ui.css", new CssRewriteUrlTransform()) 

Someway .(dots) are not recognizing in url.