I want to test an REST API endpoint written in C# (.NET 8.0).
The endpoint /import
should take multiple files from the TestFiles
folder:
using Microsoft.AspNetCore.Mvc;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddEndpointsApiExplorer();
var app = builder.Build();
app.MapGet("/", () => "Hello World!");
app.MapPost("/import", Import).DisableAntiforgery();
static async Task<IResult> Import([FromForm] List<IFormFile> xyz)
{
if (xyz == null || xyz.Count == 0)
{
return Results.BadRequest("No files were provided.");
}
// This is never reached !!!
return Results.Ok();
}
app.Run();
The test looks like this:
using Microsoft.AspNetCore.Mvc.Testing;
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
namespace Importer.Tests
{
public class IntegrationTests(WebApplicationFactory<Program> factory) : IClassFixture<WebApplicationFactory<Program>>
{
private readonly WebApplicationFactory<Program> _factory = factory;
private readonly string _testFilesPath = Path.Combine(Environment.CurrentDirectory, "TestFiles");
private MultipartFormDataContent CreateMultipartFormDataFromTestFiles(List<string> fileNames)
{
var formContent = new MultipartFormDataContent();
foreach (var fileName in fileNames)
{
string filepath = Path.Combine(_testFilesPath, fileName);
var fileBytes = File.ReadAllBytes(filepath);
var fileContent = new ByteArrayContent(fileBytes);
fileContent.Headers.ContentType = MediaTypeHeaderValue.Parse("multipart/form-data");
formContent.Add(fileContent, "xyz", fileName);
// "files" parameter name should be the same as the server side input parameter name
//https://learn.microsoft.com/en-us/aspnet/core/mvc/models/file-uploads?view=aspnetcore-8.0#match-name-attribute-value-to-parameter-name-of-post-method
}
return formContent;
}
[Fact]
public async Task API_Import_File_Should_Return_Http_Status_OK()
{
List<string> fileList = new List<string> { "Input.txt" };
var form = CreateMultipartFormDataFromTestFiles(fileList);
using var client = _factory.CreateClient();
var response = await client.PostAsync("/import", form);
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
}
}
}
The problem is the list "xyz" is always null!
If the [FromForm]
tag is removed, the response is:
StatusCode: 415, ReasonPhrase: 'Unsupported Media Type'
If the endpoint /import
is changed to handle only one file => IFormFile
, everything works!
Any suggestions are more than appreciated. Thanks
In Minimal APIs, file uploads support using IFormCollection
, IFormFile
, and IFormFileCollection
in .NET 8. Notice, List<IFormFile>
does not support so that you need change your code to:
static async Task<IResult> Import([FromForm] IFormFileCollection xyz)
{
if (xyz == null || xyz.Count == 0)
{
return Results.BadRequest("No files were provided.");
}
foreach (var file in xyz)
{
// ...
}
return Results.Ok();
}