404 on the home page of a Web API

Why a Web API returns 404 on its root address, how to show Swagger and how to serve a front end.

You published an ASP.NET Core Web API, opened the address of the website and got 404 – Not Found. In most cases nothing is broken.

A Web API has no home page

A Web API answers only on the routes of its controllers and endpoints, for example /api/products. The root address / has no content, so the application correctly answers 404. Open one of your API routes to check that the API works.

Swagger is missing after deployment

The project templates enable Swagger (OpenAPI) only in the Development environment:

if (app.Environment.IsDevelopment())
{
    app.UseSwagger();
    app.UseSwaggerUI();
}

or, in newer templates:

if (app.Environment.IsDevelopment())
{
    app.MapOpenApi();
}

On the hosting your application runs in the Production environment, so the Swagger page does not exist. To have it available, remove the IsDevelopment() condition and publish again:

app.UseSwagger();
app.UseSwaggerUI();

Warning

Swagger describes your whole API to anyone who opens it. Publish it in production only if that is what you want.

Serving a front end from the same website

If the same website should also serve a front end (Angular, React, Vue or plain HTML), the application has to be told to serve static files. Add this to Program.cs:

app.UseDefaultFiles();   // must come before UseStaticFiles
app.UseStaticFiles();

app.MapControllers();
app.MapFallbackToFile("index.html");

app.Run();

Then put the built front end (index.html and its assets) into the wwwroot folder of your project and publish the application again. On the server these files end up in /wwwroot/wwwroot.

Without UseStaticFiles() the application serves only API controllers and every other address, including / and /index.html, returns 404.

Images and uploaded files return 404

By default a Web API project does not serve static files at all, so a link to an image, a PDF or another document returns 404 even though the file is on the server. The same happens in any ASP.NET Core application with files that users upload while the application is running: the upload works, the file is in the folder, but its URL answers 404.

The published application looks like this on the server:

wwwroot/
├── appsettings.json
├── application.dll
├── web.config
├── wwwroot/
│   ├── image1.png
│   └── upload/
│       └── document1.pdf
└── Files/
    └── image2.png

Open Program.cs and add the static file middleware after builder.Build(). The plain UseStaticFiles() call enables serving the static content of the application's wwwroot folder. The second, extended call adds a folder explicitly, so that files uploaded dynamically are served too.

Files in the application's wwwroot folder — available as https://yourdomain.com/image1.png:

var app = builder.Build();
app.UseStaticFiles(); // Enables serving static files from wwwroot
app.UseStaticFiles(new StaticFileOptions {
  FileProvider = new PhysicalFileProvider(
    Path.Combine(Directory.GetCurrentDirectory(), "wwwroot")),
  RequestPath = ""
});

Uploaded files in wwwroot/upload — available as https://yourdomain.com/upload/document1.pdf:

var app = builder.Build();
app.UseStaticFiles(); // Enables serving static files from wwwroot
app.UseStaticFiles(new StaticFileOptions {
  FileProvider = new PhysicalFileProvider(
    Path.Combine(Directory.GetCurrentDirectory(), "wwwroot", "upload")),
  RequestPath = "/upload"
});

Files in a custom folder outside wwwroot, for example Files — available as https://yourdomain.com/Files/image2.png:

var app = builder.Build();
app.UseStaticFiles(); // Enables serving static files from wwwroot
app.UseStaticFiles(new StaticFileOptions {
  FileProvider = new PhysicalFileProvider(
    Path.Combine(Directory.GetCurrentDirectory(), "Files")),
  RequestPath = new PathString("/Files")
});

More details are in the Microsoft documentation: Static files in ASP.NET Core.

Still stuck? Our support team is happy to help.
Ask the community Open a support ticket