SmoothFriction.nl

posts - 39, comments - 20, trackbacks - 0

Using LessCSS in an ASP.NET site

Recently I discovered a true gem (pun intended) called LessCSS. It’s a ruby gem, which is simply an easy-to-install ruby library, which supplements the regular CSS markup with some really nice features. From their site:

“Less is Leaner css. Less extends css by adding: variables, mixins, operations and nested rules.”

I suggest you check out the site for some examples. Anyway, the way this works is by writing your LessCSS files and then running them through a commandline compiler which builds it into true CSS. This might seem fine at first, but it’s a royal pain in the ass when you’re constantly tweaking CSS (like I usually am when I write CSS). If you’re using Rails there already is a plugin available, but not for us die-hard ASP.NET guys. So I decided to roll my own.

DISCLAIMER:

THIS CODE IS VERY CRUDE, IT’S WRITTEN TO DO THE JOB IT’S SUPPOSED TO. DO NOT USE THIS IN PRODUCTION CODE, AS I WILL NOT BE HELD ACCOUNTABLE. IN OTHER WORDS, THIS CODE IS UGLY, NON PERFORMANT AND QUITE POSSIBLY BUGGY.

Alright, after warning you guys, here’s how it works. ASP.NET allows us developers to write our own HTTP handlers which will be fired if a file is requested which matches the filter we’ve configured. If you look in your out of the box web.config, you’ll see a few of those defined under system.web –> HttpHandlers. The ones defined are to handle web services, precompiled resources and such. For aesthetic reasons, we’ll add our LessCSS handler to this list, filtering for “*.css”. We do this by adding this element as a child under system.web –> HttpHandlers:

<add type="LessCSS.LessCssHttpHandler, LessCSS" validate="false" path="*.css" verb="*" />

This will make sure that files with a .css extension will be routed to the LessCssHttpHandler, which will process the request and quite possibly (and hopefully!) send something back. Remember, the only thing the request contains that’s interesting to us is the requested filename.

The handler itself is just a very crude implementation of the IHttpHandler interface. This interface defines the minimal HttpHandler implementation. It contains a method, ProcessRequest, and a property, IsReusable. Only the first one is important to us. This is the one to implement if you want to send something back over the line. Our implementation will execute these steps:

  • Retrieve requested filename;
  • Map URL to local filename;
  • Generate an ‘outfile’ name, by swapping the .css extension with .out. This is where the processed file will be after running the lessCss parser;
  • Run the parser, wait until finished;
  • Read the outfile, drop into the response stream;

All in all, pretty simple eh? And here’s the implementation:

using System; 
using System.Diagnostics; 
using System.IO; 
using System.Web; 

namespace LessCSS 
{ 
    public class LessCssHttpHandler : IHttpHandler 
    { 
        // your binary path for the ruby executable (and the gems) 
        private const string rubyPath = @"c:\ruby\bin"; 

        public void ProcessRequest(HttpContext context) 
        { 
            // our unprocessed filename 
            string lessFile = context.Server.MapPath(context.Request.Url.LocalPath); 
            // our processed filename 
            string cssFile = Path.ChangeExtension(lessFile, ".out"); 
            // formatted: lessc 'input' 'output' 
            string args = String.Format(@"{0} {1} {2}", Path.Combine(rubyPath, "lessc"), lessFile, cssFile); 

            ProcessStartInfo processInfo = new ProcessStartInfo(Path.Combine(rubyPath, "ruby.exe"), args) 
                  { 
                      WindowStyle = ProcessWindowStyle.Hidden 
                  }; 
            Process lessProcess = Process.Start(processInfo); 
            lessProcess.WaitForExit(); 

            context.Response.ContentType = "text/css"; 
            context.Response.WriteFile(cssFile); 
        } 

        public bool IsReusable 
        { 
            get { return true; } 
        } 
    } 
}

All in all it works pretty fast, it’s nice for quickly changing (Less)CSS files. I already spotted a lot of little errors, points which may cause bugs or unwanted behaviour, and so on. It also feels wrong to call a process like that and then waiting for it to finish. Maybe one day someone will take the lessCSS code and compile it using IronRuby, which would make life a lot easier for me. But for now, this is good enough! I am compiling my CSS before deploying anyway ;-) Oh, and please let me know if this worked for you.

NOTE:
Visual Studio generates a Byte-Order Mark at the start of each file it creates. This will cause the current version of LessCSS to bail out, resulting in no output. To prevent this, you should create your CSS file(s) in notepad, save them, add to your project. THEN you can edit and save them in visual studio.

 

Additionally, if anyone is interested in making a full fledged HttpHandler for this (one without calling processes for instance ;-)), please let me know. I’d love to help out on that!

Print | posted on Sunday, July 12, 2009 5:08 AM |

Feedback

No comments posted yet.

Post Comment

Title  
Name  
Email
Url
Comment   
Please add 2 and 6 and type the answer here: