Work with static files in ASP.NET Core

By Rick Anderson and Scott Addie

Static files, such as HTML, CSS, images, and JavaScript, are assets an ASP.NET Core app serves directly to clients. Some configuration is required to enable to serving of these files.

View or download sample code (how to download)

Serve static files

Static files are stored within your project's web root directory. The default directory is <content_root>/wwwroot, but it can be changed via the UseWebRoot method. See Content root and Web root for more information.

The app's web host must be made aware of the content root directory.

The WebHost.CreateDefaultBuilder method sets the content root to the current directory:

public class Program
{
    public static void Main(string[] args)
    {
        BuildWebHost(args).Run();
    }

    public static IWebHost BuildWebHost(string[] args) =>
        WebHost.CreateDefaultBuilder(args)
            .UseStartup<Startup>()
            .Build();
}

Static files are accessible via a path relative to the web root. For example, the Web Application project template contains several folders within the wwwroot folder:

  • wwwroot
    • css
    • images
    • js

The URI format to access a file in the images subfolder is http://<server_address>/images/<image_file_name>. For example, http://localhost:9189/images/banner3.svg.

If targeting .NET Framework, add the Microsoft.AspNetCore.StaticFiles package to your project. If targeting .NET Core, the Microsoft.AspNetCore.All metapackage includes this package.

Configure the middleware which enables the serving of static files.

Serve files inside of web root

Invoke the UseStaticFiles method within Startup.Configure:

public void Configure(IApplicationBuilder app)
{
    app.UseStaticFiles();
}

The parameterless UseStaticFiles method overload marks the files in web root as servable. The following markup references wwwroot/images/banner1.svg:

<img src="~/images/banner1.svg" alt="ASP.NET" class="img-responsive" />

Serve files outside of web root

Consider a directory hierarchy in which the static files to be served reside outside of the web root:

  • wwwroot
    • css
    • images
    • js
  • MyStaticFiles
    • images
      • banner1.svg

A request can access the banner1.svg file by configuring the static file middleware as follows:

public void Configure(IApplicationBuilder app)
{
    app.UseStaticFiles(); // For the wwwroot folder

    app.UseStaticFiles(new StaticFileOptions
    {
        FileProvider = new PhysicalFileProvider(
            Path.Combine(Directory.GetCurrentDirectory(), "MyStaticFiles")),
        RequestPath = "/StaticFiles"
    });
}

In the preceding code, the MyStaticFiles directory hierarchy is exposed publicly via the StaticFiles URI segment. A request to http://<server_address>/StaticFiles/images/banner1.svg serves the banner1.svg file.

The following markup references MyStaticFiles/images/banner1.svg:

<img src="~/StaticFiles/images/banner1.svg" alt="ASP.NET" class="img-responsive" />

Set HTTP response headers

A StaticFileOptions object can be used to set HTTP response headers. In addition to configuring static file serving from the web root, the following code sets the Cache-Control header:

public void Configure(IApplicationBuilder app)
{
    app.UseStaticFiles(new StaticFileOptions
    {
        OnPrepareResponse = ctx =>
        {
            // Requires the following import:
            // using Microsoft.AspNetCore.Http;
            ctx.Context.Response.Headers.Append("Cache-Control", "public,max-age=600");
        }
    });
}

The HeaderDictionaryExtensions.Append method exists in the Microsoft.AspNetCore.Http package.

The files have been made publicly cacheable for 10 minutes (600 seconds):

Response headers showing the Cache-Control header has been added

Static file authorization

The static file middleware doesn't provide authorization checks. Any files served by it, including those under wwwroot, are publicly accessible. To serve files based on authorization:

  • Store them outside of wwwroot and any directory accessible to the static file middleware and
  • Serve them via an action method to which authorization is applied. Return a FileResult object:
[Authorize]
public IActionResult BannerImage()
{
    var file = Path.Combine(Directory.GetCurrentDirectory(), 
                            "MyStaticFiles", "images", "banner1.svg");

    return PhysicalFile(file, "image/svg+xml");
}

Enable directory browsing

Directory browsing allows users of your web app to see a directory listing and files within a specified directory. Directory browsing is disabled by default for security reasons (see Considerations). Enable directory browsing by invoking the UseDirectoryBrowser method in Startup.Configure:

