This project has moved and is read-only. For the latest updates, please go here.

.less handler watching only main .less file?

Aug 16, 2013 at 7:09 PM
In my project I only need the bundle transformer's http handler for .less files.

Like most projects, I have a single .less (i call manifest.less) file that contains import statements to all of the other .less files I use.

When I alter a file referred to within manifest.less, I expect the bundle transformer http handler to recompile my .less files (this is what the dotless http handler does), but it appears the only way I can get a recompile is to touch manifest.less. Is there a setting I am missing?
Aug 16, 2013 at 10:39 PM
For those as confused as I was, buried in the example web.config is this tidbit
<bundleTransformer xmlns="http://tempuri.org/BundleTransformer.Configuration.xsd">
<core>
  <assetHandler clientCacheDurationInDays="365" enableCompression="true"
        serverCacheDurationInMinutes="15" useServerCacheSlidingExpiration="false"
        disableClientCacheInDebugMode="true" disableCompressionInDebugMode="true" />
 </core>
</bundleTransformer>
setting clientCacheDurationInDays to 0 seems to have fixed my issue.
Aug 19, 2013 at 12:00 AM
I tried this, but it doesn't solve the problem.

After updating Bundle Transformer to the version that no longer uses dotless, the bundles aren't being invalidated when I make changes to LESS files in the project. I'm forced to rebuild the project every time I make a change to the CSS for it to be reflected.

I'm running (and building) in debug mode.
Aug 19, 2013 at 11:42 AM
Hello, Bcullman!

LESS HTTP handler is intended only for debugging. LESS-files should be registered as bundles.
Aug 19, 2013 at 12:00 PM
Hello, Nettsentrisk!

In my projects a cache expiration of the LESS HTTP handler working is correct.

Verify that the HTTP handler for LESS-files is registered in the Web.config file. Must be the following handler:
<configuration>
    ...
    <system.web>
        <httpHandlers>
            ...
            <add path="*.less" verb="GET" 
                type="BundleTransformer.Less.HttpHandlers.LessAssetHandler, BundleTransformer.Less" />
            ...
        </httpHandlers>
    </system.web>
    <system.webServer>
        <handlers>
            ...
            <add name="LessAssetHandler" path="*.less" verb="GET" 
                type="BundleTransformer.Less.HttpHandlers.LessAssetHandler, BundleTransformer.Less" resourceType="File" preCondition="" />
            ..
        </handlers>
    </system.webServer>
</configuration>
Aug 19, 2013 at 12:17 PM
Yes, the handler is added in system.webServer (not in system.web/httpHandlers due to not working in Integrated mode, as far as I understand), but adding the client cache expiration only works for the first change to a LESS file after building the project anew. New changes after the first are not reflected on the site until I rebuild again.

In debug mode the bundles aren't really being used, are they? Does the LESS HTTP handler know to rebuild the generated LESS file when a change is made to it?
Aug 19, 2013 at 12:34 PM
I not have such problems in debug mode and release mode. All the dependencies (imports and data-uri functions) are handled correctly.

Give an example of your LESS-file.
Aug 19, 2013 at 1:56 PM
My problem is that after updating to Bundle Transformer that no longer use dotless, changes to my LESS-files are not showing up on the site, unless I rebuild the whole site. Both in debug and release mode.

When in debug mode, the LESS HTTP handler seems to just return HTTP 200 and serve the compiled LESS that was created on first run after build, and it never updates itself after changes are made to the LESS files. When dotless was a part of Bundle Transformer, it would serve HTTP 304 when there were no changes, and a new file with HTTP 200 when changes were made in the project.

When in release mode, the minified bundle being served does not get updated with changes to the LESS files after initial run after build.

