Home Php C# Sql C C++ Javascript Python Java Go Android Git Linux Asp.net Django .net Node.js Ios Xcode Cocoa Iphone Mysql Tomcat Mongodb Bash Objective-c Scala Visual-studio Apache Elasticsearch Jar Eclipse Jquery Ruby-on-rails Ruby Rubygems Android-studio Spring Lua Sqlite Emacs Ubuntu Perl Docker Swift Amazon-web-services Svn Html Ajax Xml Java-ee Maven Intellij-idea Rvm Macos Unix Css Ipad Postgresql Css3 Json Windows-server Vue.js Typescript Oracle Hibernate Internet-explorer Github Tensorflow Laravel Symfony Redis Html5 Google-app-engine Nginx Firefox Sqlalchemy Lucene Erlang Flask Vim Solr Webview Facebook Zend-framework Virtualenv Nosql Ide Twitter Safari Flutter Bundle Phonegap Centos Sphinx Actionscript Tornado Register | Login | Edit Tags | New Questions | 繁体 | 简体


10 questions online user: 19

463
votes
answers
41 views
+10

MVC4 StyleBundle not resolving images

My question is similar to this:

ASP.NET MVC 4 Minification & Background Images

Except that I want to stick with MVC's own bundling if I can. I'm having a brain crash trying to figure out what the correct pattern is for specifying style bundles such that standalone css and image sets such as jQuery UI work.

I have a typical MVC site structure with /Content/css/ which contains my base CSS such as styles.css. Within that css folder I also have subfolders such as /jquery-ui which contains its CSS file plus an /images folder. Image paths in the jQuery UI CSS are relative to that folder and I don't want to mess with them.

As I understand it, when I specify a StyleBundle I need to specify a virtual path which does not also match a real content path, because (assuming I'm ignoring routes to Content) IIS would then try to resolve that path as a physical file. So I'm specifying:

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

rendered using:

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

I can see the request going out to:

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

This is returning the correct, minified CSS response. But then the browser sends a request for a relatively linked image as:

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

Which is a 404.

I understand that the last part of my URL jquery-ui is an extensionless URL, a handler for my bundle, so I can see why the relative request for the image is simply /styles/images/.

So my question is what is the correct way of handling this situation?

up vote 356 down vote accepted favorite
沙发
+3560
+50

According to this thread on MVC4 css bundling and image references, if you define your bundle as:

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

Where you define the bundle on the same path as the source files that made up the bundle, the relative image paths will still work. The last part of the bundle path is really the file name for that specific bundle (i.e., /bundle can be any name you like).

This will only work if you are bundling together CSS from the same folder (which I think makes sense from a bundling perspective).

Update

As per the comment below by @Hao Kung, alternatively this may now be achieved by applying a CssRewriteUrlTransformation (Change relative URL references to CSS files when bundled).

NOTE: I have not confirmed comments regarding issues with rewriting to absolute paths within a virtual directory, so this may not work for everyone (?).

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

Grinn / ThePirat solution works well.

I did not like that it new'd the Include method on bundle, and that it created temporary files in the content directory. (they ended up getting checked in, deployed, then the service wouldn't start!)

So to follow the design of Bundling, I elected to perform essentially the same code, but in an IBundleTransform implementation::

class StyleRelativePathTransform
    : IBundleTransform
{
    public StyleRelativePathTransform()
    {
    }

    public void Process(BundleContext context, BundleResponse response)
    {
        response.Content = String.Empty;

        Regex pattern = new Regex(@"urls*(s*([""']?)([^:)]+)1s*)", 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}
{1}", response.Content, contents);
            }
        }
    }
}

And then wrapped this up in a Bundle Implemetation:

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());
    }
}

Sample Usage:

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"
            ));

Here is my extension method for 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(@"", "/");
    }

這對我來說也是最乾淨的。謝謝。我投票給你們三個人,因為這看起來是團隊的努力。:) - Josh Mouch 11年8月8日18:18

你現在擁有的代碼對我不起作用。我正在努力修復它,但我想我會告訴你的。context.HttpContext.RelativeFromAbsolutePath方法不存在。此外,如果url路徑以“/”開頭(使其成為絕對路徑),則路徑組合邏輯將關閉。 - Josh Mouch 11年8月8日18:27

@AcidPAT很棒的工作。如果url有一個查詢字符串(某些第三方庫添加它,就像FontAwesome的.woff引用一樣)邏輯失敗。但這是一個簡單的修復。可以在調用Path.GetFullPath()之前調整Regex或修復relativeToCSS。 - sergiopereira 2013年2月24日21:37

@ChrisMarisic你的代碼似乎不起作用 - response.Files是一個BundleFiles數組,這些對像沒有“Exists”,“DirectoryName”等屬性。 - Nick Coad 14年8月8日在5:54

@ChrisMarisic是否有一個我應該導入的命名空間,為BundleFile類提供擴展方法? - 尼克科德於2014年12月8日22:53

+200

Better yet (IMHO) implement a custom Bundle that fixes the image paths. I wrote one for my app.

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<string>();
        var svr = HttpContext.Current.Server;
        foreach (var path in virtualPaths)
        {
            var pattern = new Regex(@"urls*(s*([""']?)([^:)]+)1s*)", 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;
    }

}

To use it, do:

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

...instead of...

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

What it does is (when not in debug mode) looks for url(<something>) and replaces it with url(<absolutepath osomething>). I wrote the thing about 10 seconds ago so it might need a little tweaking. I've taken into account fully-qualified URLs and base64 DataURIs by making sure there's no colons (:) in the URL path. In our environment, images normally reside in the same folder as their css files, but I've tested it with both parent folders (url(../someFile.png)) and child folders (url(someFolder/someFile.png).

這是一個很好的解決方案。我稍微修改了你的Regex,這樣它也適用於LESS文件,但最初的概念正是我所需要的。謝謝。 - 蒂姆庫爾特於2012年10月17日9:28

您也可以在循環外部進行正則表達式初始化。也許作為靜態只讀屬性。 - Miha Markic 12年12月22日16:04

+120

It is not necessary to specify a transform or have crazy subdirectory paths. After much troubleshooting I isolated it to this "simple" rule (is it a bug?)...

If your bundle path does not start with relative root of the items being included, then the web application root will not be taken into account.

Sounds like more of a bug to me, but anyway that's how you fix it with the current .NET 4.51 version. Perhaps the other answers were necessary on older ASP.NET builds, can't say don't have time to retrospectively test all that.

To clarify, here is an example:

I have these files...

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

Then setup the bundle like...

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

And render it like...

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

And get the "behaviour" (bug), the CSS files themselves have the application root (e.g. "http://localhost:1234/MySite/Content/Site.css") but the CSS image within all start "/Content/Images/..." or "/Images/..." depending on whether I add the transform or not.

