MVC Bundling and Minification: converts embedded images to to URL paths
Asked Answered
C

4

28

In my MVC5.1 project I'm using bundling and minification with CSS rewriting transformation:

styleBundle.Include("~/Content/Site.css", new CssRewriteUrlTransform());
bundles.Add(styleBundle);

CssRewriteUrlTransform converts image paths relative to the root of the site. But, when I images embedded into css:

span.file {
  background-image: url(data:image/png;base64,iVBORw0KGg+...2AAAAElFTkSuQmCC);
}

this is getting translated into

span.file {
  background-image: url(http://localhost:52253/Content/data:image/png;base64,iVBORg...mCC);
}

And obviously ~/Content/data:image/png;base64... does not exist.

Any way to stop this happening, other than update CSS files to not include embedded images? Or separate into different CSS files, where with actual URL are used and URL-transform this files. And another css with only embedded images.

Chaw answered 19/2, 2014 at 11:14 Comment(0)
C
14

Scrap that question. This is a known bug. Currently work around is to separate your css into embedded images and images via url.

Vote for these work-items: https://aspnetoptimization.codeplex.com/workitem/88 and https://aspnetoptimization.codeplex.com/workitem/108

Chaw answered 19/2, 2014 at 11:19 Comment(1)
See my answer below with a fix wrapped up in a NuGet package for quick install.Imbroglio
I
8

Checkout my workaround which I've 'bundled' nicely into a NuGet package. https://github.com/benmccallum/AspNetBundling

Otherwise just upgrade to grunt/gulp ;)

Imbroglio answered 13/3, 2015 at 12:35 Comment(0)
C
6

If you don't want to extract the embedded images to actual files and you can't wait for a new version of the Microsoft.AspNet.Web.Optimization nuget, you can use the following class.

It's a verbatim copy of CssRewriteUrlTransform except it ignores (crudely ;)) URL's with the data URI syntax.

Gist: https://gist.github.com/janv8000/fa69b2ab6886f635e3df

/// <remarks>Part of Microsoft.AspNet.Web.Optimization.1.1.3, forked to ignore data-uri</remarks>
public class CssRewriteUrlTransformIgnoringDataUri : IItemTransform
{
    internal 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 = baseUrl + "/";
        return VirtualPathUtility.ToAbsolute(baseUrl + url);
    }

    internal static string ConvertUrlsToAbsolute(string baseUrl, string content)
    {
        if (string.IsNullOrWhiteSpace(content))
        { return content; }

        return new Regex("url\\(['\"]?(?<url>[^)]+?)['\"]?\\)").Replace(content, match =>
        {
            var format = match.Groups["url"].Value;
            if (format.StartsWith("data:image", StringComparison.CurrentCultureIgnoreCase))
            {
                return format;
            }

            return "url(" + RebaseUrlToAbsolute(baseUrl, format) + ")";
        });
    }

    public string Process(string includedVirtualPath, string input)
    {
        if (includedVirtualPath == null)
        {
            throw new ArgumentNullException("includedVirtualPath");
        }
        return ConvertUrlsToAbsolute(VirtualPathUtility.GetDirectory(includedVirtualPath.Substring(1)), input);
    }
}
Cyclo answered 11/7, 2014 at 13:44 Comment(2)
Nice one! Send them a pull request, will do a lot good for the entire community!Chaw
Sorry but it doesn't work. It converts "url('data:image" to data:image without the prefix "url(" . On the other hand, the exception logic should be done on RebaseUrlToAbsolute instead of ConvertUrlsToAbsolute. This other class works for me: github.com/benmccallum/AspNetBundling/blob/master/…Gimpel
M
1

We were facing the same issue for asp.net mvc with angular project. Issue was for ag-grid base 64 image which was not showing in prod environment.

As a workaround we have removed CssRewriteUrlTransform() & changed the virtual path to match with actual physical path.

Old code
bundles.Add(new StyleBundle("~/bundles/styles").Include("~/Content/Site.css", new CssRewriteUrlTransform());

New code change
bundles.Add(new StyleBundle("~/dist/styles").Include("~/Content/Site.css");

Initially base64 image was looking for bundles folder which was not existing.

Old
background: transparent url(data:image/svg+xml;base64,PHN2ZyB3a...)

was translated to

background: transparent url(/dist/data:image/svg+xml;base64,PHN2ZyB3a...)

After making the mentioned changes base 64 image was not appended with any path.

Mignonmignonette answered 9/1, 2019 at 9:3 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.