public void Configure(IApplicationBuilder app)
{
    app.UseStaticFiles(); // For the wwwroot folder

    app.UseStaticFiles(new StaticFileOptions
    {
        FileProvider = new PhysicalFileProvider(
            Path.Combine(Directory.GetCurrentDirectory(), "wwwroot", "images")),
        RequestPath = "/MyImages"
    });

    app.UseDirectoryBrowser(new DirectoryBrowserOptions
    {
        FileProvider = new PhysicalFileProvider(
            Path.Combine(Directory.GetCurrentDirectory(), "wwwroot", "images")),
        RequestPath = "/MyImages"
    });
}

Add required services by invoking the AddDirectoryBrowser method from Startup.ConfigureServices:

public void ConfigureServices(IServiceCollection services)
{
    services.AddDirectoryBrowser();
}

The preceding code allows directory browsing of the wwwroot/images folder using the URL http://<server_address>/MyImages, with links to each file and folder:

directory browsing

See Considerations on the security risks when enabling browsing.

Note the two UseStaticFiles calls in the following example. The first call enables the serving of static files in the wwwroot folder. The second call enables directory browsing of the wwwroot/images folder using the URL http://<server_address>/MyImages:

public void Configure(IApplicationBuilder app)
{
    app.UseStaticFiles(); // For the wwwroot folder

    app.UseStaticFiles(new StaticFileOptions
    {
        FileProvider = new PhysicalFileProvider(
            Path.Combine(Directory.GetCurrentDirectory(), "wwwroot", "images")),
        RequestPath = "/MyImages"
    });

    app.UseDirectoryBrowser(new DirectoryBrowserOptions
    {
        FileProvider = new PhysicalFileProvider(
            Path.Combine(Directory.GetCurrentDirectory(), "wwwroot", "images")),
        RequestPath = "/MyImages"
    });
}

Serve a default document

Setting a default home page provides visitors a logical starting point when visiting your site. To serve a default page without the user fully qualifying the URI, call the UseDefaultFiles method from Startup.Configure:

public void Configure(IApplicationBuilder app)
{
    app.UseDefaultFiles();
    app.UseStaticFiles();
}

Important

UseDefaultFiles must be called before UseStaticFiles to serve the default file. UseDefaultFiles is a URL rewriter that doesn't actually serve the file. Enable the static file middleware via UseStaticFiles to serve the file.

With UseDefaultFiles, requests to a folder search for:

  • default.htm
  • default.html
  • index.htm
  • index.html

The first file found from the list is served as though the request were the fully qualified URI. The browser URL continues to reflect the URI requested.

The following code changes the default file name to mydefault.html:

public void Configure(IApplicationBuilder app)
{
    // Serve my app-specific default file, if present.
    DefaultFilesOptions options = new DefaultFilesOptions();
    options.DefaultFileNames.Clear();
    options.DefaultFileNames.Add("mydefault.html");
    app.UseDefaultFiles(options);
    app.UseStaticFiles();
}

UseFileServer

UseFileServer combines the functionality of UseStaticFiles, UseDefaultFiles, and UseDirectoryBrowser.

The following code enables the serving of static files and the default file. Directory browsing isn't enabled.

app.UseFileServer();

The following code builds upon the parameterless overload by enabling directory browsing:

app.UseFileServer(enableDirectoryBrowsing: true);

Consider the following directory hierarchy:

  • wwwroot
    • css
    • images
    • js
  • MyStaticFiles
    • images
      • banner1.svg
    • default.html

The following code enables static files, default files, and directory browsing of MyStaticFiles:

public void Configure(IApplicationBuilder app)
{
    app.UseStaticFiles(); // For the wwwroot folder

    app.UseFileServer(new FileServerOptions
    {
        FileProvider = new PhysicalFileProvider(
            Path.Combine(Directory.GetCurrentDirectory(), "MyStaticFiles")),
        RequestPath = "/StaticFiles",
        EnableDirectoryBrowsing = true
    });
}

AddDirectoryBrowser must be called when the EnableDirectoryBrowsing property value is true:

public void ConfigureServices(IServiceCollection services)
{
    services.AddDirectoryBrowser();
}