Even tried creating the "Bundles" folder to see if it was to do with the path existing or not, but that didn't change anything. The solution to the problem is really the requirement that the name of the bundle must start with the path root.

Meaning this example is fixed by registering and rendering the bundle path like..

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

So of course you could say this is RTFM, but I am quite sure me and others picked-up this "~/Bundles/..." path from the default template or somewhere in documentation at MSDN or ASP.NET web site, or just stumbled upon it because actually it's a quite logical name for a virtual path and makes sense to choose such virtual paths which do not conflict with real directories.

Anyway, that's the way it is. Microsoft see no bug. I don't agree with this, either it should work as expected or some exception should be thrown, or an additional override to adding the bundle path which opts to include the application root or not. I can't imagine why anyone would not want the application root included when there was one (normally unless you installed your web site with a DNS alias/default web site root). So actually that should be the default anyway.

在我看來,最簡單的“解決方案”。其他可能有副作用,如圖像:數據。 - Fabrice 2014年10月21日21:55

不,它不起作用 - Abou-Emish 2015年2月2日23:38

@MohamedEmaish它確實有用,你可能有些不對勁。了解如何跟踪請求,例如使用Fiddler工具查看瀏覽器請求的URL。目標不是硬編碼整個相對路徑,以便您的網站可以安裝在同一服務器上的不同位置(根路徑),或者您的產品可以更改默認URL而無需重寫大量網站(具有和應用程序根變量的點)。 - Tony Wall 2015年2月4日7:07

使用此選項,它工作得很好。必須確保每個捆綁包只有一個文件夾中的項目(不能包含其他文件夾或子文件夾中的項目),這有點煩人,但只要它有效,我很高興!謝謝你的帖子。 - hvaughan3 2016年2月9日18:38

謝謝。嘆。有一天,我想花更多的時間來編寫代碼而不是瀏覽Stack。 - Bruce Pierson 2016年3月15日20:23

+90

I found that CssRewriteUrlTransform fails to run if you're referencing a *.css file and you have the associated *.min.css file in the same folder.

To fix this, either delete the *.min.css file or reference it directly in your bundle:

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

After that you do that, your URLs will be transformed correctly and your images should be correctly resolved.

謝謝!經過兩天的在線搜索,這是我第一次看到CssRewriteUrlTransform使用* .css文件的地方,但沒有關聯的* .min.css文件,當你沒有在調試中運行時被拉入環境。絕對看起來像是一個錯誤。將不得不手動檢查環境類型以定義具有未確定版本的捆綁包以進行調試,但至少我現在有一個解決方法! - 肖恩2016年3月17日16:31

這解決了我的問題。這當然看起來像一個bug。如果找到預先存在的.min.css文件,它應該忽略CssRewriteUrlTransform是沒有意義的。 - user1751825 19年3月19日23:59

+70

Although Chris Baxter's answer helps with original problem, it doesn't work in my case when application is hosted in virtual directory. After investigating the options, I finished with DIY solution.

ProperStyleBundle class includes code borrowed from original CssRewriteUrlTransform to properly transform relative paths within virtual directory. It also throws if file doesn't exist and prevents reordering of files in the bundle (code taken from 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<IItemTransform>( 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<BundleFile> OrderFiles( BundleContext context, IEnumerable<BundleFile> 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\(['"]?(?<url>[^)]+?)['"]?\)" )
                    .Replace( content, ( match =>
                                         "url(" + RebaseUrlToAbsolute( baseUrl, match.Groups["url"].Value ) + ")" ) );
            }
        }
    }
}

Use it like 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" ) );

很好的解決方案,但仍然失敗(就像CssRewriteUrlTransform),如果你的CSS中有一個數據URI(例如“data:image / png; base64,...”)。您不應該在RebaseUrlToAbsolute()中以“data:”開頭更改url。 - 英里時間2015年1月27日14:36

@ miles82當然!感謝您指出了這一點。我更改了RebaseUrlToAbsolute()。 - nrodic於2015年1月27日15:43

+70

Maybe I am biased, but I quite like my solution as it doesn't do any transforming, regex's etc and it's has the least amount of code :)

This works for a site hosted as a Virtual Directory in a IIS Web Site and as a root website on IIS

So I created an Implentation of IItemTransform encapsulated the CssRewriteUrlTransform and used VirtualPathUtility to fix the path and call the existing code:

/// <summary>
/// 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
/// </summary>
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()));
}

Seems to work fine for me?

這對我來說非常適合。優秀的解決方 我的投票是+1 - imdadhusen 2016年1月8日9:28

這是正確的答案。框架提供的CssUrlTransformWrapper類解決了該問題,但它僅在應用程序不在Web站點根目錄時才起作用。這個包裝器簡潔地解決了這個缺點。 - Nine Tails 2017年4月19日11:16

+60

As of v1.1.0-alpha1 (pre release package) the framework uses the VirtualPathProvider to access files rather than touching the physical file system.

The updated transformer can be seen below:

public class StyleRelativePathTransform
    : IBundleTransform
{
    public void Process(BundleContext context, BundleResponse response)
    {
        Regex pattern = new Regex(@"urls*(s*([""']?)([^:)]+)1s*)", 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}
{1}", response.Content, contents);
            }
        }
    }
}

實際上,如果用絕對值替換CSS中的相對URL,會發生什麼。 - Fabrice 2013年1月12日14:48

+40

Another option would be to use the IIS URL Rewrite module to map the virtual bundle image folder to the physical image folder. Below is an example of a rewrite rule from that you could use for a bundle called "~/bundles/yourpage/styles" - note the regex matches on alphanumeric characters as well as hyphens, underscores and periods, which are common in image file names.

<rewrite>
  <rules>
    <rule name="Bundle Images">
      <match url="^bundles/yourpage/images/([a-zA-Z0-9-_.]+)" />
      <action type="Rewrite" url="Content/css/jquery-ui/images/{R:1}" />
    </rule>
  </rules>
</rewrite>

This approach creates a little extra overhead, but allows you to have more control over your bundle names, and also reduces the number of bundles you may have to reference on one page. Of course, if you have to reference multiple 3rd party css files that contain relative image path references, you still can't get around creating multiple bundles.

+40

Grinn solution is great.

However it doesn't work for me when there are parent folder relative references in the url. i.e. url('../../images/car.png')

So, I slightly changed the Include method in order to resolve the paths for each regex match, allowing relative paths and also to optionally embed the images in the css.

I also changed the IF DEBUG to check BundleTable.EnableOptimizations instead of 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<string>();
        var server = HttpContext.Current.Server;
        var pattern = new Regex(@"urls*(s*([""']?)([^:)]+)1s*)", 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;
    }

