Dynamic Dot Less Css With Asp.net MVC 2

I have been having a look at the best way to theme a asp.net mvc website in the last few weeks. I heard about dot less css late last year but hadn’t had time to integrate it into a project until now.

Integrating dot less css is pretty easy by default, as shown on its home page however I wanted something that could be configured by application users. We want to be able to specify the link html tag like the following.

<link href="/public/css/sites.less" rel="stylesheet" type="text/css" />

There are few steps involved in the solution I have come up with so bare with me as I go through them. Firstly we’ll start with the web.config:

                <add extension=".lessx" type="System.Web.Compilation.PageBuildProvider" />

Insert the builderProviders block inside the compilation section. The compilation section will be under the system.web section. This will enable us to use code blocks in our lessx files.

Secondly, is the routing.

        //Special Route for css so that images are relative to it
                           new { controller = "Css", action = "Index” },
                           new[] { "eLearning.Controllers" });

This specifies that any url matching /public/css/{filename}.less should be routed to the CssController passing the filename as the parameter to the Index method.

    public class CssController : BaseController
        [OutputCache(Duration = 10, VaryByParam = "")]
        public ActionResult Index(string filename)
            if (string.IsNullOrEmpty(filename))
                throw new ArgumentException("A filename must be supplied");

            ViewData["baseColor"] = "#aabbcc";

            var less = RenderViewToString(filename + ".lessx", null);
            var css = LessCss.Generate(less, true);
            return Content(css, "text/css");

    public static class LessCss
        public static string Generate(string less, bool minify)
            var lessEngine = new EngineFactory();
            lessEngine.Configuration.MinifyOutput = minify;
            var output = lessEngine.GetEngine().TransformToCss(less, null);
            return output;

This is the css controller class. It receives the filename as the input, finds the corresponding .lessx file and returns the file with appropriate view data replaced. Is then takes the less formatted string and runs it through the dot less parser to return a css string. This is then returned to the browser with the appropriate content-type. One method I have not shown is the RenderViewToString() and how the .lessx file is located. This method is located on the base controller class that the css controller inherits from. I have also turned Caching on so that it will cache the result for 10seconds.

        protected string RenderViewToString(string viewName, object model)
            if (string.IsNullOrEmpty(viewName))
                viewName = ControllerContext.RouteData.GetRequiredString("action");

            ViewData.Model = model;

            using (StringWriter sw = new StringWriter())
                ViewEngineResult viewResult = ViewEngines.Engines.FindView(ControllerContext, viewName, null);
                ViewContext viewContext = new ViewContext(ControllerContext, viewResult.View, ViewData, TempData, sw);
                viewResult.View.Render(viewContext, sw);

                return sw.GetStringBuilder().ToString();

This method finds the .lessx file and returns the result as a string. Now usually the view engine will take controller name and method name and by convention look in the /Views/css/index.aspx file. It doesn’t quite make sense to put it in the views folder so I have overridden the default web forms view engine so that they can be placed in the /Public/Css folder. This can be configured to your liking (convention).

    public class CustomViewEngine : WebFormViewEngine
        public CustomViewEngine()
            var locs = new List<string>(base.ViewLocationFormats);
            locs.Add("~/Public/{1}/{0}"); //My personal choice
            locs.Add("~/Views/{1}/{0}");  //An alternative choice
            base.ViewLocationFormats = locs.ToArray();

Once your Custom View Engine has been overridden, you will need to add it to the ViewEngines.Engines collection in the application start method in the global.asax.cs.

        ViewEngines.Engines.Add(new CustomViewEngine());

This will then allow us to write a *.lessx file like the following; you can also pass a strongly typed model to the .lessx file if you so wish in the same way you would to a regular aspx view.

<%@ Page Language="C#" Inherits="System.Web.Mvc.ViewPage" %>

@basecolor: <%= ViewData["baseColor"] %>;

body {
    background: @basecolor;

Which will be rendered to the browser as:

body {
    background: #aabbcc;

And that’s it. I’m still working on the finer details but I am liking how it works at the moment. If you have any thoughts or suggestions, please leave a comment.


This entry was posted in .NET and tagged , , , , . Bookmark the permalink.

11 Responses to Dynamic Dot Less Css With Asp.net MVC 2

  1. Pingback: Tweets that mention Dynamic Dot Less Css With Asp.net MVC 2 | Schotime.net -- Topsy.com

  2. tgmdbm says:


    To be more in keeping with MVC this would be better implemented as an ActionResult and an extension method on Controller.

    return Less(filename, model);

    also be aware that you can pass variables to the less parser by including them on the query string. you might not need to run it through the whole WebForms engine

    <link href="/public/css/sites.less?basecolor=#aabbcc" rel="stylesheet" type="text/css" />

    • Schotime says:

      You are indeed correct about the extension method. That is a better way to do it.

      I did see the variables you can pass into the query string. If I was to use that I think I would still run it through a controller as its easy to gather the resources needed to pass to the style sheet in the controller rather than in the master page using a action filter or something.

      Is there a way to pass a list of key value pairs to the parser to be processed with the less file?

  3. Pingback: Dynamic Dot Less Css With Asp.net MVC 2 | Schotime.net | My Blog

  4. Pingback: ASP.NET MVC Archived Blog Posts, Page 1

  5. Nathan says:

    Nice walkthrough and a clever approach, but like some of the other commenters I also think that involving the ViewEngine may be an unnecessary step. Returning a custom ActionResult is more in-line with the intended model in MVC.

  6. Szymon Sasin says:


    instea creatning custom ViewEngine why not use existing facility?

    public static class LessCssHelper
    static LessCssHelper()
    _fileFormats = new[] {
    public static string Generate(string fileName, bool minify)
    var lessEngine = new EngineFactory();
    lessEngine.Configuration.MinifyOutput = minify;
    var output =
    .TransformToCss(GetFile(fileName), null);
    return output;

    private static string GetFile(string fileName)
    var result = string.Empty;
    var pathProvider = HostingEnvironment.VirtualPathProvider;

    foreach (var format in _fileFormats)
    var nameWithExtension = String.Format(format, fileName);
    if (pathProvider.FileExists(nameWithExtension))
    var file = pathProvider.GetFile(nameWithExtension);
    using (var stream = new StreamReader(file.Open()))
    result += stream.ReadToEnd();

    return result;

    private static string[] _fileFormats;

    All you have to do is to pass a file name requested.

    Second thing is to keep a MC style ( so without .less extension)


  7. Pingback: .LESS–dynamische Stylesheets für .NET Entwickler | Code-Inside Blog

  8. Pingback: .LESS – dynamic stylesheets for .NWT Developer | Code-Inside Blog International

  9. Pingback: .LESS – dynamic stylesheets for .NET Developer | Code-Inside Blog International

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s