首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >MVC4 StyleBundle不解析图像

MVC4 StyleBundle不解析图像
EN

Stack Overflow用户
提问于 2012-07-06 04:39:42
回答 16查看 107.5K关注 0票数 297

我的问题与此类似:

ASP.NET MVC 4小型化&背景图像

不过,如果可以的话,我想坚持MVC自己的捆绑。我的大脑崩溃了,试图找出指定样式包的正确模式,比如独立的css和图像集,比如jQuery UI工作。

我有一个典型的MVC站点结构与/Content/css/,其中包含我的基本CSS,如styles.css。在这个css文件夹中,我还有一些子文件夹,比如/jquery-ui,它包含它的CSS文件和一个/images文件夹。jQuery UI CSS中的图像路径相对于该文件夹,我不想弄乱它们。

据我所知,当我指定一个StyleBundle时,我需要指定一个与实际内容路径不匹配的虚拟路径,因为(假设我忽略了到内容的路由),IIS将尝试将该路径解析为一个物理文件。所以我要说的是:

代码语言:javascript
复制
bundles.Add(new StyleBundle("~/Content/styles/jquery-ui")
       .Include("~/Content/css/jquery-ui/*.css"));

使用:

代码语言:javascript
复制
@Styles.Render("~/Content/styles/jquery-ui")

我可以看到这样的请求:

代码语言:javascript
复制
http://localhost/MySite/Content/styles/jquery-ui?v=nL_6HPFtzoqrts9nwrtjq0VQFYnhMjY5EopXsK8cxmg1

这是返回正确的,小型化的CSS响应。但是,浏览器发送一个相对链接图像的请求如下:

代码语言:javascript
复制
http://localhost/MySite/Content/styles/images/ui-bg_highlight-soft_100_eeeeee_1x100.png

这是一个404

我知道我的URL的最后一部分是一个无扩展的jquery-ui,它是我的包的一个处理程序,所以我可以理解为什么对图像的相对请求只是/styles/images/

所以我的问题是处理这种情况的正确方法是什么?

EN

回答 16

Stack Overflow用户

回答已采纳

发布于 2012-07-08 21:47:21

根据MVC4 css捆绑和图像引用上的这个线程,如果您将包定义为:

代码语言:javascript
复制
bundles.Add(new StyleBundle("~/Content/css/jquery-ui/bundle")
                   .Include("~/Content/css/jquery-ui/*.css"));

在与组成包的源文件相同的路径上定义包时,相对图像路径仍然可以工作。包路径的最后一部分实际上是该特定包的file name (即,/bundle可以是您喜欢的任何名称)。

只有当您将CSS从同一个文件夹捆绑在一起时(我认为从捆绑的角度来看这是有意义的),这才能起作用。

更新

根据@Hao下面的评论,或者现在可以通过应用CssRewriteUrlTransformation (绑定时更改对CSS文件的相对URL引用)来实现这一点。

注意:我还没有确认关于重写虚拟目录中绝对路径的问题的评论,所以这可能并不适用于每个人(?)。

代码语言:javascript
复制
bundles.Add(new StyleBundle("~/Content/css/jquery-ui/bundle")
                   .Include("~/Content/css/jquery-ui/*.css",
                    new CssRewriteUrlTransform()));
票数 364
EN

Stack Overflow用户

发布于 2012-10-22 20:30:03

Grinn / ThePirat溶液工作良好。

我不喜欢它新增了包上的Include方法,并且它在内容目录中创建了临时文件。(他们最终会被签入、部署,这样服务就不会启动!)

因此,为了遵循捆绑的设计,我选择执行本质上相同的代码,但在IBundleTransform实现中::

代码语言:javascript
复制
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);
            }
        }
    }
}

然后将它封装在一个Bundle内嵌:

代码语言:javascript
复制
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());
    }
}

样本使用情况:

代码语言:javascript
复制
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"
            ));

下面是我对RelativeFromAbsolutePath的扩展方法:

代码语言:javascript
复制
   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(@"\", "/");
    }
票数 34
EN

Stack Overflow用户

发布于 2012-10-02 18:41:30

更好的是(IMHO)实现一个自定义绑定来修复图像路径。我为我的应用程序写了一个。

代码语言:javascript
复制
using System;
using System.Collections.Generic;
using IO = System.IO;
using System.Linq;
using System.Text.RegularExpressions;
using System.Web;
using System.Web.Optimization;

..。

代码语言:javascript
复制
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<string>();
        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;
    }

}

要使用它,请做:

代码语言:javascript
复制
bundles.Add(new StyleImagePathBundle("~/bundles/css").Include(
  "~/This/Is/Some/Folder/Path/layout.css"));

...instead的.

代码语言:javascript
复制
bundles.Add(new StyleBundle("~/bundles/css").Include(
  "~/This/Is/Some/Folder/Path/layout.css"));

它所做的是(当不处于调试模式时)查找url(<something>)并将其替换为url(<absolute\path\to\something>)。我大约10秒钟前就写了这个东西,所以可能需要稍微修改一下。通过确保URL路径中没有冒号(:),我考虑了完全限定的URL和base64数据URL。在我们的环境中,图像通常与它们的css文件位于同一个文件夹中,但我已经用父文件夹(url(../someFile.png))和子文件夹(url(someFolder/someFile.png)对其进行了测试。

票数 20
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/11355935

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档