Hope it helps, regards.

此解決方案有效,但它會創建臨時捆綁文件。 - Andrej Kaurin 2014年11月24日12:16

+20

You can simply add another level of depth to your virtual bundle path

    //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"));

This is a super low-tech answer and kind of a hack but it works and won't require any pre-processing. Given the length and complexity of some of these answers I prefer doing it this way.

當您將Web應用程序作為IIS中的虛擬應用程序時,這無濟於事。我的意思是它可以工作,但你必須在你的代碼中命名你的IIS虛擬應用程序,這不是你想要的,對吧? - psulek 2014年4月23日17:59

當應用程序是IIS中的虛擬應用程序時,我遇到了同樣的問題。這個答案對我有幫助。 - BILL 6月2日9:45

+20

I had this problem with bundles having incorrect path's to images and CssRewriteUrlTransform not resolving relative parent paths .. correctly (there was also problem with external resources like webfonts). That's why I wrote this custom transform (appears to do all of the above correctly):

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;
            }
        );
    }
}

Edit: I didn't realize it, but I used some custom extension methods in the code. The source code of those is:

/// <summary>
/// Based on: http://stackoverflow.com/a/11773674
/// </summary>
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;
}

Of course it should be possible to replace String.StartsWith(char) with String.StartsWith(string).

我沒有接受字符串的String.Count()重載(m.Groups [2] .Value.Count(“..”)不起作用。)和Value.StartsWith('/')沒有'因為StartsWith需要一個字符串而不是一個char,所以要么工作。 - jao 2014年11月13日9:18

@jao我的錯誤我在代碼中包含了我自己的擴展方法而沒有意識到它。 - jahu 2014年11月13日10:24

@jao將這些擴展方法的源代碼添加到答案中。 - jahu 2014年11月13日10:30

+10

After little investigation I concluded the followings: You have 2 options:

  1. go with transformations. Very usefull package for this: https://bundletransformer.codeplex.com/ you need following transformation for every problematic bundle:

    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.
0

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())

To:

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

Someway .(dots) are not recognizing in url.

115
votes
answers
38 views
+10

A cycle was detected in the build path of project xxx - Build Path Problem

I'm in the process of converting my projects to OSGI bundles using maven and eclipse. Maven builds the stuff just fine, only I get the above error now within Eclipse. How can I find out which project causes this? Is there a special view or something? How can this happen, I would expect that maven can detect cyclic dependencies as well?

Update

Ok, I found something here and here

Could this be caused by the felix maven-bundle-plugin which does for each export also an import?

沙发
+850

Mark circular dependencies as "Warning" in Eclipse tool to avoid "A CYCLE WAS DETECTED IN THE BUILD PATH" error.

In Eclipse go to:

Windows -> Preferences -> Java-> Compiler -> Building -> Circular Dependencies

為我節省了大量時間 - Sagar 2015年5月15日14:15

這個答案是正確的,因為使用gradle的開源項目具有循環依賴性,並且它們在gradle上構建正常。日食不應該因為這個錯誤而哭泣--Siddharth 2015年10月12日凌晨4點49分

當我這樣做時,錯誤從6增加到2000+。 - Arvindh Mani 2016年11月15日23:23

如何永久刪除此警告。它會導致我的一些問題,例如是否有未使用的導入。 - user7485924 18年1月30日2:10

在我的情況下,當我做這個改變時,錯誤從15到2000+。還有其他方法嗎? - Sanchit Khera 18年2月23日6:58

板凳
+110

When we have multiple projects in workspace, we have to set the references between the projects, not among the projects. If P1 references P2, P2 references P3, and P3 reference back to P1. That will cause a cycle.

The Solution is to draw a Diagram of the reference between projects in workspace. Check the Java Build Path of each of the projects to see the Tab of the Projects window. Take out the Project that are refering back to the main project, e.g. P3 references P1, in this example above.

Detailed operation is to select P3 project in RAD OR eclipse, right click on the project and choose the properties option, it brings up a new window for properties of P3. Click on the "Java Build Path" section, Choose the "Projects" option Tab. You can see the P3 has referenced P1 in the field. Select the P1 reference, click "Remove" button on the right side of the window. Then, click okay. The IDE will start to reset the path automatically.

Done.

Keep find all of the mis-referenced reference in every each projects until you have the right references to each of the projects in your Diagram. Good Luck!

但是如果存在P1引用的情況,則P2引用P1。例如。P1包含DAO層代碼,P2包含實用程序。實用程序有時使用DAO層從DB表獲取配置屬性,DAO層使用實用程序。那麼如何解決這個問題呢? - Sanjeev Kumar Dangi 2011年6月20日10:06

我也有完全相同的問題@Sanjeev。你有任何解決方案,請分享... - AndEngine 2014年5月23日9:54

@SanjeevKumarDangi可能會將DAO專用的實用程序放在DAO項目中。 - 湯姆布里托2016年4月11日13:53

地板
+70

I had this due to one project referencing another.

  1. Remove reference from project A to project B
  2. Try running stuff, it will break
  3. Re-add reference
  4. Clean/Clean and build
  5. Back in business
4楼
+40

In simple terms, a cycle is when bundle A depends on bundle B which depends on bundle A. If this is source code, then there's no way of building the bundles seperately in one pass.

Since the problem only shows in Eclipse, it may be a binary circular dependency as opposed to a source code circular dependency.

There is support for binary cycles in recent versions of Eclipse: Eclipsesource Blog

If the cycle is in your code, then I suggest refactoring the code by breaking out some of the code to a 3rd bundle to remove the circular dependency.

And watch out if you are using OSGi fragments (a common pattern for unit testing) as it is very easy to introduce cycles.

Eclipse's manifest editor does have functionality on the "Dependencies" tab for looking for cycles (you need to click on "Dependency Analysis"), but I've never seen it show a cycle even when Eclipse has a big red X telling me there's a cycle!

感謝有關Eclipse的清單編輯器“依賴性分析>查找循環”功能的提示。它確實顯示了循環(但僅在循環中的一個包中)。 - wisbucky 18年10月9日0:01

5楼
+30

Problem

I have an old project that tests two different implementations of a Dictionary interface. One is an unsorted ArrayList and the other is a HashTable. The two implementations are timed, so that a comparison can be made. You can choose which data structure from the command line args. Now.. I have another data structure which is a tree structure. I want to test the time of it, in order to compare it to the HashTable. So.. In the new dataStructure project, I need to implement the Dictionary interface. In the Dictionary project, I need to be able to add code specific to my new dataStructure project. There is a circular dependency. This means that when Eclipse goes to find out which projects are dependent on project A, then it finds project B. When it needs to find out the sub-dependencies of the dependent projects, it finds A, which is again, dependent on B. There is no tree, rather a graph with a cycle.

