- Home
- .NET tutorials
- How to upload files in an ASP.NET Core Web API
How to upload files in an ASP.NET Core Web API
Published: Monday 1 December 2025
File uploads are a common requirement when building APIs. Whether you're working with images, documents, or other file types.
In this article, we'll walk through how to upload files in an ASP.NET Core Web API using minimal APIs, how to handle antiforgery tokens, how to support multiple file uploads, and what security considerations you should keep in mind.
Uploading a single file
Let's start with a simple endpoint that accepts a single upload:
// Program.cs
app.MapPost("/upload-file", async (
IFormFile file
) =>
{
var directory = $"{Environment.CurrentDirectory}/Files";
if (!Directory.Exists(directory))
{
Directory.CreateDirectory(directory);
}
var fullFilePath = $"{directory}/{file.FileName}";
if (!File.Exists(fullFilePath))
{
using var fileStream = File.Create(fullFilePath);
await file.CopyToAsync(fileStream);
return new { Success = true };
}
return new { Success = false };
});
Here's what's happening:
- We set up a
/upload-fileendpoint - The file is stored inside a
Filesdirectory within the application root. - We create the directory if it doesn't exist.
- If the file doesn’t already exist, it gets saved.
- A simple JSON response indicates success or failure.
However, if you run this and attempt to upload the file, you get the following exception:
System.InvalidOperationException: Endpoint HTTP: POST /upload-file contains anti-forgery metadata, but a middleware was not found that supports anti-forgery.
Configure your application startup by adding app.UseAntiforgery() in the application startup code.
If there are calls to app.UseRouting() and app.UseEndpoints(...), the call to app.UseAntiforgery() must go between them.
Calls to app.UseAntiforgery() must be placed after calls to app.UseAuthentication() and app.UseAuthorization().
Handling antiforgery tokens
ASP.NET Core protects against cross-site request forgery (CSRF) by default in minimal APIs. Disabling antiforgery validation isn't recommended as it leaves your API vulnerable. Instead, the correct approach is to include an antiforgery token with your request.
First, install the Microsoft.AspNetCore.Antiforgery NuGet package, then configure it in Program.cs:
// Program.cs
builder.Services.AddAntiforgery();
app.UseAntiforgery();
Next, create an endpoint to generate a token:
// Program.cs
app.MapGet("/generate-token", (
IAntiforgery antiforgery,
HttpContext httpContext) =>
new { antiforgery.GetAndStoreTokens(httpContext).RequestToken });
The token can be included as a cookie, request header or a form value when uploading a file. We are going to add it as a form value. The default form name for the token is __RequestVerificationToken and this could be stored as a hidden input field in your file upload form.
We need to accept the token as a parameter in the endpoint. As a result, we need to make a change to the /upload-files endpoint to do this.
app.MapPost("/upload-file", async (
IFormFile file,
[FromForm(Name = "__RequestVerificationToken")] string token // <- Add this line
) =>
{
...
});
Here's what's happening:
- Added a new parameter called
tokenin the endpoint handler - We've specified that it's from a form value by including the
FromFormattribute - We've specified that the name of the form value is
__RequestVerificationToken
Now the workflow looks like this:
- Call
/generate-tokento get a CSRF token. - Include that token in your upload request.
- The upload will succeed.
Upload multiple files
Often, you'll need to upload several files at once. You can use IFormFileCollection for this.
// Program.cs
app.MapPost("/upload-files", async (
IFormFileCollection fileCollection,
[FromForm(Name = "__RequestVerificationToken")] string token
) =>
{
var directory = $"{Environment.CurrentDirectory}/Files";
if (!Directory.Exists(directory))
{
Directory.CreateDirectory(directory);
}
var anyUploadSuccessful = false;
foreach (var file in fileCollection)
{
var fullFilePath = $"{directory}/{file.FileName}";
if (!File.Exists(fullFilePath))
{
using var fileStream = File.Create(fullFilePath);
await file.CopyToAsync(fileStream);
anyUploadSuccessful = true;
}
}
return new { Success = anyUploadSuccessful };
});
This endpoint loops through all uploaded files, saving each one if it doesn't already exist. You still need to pass in the antiforgery token, just like in the single-file example.
Watch the video
Watch this video to learn more about how to upload files using minimal APIs.
Security considerations
Allowing users to upload files comes with risks. Malicious actors might upload files containing viruses or malware. At a minimum, you should:
- Restrict allowed file types and sizes.
- Scan uploads with an antivirus tool.
A popular choice is ClamAV, which integrates well with .NET applications. If this is a tutorial you'll interested in, drop us a message.
Related tutorials
How .NET 6 Minimal APIs has evolved ASP.NET Core
Converting a small front-end ASP.NET Core Web API from ASP.NET Core 2.1 to ASP.NET Core 6 using Minimal APIs & remove dead code.