cssvisual-studiorazorserver-side

Dynamic Stylesheets Using Razor


How can I use Razor in CSS files?

I'm using Razor View Engine for some time and I was curious about using it on style sheets. I can use Razor in <style> blocks of .cshtml files but I was wondering if I can use it in external .css files also (would like to have a .cscss format). So I googled it and found two things:

The first one is LESS: "The dynamic stylesheet language". It seems easy-to-use and powerful with all the features but I need Razor-C#, really.

The second is Dynamic CSS Using Razor Engine, a CodeProject article which is more like what I want but it has no caching or pre-compiling support (by "no support" I meant the writer didn't mention these aspects). I also would like to have some syntax highlighting in Visual Studio but this is secondary.

So, how can I write Razor in CSS files with minimum performance cost and preferably with syntax highlighting?

  • Is there a "more complete" project for that?
  • Can I improve the above project to achieve caching/compiling? If so, how?

As a side note:
I found a project called RazorJS. It's like the Javascript version of the same thing I want for CSS with its caching support. I'm mentioning this just to clarify my needs. I don't need to use Razor in Javascript currently but I guess if I make it out with CSS, doing the same thing with Javascript wouldn't be too hard.


Solution

  • You could create a custom view engine:

    public class CSSViewEngine : RazorViewEngine
    {
        public CSSViewEngine()
        {
            ViewLocationFormats = new[] 
            { 
                "~/Views/{1}/{0}.cscss", 
                "~/Views/Shared/{0}.cscss" 
            };
            FileExtensions = new[] { "cscss" };
        }
    
        protected override IView CreateView(ControllerContext controllerContext, string viewPath, string masterPath)
        {
            controllerContext.HttpContext.Response.ContentType = "text/css";
            return base.CreateView(controllerContext, viewPath, masterPath);
        }
    }
    

    and also register it with a custom extension in Application_Start:

    ViewEngines.Engines.Add(new CSSViewEngine());
    RazorCodeLanguage.Languages.Add("cscss", new CSharpRazorCodeLanguage());
    WebPageHttpHandler.RegisterExtension("cscss");
    

    and inside web.config associate the extension with a build provider:

    <compilation debug="true" targetFramework="4.0">
        <assemblies>
            ...
        </assemblies>
    
        <buildProviders>
            <add extension=".cscss" type="System.Web.WebPages.Razor.RazorBuildProvider, System.Web.WebPages.Razor, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>
        </buildProviders>
    </compilation>
    

    [note, if you get an assembly binding error you might need to change the version number in the extension type to match your version of the Razor engine. You can check which version you are using by looking at the properties of your reference to the System.Web.WebPages.Razor assembly in your project]

    And the last step is to have some controller:

    public class StylesController : Controller
    {
        public ActionResult Foo()
        {
            var model = new MyViewModel
            {
                Date = DateTime.Now
            };
            return View(model);
        }
    }
    

    and a corresponding view: (~/Views/Styles/Foo.cscss):

    @model AppName.Models.MyViewModel
    
    /** This file was generated on @Model.Date **/
    
    body {
        background-color: Red;
    }
    

    which could now be included as a style in the Layout:

    <link href="@Url.Action("Foo", "Styles")" rel="stylesheet" type="text/css" />