Dynamic Stylesheets Using Razor
Asked Answered
J

2

15

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.

Jailbird answered 23/4, 2012 at 11:43 Comment(3)
You keep talking about syntax highlighting, this has nothing to do with razor. It is Visual Studio that does your editor. What is it you are trying to achieve, why do you want 'razor' in your css?Symmetry
@Symmetry why do anyone want razor in their html? Why people use server-side scripting languages? Because they want their pages to be dynamic. This way they can store their data in a database instead of an html file. So why do I want razor in my css is because I want my css to be dynamic as well. I may keep design related data in my database (like background-color) and want to use it in my css. As for intellisense, visual-studio is one of this qustion's tags. I want to know how I can (if I can) use razor intellisense in css files and as I mentioned it's just a secondary thing to me.Ineffable
@d4wn: Why do you want your CSS to be dynamic? There is quite a distinction between SASS/LESS and a view engine approach, in the latter case you're just sending the client non-cached stuff that could just be static... :SInvidious
R
30

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" />
Refract answered 23/4, 2012 at 13:14 Comment(3)
That's exactly what I was looking for, thank you. My next quest is to find how to make VS do some syntax higlighting (& intellisense) for .cscss files, I guess.Ineffable
@Darin Dimitrov I have copied this code. And when I want to compile(F5) my asp.net mvc3 solution in VS I got this error: Error 136 Could not determine the code language for "~/Views/Styles/Test.cscss". AMS\AMS\ASPNETCOMPILER any idea why?Manganite
@Darin, the code's awesome but I'm wondering how it could be modified to serve a Less file since that involved an extra level of interpretation… thoughts?Toshiatoshiko
B
0

Google brought me here so here's my answer for a Razor Pages Application

Have a controller route where you can return the css file. Don't forget to app.MapControllers(); in start up

public class StyleController : ControllerBase
{
    [HttpGet("themes.css")]
    public IActionResult GenerateApplicationTheme()
    {        
        var applicationStyles = GenerateStyles();
        var fileBytes = Encoding.UTF8.GetBytes(applicationStyles);

        return new FileContentResult(fileBytes, "text/css");
    }
}

In shared _Layout.cshtml or where ever reference it. If you don't set the route in the Get attribute it won't be referenced correctly.

<link rel="stylesheet" href="@Url.Action("GenerateApplicationTheme", "Style")" />
Boatyard answered 8/12, 2023 at 23:53 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.