CSS Preprocessing with Visual Studio

ASP.NET Core gives breaths new life into web development on the .NET platform. In Visual Studio 2015 with .NET Core, support was added for massively popular package management sources npm and Bower, as well as the task runner utilities Gulp and Grunt.

In this article, we’ll learn how to add a CSS preprocessor to an ASP.NET Core application. We’ll utilize the support for Gulp and npm, while understanding how these tools are used to make a productive workflow by creating simple Gulp tasks that compile Sass to CSS.

Knowing Your Package Manager

With three different package managers, an ASP.NET Core project might seem like a busy place, however each package manager fulfills a specialized need. Choosing between package managers means picking the right tool for the job. In the case of ASP.NET Core, that job can be Node-based JavaScript tooling, client-side development libraries, or server-side .NET application components.

  • npm (Node Package Manager) is a JavaScript package manager. npm packages are commonly for Node.js and Node-based tools like Grunt and Gulp.
  • Bower was designed to for use with front-end development packages. Ideally these are items that will be deployed with the application, like Bootstrap, for instance.
  • NuGet is the package manager for .NET. From .NET Core and Visual Studio 2015 and forward, NuGet should be primarily used for installing .NET application components.
Package Manager Responsibility
NPM JavaScript (node.js) tooling
Bower Client-side Development
NuGet .NET Application components

Taking It to Task

In ASP.NET Core multiple task runners are supported: Gulp, Grunt and MSBuild. Unlike the previously mentioned package managers, task runners do tend to overlap each other in terms of functionality. Each task runner is capable of doing many of the same tasks, however their approach varies greatly.

  • Gulp is a task runner that utilizes Node.js streams to build and manage tasks. Gulp focuses on coded tasks rather than configuration.
  • Grunt is a configuration based task runner that utilizes a JavaScript configuration file to organize and initialize tasks.
  • MSBuild utilizes an XML schema that controls how the build platform processes and builds software.
Task Manager Approach / Style Language
Gulp Functional Code JavaScript
Grunt Configuration File JavaScript
MSBuild Configuration File XML Schema

Install and Configure a CSS Preprocessor

CSS preprocessors like Sass and Less are tools that greatly enhance CSS development. Sass and Less have been around for a while now and are widely adopted by the web development community. CSS preprocessors bring real language features to CSS such as variables and mixins (functions) which result in clean, extensible and reusable CSS code.

For this example, we’ll setup and use Sass (Syntactically Awesome Style Sheets), a preprocessor that is used to build CSS frameworks like Foundation 6 and Bootstrap 4. Since Sass is a superset of CSS it requires a compiler to generate .scss (i.e. Sass) files into .css files that can be understood by the browser.

Installing a Sass compiler is done using the npm package manager since it specializes in the JavaScript based tooling that’s needed for compilation. To install the compiler we’ll open the npm configuration file, package.json, and add "gulp-sass" to the list of dependencies. This tells npm to install a Sass compiler that is designed to work with the Gulp task runner.

"devDependencies": {
  "gulp-sass": "2.1.0"

We’ll need to instruct Gulp on how to use the gulp-sass compiler. In gulpfile.js the dependency for gulp-sass is added using the require function.

var gulp = require("gulp"),
    // more modules...
    sass = require("gulp-sass");

With the dependency resolved, the .sass source and destination .css paths are defined and then a gulp-sass task is added to the pipeline. When the task is executed any .scss files found in the source directory will be compiled and output as .css to the destination. Using the .on('error', sass.logError) function will output errors to the console if there is a problem during compilation.


//where to find sass code
paths.sassSource = paths.webroot + "css/**/*.scss";

//where to output compiled CSS code
paths.cssOutput = paths.webroot + "css";

gulp.task('sass', function () {
        .pipe(sass().on('error', sass.logError))

When the gulpfile.js is saved, the task will show in Visual Studio’s Task Runner Explorer. From here the task can be run on demand or bound to events like build, clean, and project load.


To test the Sass compilation task, convert a .css file to Sass by simply changing the file extension to .scss– any valid .css is also valid .scss. No further changes are needed to convert the code, however features are available that don’t exist in CSS yet like variables, nesting, mixins, inheritance. Once the file is renamed, run the Sass compile task to regenerate the .css file.


Workflow Setup

Having to manually compile .css code after each change would be counterproductive, to solve this problem we’ll setup a seamless workflow. Using Gulp we can create a watch task that looks for changes in our sass directory and, whenever a change is made, the compile task will execute.

A watch task in Gulp is created using the gulp.task function which accepts a list of tasks to run when a change is detected on the target directory. In this case we’ll reuse the sassSource directory and the ‘sass’ compile task.

//Watch task
gulp.task('sass:watch', function () {
    gulp.watch(paths.sassSource, ['sass']);

In addition to the ‘sass’ compile task the minificication task supplied with the MVC template can also be included so a <file-name>.min.css file is created when the .sass code is modified.

//Watch task
gulp.task('sass:watch', function () {
    gulp.watch(paths.sassSource, ['sass', 'min:css']);

To further enhance the CSS workflow, the watch task can be started when the project is opened by adding the task to the Project Open binding. To create the binding, right-click the sass:watch task in Visual Studio’s Task Runner Explorer and choose Bindings > Open Project from the menu.


With the binding created, the sass:watch task will be executed and running every time the project is opened. Now that CSS compilation is completely automated the Sass workflow is completely seamless, as .sass is created or modified, .css files will automatically be generated.


ASP.NET Core and Visual Studio 2015 ships with new tooling to manage packages and automate repetitive tasks. Using npm, powerful tooling like CSS precompliers can be added to a project and, with Gulp, can be set up to easily create a seamless workflow. Consider trying Sass on your next project and enhance your CSS development experience.