Solution

When you go to configure your build path, instead of entering dependent projects ('projects' tab), go to the Libraries tab. Click the 'Add Class Folder...' button (assuming that your referenced projects are in your workspace), and select the class folder. Mine is arget. Select this as a library folder. Do this in project A, to reference project B. Do this in project B to reference project A. Make sure that you don't reference argetprojectNameFolder or you won't have a matching import. Now you won't have to remove a dependency and then reset it, in order to force a rebuild.

Use class libraries instead of project references.

我非常喜歡Project References,因為它允許我在不同項目的源代碼之間跳轉(使用類庫讓我最終在二進製文件中,然後我不得不手動去尋找相應的源文件 - 這是一個令人頭痛的問題)。但是,在這種循環依賴的情況下,我只能通過將A引用為項目引用來解決它,而B將引用回A作為類庫。我必須做一點犧牲來解決週期依賴問題。 - ADTC 2013年10月28日7:23

6楼
+20

Sometimes marking as Warning

Windows -> Preferences -> Java-> Compiler -> Building -> Circular Dependencies

doesn't solve the problem because eclipse don't compile the projects that have another project in the dependencies that isn't compiled.

So to solve this problem you can try forcing Eclipse to compile every class that it be able to.

To make this just:

  1. Deselect

Windows -> Preferences -> Java-> Compiler -> Building -> Abort build when build path error occur

  1. Clean and rebuild all project

Project -> Clean...

  1. Reselect:

Windows -> Preferences -> Java-> Compiler -> Building -> Abort build when build path error occur

If you have the Automatic Build selected then you will not need to do this every time that you change the code

7楼
+10

Maven will fail the build if it detects a cycle, as the dependencies must be a tree.

You may find that you have additional declarations in the manifest.mf over those defined in the pom.xml. any extra declaration could introduce a cycle that wouldn't be apparent to Maven.

8楼
+10

As well as the Require-Bundle form of dependency management (most similar to Maven's pom dependencies), it's also possible to have Import-Package dependencies. It's much easier to introduce circular dependencies with Import-Package than Require-Bundle, but YMMV.

Also, Eclipse projects have a 'project references' which says which other projects it depends on. Eclipse uses this at a high level to decide what projects to build, and in which order, so it's quite possible that your Manifest.MF lists everything correctly but the project references are out of whack. Right click on a project and then go to properties - you'll see which projects you depend on. If you're a text kind of person, open up the .project files and see which ones you depend on there - it's probable that a project cyclic link is being defined at that level instead (often caused when you have an A-B dependency and then flipped from B-A but without updating the .project references).

用於提及.project文件的Eclipse問題的+1。有時唯一的解決方案就是丟棄與Eclipse相關的所有內容,並讓它從pom中再次弄清楚.. - Tim Jul 27 '09 at 21:53

9楼
+10

I faced similar problem a while ago and decided to write Eclipse plug-in that shows complete build path dependency tree of a Java project (although not in graphic mode - result is written into file). The plug-in's sources are here http://github.com/PetrGlad/dependency-tree

謝謝,救了很多痛苦。 - kakopappa 18年8月23日9:51

10楼
0

When I've had these problems it always has been a true cycle in the dependencies expressed in Manifest.mf

So open the manifest of the project in question, on the Dependencies Tab, look at the "Required Plugins" entry. Then follow from there to the next project(s), and repeat eventually the cycle will become clear.

You can simpify this task somewhat by using the Dependency Analysis links in the bottom right corner of the Dependencies Tab, this has cycle detection and easier navigation depdendencies.

I also don't know why Maven is more tolerant,

11楼
0

Try to delete references and add it back, some times eclipse behave weird because until and unless you fix that error it wont allow you refresh. so try to delete all dependencies project and add it back Clean and build

12楼
0

Just restarting Eclipse fixed the issue in my project

13楼
0

Although "Mark Circular Dependencies" enables you to compile the code, it may lead to a slower environment and future issues.

That's happening because at some point Eclipse has lost it's directions on your build path.

1 - Remove the project and it's references from the workspace. 2 - Import it back again. 3 - Check the references.

It is the best solution.

我寫了這本書,我不知道這個。謝謝! - mhartl 2011年12月22日4:37

14楼
0

I faced this same problem today. The error was apt. By mistake, I added cyclic dependency. A was dependent on B. In my case, by mistake, apart from adding B as dependent to A. I added A as dependent to B too. It was a foolish mistake.

15楼
0

I have this problem,too.I just disable Workspace resolution,and then all was right.enter image description here

這不是問題的解決方案。Maven抱怨文物的循環依賴性。它會造成問題。 - kk。17年6月6日10:54

16楼
0

This could happen when you have several projects that include each other in JAR form. What I did was remove all libraries and project dependencies on buildpath, for all projects. Then, one at a time, I added the project dependencies on the Project Tab, but only the ones needed. This is because you can add a project which in turn has itself referenced or another project which is referencing some other project with this self-referencing issue.

This resolved my issue.

90
votes
answers
34 views
+10

The application bundle does not contain a valid identifier

I try to run my project but i get the following error "The application bundle does not contain a valid identifier."

here my info.plist

enter image description here

I followed other answer on the question. I don't have any "Ressources" folder inside my project.

Thanks for your help

up vote 86 down vote accepted favorite
沙发
+860
+50

I solve this problem after I delete all build files by Xcode. Your build file path at Xcode > Preferences > Locations > Derived Data

If you didn't change the default path, Your path is like

File Path

I just deleted all files under DerivedData

等效鍵盤快捷鍵。cmd + alt + shift + k - Eager Logic 17年5月23日13:48

+40

In my case, this problem occurred when I manually removed a pod from my file browser in XCode. In order to fix it, I deleted the associated entry in my podfile, and ran 'pod install' from the terminal. Additionally, I had to delete the relevant search paths and other references to that pod. And of course I had to clean the project.

0

In my case the info.plist had the wrong encoding format, I still don't know why it changed. So I had to create a new one from Xcode and copy paste all the keys.

0

Cleaning the project solves my issue. Product -> Clean

0

I was building the wrong target on a device in my case. I was building the Test target rather than the normal app target.

0

In my case, I've added a framework into Embed Binaries phase, but it was already in my Link Frameworks and Binaries phase, which created a duplicate entry. Once I deleted one of them, this error starting appearing.

To fix it, I've removed the framework from both build phases and added it one more time

0

In my case, my app's bundle contained a dash like com.some-thing.app so I just changed it to com.something.app and the problem was fixed.

除了generatePom部分之外,在我的構建中安裝的說明包含所有內容。這似乎至關重要。 - 傑森D 2014年7月14日18:43

這是什麼意思 ?像C:/Users/XXX/WorkspaceDocx/maven/src/main/resources/myJar.jar ......或者我們可以做$ {project.basedir} /src/main/resources/myJar.jar - Igor Beaufils 2015年8月10日14:06

答案沒有提到自述文件,也沒有提到罐子。但是,如果項目帶來了罐子那麼你也可以將repo放在這裡提到的堆棧中,如下所述stackoverflow.com/a/36602256/1000011那麼你就不需要README了,因為項目就像jar一樣工作在maven中心沒有任何額外的手動步驟。 - opticyclic 2016年6月27日23:34

@opticyclic你的評論需要更多的讚成,或者這個答案需要編輯。對於那些沒有意識到安裝到本地Maven倉庫的人來說,這是一個災難的秘訣。 - Mike S 2016年7月28日18:40

Maven的安裝第三方JAR的指南 - 尼克格雷厄姆2016年11月11日19:17

11
votes
answers
40 views
+10

osgi bundle lifecycle question

I try to learn how osgi works. I've written my first hello-world bundle which gives some console output when the start-method of the bundle activator class is executed. Now, I've read about the lazy starting mechanism and I put this flag to my bundle manifest. then, I started the equinox console, installed my bundle and started it. but now I would have expected my bundle to be marked as 'starting'. but instead it already calls it's start method and is marked as active. did I understand anything wrong with the lazy starting mechanism???

沙发
+80
+50

The lazy-start flag is used when you have other bundles that depend on your bundle and classes in your bundle.

Say you have two bundles A and B, where

  • A exports the class C
  • B depends on A
  • B contains a class D that refers C

What happens when the bundle B is activated?

Without the lazy-load flag, the A bundle is loaded and activated first.

With the lazy-load flag, the A bundle is not loaded or activated until the class D needs to refer to the class C.

That can make a very big difference in the activation profile, as the load and activation of bundles are postponed to happen as late as possible with the lazy-load flag so the initial response from the bundle is very fast...

On the contrary, this flag also makes it a hole lot more difficult to reason about the execution time for methods in B as this can be intercepted with load and activation of bundles at any time....

非常感謝你們兩個!這在我的書中沒有得到很好的解釋,但現在我明白了:-) - 2011年7月16日在19:55

