Empty Bundle using MS Bundling
This exact scenario occurred (v=[no value]
) because the Build Action
value on the .less
file was accidentally set to None
. This happened because the file was added to the project in an unusual way and then renamed to .less
. Since VS.NET didn't know originally the file type it set it's property for Build Action
to none
.
Make sure the .less
file has its Build Action
configuration set to Compile
, thus allowing the actual file is included in the build. This is also why the problem will not occur locally as it will be present, but once deployed it will be missing.
Does ASP.NET store bundled scripts in memory?
Short answer
Memory. But also remember that the browser already caches the information in the client.
Long answer
First of all, the bundle will be cached by the browser as it's said in the Bundling and Minification page:
Once you update one file in a bundle, a new token is generated for the
bundle query string parameter and the full bundle must be downloaded
the next time a client requests a page containing the bundle. In
traditional markup where each asset is listed individually, only the
changed file would be downloaded. Assets that change frequently may
not be good candidates for bundling.Bundling and minification primarily improve the first page request load time.
Once a webpage has been requested, the browser caches the assets (JavaScript,
CSS and images) so bundling and minification won’t provide any performance
boost when requesting the same page, or pages on the same site
requesting the same assets. If you don’t set the expires header
correctly on your assets, and you don’t use bundling and minification,
the browsers freshness heuristics will mark the assets stale after a
few days and the browser will require a validation request for each
asset
And also shown here, in the image taken from the same page, where they tested with Fiddler:
So far we are safe as it's cached by the browser.
However, I went a bit further and created a small test project with this code in the Controller:
public ActionResult Index()
{
return View(HttpRuntime.Cache);
}
And this code in the View:
<p>
@Html.DisplayForModel()
</p>
Which gave me the following results:
First run:
:ViewCacheEntry:System.Web.Mvc.RazorViewEngine, System.Web.Mvc, Version=5.2.3.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35:View:Index:Home:::__AppStartPage__~/_appstart.cshtml
:ViewCacheEntry:System.Web.Mvc.RazorViewEngine, System.Web.Mvc, Version=5.2.3.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35:View:Index:Home::Mobile:__AppStartPage__~/_appstart.vbhtmlSecond run:
:ViewCacheEntry:System.Web.Mvc.RazorViewEngine, System.Web.Mvc, Version=5.2.3.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35:Partial:_LoginPartial:Home::Mobile:
:ViewCacheEntry:System.Web.Mvc.RazorViewEngine, System.Web.Mvc, Version=5.2.3.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35:View:Index:Home:::System.Web.Optimization.Bundle:~/bundles/modernizr
:ViewCacheEntry:System.Web.Mvc.RazorViewEngine, System.Web.Mvc, Version=5.2.3.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35:Partial:_LoginPartial:Home:::System.Web.Optimization.Bundle:~/bundles/bootstrap__AppStartPage__~/_appstart.cshtml
:ViewCacheEntry:System.Web.Mvc.RazorViewEngine, System.Web.Mvc, Version=5.2.3.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35:View:Index:Home::Mobile:System.Web.Optimization.Bundle:~/bundles/jquerySystem.Web.Optimization.Bundle:~/Content/css__AppStartPage__~/_appstart.vbhtml
On the second run you will see that modernizr, bootstrap, jquery and css (my bundles!) are in the cache. That would explain why if we load the same page in 2 different browsers we will get the same query string, even after being loaded 5mins apart:
- Edge:
- Firefox Dev Edition:
BundleTable.Bundles.GetBundleFor() returns but not Items inside
You need to register your VirtualPathProvider before bundle registration, in order to be able to find your files. Any files not found will not be included in bundle.Items
var vpp = new MyVirtualPathProvider();
BundleTable.VirtualPathProvider = vpp;
BundleConfig.RegisterBundles(BundleTable.Bundles);
Unless of course you already have it registered as HostingEnvironment.VirtualPathProvider.
ASP.NET MVC bundle working on local but not in server
I found the issue, after trying everything I went back an check the build scripts on the TFS server, we have continuous integration configured, turns out the build server was removing the .js and only letting the .min.js files on the final build. I removed that instruction and it started working.
Basically the .js did not exist on the server so there was nothing to bundle.
Thank you guys for your help!
Bundling and minification without ASP.NET MVC
It is absolutely possible to use the bundling and minification in a blank project.
- Use Nuget to install the package:
Install-Package Microsoft.AspNet.Web.Optimization
Create a BundleConfig Class and define your bundles:
using System.Web.Optimization;
public class BundleConfig
{
public static void RegisterBundles(BundleCollection bundles)
{
bundles.Add(new ScriptBundle("~/bundles/js").Include(
"~/Scripts/*.js"));
bundles.Add(new StyleBundle("~/bundles/css").Include(
"~/Styles/*.css"));
}
}Register the BundleConfig class within the application start in the global.asax
void Application_Start(object sender, EventArgs e)
{
BundleConfig.RegisterBundles(BundleTable.Bundles);
}- reference the bundles in your HTML document.
- Enable bundling by disabling debug mode.
less bundle is empty in production
I removed dotless and the transformation pakcages and only used Web optimization framework. This way You can set the framework to compile the less code at build time.
How asp.net Bundling works internally
Let's take a look at what happens when we use the bundling in System.Web.Optimization.
In this example I used the "Empty ASP.NET MVC 4 template" and grabbed the latest "Microsoft.AspNet.Web.Optimization" package from nuget.
I then proceeded to register 2 javascript files. One for jquery and another for bootstrap.
public static void RegisterBundles(BundleCollection bundles)
{
var javascriptBundle = new Bundle("~/bundles/javascripts")
.Include("~/Scripts/jquery-{version}.js")
.Include("~/Content/bootstrap/js/bootstrap.js");
bundles.Add(javascriptBundle);
}
Now that we have our setup done, let's see what happens when we view the page.
You can see that both the javascript files were just included as we would normally do. This is what happens when you have the "debug" flag set in your web.config.
Let's turn this to false and see what happens now.
Now what we see is a single reference was added but with a very unique looking location. By clicking on it, we see that it spits out a minified and combined version of both of the javascript files that were referenced in our bundle.
This funny query string parameter v=loMmcAiXrKwMoVsM8Ok8Q5jVmuFQUI3fiiRVJQC33Hs1 is a reference to our content and we can see that no matter how many times we hit the website, it's going to stay the same. (i.e. refreshing multiple times).
Let's see what fiddler says about the reference to our javascript files.
We can see that the response is cachable. The cache expiration has been set for "Wed, 26 Mar 2014 06:49:06 GMT". Almost a year from today.
Subsequent requests to the resource will get read from the browser's cache.
"This HTTP/304 response indicates that the existing cached response remains fresh. Cache-lifetime headers on a HTTP/304 response may be used to update the cached response's freshness."
If you require any more information, see also http://www.asp.net/mvc/tutorials/mvc-4/bundling-and-minification
Related Topics
Asp.Net MVC Using Web API to Return a Razor View
Attach Debugger to Iis Instance
Webutility.HTMLdecode Vs Httputilty.HTMLdecode
Piecewise Linear Integer Curve Interpolation in C#/Unity3D
"Can't Find Pinvoke Dll 'Dbnetlib.Dll'." Error in Smart Device Application
Cefsharp 3 Set Proxy at Runtime
How to Share Sessions Between PHP and ASP.NET Application
Change the Bordercolor of the Textbox
Are P/Invoke [In, Out] Attributes Optional for Marshaling Arrays
Reading Data from CSV to Screen Output
Is C# Really Slower Than Say C++
How to Get All Input Elements in a Form with HTMLagilitypack Without Getting a Null Reference Error
How to Target Mono Framework from Vs2015
Internal Server Error While Running a Simple .Net Core MVC Application on Ubuntu 16.04