Font-Awesome Get Request Failure When Bundling EnableOptimizations is true - asp.net-mvc

I am experiencing a problem with font-awesome and ASP.NET’s optimisation/bundling feature.
When EnableOptimizations is set to false, the font which I'm using for a loading image works perfectly:
However, when EnableOptimizations is set to true, the font is no longer found and the following is displayed:
I’ve noticed there is a disparity between the paths which the GET requests are hitting:
EnableOptimizations = false: localhost:3620/Content/fonts/fontawesome-webfont.woff?v=4.1.0
EnableOptimizations = true: localhost:3620/fonts/fontawesome-webfont.svg?v=4.1.0
The bundle in question looks like this:
bundles.Add(new StyleBundle("~/Content/BootstrapAndFontAwesome").Include(
"~/Content/bootstrap/bootstrapLabel.css",
"~/Content/font-awesome/font-awesome.css"
));
What’s going on here and what’s the best way to fix it?
Cheers
Update
On Rowan's suggestion in the comments to this post, I implemented the following code from this stackoverflow answer which has fixed the problem on my dev machine:
public class CssRewriteUrlTransformWrapper : IItemTransform
{
public string Process(string includedVirtualPath, string input)
{
return new CssRewriteUrlTransform().Process("~" + VirtualPathUtility.ToAbsolute(includedVirtualPath), input);
}
}
I will need to do a few practice deployments to make sure it is solid (e.g. use virtual IIS directories etc.). Looks good so far!
Note that I did have to separate out the font-awesome file into it's own bundle as it cannot be bundled with another resource when adopting the CssRewriteUrlTransform solution.
Thanks.

Use CssRewriteUrlTransform.
Rewrites urls to be absolute so assets will still be found after bundling.
Example:
bundles.Add(new StyleBundle("~/Content/mycss")
.Include("~/Content/font-awesome.css", new CssRewriteUrlTransform()));

This SO post has a useful solution to this issue, and it appears to have been written by someone who actually works for Microsoft on the ASP.net Bundle code.
The issue is most likely that the icons/images in the css files are
using relative paths, so if your bundle doesn't live in the same app
relative path as your unbundled css files, they become broken links.
We have rebasing urls in css on our todo list, but for now, the easist
thing to do is to have your bundle path look like the css directory so
the relative urls just work, i.e:
new StyleBundle("~/Static/Css/bootstrap/bundle")
Update: We have added support for this in the 1.1beta1 release, so to
automatically rewrite the image urls, you can add a new ItemTransform
which does this rebasing automatically.
bundles.Add(new StyleBundle("~/bundles/publiccss").Include(
"~/Static/Css/bootstrap/bootstrap.css",
"~/Static/Css/bootstrap/bootstrap-padding-top.css",
"~/Static/Css/bootstrap/bootstrap-responsive.css",
"~/Static/Css/bootstrap/docs.css", new CssRewriteUrlTransform()));
This fixed my issue with getting 404 errors on Font Awesome icons, on the production server, due to the relative paths not being used correctly.
bundles.Add(new StyleBundle("~/Content/font-awesome/css/bundle").Include(
"~/Content/font-awesome/css/font-awesome.css", new CssRewriteUrlTransform()));

There’s a little know class called CssRewriteUrlTransform in the Sytem.Web.Optimization namespace that will help us solve this issue, or any css file that references url relative resources. The new code would now look something like:
bundles.Add(new StyleBundle("~/content/smartadmin")
.Include("~/content/css/font-awesome.css", new CssRewriteUrlTransform())
.Include("~/content/css/dataTables.responsive.css")
.IncludeDirectory("~/content/css", "*.min.css"));

Related

Multiple CDN Bundling and Mimification in Mvc5

From this post I can bundle a single CDN file. So How to bundle many CDN files in one line ? Do I only need a list of strings and repeat this line for each item?
public static void RegisterBundles(BundleCollection bundles){
bundles.UseCdn = true;
var jqueryCdnPath = "http://ajax.aspnetcdn.com/ajax/jQuery/jquery-1.7.1.min.js";
bundles.Add(new ScriptBundle("~/bundles/jquery",
jqueryCdnPath).Include("~/Scripts/jquery-{version}.js"));
}
I think your answer is here: https://stackoverflow.com/a/31069580/2158136
When you use a CDN, you can´t bundle them in one line.
Even, if you add multiple bundles with the same virtual path, only the last item will be considered (It happened to us, and it took some time before we realized what was happening).
You have to add one line per each CDN that you need to add to the bundle.

Deploy ZF2 site to shared host

When you deploy a Zend Framework website to a shared host, you usually cannot change the DocumentRoot to point at the public/ folder of the website. As a result the URL to the website is now http://www.example.com/public/. This doesn't look very professional, so I'd like to remove it. Up to now I have used ZF1 and Rob Allen kindly provides a method for doing this on his blog http://akrabat.com/zend-framework/zend-framework-on-a-shared-host/ . I have tried to modify this for ZF2. He proposes placing an index.php file in the root with the line:
include 'public/index.php';
After doing this, http://www.example.com opens the index page OK but the CSS links are broken. Rob adds a controller plugin to reset the baseUrl to /public to deal with public facing CSS and image files etc. To do this in ZF2 I found an item from Matthew Weier O' Phinney http://zend-framework-community.634137.n4.nabble.com/Setting-the-base-url-in-ZF2-MVC-td3946284.html where he describes how to set the baseUrl. Based on his code I added this to modules/Application/Module.php
class Module {
public function onBootstrap(MvcEvent $e) {
$config = $e->getApplication()->getServiceManager()->get('config');
$router = $e->getApplication()->getServiceManager()->get('router');
$router->setBaseUrl($config['base_url']);
}
}
The base_url key is set in modules/Application/configs/module.config.php:
'base_url' => '/public'
I was able to dump the router object and confirm that the base_url was being set correctly at this stage. Unfortunately, now http://www.example.com no longer opens the index page and gives a 404 routing error.
Is anyone able to tell me what I am doing wrong or point me in the right direction for running a ZF2 site in a shared hosted environment?
Are you using the skeleton app?
that seems a little over the top, surely it's lot simpler than that.
move everything from public to the root
change index.php
<?php
/**
* This makes our life easier when dealing with paths. Everything is relative
* to the application root now.
*/
//chdir(dirname(__DIR__));
chdir(__DIR__);
// Setup autoloading
require 'init_autoloader.php';
// Run the application!
Zend\Mvc\Application::init(require 'config/application.config.php')->run();
Simples.
If you are running an application like this you may want to block direct access to some of the Zend Framework folders using htaccess etc