+30

You said, you already started your bundle after install - if you start your bundle manually, it is activated regardless of the lazy activation policy.

According to the OSGi specification the following is true for activation:

A lazy activation policy indicates that the bundle, once started, must not be activated until a class is loaded from it; either during normal class loading or via the Bundle loadClass method. Resource loading does not trigger the activation. This change from the default eager activation policy is reflected in the state of the bundle and its events. When a bundle is started using a lazy activation policy, the following steps must be taken:

  • A Bundle Context is created for the bundle.
  • The bundle state is moved to the STARTING state.
  • The LAZY_ACTIVATION event is fired.
  • The system waits for a class load from the bundle to occur.
  • The normal STARTING event is fired.
  • The bundle is activated.
  • The bundle state is moved to ACTIVE.
  • The STARTED event is fired.

If the activation fails because the Bundle Activator start method has thrown an exception, the bundle must be stopped without calling the Bundle Activator stop method. These steps are pictured in a flow chart in Figure 4.29. This flow chart also shows the difference in activation policy of the normal eager activation and the lazy activation.

Update: as I cannot say which version of the specification I have opened at the time I wrote the answer (however, I believe, it was either 4.2 or 4.3), I have checked the current, v5.0 specification, and section 4.4.6.2 contains the actual, semantically equivalent place.

您應該提供規範的來源。規格可能會隨著時間的推移而變化,未來的讀者(像我一樣)不知道你從哪個版本得到報價。 - Rui Marques 2013年9月2日10:59

感謝您的評論; 我添加了對規範的引用。 - ZoltánUjhelyi2013年9月2日14:46

37
votes
answers
38 views
+10

Composer - The requested package exists as but these are rejected by your constraint

When I run my install from composer, I have this error :

λ composer install You are running composer with xdebug enabled. This has a major impact on runtime performance. See https://getcomposer.org/xdebug Loading composer repositories with package information Updating dependencies (including require-dev) Your requirements could not be resolved to an installable set of packages.

Error :

Problem 1 - The requested package antoineb1/smoney_bundle 1.0 exists as antoineb1/smoney_bundle[dev-master] but these are rejected by your constraint.

My composer.json

{
    "name": "project",
    "license": "proprietary",
    "type": "project",
    "minimum-stability": "dev",
    "prefer-stable" : true,
    "autoload": {
        "psr-4": {
            "": "src/"
        }
    },
    "config": {
        "preferred-install": "dist"
    },
    "repositories": [
        {
            "url": "bitbucket url",
            "type": "vcs"
        }
    ],
    "require": {
        "php": ">=5.5.9",
        "antoineb1/smoney_bundle": "1.0"
    }
}
沙发
+280

The version constraint "1.0" is interpreted internally as "1.0.0.0-stable" version.

But the only version available is:

antoineb1/smoney_bundle[dev-master].

So you could change the specified version to either one of the following depending on what version is suitable for you:

  • 1.0.* (which is seen by composer as >=1.0.0.0-dev <1.1.0.0-dev -- probably won't work because there obviously aren't any versions in that package)
  • dev-master
  • dev-master#<hash>
  • @dev
  • etc.

See the composer schema for reference.

我有這個問題,因為我忽略了將我的標籤推到遙控器上。它可能也值得運行composer clear-cache。 - 1981年8月23日在洛杉磯9:57

@BVengerov有沒有辦法指定一個特定的分支? - crmpicco 18年7月24日7:53

板凳
+50

The comment by @Guillaume below this answer deserves a larger presentation.

It seems that composer wants a git release that has a v in it.

So it should be v1.1.0 and not 1.1.0.

I spent about 90 minutes looking at

mikeill/my_repo 3.3.10 requires composer/installers 1.0.*@dev -> satisfiable by composer/installers[1.0.x-dev, v1.0.0, ...] but these conflict with your requirements or minimum-stability.

And a lot of github issues as well as an SO post or two before finally discovering this thread.

瑣碎而容易被忽視 - i_v_harish 18年10月3日在13:32

地板
+20

I came across this question, and found another issue, which I had completely forgotten about, which someone may find useful to have to check.

