Home > database >  .Net 6 core C# -building a rest webservice with binary multipart/form-data upload returning json
.Net 6 core C# -building a rest webservice with binary multipart/form-data upload returning json

Time:05-25

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.

  • The files are separated by an '&' and not by the boundary from the header, so it is not possible to separate them.
  • Somehow the framework should do the separation instead.
  • The multipart body is a string and not a byte array.
  • The webservice is blocked during the body read.

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:

  • which Visual Studio 2022 starting project type should I use?
  • what framework to use (minimal api, api with controllers, [ApiController] attribute ...)?
  • the necessary attributes for POST - binary multipart/form-data?

CodePudding user response:

I checked your codes,you want to post mutiple files at one time,but --data-binary allows you post one file per request,you could try with -F to post serverl files and access the files from HttpContext.Request.Form. You could try with postman,and you will find what's wrong immediately: enter image description here enter image description here

CodePudding user response:

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 };
});
  • Related