In debug with the dotless-version, a less file returns the following HTTP headers:
  • Cache-Control:public
  • Content-Encoding:gzip
  • Content-Length:942
  • Content-Type:text/css; charset=utf-8
  • Date:Mon, 19 Aug 2013 12:40:55 GMT
  • ETag:"2nPcVSuOqsE2f2Fa+Zvv+RZKwm/tt0j5Q8Fb+bpjiYE="
  • Expires:Mon, 26 Aug 2013 12:40:55 GMT
  • Last-Modified:Mon, 19 Aug 2013 12:40:53 GMT
  • Server:Microsoft-IIS/8.0
  • Vary:*
  • X-SourceFiles:=?UTF-8?B?RDpcUHJvamVjdHNcRXBpbm92YVxFcGlub3ZhLlNvbHV0aW9udGVtcGxhdGVcc3JjXEVwaW5vdmFUZW1wbGF0ZS5XZWJcU3R5bGVzXGdsb2JhbFx+c2l0ZS5sZXNz?=
  • X-UA-Compatible:IE=Edge,chrome=1
In debug with the latest version of BT, the less file returns the following headers:
  • Cache-Control:no-cache, no-store, must-revalidate
  • Content-Encoding:gzip
  • Content-Length:1161
  • Content-Type:text/css; charset=utf-8
  • Date:Mon, 19 Aug 2013 12:44:56 GMT
  • Expires:-1
  • Pragma:no-cache
  • Server:Microsoft-IIS/8.0
  • Vary:Accept-Encoding
  • X-SourceFiles:=?UTF-8?B?RDpcUHJvamVjdHNcRXBpbm92YVxFcGlub3ZhLlNvbHV0aW9udGVtcGxhdGVcc3JjXEVwaW5vdmFUZW1wbGF0ZS5XZWJcU3R5bGVzXGdsb2JhbFx+c2l0ZS5sZXNz?=
  • X-UA-Compatible:IE=Edge,chrome=1
Setting clientCacheDurationInDays=0 gives the exact same headers.

The test file itself is just this:
body {
    background: blue;
}
I can change the background color in this file as much as I want, and the changes will never be reflected on the site until I rebuild it. WIth the dotless version, the changes would show upon refresh of the page.

So it seems the HTTP handling of the LESS files - and the bundles, has been altered for the worse after removing the dotless handler.