In my case I had a very old git project, which had been forked some time back, and I had to merge them together (albeit the forked project hadn't had many changes). So I identified the split point on the old project, and tagged it as version for composer, so I could use that in place of the new project.

What I had forgotten though, was that originally we didn't use composer. So the file structure at the tag point was missing composer.json. I couldn't figure out why my new tags weren't appearing on the 'exists as' list of things which were 'rejected by your contraint'. Eventually I realised I had to create a branch on the old tag, cherry-pick the commit which created the composer.json for the project, and retag that, and then it all worked.

Hopefully this will jog someones memory, if they come hunting with this error message in mind.

4楼
+20

I lost a significant amount of hair, time and sanity over this question for a while - it turned out that the problem in my case was that I was specifying a version in the composer.json within the package itself as "dev-master".

Refer to: https://getcomposer.org/doc/04-schema.md#version

Where it states:

Note: Packagist uses VCS repositories, so the statement above is very much true for Packagist as well. Specifying the version yourself will most likely end up creating problems at some point due to human error.

(emphasis mine)

I removed this version element and it worked perfectly :)

46
votes
answers
52 views
+10

bundle install returns “Could not locate Gemfile”

I'm new to Rails and am currently working through a guide. The guide states:

Use a text editor to update the Gemfile needed by Bundler with the contents of Listing 2.1.

source 'https://rubygems.org'

gem 'rails', '3.2.3'

group :development do
  gem 'sqlite3', '1.3.5'
end


# Gems used only for assets and not required
# in production environments by default.

group :assets do
  gem 'sass-rails',   '3.2.4'
  gem 'coffee-rails', '3.2.2'
  gem 'uglifier', '1.2.3'
end

gem 'jquery-rails', '2.0.0'

group :production do
  gem 'pg', '0.12.2'
end

We then install and include the gems using the bundle install command:

    $ bundle install --without production 

If Bundler complains about no such file to load -- readline (LoadError) try adding gem ’rb-readline’ to your Gemfile.)

I followed the steps even adding on gem 'rb-readline' to the Gemfile, but apparently the file can't be found and when I go to my text editor I do see the Gemfile itself. I noticed that they made me put gem 'rails', 3.2.3 and my version of Rails is 3.2.1 so I tried changing it to 3.2.1 but that didn't work either.

Any thoughts or advice would be much appreciated.

沙发
+180

You may also indicate the path to the gemfile in the same command e.g.

BUNDLE_GEMFILE="MyProject/Gemfile.ios" bundle install
板凳
+140

I had this problem as well on an OSX machine. I discovered that rails was not installed... which surprised me as I thought OSX always came with Rails. To install rails

  • sudo gem install rails
  • to install jekyll I also needed sudo
  • sudo gem install jekyll bundler
  • cd ~/Sites
  • jekyll new <foldername>
  • cd <foldername> OR cd !$ (that is magic ;)
  • bundle install
  • bundle exec jekyll serve
  • Then in your browser just go to http://127.0.0.1:4000/ and it really should be running
地板
+70

You should be in the same directory of Gemfile

4楼
+70

When I had similar problem gem update --system helped me. Run this before bundle install

5楼
0

Search for the Gemfile file in your project, go to that directory and then run "bundle install". prior to running this command make sure you have installed the gem "sudo gem install bundler"

6楼
-80

Think more about what you are installing and navigate Gemfile folder, then try using sudo bundle install

這會產生關於未經檢查的強制轉換的警告。這是安全的嗎? - 2017年10月20日21:16

4
votes
answers
34 views
+10

How to pass non parcelable objects to from activity to another activity?

I have two objects instantiated from two different class and both classes do not implement parcelable nor serializable. and I want to pass those objects to another activity, so I wrote the below code:

*code:

 //send object
 Intent intConnect = new Intent(mCtx.getApplicationContext(), ActConnect.class);
            Bundle bndConnect = new Bundle();
            bndConnect.putParcelable("HeaderModel", (Parcelable) mHeaderModel);
            bndConnect.putParcelable("DetailsModel", (Parcelable) mDetailsModel);
            intConnect.putExtras(bndConnect);
            intConnect.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            mCtx.startActivity(intConnect);

//receive objects in the receiving activity
 Bundle extras = getIntent().getExtras();
    Header headerModel = (Header) extras.get("HeaderModel");
    Details detailsModel = (Details) extras.get("DetailsModel");

but at run time, I receive the below logcat:

logcat:

10-08 11:55:44.225  13138-13138/com.example.com.bt_11 E/AndroidRuntime﹕ FATAL EXCEPTION: main
Process: com.example.com.bt_11, PID: 13138
java.lang.ClassCastException: com.example.com.adapter.Header cannot be cast to android.os.Parcelable
        at com.example.com.adapter.MyExpandableList$1.onClick(MyExpandableList.java:152)
        at android.view.View.performClick(View.java:5184)
        at android.view.View$PerformClick.run(View.java:20893)
        at android.os.Handler.handleCallback(Handler.java:739)
        at android.os.Handler.dispatchMessage(Handler.java:95)

how can I pass non parcelable objects to from activity to another activity?

沙发
0
+50

You can do this way:

Your Model class will looks like below:

public class ModelClass implements Serializable{

  // Other stuff

}

How to pass:

Intent mIntent = new Intent(mContext, NextActivity.class);
mIntent.putExtra("HeaderModel", mHeaderModel);
startActivity(mIntent);

How to get:

Header headerModel = (Header) getIntent.getSerializableExtra("HeaderModel");

Hope this will help you.

你讀過OP問題嗎?這兩個類都沒有實現parcelable或serializable - Rustam 2015年10月8日10:13

OP請問什麼? - LetsamrIt 2015年10月8日10:15

OP是那個問這個問題的人,你。@LetsamrIt - Manza 2016年7月20日13:11

@LetsamrIt“OP”的意思是“原創海報”,就是你。 - RCB '18年12月3日20:49

+30

If your class doesn't implement parcelable nor serializable, and you cannot modify them (code not under your control perhaps), then you have no way to directly send the data between the two activities.

However, you can pass the data indirectly between the two activities. You could store them in a singleton class (however singletons are hard to test etc.), you could save and retrieve them off your application class, or you could persist them into sharedpreferences, a file or a database to be loaded by the second activity.

+10

The best way to pass object without parcelable or serializable is to use Gson Lib

And use this extensions:

fun Intent.putObject(name: String, value: Any) {
    val jsonValue = Gson().toJson(value)
    this.putExtra(name, jsonValue)
}

inline fun <reified T : Any> Intent.getObjectExtra(name: String): T? {
    val json = this.getStringExtra(name)

    val obj = Gson().fromJson<T>(json, T::class.java)
    return (obj as T)
}

inline fun <reified T : Any> Bundle.getObject(name: String): T? {
    val json = this.getString(name)

    val obj = Gson().fromJson<T>(json, T::class.java)
    return (obj as T)
}

Using:

val intent = Intent(this,YourActivity::class.java)
intent.putObject(name = "myKey", value = MyObject)

//To get the object in the other activity
val product = intent.extras?.getObject<MyObject>(name = "myKey")
// or
val product = intent.getObjectExtra<MyObject>(name = "myKey")
0

