Serving Different CSS Files in ASP.NET Core with Angular

Serve different CSS files based on a header parameter on an Angular application with an ASP.NET Core backend.


Serving different CSS files

This is a guide on how to serve different CSS files based on a passed on styling header that is all made up. So, if the user passes a header called basic, one CSS file will be used, and if the header is called advanced, another CSS file is passed to an Angular application.

This approach can be used with many different scenarios - you could for example use query strings - but this example will use a custom styling header.

Also, this applies to any type of SPA application used with ASP.NET Core (Vue, React, etc), but this example is used with Angular. Worth mentioning is that you can serve any types of static files, it does not have to be different CSS files. I can be logos, favicons or pictures.

Creating the files

First, we need the different CSS files. I have created a folder called StaticFiles in the root of the ASP.NET Core project, and created a folder for each file that I want.

folder structure

All files that we want to change depending on the header, need to have the same name. For example, the CSS file will always be named index.css.

Creating the middleware

I will create a middleware called StatisFilesHelper.cs, and the whole file looks like this.

using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.FileProviders;
using System.IO;

namespace DifferentCSS.Helpers
{
    public static class StaticFilesHelper
    {
        public static void AddCompanySpecificFiles(this IApplicationBuilder app, params string[] companies)
        {
            foreach (string company in companies)
            {
                // Add static files based on styling header for a specific company
                app.UseWhen(
                    context => context.Request.Headers["styling"] == company,
                    appBuilder => appBuilder.UseStaticFiles(new StaticFileOptions()
                    {
                        FileProvider = new PhysicalFileProvider(
                            Path.Combine(Directory.GetCurrentDirectory(), "staticfiles", company)),
                        RequestPath = new PathString("/staticfiles")
                    }));
            }

            // add base fíles if no header is specified
            app.UseWhen(
                context => !context.Request.Headers.ContainsKey("styling"),
                appBuilder => appBuilder.UseStaticFiles(new StaticFileOptions()
                {
                    FileProvider = new PhysicalFileProvider(
                        Path.Combine(Directory.GetCurrentDirectory(), "staticfiles", "base")),
                    RequestPath = new PathString("/staticfiles")
                }));
        }
    }
}

The AddCompanySpecificFiles method needs a list of strings as a parameter, in which each string represents a company (and each company should have its own CSS).

// ...
foreach (string company in companies)
{
    // Add static files based on styling header for a specific company
    app.UseWhen(
        context => context.Request.Headers["styling"] == company,
        appBuilder => appBuilder.UseStaticFiles(new StaticFileOptions()
        {
            FileProvider = new PhysicalFileProvider(
                Path.Combine(Directory.GetCurrentDirectory(), "staticfiles", company)),
            RequestPath = new PathString("/staticfiles")
        }));
}
//...

In this part, I loop through each string to see if it matches the styling header. If it does, I will use the UseStaticFiles method and point it to the path of the CSS with the same name. So if the header is basic, it points /staticfiles to the path StaticFiles/basic, which one of our CSS is located within.

If the styling header would be advanced, the url /staticfiles would point to StaticFiles/advanced.

// ...
 // add base fíles if no header is specified
app.UseWhen(
    context => !context.Request.Headers.ContainsKey("styling"),
    appBuilder => appBuilder.UseStaticFiles(new StaticFileOptions()
    {
        FileProvider = new PhysicalFileProvider(
            Path.Combine(Directory.GetCurrentDirectory(), "staticfiles", "base")),
        RequestPath = new PathString("/staticfiles")
    }));

If no header is specified, it will use the base folder and use that instead.

Adding to Startup

We need to add our middleware to the Startup.cs file. I put my middleware in a Helpers folder, so I have the include it with the using keyword to apply the middleware.

using DifferentCSS.Helpers;
// ...

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    // ...
    app.AddCompanySpecificFiles(new string[] { "basic", "advanced" });

}

I am passing in a list of strings, each string with the same name as the folders we declared earlier.

Adding to HTML

We need to add the reference in main HTML file as well. In my case, this file is served within the ClientApp, which the Angular application resides in. For me, its located in the src application, and called index.html.

In the head, I simply add a link referencing the /staticfiles url.

<link rel="stylesheet" href="/staticfiles/index.css" type="text/css" />

This will apply the CSS file based on the styling header that is passed on.

Be sure to clear your cache if you change header in the middle of a session, or else the CSS won’t change.