Multiple Directories for Static Files in ASP.NET Core
Tags: aspnetcore, webdev
Published: 2022-07-17 22:44:49

---
title: Multiple Directories for Static Files in ASP.NET Core
published: true
date: 2022-04-25 00:00:00 UTC
tags: 
  - aspnetcore
  - webdev
canonical_url: https://wildermuth.com/2022/04/25/multiple-directories-for-static-files-in-aspnetcore/
cover_image: https://wilderminds.blob.core.windows.net/img/2022/04/25/mistake.jpg
---

My recent video, [SPAs in ASP.NET Core Another Attempt](https://www.youtube.com/watch?v=HOJ8ge0Mi7Q), elicited several interesting responses. But immediately, I noticed that using [ASP.NET](http://asp.net/) Core’s cache busting (e.g. asp-append-version) wasn’t working quite right for additional StaticFiles middleware. Evidently, I wasn’t doing it correctly. Let’s walk you through it.

I forked the [ASP.NET Core Repository](https://github.com/dotnet/aspnetcore) and decided I’d get digging into the source. I had thought I’d try to do a Pull Request to fix what I thought was a bug in the framework. But as they say, “Pride before a Fall” and all that. It was my misunderstanding of how some internals worked.

I naively recommended that you added the StaticFiles middleware twice:

```
// WRONG WRONG WRONG
app.UseStaticFiles();

app.UseStaticFiles(new StaticFileOptions()
{
  // Add the other folder, using the Content Root as the base
  FileProvider = new PhysicalFileProvider(
    Path.Combine(builder.Environment.ContentRootPath, "OtherFolder"))
});

```

On the face of it, this seems to work. The middleware will look for the files in the typical `wwwroot` folder and then in my `OtherFolder` and return them. When I would try to add `asp-append-version` to files in the `OtherFolder`, it would just fail to add a version. Appending the version depends on a checksum of the file and since it couldn’t find it, it just skipped it.

I mistakenly believed that StaticFiles depended on the middleware to find the file. Instead, it relies on the `WebRootFileProvider`. But first, what is a `FileProvider` (e.g. implements the `IFileProvider` interface)?

The docs have a good write it up on it ([here](https://docs.microsoft.com/aspnet/core/fundamentals/file-providers)), but i’ll summarize by simply saying service that knows how to find files in different ways. The framework has several implementations including `PhysicalFileProvider` and `ManifestEmbeddedFileProvider`. In fact, our bad example above actually uses the PhysicalFileProvider. Since we know about these providers, what the UseStaticFiles actually does is just use the `WebRootFileProvider` as the way to find static files (and that one is just looking in `wwwroot`). So the real way to handle this is to change the FileProvider.

So, we need a way to take the two providers we care about and use both of them. First we create the providers we need (two providers in this example):

```
// Build the different providers you need
var webRootProvider = 
  new PhysicalFileProvider(builder.Environment.WebRootPath);

var newPathProvider = 
  new PhysicalFileProvider(
   Path.Combine(builder.Environment.ContentRootPath, @"Other"));

```

Next we can use the third kind of FileProvider that is supplied in [ASP.NET](http://asp.net/) Core. It allows us to compose our providers into a combination of the other providers. This provider is called `CompositeFileProvider`. So to solve our issue, we need to create a new CompositeFileProvider:

```
// Create the Composite Provider
var compositeProvider = 
  new CompositeFileProvider(webRootProvider,
                            newPathProvider);

```

Finally we replace the `WebRootFileProvider` with our new `CompositeFileProvider`:

```
// Replace the default provider with the new one
app.Environment.WebRootFileProvider = compositeProvider;

```

If you want to see the entire sample, you can see it in the reproduction case I wrote for the Issue I created:

**[AppendVersionRepro](https://github.com/shawnwildermuth/AppendVersionRepro/blob/2bce7500bad5bea7f9a7d45134421c678081155c/Program.cs#L21)**

P.S. I closed the issue I created in the [ASP.NET](http://asp.net/) Core repo since it was a user error, like it is too many times.

[![Creative Commons License](http://i.creativecommons.org/l/by-nc-nd/3.0/88x31.png)](http://creativecommons.org/licenses/by-nc-nd/3.0/)

 This work by [Shawn Wildermuth](http://wildermuth.com) is licensed under a [Creative Commons Attribution-NonCommercial-NoDerivs 3.0 Unported License](http://creativecommons.org/licenses/by-nc-nd/3.0/).  
 Based on a work at [wildermuth.com](http://wildermuth.com).

* * *

If you liked this article, see Shawn's courses on [Pluralsight](http://shawnw.me/pscourses).