Core Concepts:

Serving static files

In this article, we'll talk about how to serve static files in an ASP.NET Core MVC application. But first, let's talk about what a static file is. In this world of dynamic websites, where content is generated on-the-fly, for instance by code written in C#, a static file is the exact opposite: It's written by you in your editor, saved to the disk and then served completely as it is by the webserver. This is commonly used for images, CSS and JavaScript files, because even though these could be generated on the fly (and sometimes that can be very useful) and be dynamic, it's often sufficient to serve them as static files.

The next important question is: Why does this subject even need an article in this tutorial? If you have worked with other serverside frameworks, like PHP, ASP Classic or even ASP.NET WebForms, you are used to the fact that a static file can be served through the webserver just as easily as a dynamic file - in these frameworks it usually just depend on the extension. So for instance, a file called "style.css" will be served directly, without going through the ASP.NET pipeline (which will save some resources), while a file called "style.aspx" will be handled by the ASP.NET framework (but the final result can still be a Stylesheet!).

Enabling support for static files

However, in ASP.NET Core, things are a bit different. Support for static files is not even enabled by default - you will have to enabled it by calling UseStaticFiles() in the Startup.cs file. This is very much in line with the modular approach used by ASP.NET Core, where things are enabled on a need-to-use basis, to keep your application fast and lean.

So, the first thing we need to do is to open the Startup.cs file and modify the Configure() method so that it includes the call to UseStaticFiles(). Here's how it could look:

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)

With this in place, your application will be allowed to serve static files.

Including static files

But there's another little detail which you need to be aware of, which separates ASP.NET Core from e.g. PHP or ASP Classic: Static files can't just be placed in the root of your application or in a random folder beneath it. Instead, a special folder has been introduced, called "wwwroot". This will be the location for all your static files and folders and it can be added to your project like any other folders. Just right-click the project in the Solution Explorer and select Add -> New Folder:

When prompted for a name, make sure to call it wwwroot. If you did it right, you will see that this is indeed a special folder in ASP.NET Core, because despite the fact that the folders and files of the Solution Explorer is usually sorted alphabetically, the wwwroot folder is immediately moved to the top of the tree and it even has its own icon:

You are now ready to serve static files in your application! Files and folders placed in the wwwroot folder will be directly accessible through the root of your web application URL. Test this out by adding an HTML file to this new folder (right-click the folder and select Add -> New Item... and then select the HTML Page) and call it e.g. "test.html". Just add some random stuff to it and then try calling it through the URL of your application. So for instance, if your application is located at https://localhost:44380/, you will be able to access the file at https://localhost:44380/test.html.

You can of course add child-folders to your wwwroot folders - this is usually a good idea if you have severeal files of different types. A common thing to do is to create folders for Stylesheets (CSS), JavaScript and Images, but that's completely up to you. Just remember that the folder names will of course have to be included in the URL you use to access the files, e.g. https://localhost:44380/Images/logo.png.

Enabling directory browsing

A lot of webservers will automatically generate a list of the files found in a directory and display it to the visitor if you access the path of it and no default file is found (e.g. index.html). However, for security reasons, this is disabled by default in ASP.NET Core - generally, there's simply no reason to let the visitor know which files exist on your webserver unless you specifically link to them and in theory. However, in rare cases, it can be useful to allow the visitor to browse the files of a specific folder, usually in situations where you want to give access to a folder of files without having to manually create a link to each one.

Fortunately, this is still possible with ASP.NET Core - to illustrate it, I have created a folder inside my wwwroot folder called "Images". I want to make the content of this folder browsable by the visitor and allow them to see which files are present in this specific folder.

First of all, you need two additional using statements in your Startup.cs file:

using Microsoft.Extensions.FileProviders;
using System.IO;

Then you need to modify the Configure() method once again - you should still call UseStaticFiles() without arguments, to enable default access to static files, but on top of that, we're going to use a method called UseDirectoryBrowser() to give directory access to our Images folder:

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    app.UseDirectoryBrowser(new DirectoryBrowserOptions
FileProvider = new PhysicalFileProvider
    Path.Combine(Directory.GetCurrentDirectory(), "wwwroot", "Images")    
RequestPath = "/Images"

With this in place, you can now browse the "Images" folder of your wwwroot - a nice file listing with links and details for each file will be automatically generated and served to the visitor:

As soon as you add files inside the directory, they will be automatically included in this list.


Serving static files in ASP.NET Core MVC is slightly different than in other frameworks like ASP.NET WebForms, because it has to be specifically enabled (by calling the UseStaticFiles() method) and placed in a special folder called "wwwroot". However, as illustrated in this article, it's not difficult at all.

This article has been fully translated into the following languages: Is your preferred language not on the list? Click here to help us translate this article into your language!