DotLessResult - MVC ActionResult for dotless

May 23, 2011 - dotless mvc

I’ve recently had the need to generate dynamic css for a themable MVC web application. I considered using a basic homegrown templating mechanism, or repurposing Razor, but then found the dotless project on the interwebs.

With the NuGet package it was relatively easy to get up & running, and I’ve abstracted the clunky regex code into an ActionResult subclass, recorded here in case it’s useful for somebody else.

public class DotLessResult : ActionResult
{
    public IDictionary<string, string> Parameters { get; set;}
    public string Less { get; set; }
    public bool Minify { get; set; }

    public DotLessResult(string less, IDictionary<string, string> parameters = null, bool minify = false)
    {
        Less = less;
        Parameters = parameters ?? new Dictionary<string, string>();
        Minify = minify;
    }
    
    public DotLessResult(Stream stream, IDictionary<string, string> parameters = null, bool minify = false)
        : this(new StreamReader(stream).ReadToEnd(), parameters, minify) { }

    public override void ExecuteResult(ControllerContext context)
    {
        var output = Less;
        foreach (var key in Parameters.Keys)
        {
            output = Regex.Replace(output, @"\s*@" + key + @":\s*\S+;", "@" + key + ":" + Parameters[key] + ";");
        }
        var css = dotless.Core.Less.Parse(output, new DotlessConfiguration { MinifyOutput = Minify });
        context.HttpContext.Response.ContentType = "text/css";
        using (var writer = new StreamWriter(context.HttpContext.Response.OutputStream, Encoding.UTF8)) {
            writer.Write(css);
            writer.Flush();
        }
    }
}

This can then be used from your action method like so:

public ActionResult Styles(string id)
{
    var stream = GetType().Assembly.GetManifestResourceStream(stylePath + id.Replace(".css", ".less"));
    if (stream == null)
    {
        return HttpNotFound();
    }
    Dictionary<string, string> parameters = new Dictionary<string, string>();
    parameters["backgroundcolor"] = "#1f1400"; // continue for all replaceable parameters
    return new DotLessResult(stream, parameters, true);
}

The .less source should be stored in your web assembly as an embedded resource, with configurable parameters declared using the syntax @: <placeholderValue>;. Then it's just a case of looping through the supplied parameters dictionary and changing the declaration in the .less source. In the example code here I’m looking for a .less resource with the same name as the requested .css file, but you can obviously use your imagination.