24

ASP.NET Core hapily serves up files from the wwwroot folder based on the mime type of the file. But how do I get it serve up a file with no extension?

As an example, Apple require that you have an endpoint in your app /apple-app-site-association for some app-intergration. If you add a text file called apple-app-site-association into your wwwroot it won't work.

Some things I've tried:

1) Provide a mapping for when there's no extension:

var provider = new FileExtensionContentTypeProvider();
provider.Mappings[""] = "text/plain";
app.UseStaticFiles(new StaticFileOptions
            {
                ContentTypeProvider = provider
            });

2) Adding an app rewrite:

var options = new RewriteOptions()
.AddRewrite("^apple-app-site-association","/apple-app-site-association.txt", false)

Neither work, the only thing that does work is a .AddRedirect which I'd rather not use if possible.

Matt Roberts
  • 26,371
  • 31
  • 103
  • 180

4 Answers4

37

Adding an alternative solution. You have to set ServeUnknownFileTypes to true and after that set the default content type.

        app.UseStaticFiles(new StaticFileOptions
        {
            ServeUnknownFileTypes = true,
            DefaultContentType = "text/plain"
        });
sinofis
  • 556
  • 1
  • 5
  • 15
  • 8
    Downvoting because this adds a security risk as explained in the ASP Core docs. The accepted answer is the best way to "whitelist" files to be served without opening up all file types. – Brad Sep 24 '18 at 19:28
  • 3
    If you are concerned about security you can either reduce the scope of the served file with this option with a specific PhysicalFileProvider, or implement your own IFileProvider as the StaticFileOptions.FileProvider property. – chaami Nov 07 '18 at 13:26
  • 1
    Warning Enabling ServeUnknownFileTypes is a security risk. It's disabled by default, and its use is discouraged. – AEMLoviji Nov 27 '20 at 10:37
  • Just what I needed thanks. This is development work, i dont need to worry about deep security. If you want your default to be binary files use "application/octet-stream" – user430788 Jan 19 '21 at 23:51
  • The Core docs don't actually explain how it's a security risk, they just state it. On its own I don't see how it's a risk. – Kristaps Baumanis Mar 08 '23 at 10:28
23

Rather than fighting with static files, I think you'd be better off just creating a controller for it:

using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Mvc;
using System.IO;

namespace MyApp.Controllers {
    [Route("apple-app-site-association")]
    public class AppleController : Controller {
        private IHostingEnvironment _hostingEnvironment;

        public AppleController(IHostingEnvironment environment) {
            _hostingEnvironment = environment;
        }

        [HttpGet]
        public async Task<IActionResult> Index() {
            return Content(
                await File.ReadAllTextAsync(Path.Combine(_hostingEnvironment.WebRootPath, "apple-app-site-association")),
                "text/plain"
            );
        }
    }
}

This assumes your apple-app-site-association file is in your wwwroot folder.

Gabriel Luci
  • 38,328
  • 4
  • 55
  • 84
8

An easier option may be to put a file with a proper extension on the server, and then use URL rewrite as follows.

app.UseRewriter(new RewriteOptions()
    .AddRewrite("(.*)/apple-app-site-association", "$1/apple-app-site-association.json", true));
Serge S
  • 81
  • 1
  • 2
  • Best answer! No security risks like allowing all unknown static filetypes and no overhead by creating a controller for returning a simple json file. – d03090 Dec 26 '20 at 14:31
  • This somehow didn't work for me in .NET 6. I had to use `app.UseRewriter(new RewriteOptions().AddRewrite("^apple-app-site-association$", "/apple-app-site-association.json", true));` – Marthijn Dec 31 '21 at 09:00
4

I think the easiest way is to add the apple-app-site-association file in a .well-known folder in the root folder of the application as described here: [https://developer.apple.com/documentation/safariservices/supporting_associated_domains] and then allow access to it from your code, like this (Startup.cs):

 // to allow access to apple-app-site-association file
app.UseStaticFiles(new StaticFileOptions()
{
    FileProvider = new PhysicalFileProvider(Path.Combine(env.ContentRootPath, @".well-known")),
    RequestPath = new PathString("/.well-known"),
    DefaultContentType = "application/json",
    ServeUnknownFileTypes = true,
});

Tested in AWS Serverless Application (.NET Core 3.1)