Azure .NET Core Web App and Where to Locate Static Files

In Azure your web app is written to the “d:\home\site\wwwroot” folder, and if you deploy with Visual Studio and choose “Remove additional files at destination” anything not in your project will be removed from “d:\home\site\wwwroot”. The default Continuous Integration profile on Azure DevOps does not remove files in “d:\home\site\wwwroot” but overwrites, this can get you into a fix sometimes as a bad file can persist, it’s something to keep in mind if you are struggling to work out why a fresh deploy after you removed a troublesome DLL from the project is still failing as the DLL may still be on Azure.

I would not recommend having large static files (images, PDFs and such like) stored under the “d:\home\site\wwwroot” folder. You do not really want to include these in your Azure DevOps repository or project, and you don’t want to risk them being removed by someone using “Remove additional files at destination” when publishing from Visual Studio.

My suggestion is to store the static files in a new subfolder under the “d:\home\site” folder, or use a Blob in an Azure Storage Account and manage them separately, but the problem to solve is how to reference them within your app so an end user can reference them with a URL as if the files are part of the site. Files hosted in Azure Blob Storage can be setup to be accessed on a separate domain or a sub-domain, but that’s not we usually want.

Serving files in a subfolder of “d:\home\site” can be achieved by passing parameters into the app.UseStaticFile method in the Configure method of startup.cs as described in https://docs.microsoft.com/en-us/aspnet/core/fundamentals/static-files. This is how I implement it so I can change the referenced folder depending on environment:

// Any static files under wwwroot handled normally
app.UseStaticFiles();
// The path in the url we will manage
var staticFilesPath =
    Configuration.GetSection("StaticFilesPath").Value;
// The local/network folder containing static files we are mapping to
var staticFilesFolder =
    Configuration.GetSection("StaticFilesFolder").Value;
if (!string.IsNullOrWhiteSpace(staticFilesFolder))
{
    app.UseStaticFiles(new StaticFileOptions
    {
        FileProvider = new PhysicalFileProvider(staticFilesFolder),
        RequestPath = staticFilesPath
    });
}

In appsettings.Production.json you might have something like this to have files with a url path of /files get them from a subfolder called staticfiles you have created on Azure in “d:\home\site”:

"StaticFilesFolder": "D:\\home\\site\\staticfiles",
"StaticFilesPath": "/files"

In appsettings.Development.json you might have something like this to have files with a url path of /files get them from a subfolder called staticfiles you have created locally in “c:\temp”:

"StaticFilesFolder": "C:\\temp\\staticfiles",
"StaticFilesPath": "/files"

The development environment could be setup to a local folder or a network share that all the developers on your team then reference for their static files.

Providing the files via Azure Blob Storage can be achieved using the NuGet package Strathweb.AspNetCore.AzureBlobFileProvider described at https://www.strathweb.com/2018/08/azure-blob-storage-ifileprovider-for-asp-net-core/.

You could also use a combination of the options, using the local static files via the PhysicalFileProvider on Development, but then switching to Blob storage in production similar to this:

// Any static files under wwwroot handled normally
app.UseStaticFiles();
// The path in the url we will manage
var staticFilesPath =
    Configuration.GetSection("StaticFilesPath").Value;
if (env.IsDevelopment())
{
    // The local/network folder containing static files we are mapping to
    var staticFilesFolder =
        Configuration.GetSection("StaticFilesFolder").Value;
    if (!string.IsNullOrWhiteSpace(staticFilesFolder))
    {
        app.UseStaticFiles(new StaticFileOptions
        {
            FileProvider = new PhysicalFileProvider(staticFilesFolder),
            RequestPath = staticFilesPath
        });
    }
}
else
{
    // We will map to blob storage for the path
    var blobFileProvider =
        app.ApplicationServices.GetRequiredService<AzureBlobFileProvider>();
    if (blobFileProvider != null)
    {
        app.UseStaticFiles(new StaticFileOptions()
        {
            FileProvider = blobFileProvider,
            RequestPath = staticFilesPath
        });
    }
}

Posted

in

, ,

by

Tags: