I'm trying to build a .NET 6.0 C# rest webservice, receiving a string and three files, one of them a binary image. The files are not saved, just checked/evaluated and the result is returned in a json structure. The string can be an url path parameter. The webservice should run on windows and in a linux docker container. It is called only from C# clients and is not accessible from the internet.
So the curl looks like that:
curl -X POST -H "Content-Type: multipart/form-data; boundary=------------------------d74496d66958873e" \
--data-binary "@KeyValue.json" \
--data-binary "@Text.txt" \
--data-binary "@Image.tif" \
http://localhost:5000/check/CheckType01
I tried an approach starting with the Visual Studio 2022 Project "ASP.NET Core-Web-Api"
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.MapPost("/check/{checkType}", (string checkType, HttpContext ctx) =>
{
ctx.Request.EnableBuffering();
ctx.Request.Body.Position = 0;
var reader = new StreamReader(ctx.Request.Body);
var body = Task.Run(async () => await reader.ReadToEndAsync().ConfigureAwait(false));
Console.WriteLine("Parameter: " + checkType);
Console.WriteLine("MultiPart: " + body.Result);
return new { check = "Ok", confidence = 100 }; ;
});
app.Run();
With the three files containing "KeyValueContent", "TextContent" and "ImageContent", this code partially works:
Output:
Parameter: CheckType01
MultiPart: KeyValueContent&TextContent&ImageContent
Return:
{"check":"Ok","confidence":100}
But this can't be the correct approach to solve this, I assume.
I have read a lot about how to upload files in ASP.Net Core, about webapi-controllers, model view controllers, annotations, minimal API or not and so on, but I'm still not sure what the correct way to go is, I couldn't find a working minimal example.
I would like to know:
Besides fixing the curl request to read multiple file you can use IFormFileCollection
returned by HttpRequest.Form.Files
(inject HttpRequest
as handler parameter or use ctx.Request
to access it).
Also note that Task.Run
not only pointless here but harmful, just mark the lambda handler as async
:
app.MapPost("/check/{checkType}", async (string checkType, HttpRequest request) =>
{
var formFileCollection = request.Form.Files;
foreach (var formFile in request.Form.Files)
{
using var openReadStream = new StreamReader(formFile.OpenReadStream());
var readToEndAsync = await openReadStream.ReadToEndAsync();
// do something here
}
...
return new { check = "Ok", confidence = 100 };
});