Using the file hierarchy and preceding code, URLs resolve as follows:

URI Response
http://<server_address>/StaticFiles/images/banner1.svg MyStaticFiles/images/banner1.svg
http://<server_address>/StaticFiles MyStaticFiles/default.html

If no default-named file exists in the MyStaticFiles directory, http://<server_address>/StaticFiles returns the directory listing with clickable links:

Static files list

Note

UseDefaultFiles and UseDirectoryBrowser use the URL http://<server_address>/StaticFiles without the trailing slash to trigger a client-side redirect to http://<server_address>/StaticFiles/. Notice the addition of the trailing slash. Relative URLs within the documents are deemed invalid without a trailing slash.

FileExtensionContentTypeProvider

The FileExtensionContentTypeProvider class contains a Mappings property serving as a mapping of file extensions to MIME content types. In the following sample, several file extensions are registered to known MIME types. The .rtf extension is replaced, and .mp4 is removed.

public void Configure(IApplicationBuilder app)
{
    // Set up custom content types - associating file extension to MIME type
    var provider = new FileExtensionContentTypeProvider();
    // Add new mappings
    provider.Mappings[".myapp"] = "application/x-msdownload";
    provider.Mappings[".htm3"] = "text/html";
    provider.Mappings[".image"] = "image/png";
    // Replace an existing mapping
    provider.Mappings[".rtf"] = "application/x-msdownload";
    // Remove MP4 videos.
    provider.Mappings.Remove(".mp4");

    app.UseStaticFiles(new StaticFileOptions
    {
        FileProvider = new PhysicalFileProvider(
            Path.Combine(Directory.GetCurrentDirectory(), "wwwroot", "images")),
        RequestPath = "/MyImages",
        ContentTypeProvider = provider
    });

    app.UseDirectoryBrowser(new DirectoryBrowserOptions
    {
        FileProvider = new PhysicalFileProvider(
            Path.Combine(Directory.GetCurrentDirectory(), "wwwroot", "images")),
        RequestPath = "/MyImages"
    });
}

See MIME content types.

Non-standard content types

The static file middleware understands almost 400 known file content types. If the user requests a file of an unknown file type, the static file middleware returns a HTTP 404 (Not Found) response. If directory browsing is enabled, a link to the file is displayed. The URI returns an HTTP 404 error.

The following code enables serving unknown types and renders the unknown file as an image:

public void Configure(IApplicationBuilder app)
{
    app.UseStaticFiles(new StaticFileOptions
    {
        ServeUnknownFileTypes = true,
        DefaultContentType = "image/png"
    });
}

With the preceding code, a request for a file with an unknown content type is returned as an image.

Warning

Enabling ServeUnknownFileTypes is a security risk. It's disabled by default, and its use is discouraged. FileExtensionContentTypeProvider provides a safer alternative to serving files with non-standard extensions.

Considerations

Warning

UseDirectoryBrowser and UseStaticFiles can leak secrets. Disabling directory browsing in production is highly recommended. Carefully review which directories are enabled via UseStaticFiles or UseDirectoryBrowser. The entire directory and its sub-directories become publicly accessible. Store files suitable for serving to the public in a dedicated directory, such as <content_root>/wwwroot. Separate these files from MVC views, Razor Pages (2.x only), configuration files, etc.

  • The URLs for content exposed with UseDirectoryBrowser and UseStaticFiles are subject to the case sensitivity and character restrictions of the underlying file system. For example, Windows is case insensitive—macOS and Linux aren't.

  • ASP.NET Core apps hosted in IIS use the ASP.NET Core Module to forward all requests to the app, including static file requests. The IIS static file handler isn't used. It has no chance to handle requests before they're handled by the module.

  • Complete the following steps in IIS Manager to remove the IIS static file handler at the server or website level:

    1. Navigate to the Modules feature.
    2. Select StaticFileModule in the list.
    3. Click Remove in the Actions sidebar.

Warning

If the IIS static file handler is enabled and the ASP.NET Core Module is configured incorrectly, static files are served. This happens, for example, if the web.config file isn't deployed.

  • Place code files (including .cs and .cshtml) outside of the app project's web root. A logical separation is therefore created between the app's client-side content and server-based code. This prevents server-side code from being leaked.

Additional resources