As soon as I roll back from the newest version of BT to 1.7.16, everything works fine again.
Aug 19, 2013 at 2:02 PM
Have you read the readme.txt file of BundleTransformer.Less 1.7.16?


   ----------------------------------------------------------------------
              README file for Bundle Transformer: LESS 1.7.16

   ----------------------------------------------------------------------

          Copyright 2013 Andrey Taritsyn - http://www.taritsyn.ru
          

   ===========
   DESCRIPTION
   ===========
   BundleTransformer.Less contains translator-adapter LessTranslator. 
   This adapter makes translation of LESS-code to CSS-code. Also contains 
   HTTP-handler LessAssetHandler, which is responsible for text output 
   of translated LESS-asset.

   Uses NuGet-package the dotless (http://nuget.org/packages/dotless).
 
   ====================
   POST-INSTALL ACTIONS
   ====================
   To make LessAssetHandler is the default HTTP-handler for LESS-assets, 
   you need to make changes to the Web.config file.
   In the configuration\system.web\httpHandlers element you need to 
   find the following code:
   
   <add path="*.less" verb="GET" 
     type="dotless.Core.LessCssHttpHandler, dotless.Core" />
     
   And replace it with:

   <add path="*.less" verb="GET" 
     type="BundleTransformer.Less.HttpHandlers.LessAssetHandler, BundleTransformer.Less" />

   Then in the configuration\system.webServer\handlers element you need to 
   find the following code:
   
   <add name="dotless" path="*.less" verb="GET" 
     type="dotless.Core.LessCssHttpHandler,dotless.Core" resourceType="File" 
     preCondition="" />

   And replace it with:
   
   <add name="LessAssetHandler" path="*.less" verb="GET" 
     type="BundleTransformer.Less.HttpHandlers.LessAssetHandler, BundleTransformer.Less" 
     resourceType="File" preCondition="" />  
   
   =============
   DOCUMENTATION
   =============
   See documentation on CodePlex - 
   http://bundletransformer.codeplex.com/documentation
Aug 19, 2013 at 2:08 PM
Ah! So I'm using the dotless LESS handler for it to work properly. I remember now, I couldn't use the Bundle Transformer LESS handler, because it didn't work properly. No wonder it's not working now in the newest version.

Why doesn't the BT LESS handler work the same way as the dotless one? How can you make it so that it serves up changes on refresh instead of having to rebuild the project after every CSS change?

And if this just doesn't work properly with the BT handler, can I install the dotless one again and still use it or will this be broken since it's not a part of the BT project anymore?
Aug 19, 2013 at 2:57 PM
I have everything works correctly.

These headers do not allow caching on the client:

•Cache-Control:no-cache, no-store, must-revalidate
•Content-Encoding:gzip
•Content-Length:1161
•Content-Type:text/css; charset=utf-8
•Date:Mon, 19 Aug 2013 12:44:56 GMT
•Expires:-1
•Pragma:no-cache
•Server:Microsoft-IIS/8.0
•Vary:Accept-Encoding
•X-SourceFiles:=?UTF-8?B?RDpcUHJvamVjdHNcRXBpbm92YVxFcGlub3ZhLlNvbHV0aW9udGVtcGxhdGVcc3JjXEVwaW5vdmFUZW1wbGF0ZS5XZWJcU3R5bGVzXGdsb2JhbFx+c2l0ZS5sZXNz?=
• X-UA-Compatible:IE=Edge,chrome=1

The problem here is not in the HTTP handler.

I need the following information from you:
  1. How do you register a LESS-files?
  2. Content of the configuration/bundleTransformer element from your the Web.config file
  3. Content of your real LESS-file (with @import directives).
Aug 19, 2013 at 3:13 PM
The caching isn't the problem, a new version of the LESS files isn't being returned/compiled after making changes, period. Not in release mode either, when the LESS is being bundled. Only way to make it show changes is to build the project or touch web.config.

Answers to your questions:
  1. Run in an initializer:
var cssTransformer = new CssTransformer();
var globalStyles = new Bundle("~/ui/css");
globalStyles.IncludeDirectory("~/Styles/global", "*.less", true);
globalStyles.Include("~/Styles/global/normalize.css");
globalStyles.Transforms.Add(cssTransformer);
BundleTable.Bundles.Add(globalStyles);
In Global.asax:
System.Web.Optimization.Styles.DefaultTagFormat = "<link rel=\"stylesheet\" media=\"screen\" href=\"{0}\" />";
In the MVC view template:
@Styles.Render("~/ui/css")
  1. web.config:
<bundleTransformer xmlns="http://tempuri.org/BundleTransformer.Configuration.xsd">
    <core>
      <css>
        <translators>
          <add name="NullTranslator" type="BundleTransformer.Core.Translators.NullTranslator, BundleTransformer.Core" enabled="false" />
          <add name="LessTranslator" type="BundleTransformer.Less.Translators.LessTranslator, BundleTransformer.Less" />
        </translators>
        <minifiers>
          <add name="NullMinifier" type="BundleTransformer.Core.Minifiers.NullMinifier, BundleTransformer.Core" />
        </minifiers>
      </css>
      <js>
        <minifiers>
          <add name="NullMinifier" type="BundleTransformer.Core.Minifiers.NullMinifier, BundleTransformer.Core" />
        </minifiers>
        <translators>
          <add name="NullTranslator" type="BundleTransformer.Core.Translators.NullTranslator, BundleTransformer.Core" enabled="false" />
        </translators>
      </js>
    </core>
  </bundleTransformer>
  1. I have lots of LESS-files being included, but they run fine every time the project is built, so there can't be any errors there. They all start with:
@import "_vars";
But as I'm saying, the actual compiling of the LESS files works fine because whenever I build the project, it creates correct CSS and there's no errors.

The dotless HTTP LESS handler works as expected, so I'm not sure why the Bundle Transformer version acts completely differently. It should act the same (with the same way of handling caching).
Aug 19, 2013 at 3:58 PM
Unfortunately, not able to reproduce your error.

A similar problem was fixed in BundleTransformer.Core 1.7.11 Beta 1 (http://nuget.org/packages/BundleTransformer.Core/1.7.11-Beta1).

It is possible that you also as Ryno1234 jumped the gun .
Aug 19, 2013 at 4:08 PM
I've been looking at this and testing different things for hours, so no, I haven't jumped the gun. I'd love to know what Ryno1234 did to solve his problem, though.

What still hasn't been explained is why the dotless version of the handler works, and the Bundle Transformer one does not. That's the whole reason I switched from the Bundle Transformer one to the dotless one, because it has never worked as it should.

When you change a file, it should return HTTP 200 with a new version of the file. If no changes are made, it should return HTTP 304. That simple functionality is just not working right now. I have to rebuild the project after every CSS change to get the new version.

Can you send me a working test project so I can see whether it works as it should in my environment?
Aug 19, 2013 at 4:18 PM
Explain to me: not working expiration of cache or are you just want ETag and Last-Modified headers with 302 status?

My example project is called BundleTransformer.Example.Mvc - https://bundletransformer.codeplex.com/SourceControl/latest.
Aug 19, 2013 at 6:24 PM
Edited Aug 19, 2013 at 6:24 PM
There were actually a few bits i twiddled for the <asset> node in web.config. perhaps these options will help
<assetHandler clientCacheDurationInDays="0" enableCompression="false" serverCacheDurationInMinutes="1" useServerCacheSlidingExpiration="false" disableClientCacheInDebugMode="true" disableCompressionInDebugMode="true" />
Aug 19, 2013 at 6:33 PM
Edited Aug 19, 2013 at 6:33 PM
In the next version I plan to remove this configuration element, because the HTTP handlers of Bundle Transformer are used only when debugging.
Aug 19, 2013 at 9:24 PM
My org already has a pretty entrenched tool for dealing with bundling and minimizing.

My problem (along with others, likely) is that we want to move to Bootstrap 3.0, which is utilizing features of .less 1.4x.

Dotless, our current http handler, is only valid to less 1.3.2, so it can't compile Boostrap 3.0 less files.

Your http handler is the only game in town.
Aug 19, 2013 at 9:34 PM
OK, I've tried your example project, and the problem does not happen there. I'm trying to use this within a CMS, and it might be doing something with the requests, although that doesn't explain why the dotless handler is working fine. I tried rewriting the code in my solution to be virtually identical to how the setup is in your example project, but the problem still persists. Changes to LESS files do not result in a newly compiled LESS file in the browser, until a new build is run.

Thanks for the attempt to help, but I guess I'll have to see whether the CMS is doing something that only applies to your handler and not the dotless handler. If you know of any main differences between how they work, let me know.

I hope we get it figured out, Bundle Transformer is a great library!

PS. You should definitely look at having the less http handler work the same way as the dotless one, when it comes to response headers and HTTP codes. The no-cache stuff isn't really necessary if the response headers are correct and guide the browser to know whether it should update or not. Sending an HTTP 200 code when the file has changed and ensuring the modified date is given correctly will make the browser download the new one, anyway. It should return 304 if the file is not changed, even in debug mode.
Aug 27, 2013 at 8:12 AM
Hello, Bcullman and Nettsentrisk!

In new version I added to the base debugging HTTP handler support of the ETag HTTP header. But, unfortunately, I do not have technical possibilities to add support of the Last-Modified HTTP header (to access the file system I use BundleTable.VirtualPathProvider).

Perhaps they might help solve your problem.