try like this:

     Bundle bundle=getIntent().getExtras();

    Header headerModel =(Header)) bundle.getParcelable("HeaderModel");

我收到了完全相同的錯誤 - LetsamrIt 2015年10月8日10:43

6
votes
answers
198 views
+10

Putting a Bitmap into a Bundle

I want to pass a String and a Bitmap to a Service using AIDL. The Service implements this AIDL method:

void addButton(in Bundle data);

In my case, the Bundle contains a String and a Bitmap.

The calling application (client) has this code:

...
// Add text to the bundle
Bundle data = new Bundle();
String text = "Some text";
data.putString("BundleText", text);

// Add bitmap to the bundle
Bitmap icon = BitmapFactory.decodeResource(getResources(), R.drawable.myIcon);
data.putParcelable("BundleIcon", icon);

try {
    myService.addButton(data);

} catch (RemoteException e) {
    Log.e(TAG, "Exception: ", e);
    e.printStackTrace();
}
...

On the service end, I have a ButtonComponent class with this code:

public final class ButtonComponent implements Parcelable {
    private final Bundle mData;

    private ComponComponent(Parcel source) {
        mData = source.readBundle();
    }

    public String getText() {
        return mData.getString("BundleText");
    }

    public Bitmap getIcon() {
        Bitmap icon = (Bitmap) mData.getParcelable("BundleIcon");
        return icon;
    }

    public void writeToParcel(Parcel aOutParcel, int aFlags) {
        aOutParcel.writeBundle(mData);
    }

    public int describeContents() {
        return 0;
    }
}

After creating a ButtonComponent, the Service creates a button using the text and icon from the ButtonComponent object:

...
mInflater.inflate(R.layout.my_button, aParent, true);
Button button = (Button) aParent.getChildAt(aParent.getChildCount() - 1);

// Set caption and icon
String caption = buttonComponent.getText();
if (caption != null) {
    button.setText(caption);
}

Bitmap icon = buttonComponent.getIcon();
if (icon != null) {
    BitmapDrawable iconDrawable = new BitmapDrawable(icon);
    button.setCompoundDrawablesWithIntrinsicBounds(iconDrawable, null, null, null);
}
...