ASP.Net MVC Bundles and Minification

When moving from development to a production environment I have run into some problems with the way in which my javascript files are being minified. It seems that some do not minify properly, and so I have been looking around to find a way to not minify a specific bundle.
public static void RegisterBundles(BundleCollection _bundles)
{
_bundles.Add(new ScriptBundle("~/bundles/toNotMinify").Include(
"~/Scripts/xxxxxx.js"
));
_bundles.Add(new ScriptBundle("~/bundles/toMinify").Include(
"~/Scripts/yyyyy.js"
));
etc..
This is the basic layout in my bundle config class. I want to find a way in which to have all of my bundles minified, apart from the first one. Is this possible? So far the only solution I have found to achieve something similar is to turn off minification globally.
You have a couple of options, you can either replace your use of ScriptBundle with Bundle as in this example:
_bundles.Add(new Bundle("~/bundles/toNotMinify").Include(
"~/Scripts/xxxxxx.js"
));
.. or you could disable all transformations on a newly created bundle, like so:
var noMinify = new ScriptBundle("~/bundles/toNotMinify").Include(
"~/Scripts/xxxxxx.js"
);
noMinify.Transforms.Clear();
_bundles.Add(noMinify);
Obviously the first solution is much prettier :)
You just have to declare a generic Bundle object and specify the transforms you need:
var dontMinify = new Bundle("~/bundles/toNotMinify").Include(
"~/Scripts/xxxxx.js");
bundles.Add(dontMinify);
var minify = new Bundle("~/bundles/toNotMinify").Include(
"~/Scripts/yyyyyy.js");
minify.Transforms.Add(new JsMinify());
bundles.Add(minify);

Using ASP.NET Javascript Bundles from the controller

I realise this breaks the MVC pattern, but there is a viable reason for doing it this way in an application I am currently building :)
What I am trying to do is output a JavaScript bundle directly from the Controller rather than via a link via a View.
So for example I have a bundle called "~/jQueryPlugin" what I'd like to do is something along the lines of
return this.JavaScript(BundleTable.GetBundle("~jQueryPlugin").BundleContent)"
However for the life of me I cannot figure out what the BundleTable.GetBundle("~jQueryPlugin").BundleContent part should be in order to get a string representation of the combined minimized bundle.
Any help would be appreciated·
In the 1.1-alpha1 release we added a new Optimizer class which should allow you to more easily do this. Its intended to be a standalone class that's useable out of side of ASP.NET hosting, so setting it up will be slightly different.
You can get the bundle contents out via something like this:
OptimizationSettings config = new OptimizationSettings() {
ApplicationPath = "<your physical path to the app>",
BundleSetupMethod = (bundles) => {
bundles.Add(new ScriptBundle("~/bundles/js").Include("~/scripts/jqueryPlugin.js"));
}
};
BundleResponse response = Optimizer.BuildBundle("~/bundles/js", config);
Assert.IsNotNull(response);
Assert.AreEqual("<your bundle js contents>", response.Content);
Assert.AreEqual(JsMinify.JsContentType, response.ContentType);
The next release should be fleshing this scenario out more, as it is needed for build time bundling integration with Visual Studio.

ASP.NET MVC IIS problem

I have this piece of code in a .cs file in an ASP.NET MVC application:
HtmlTableCell r2c1 = new HtmlTableCell();
r2.Cells.Add(r2c1);
r2c1.ColSpan = 2;
r2c1.Style.Add("font", "1px arial");
r2c1.Style.Add("height", "10px");
r2c1.Style.Add("background-image", "url(/Content/Images/pagebgbottomwhite.jpg)");
r2c1.Style.Add("background-repeat", "repeat-x");
This works OK locally, but when I deploy my app using IIS 5 I don't see that picture.
How can I change that format of the URL so I can see it?
First off, you don't really want to have this kind of code in your presenter.
As for URL format, try Server.MapPath("~/Content/Images/pagebgbottomwhite.jpg");. And ensure that this file is indeed where it should be.
You really ought to be using CSS and defining a class that has these attributes. The url would then be relative to the location of the CSS file in the site: url(../Images/pagebgbottomwhite.jpg) -- assuming that your css file is in a sibling directory to Images. Then you would apply the CSS class to your element.
I also agree with Anton that, using MVC, this code should not be in your controllers/models, but rather in the view -- in which case you would not be using HtmlTableCell. In that case, and using pure CSS, it's simply a matter of creating the proper row in the table.
<tr><td class="bottom-row" colspan="2"></td></tr>
Confirm that this file (/Content/Images/pagebgbottomwhite.jpg) is deployed. Is it set not to copy or was it left behind in deployment.

Resources