我想测试用 C# (.NET 8.0) 编写的 REST API 端点。
端点
/import
应从 TestFiles
文件夹中获取多个文件:
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();
测试看起来像这样:
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);
}
}
}
问题是列表“xyz”始终为空!
如果删除
[FromForm]
标签,则响应为:
状态代码:415,原因短语:“不支持的媒体类型”
如果端点
/import
更改为仅处理一个文件 => IFormFile
,一切正常!
如有任何建议,我们将不胜感激。谢谢
在最小 API 中,文件上传支持使用
IFormCollection
、IFormFile
和 .NET 8中的
IFormFileCollection
。请注意,不是 List<IFormFile>
,因此您需要将代码更改为:
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();
}