DotLessResult - MVC ActionResult for dotless
May 23, 2011 -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.