As a result, the button is displayed with the correct text and I can see the space for the icon, but the actual bitmap is not drawn (i.e. there's an empty space on the left side of the text).

Is it correct to put a Bitmap into a Bundle in this way?

If I should use a Parcel (vs a Bundle) is there any way to maintain a single 'data' argument in the AIDL method to keep text and icon together?

Side question: How do I decide to use Bundles vs Parcels?

Many thanks.

+30

Here is answer for your second question.

Source : http://www.anddev.org/general-f3/bundle-vs-parcel-vs-message-t517.html

A Bundle is functionally equivalent to a standard Map. The reason we didn't just use a Map is because in the contexts where Bundle is used, the only things that are legal to put into it are primitives like Strings, ints, and so on. Because the standard Map API lets you insert arbitrary Objects, this would allow developers to put data into the Map that the system can't actually support, which would lead to weird, non-intuitive application errors. Bundle was created to replace Map with a typesafe container that makes it explicitly clear that it only supports primitives.

A Parcel is similar to a Bundle, but is more sophisticated and can support more complex serialization of classes. Applications can implement the Parcelable interface to define application-specific classes that can be passed around, particularly when using Services. Parcelables can be more sophisticated than Bundles, but this comes at a cost of significantly higher overhead.

Bundle and Parcel are both data serialization mechanisms, and for the most part both are used when application code is passing data across processes. However, because Parcel is much higher overhead that Bundle, Bundles are used in the more common places like the onCreate method, where overhead must be as low as possible. Parcels are most commonly used to allow applications to define Services with logical APIs that can use application-meaningful classes as method arguments and return values. If we required Bundle there, it would result in really clunky APIs. You should in general still keep your Service APIs as simple as possible, because primitives will serialize more efficiently than custom Parcelable classes.

板凳
+20
+50

Solved.

Problem was that the PNG I was using is not supported by Android. The code:

icon.getConfig()

returns null.

+10

While gt_ebuddy gives a nice answer, I just have a little side note to your question:

Problem: You are trying to pass a Bitmap object to memory, it can be fine; however, it's absolutely not good to pass many Bitmap objects like this. Really bad practice.

My Solution: The image is already existed in resources, it has an unique ID; make use out of it. Instead of trying to pass a lot of heavy Bitmaps, you can pass its ID using Bundle or Parcel, but Bundle is preferable for simple data structure.

謝謝。在我的場景中,位圖大約是900字節,這可能是一個公平的大小,我想避免在服務的APK中包含所有這些(可能有許多不同的客戶端)。如果我使用了唯一的ID,我猜客戶端和服務的包都會包含實際的PNG ......對嗎? - rippeltippel 2011年10月11日16:39

您的所有圖片都應該包含在/ res / drawable目錄中 - Pete Houston 2011年10月12日1:43

164
votes
answers
35 views
+10

How to make an iOS asset bundle?

I saw a custom asset bundle in an iOS project I evaluated, so at least I know it's possible.

My issue is that I'm using a CATiledLayer with about 22,000 tiles for a given image and it takes a very long time to compile (half an hour clean build, 5-10 minutes for regular build). So, I want to take all of the images and make a custom bundle to make it portable and hopefully not recompile into the app bundle each time.

How do I go about this? I checked the docs, but didn't see an explanation on how to actually create the bundle.

up vote 92 down vote accepted favorite
沙发
+920
+50

Answer is stupidly simple

Make a folder in finder, add files to it, rename it to bundlename.bundle

drag into Xcode - success!

to access, use the form of PathToMainBundle+"/bundlename.bundle"

對我不起作用。我無法訪問資產包中的文件,因為沒有加載包,當我加載包時,我收到一條錯誤,說無法加載包,因為無法找到它的可執行文件。 - LandedGently於2011年7月8日23:02

@LandedGently,我遇到了同樣的問題,事實證明這不是因為沒有加載包。這是因為我有一個大寫字母用於pathForResource:ofType(ofType:@“PNG”)的ofType部分,它在模擬器上工作但在實際設備上沒有。從這裡我可以說你不需要在非可執行包上調用load方法來提取資源。 - Hari Karam Singh 11年11月19日12:37

僅供參考,我的自定義捆綁包中沒有一個說它們已加載,我從不打算嘗試手動加載它們。無論如何,它們按預期運行。 - 邁克爾11年11月21日18:34

但那不是捆綁。它只是名稱中包含“bundle”的文件夾。 - 暗於2016年10月14日21:04

@michael同意了,但是如果這只是一個文件夾,那麼這裡什麼都不會發生。換句話說,你對捆綁的定義和期望是什麼?如果你想要做的只是將一個東西的文件夾拖入Xcode以包含在應用程序中,你可以在沒有使用.bundle後綴重命名的情況下完成。 - 暗於2016年10月20日19:42

+360

How to create a bundle

  1. Create a folder in finder.
  2. Add files to the folder
  3. Rename the folder so that its extension is .bundle (e.g. "New folder" -> "BundleName.bundle")

PS: You can at any time right click the folder and hit "Show package content" in order to add, remove or modify any of the files.

How to add the bundle to Xcode

  1. Drag it into Xcode

How to use the bundle

NSString *bundlePath = [[NSBundle mainBundle] pathForResource:@"BundleName" ofType:@"bundle"];
NSBundle *bundle = [NSBundle bundleWithPath:bundlePath]; 
NSString *resource = [bundle pathForResource:@"fileName" ofType:@"fileType"];

(Replace BundleName, fileName and fileType with appropriate names)

+250

Two other helpful bits of advice:

First, in order to see the contents of the bundle in XCode you need to set its type in the File Inspector Utility Pane, to "Application Bundle". You still won't be able to copy to and from via XCode. You'll need to use Terminal but XCode will update it immediately.

Second, in order to use resources in the bundle here's a helpful snippet...

NSString *bundlePath = [[NSBundle mainBundle] pathForResource:@"AquarianHarp" ofType:@"bundle"];
NSString *imageName = [[NSBundle bundleWithPath:bundlePath] pathForResource:@"trebleclef2" ofType:@"png"];
UIImage *myImage = [[UIImage alloc] initWithContentsOfFile:imageName];

As mentioned in my comment above, you needn't actually load the bundle (you can't as it's not executable) and the ofType needs to match the case of your actual file for it to work on the device. It will work either way in simulator so don't be fooled by this red herring!

Finally, you don't need to put your resources in the "Resources" subfolder inside the bundle. It seems you can use an arbitrary layout but there may be unknown performance implications.

此外,如果捆綁包中有文件夾,請確保文件夾名稱不包含空格。模擬器可以工作,但設備不允許文件夾名稱中的空格。 - LandedGently 12月12日在21:31

在上面的代碼中myBundle怎麼樣? - Venk 2013年4月15日11:39

+100

Here's how I got this to work: In XCode create a new file | Resource | Settings Bundle. Then in the Finder select that bundle and choose Show Package Contents, and add whatever image files.

Then in the code reference an image this way:

NSString *imgName = @"bundlename.bundle/my-image.png";
UIImage *myImage = [UIImage imageNamed:imgName]; 

但是沒有任何有意義的意義,這是一個捆綁。它只是一個文件夾。您只需執行通常從文件夾加載圖像的操作。 - 暗於2016年10月14日21:02

+10

My notes on bundling and reading files in an XCode project

Steps:

  1. Create a test.txt file and add the text "testing??" to it then put it in a folder named test.bundle
  2. Drag and drop it next to your .app file in xcode (copy)
  3. print(Bundle.main.resourcePath!+"/temp.bundle/test.txt") Output: /Users/James/Library/Developer/Xcode/DerivedData/GitSyncMac-heiwpdjbtaxzhiclikjotucjguqu/Build/Products/Debug/GitSyncMacApp.app/Contents/Resources/temp.bundle/test.txt

Example:

print(content(Bundle.main.resourcePath!+"/temp.bundle/test.txt"))// testing??
static func content(_ path:String)->String?{
    do {
        let content = try String(contentsOfFile:path, encoding:String.Encoding.utf8) as String//encoding: NSUTF8StringEncoding
        return content
    } catch {
        return nil
    }
}
0

Here are the steps to create an asset or resource bundle (ex. FrameworkResources.bundle) - it's surprisingly non-obvious. This is especially useful if you are creating static frameworks.

  1. Press File -> New -> Target in Xcode
  2. Select "macOS" tab, search "Bundle"
  3. Tap "Bundle" -> click "Next" -> type product name "MyResources" -> tap "Finish"
  4. Go to "Build Settings" for the newly created Bundle. Change "Base SDK" (SDKROOT) to "iOS'
  5. Go to "Build Phases" for the newly created Bundle. Delete "Compile Sources" and "Link Binary With Libraries" (this will remove the executable within the bundle which can cause all sorts of build and app submission errors)
7
votes
answers
28 views
+10

Override bundle template from another bundle in symfony 3.4/4

because bundle inheritance is deprecated since Symfony 3.4 and will be removed in 4.0, I'm finding a new solution. I have:

  • Application
  • FooBundle
  • BarBundle

And I haven't problem with overriding templates in Application. But I need to override templates from BarBundle in FooBundle. It was so easy with bundle inheritance but I'm lost now :)

I tried twig namespaces - no success, but I configured it in wrong way maybe. My goal is to have base templates in BarBundle that I can override in FooBundle or Application or both. (it is because BarBundle is third-party bundle and FooBundle is my bundle used in many projects).

Is it still possible without bundle inheritance and how?

Thanks.

沙发
+40

So I have recently needed same functionality and with help from comment @NicoHasse I managed to make working example

In your bundle bundle extension class you need to implement PrependExtensionInterface and then you can modify twig paths. Then you need to know original namespace your you need to override (php bin/console debug:twig).

You can confirm its working with twig debug command where you should see your path at first place of that namespace.

class YourExtensionClass extends Extension implements PrependExtensionInterface
{
    public function prepend(ContainerBuilder $container)
    {
        $container->loadFromExtension('twig', [
            'paths' => [
                '%kernel.project_dir%/vendor/xx/yy/zzz' => 'OriginalVNamespace',
            ]
        ]);
板凳
+30

Here's a more comprehensible example

Let's start with making some assumptions

Your bundle's name: AcmeBundle

Bundle you want to override: FOSUserBundle

Run command php bin/console debug:twig and find the namespace of the bundle you want to override. In this case it's @FOSUser.

Your bundle extension should look like this

<?php // src/AcmeBundle/DependencyInjection/AcmeExtension.php

namespace AcmeBundleDependencyInjection;

// ...

use SymfonyComponentDependencyInjectionExtensionPrependExtensionInterface;

class AcmeExtension extends Extension implements PrependExtensionInterface
{
    // ...

    public function prepend(ContainerBuilder $container)
    {
        $container->loadFromExtension('twig', array(
            'paths' => array(
                '%kernel.project_dir%/src/AcmeBundle/Resources/FOSUserBundle/views' => 'FOSUser', // You use the namespace you found earlier here. Discard the `@` symbol.
            ),
        ));
    }
}

Now you can create src/AcmeBundle/Resources/FOSUserBundle/views/Security/login.html.twig to override the login template of FOSUserBundle.

This was just an example for FOSUserBundle. You can change bundle names depending on what you're trying to override.